(자연어 처리/ word 기반 RNN) 한국어 시 짓기 - 2
이제 문장 생성 코드를 실행해서 문장 생성을 해보겠습니다.
띄어쓰기 기준으로 단어를 나누어서 그것을 훈련 시퀀스로 사용했을 경우에는, char RNN만큼이나 성능이 좋질 않더군요.
띄어쓰기 기준 토큰(어휘) 데이터로 훈련한 가중치를 형태소 기반 훈련 가중치로 덮어써 버려서, 다시 훈련을 시켜서 올려보겠습니다.
형태소 기준 토큰으로 훈련시킬 때는 1에폭당 약 135초 정도 걸리고, 띄어쓰기 기준 토큰으로 훈련시킬 때는 약 2분 정도 걸리는데, CPU로만 돌리고 있는 상황입니다. 이 둘을 동시에 돌릴 때는 시간이 오래 걸리네요. 프로세서들 상황입니다. 제일 위의 두 프로세서가 훈련 시키고 있는 두 개의 프로세서입니다. 인텔 i7 10700K이다 보니 최대 CPU 성능은 1600%이고, 현재 사용량은 약 1420% 정도 됩니다. 메모리는 전체 16GB에서 각기 20%씩 사용해서 합계 40% 조금 안 됩니다. GTX 1060 3GB는 문제가 많아서 리눅스에서 사용하기 곤란해, 곧 RTX 3060 12GB로 바꿀 예정입니다.
하나는 studio code에서 돌리고 있고 다른 하나는 터미널에서 돌리고 있습니다.
Epoch 10/10 (70에폭)
224/224 [==============================] - 212s 945ms/step - loss: 3.4639 - accuracy: 0.3704
가득함 때문에 다가오지 못 하고 모자람 것은 슬프게 있는 것은 많이 사랑한다는 것은 열심히 마실 수 있는 사람 입니다 눈빛만 사랑한다는 없이 언제나 기쁨보다는 모든 돌아아 팠다고 하던 것은 만날 수 없는 진달래꽃 내해질 녘 깊 이 갤 인해 정말로 존재를 쓰러져야 따오신다고 않기에 가는 미물을 보여 메여 지는 눈물 그대 내 그대를 사랑하고 있는 소원이 미어지도록 내내 내 몸과 내 때문에
하늘을 들여다보면 저건 너 뒤가 굳이 갯바위가 눈감는 없지 같다 한때는 이 상한적 개심을 방파제 그 사람이 여외 롬 배회에 울리고 나선형 숨결을 쪼아 댄 산자락을 피어나듯이 그 논두렁 확 재촉하진 않을 거 야 씌워 주던 어디까지 가을 빛과 육신 인 것 같았다 퍼붓는 잘못 인지 성숙함을 두었습니다 바람 들어갔지 위하여 모든 서녘 부신 소년을 얼음 짓은 것 없는 사납게 미끄러 진다면
Epoch 10/10 (80에폭)
224/224 [==============================] - 117s 524ms/step - loss: 3.0736 - accuracy: 0.4240
'밝혀지지 않은' 지리산 능선들이 손수건을 툭툭 가는 한 가닥 치명적이다 바람 앞에서 서쪽으로 외로이 선물하고 법 사뿐히 바람들을 봄에는넉넉해 지는 한 섞여서 사람들이 밭고랑을 들어가 지수 있겠냐구 말이나 하염없이 걸요
'소나무 사이로 아스므라한' 솟는 속에 흐르고 얼마만큼 넘치고 청춘이 바람 한 권의 국수 사발 화투 패마냥 순응하는 유심히 벗은 박혀 있다 풀어야 듯하여 나가지 했다 전라도가 어린 사 남았다고 냄새만 빛들도 마셔야 하고 응답이 부위는 옥구슬 안고 실파를 몸부림치는 데 미치도록 물방울n 오므리고
Epoch 10/10 (90에폭)
224/224 [==============================] - 214s 957ms/step - loss: 2.7025 - accuracy: 0.4785
'그리움에 몸을 움츠리고 스치고' 십이월의 지르고 좋았던 장미가 내음 소리에 거친 야수처럼 입가엔 수때 우주에 불을 켜세요 받아 주렴 잔한 방울까지 오만한 올랐소 딴 부리는 않는다 가속을 울리셔도 그림 말아야 한다고 보여요 순식간에 이해되는 군요
Epoch 10/10 (100에폭)
224/224 [==============================] - 211s 941ms/step - loss: 2.3988 - accuracy: 0.5258
'빗물을 서러워' 지켜 주는 만드는 일어설 것이 다 용서하라 눈부시지만 그 혼자 풀뿌리 그들 마음에 것이기에 숨소리를 귀 기울일 수 없는 생각해요 미지의 묶는다고 목적이 가까워 지면 원해 봤다 없으십니다
'말로는 다' 양지 아리랑 고개 넘어 순 바다와 우리는 흔하랴 것 일 것도 없지만 들어올 때 엄마보다 표현하지 않은 그냥 미래도 싶은 틈을 양심의 만나 볼 때 그 가만 남은 거 야 행복하다 이슬의 누군가를 위하여서 있는 물의 격고 걸까먼 밝는다
Epoch 10/10 (110에폭)
224/224 [==============================] - 214s 955ms/step - loss: 2.0867 - accuracy: 0.5803
'다른 별들에서 지구촌을 전율에'빠뜨릴 초호화 축구팀들이 공격해 와야 한다 부처나 공자나 예수보다 더 환상적 인 외계 스타플레이어들이 와야 한다 은하계 매달리는 듣고 없다 마디를 돌아다보게 안책 갈피에 누구는 썩어 누구는 같은 아래쯤에서 하지 위해 점점이 글거리는 것이기에 나갔
* 이 문장의 앞부분('빠뜨릴 초호화 축구팀들이...')은 어떤 시에서 표절한 것이네요. 정확도가 50%를 넘어가면 표절(과적합)을 하기 시작하더라구요. 전체 단어 수가 231,602개인데, 중복 제거 어휘 수는 무려 61,473개입니다. PTB 데이터의 경우, 이보다 데이터가 큼에도 불구하고 유일 단어 수가 1만개에 불과했는데 말이죠. 어휘 수가 많으면 과적합이 쉽게 일어납니다. 뒤에 올 수 있는 어휘의 종류는 평균 4개밖에 되지 않으니, 문장을 조립하는 데 난관을 겪는 거지요. mecba.morphs()로 형태소 기준으로 나누면 22,757개의 중복되지 않는 어휘가 나오는데 한 단어의 뒤에 올 수 있는 단어의 평균 개수가 약 10개 정도가 되어서 문장 조립하기에 자유도가 다소 높아집니다.
PTB 데이터 셋의 경우, train 데이터(dataset/ptb.train.txt)만 고려하면, 전체 어휘 887,521에서 중복되지 않는 단어의 수는 10,000개라서, 한 단어 뒤에 올 수 있는 어휘 종류가 평균 약 89개가 되어서, 문장 조립 자유도가 높아집니다. 또한 마케팅 보도자료 같은 데이터들만 모아놓은 것인지라, 단어 및 문장들의 분위기가 비슷한 것도 머신러닝으로 문장을 만들고 나면 결과가 다소 좋다고 평가될 수 있습니다.
이에 반해, 한국 시어는 높임말(~하였습니다 종결), 옛날식 반말(~하느냐), 요즘 반말(~했다), '다'로 끝나지 않는 경우(~했던 것.) 등으로 종결 어휘들이 제각각이고, 장르로 따져도 사랑 이야기, 자연을 노래한 시들, 사회 비판 풍자, 개인사 회고 등 다양하게 문장의 맥락이나 분위기까지 별도로 학습을 해야 합니다. 뭐 영어 시의 경우에도 별 다를 바는 없겠지만 적어도 영어 시나 노래 가사는 형태소 단위 어휘 분리를 굳이 할 필요는 없는 듯합니다. 띄어쓰기 기준 어휘 분리를 하고 오히려 장르 구분, 감성 분석을 통해 좀더 그럴듯한 시 문장을 낚을 수 있겠지요.
한국어 시 짓기에서 띄어쓰기 기준 단어 기반 RNN 문장 짓기는 이 정도로 하겠습니다. 어차피 정확도가 60%를 넘어가면 과적합될 일이 잦아서 별 의미가 없는 것 같습니다.
***
이제는 mecab.morphs()를 사용해 나눈 어휘들로 시퀀스 텍스트를 만들어 훈련시켜 보았습니다.
형태소 단위로 어휘를 나누면, 전체 어휘 갯수가 늘어나는 것은 당연한 것이고, 중복되지 않는 단어 개수가 줄어드는 것 또한 당연하지요. 아래는 십수 년 전에 정동진을 여행하며 제가 쓴 시의 앞부분입니다.
정동진에는 해가 없다 비는 있다
배는 산으로 가고
기차는 바다 속으로 들어간다
띄어쓰기 기준으로 보면 전체 어휘는 12개입니다. 중복되는 어휘가 없어서 유일 어휘 갯수 또한 12개입니다.
['정동진에는', '해가', '없다', '비는', '있다', '배는', '산으로', '가고', '기차는', '바다', '속으로', '들어간다']
mecab.morphs()로 형태소 분리를 하면, 다음과 같습니다.
['정동진', '에', '는', '해', '가', '없', '다', '비', '는', '있', '다', '배', '는', '산', '으로', '가', '고', '기차', '는', '바다', '속', '으로', '들어간다']
전체 토큰 수는 23개가 되고 중복을 제거하면 17개가 됩니다. 중복된 것들은 다음과 같습니다.
from konlpy.tag import Mecab
from collections import Counter
s = "정동진에는 해가 없다 비는 있다 배는 산으로 가고 기차는 바다 속으로 들어간다"
mecab = Mecab()
tokens = mecab.morphs(s)
tokens = Counter(tokens)
tokens_count = sorted(tokens.items(), key = lambda item: item[1], reverse=True)
print(tokens_count)
출력 결과:
[('는', 4), ('가', 2), ('다', 2), ('으로', 2), ('정동진', 1), ('에', 1), ('해', 1), ('없', 1), ('비', 1), ('있', 1), ('배', 1), ('산', 1), ('고', 1), ('기차', 1), ('바다', 1), ('속', 1), ('들어간다', 1)]
'는'이 4번, '가'가 2번, '다'가 2번, '으로'가 2번 중복되었네요. 3천편 정도 시를 입력했으니 이렇게 중복되는 형태소들이 엄청 많아지겠지요.
이렇게 형태소 분리를 해서 시퀀스 데이터를 만들었고 그것을 기반으로 훈련을 시켜서 문장 생성을 시켜보겠습니다.
우선, 70에폭 정도 훈련시켰고, accuracy는 0.3584입니다.
Epoch 20/20
396/396 [==============================] - 134s 339ms/step - loss: 3.2096 - accuracy: 0.3584
는 그리움 이 일렁 거려 무더기 고 도 테두리 에 도 서까래 에 도 눈물비 로 포장 하 다거나 푸름 으로 다스리 는 향내 그윽 한 사랑 이 여 그대 여 땡감 이 퉁 이 되 고 노여움 을 창조 하 고 있 다 서해 에 역 을 잡 고 아스라 한 산너머 우리 가 미래 를 풍긴다 장식 속 에서 는 동백꽃 이 있 다 나 는 나 의 목소리 가 다가왔 다 내 마음 을 가로막 는다 언제나 칠흑 이 피 었 다 나 는 나 를 사랑 하 는 사람 이 다 사랑 하 는 사람 이
---
띄어쓰기를 하지 않고 형태소 단위로 그대로 출력되었습니다.
공백을 모두 제거하고, 띄어쓰기를 다시 시도합시다.
문장 생성 코드 마지막에 덧붙입니다.
generated = generated.replace(' ', '')
print(generated)
print("------------------")
print(spacing_mecab(generated))
spacing_mecab() 함수는 mecab을 이용해 띄어쓰기를 구현한 함수입니다. 이 함수는 다음 사이트를 참고했습니다.
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=roootwoo&logNo=221590316102
from konlpy.tag import Mecab
def spacing_mecab(sentence):
mecab = Mecab()
tagged = mecab.pos(sentence)
corrected = ""
for tag in tagged:
if tag[1][0] in "JEXS": # S는 부호 포함, SL외국어, SH한자, SN숫자
corrected += tag[0]
elif tag[1] == "VCP":
corrected += tag[0]
else:
corrected += " " + tag[0]
if corrected[0] == " ":
corrected = corrected[1:] # 문장 처음의 공백을 제거
return corrected
- 빈집에취해너의사랑은얼마나기쁜날이면그대의사랑이단조롭고건조하고풍부하다나를빤히들여다보고있다나는물풀밑을마구비칠때이다유쾌하게찢긴독의양식으로세워있다문안에팽팽한옷이있다전광판에는엎드린고개를지나고있다구릉과자본이대물림하는사람들이빠른것이다나는나의재산이다나는나의재산이다나
------------------
- 빈집에 취해 너의 사랑은 얼마나 기쁜 날이면 그대의 사랑이단조롭고 건조하고풍부하다 나를 빤히 들여다보고 있다 나는 물풀 밑을 마구 비칠 때이다유쾌하게 찢긴 독의 양식으로 세워 있다문 안에팽팽한 옷이 있다 전광판에는 엎드린 고개를 지나고 있다구 릉과 자본이 대물림하는 사람들이 빠른 것이다 나는 나의 재산이 다 나는 나의 재산이다나
** 띄어쓰기는 아직 제대로 되지 않았지만, 문장 생성 자체는 꽤 좋아졌습니다. 정확도가 0.3584인 것치고는 말이죠. 지금까지 출력된 시 중에서는 제일 무난합니다. 에폭을 더 주어서 훈련시키고, 시 데이터를 좀 더 넣으면 한결 좋아질 것도 같습니다.
몇 개 더 출력해보겠습니다. 띄어쓰기 조정한 것만 적습니다. 문장이 그럴 듯해질수록 기존 시를 베꼈을 가능성이 있으므로, 표절 검사하는 코드를 추가해야 할 듯하네요.
- 그대의 사랑이 빛날 때마다 음모를 묻고 상추를 세우고 날아간다 너는 그대가 나를 사랑하는 사람이 되지 않는 사람이 되지 않는 것이다 나는 나를 지킨다 하루살이는 안고 있다 나는 허들을 잡고 나는 나의 창조의 시간이 다 다르지 않은 것이다 나는 나의 창조의 의미를 알고 있었다 나는 나의 참회를 발견하다 면도를 하고 있
- 알았습니다 양주는 그리하여 이 세상을 조롱하는 것이다 나는 나를 가져갈 수가 없었다 무표정한 겨울이여 나의 어휘는 이삭이 되고 있다 별장 접견실에서 두리번거리는 것을 환호하는 것이다 나는 나를 순장한다 옷을 먹으며 쇠들이 털옷으로 양동이를 꼬고 나온 반만년이 아기의 숨길을 알 수 없는 실종 산동네는 고모의 업이 보인다 사뭇 식물이 된 노예의 제기 글자에
Epoch 20/20 (90에폭)
396/396 [==============================] - 133s 337ms/step - loss: 2.8900 - accuracy: 0.4081
- 색으로 피어나고 있다 파아랗게 아홉 잔의 속삭임 찔레꽃이 창호지를 들고 창틀에서 낮잠을 만들어 검버섯 밤낮을 잔다 아버지는 지팡이 없이 흘러온 나의 부피를 결정하고 나의 미래를 부지런히 당겨 들여다보고 있다 지겨운 머리통은 푸른 지음을 찾으며 캐어 놓은 알몸의 마네킹들이무성하다 초읍 동일층 단칸방이 몇 마리구수한 코트의 생식기 같은 곳이래야 부르는 장수들은 기뻤다 인터넷 겸 굴레 긁지
- 그대의 가슴에 간직하고 싶은 날엔 그리움이여 그대는 정녕 모르고 싶습니다 그대를 사랑하고 싶습니다 당신은 모를 그리움으로 표현하고 싶다 잔잔히 웃으며도 좋은 소망을 모른 줄 알았다 내 앞에서 있는 것이다 내 앞에 있는 것이다 나는 나를 만나고 있었다 내가 나를 사랑하고 있다는 것을 사랑하는 것은 없다 나는 나를 보
Epoch 40/40 (130에폭)
396/396 [==============================] - 132s 334ms/step - loss: 2.4045 - accuracy: 0.4916
<냉장고 야채> 칸의 흔적들이 빨려 들어간다 값싼 천사들도 즈하지 말아라 한다 월식으로 이르는 것 같았다 진흙이 불꽃은 사진을 했다 내가 죽으면 나는 총총히 지운 얼굴 비비고 아치형 유한 강바람은 깃을 달고 쓰러져 감기던 나의 집이면 내어 금니의 모두 감나무의 지문을 보고 긴 띠가 되어 버린다 날짐승도 부럽지 않다 출혈하고 물소리가 아들을 피하면 유서를 먹고 동굴의 통증이 있
시간만이 고여 있다 한참을 바라보는 그녀는 문자의 끝자락을 읽어 보고 있었다 제비는제 설움을 써야 한다 주검은 모두 버리고 무모하고 당당한 바닷길을 가르는 유람선은 없는 감나무의 청년 가운데 오직 아아 오늘의 얼음장을 가지런히 빗어 가고 있었다 물때를 기다렸던 것 같은 날이었다 나는 용석을 기록하리라 나의 산길 청소부는 캉캉을 입고 비껴서 있다 밤새워 쓰였다 심각함이 설움
Epoch 10/10 (140에폭)
396/396 [==============================] - 293s 740ms/step - loss: 2.3130 - accuracy: 0.5087
'마침내 변성기'의 이름 굽이굽이 화석 소리로 녹아야 했다 여린 은행잎이 어루만져 가버린 날에는 내 울안 벙어리 사방으로 흩날리고 영혼이 흐르고 꺼칠한 부지깽이 인형의 의자에 산들 시절 긍정 얘기했을 수 없는 곁가지를 꺾어 오는 의혹들을 뚫고 뚫고 동트는 길이니까 일행의 멱살을 좌우한다 게 감히 갈라진 오후 거미는 점점 날리며 해당로 내려와 환하게 울어 놓았다
'숨 쉬다 끝'나는 날이면 내가 나를 사랑하는 사람이 나를 사랑하는 일이 다 사랑하는 사람과 헤어짐이 있는 사람이 다 세상일이 된다 사랑은 움막하는 목표에서 나는 바늘처럼 우리의 마음을 이어주는 정겨움이므로 서른 이여 정열 투쟁스런 적막이 있어 졌다 낮술을 보려고 한다 오후가 크도록 계속 클렌 나는 답처럼 말을 못 하겠습니다 우리는 평소 폭발을 지우며 새순이 컵
'그런데' 촛불들이 번쩍 들려 있다 여기가 있다 자유를 울렸다 찔레꽃이서늘해서 핏줄의 발목에 비례하고옹졸하게 포구을 잡힌 거울의 어귀의 기둥이 있다 그는 불안의 눈초리를 흘기고 있는데 주먹은 국수 옷이라는 허기진 노동을 재촉해 흔들림 못 올린다 늦게 손바닥을 벗어난 골목이 있고 폐수를 배설하는 것이다손 바닥에서기는 파리의 시선을 지니고 있다는 것이 있다 나는 그것
Epoch 10/10 (150에폭)
396/396 [==============================] - 207s 523ms/step - loss: 2.2249 - accuracy: 0.5250
'사십 대 후반의' 이빨을 닮은 바람결에 누우니 정말로 소녀의 지층이 허물어진다 보낸 노니 숨기는데 눈꼽처럼 거미줄이 컵을 파고 떠나왔다 비닐 계곡 뒤에 하얀 밥알들을 펄럭였던 듯 굳은살더러는 소리에 앉아 있다 나는 말끝처럼 밀려 진다 계속 부활의 통증이 다르게 말해 연기도 없는 만경강 캐던 뒤에도 물길이 걸려 있었다
Epoch 10/10 (160에폭)
396/396 [==============================] - 165s 417ms/step - loss: 2.1446 - accuracy: 0.5393
'눈물 흘리는 내 모습에 그대가 아파'할까봐 사랑하며 화해하지 않는 틈에이러한 그대 모습으로 행복하게 해 주소서 그대가 나무라면 언제부터가 아닌 그리움으로 행복할 수 없다면수수한 사랑이 오고 무척 사랑이란 이름으로 사랑했었기에 하여 그대의 가슴에 뿌려 주어 주는 그대를 사랑하고 싶습니다 그대가 그립습니다 그대가 그립습니다 당신이 그리워질 때마다 그대가 생각났습니다
'네 생각만 한다 오늘'은 내 이렇게 그리워 옷깃에 들어 있는 꽃나무를 닮은 사람들을 위해 기도하지 않아도 나는 다시 넝마를 쓰고 허파를 찾을 수 있으랴 그렇지도 않은 것이다 나는 아무것도 없다 나는 오로지 거짓말이다 않고 싶었습니다 남남이란 걸을 사랑하였고 시련의 탈출을 하고 싶었다 원래가 나에게 주어진 이야기를 지니고 있다
Epoch 10/10 (170에폭)
396/396 [==============================] - 134s 340ms/step - loss: 2.0692 - accuracy: 0.5531
'쌓고 또 쌓다' 지치면 헐겁고 널브러지게 내버려 두는 것이 다 먼 세상의 시를 덮으며 삼월에 서성대는 울음들이 춤추는 대지에서 어머니의 씨를 뿌린 당신의 길이면 그의 마음이라 하지 못했다 생활이라는 말들이 많습니다 그대 여 어머님도 나는 당신의 향기가 들리는지요 그대도 아닌데 그대는 아픈 겁니까 잊은 것처럼 서로의 감정이 있어 가슴에 가시나무 저렇게 태워 금방은 행복이겠지
'진짜가 어디 있니 입이나' 다물어질라건 모르고 나태화처럼 흔들릴 수도 없다 나는 모른다 베레모 헐렁한 물소리가 꽃대 나의 나라 공주에 사는 잔설의 열기가 오래 다르다 드디어 울음 소리가 작은 눈알이 밴 통일은 미명의 이야기가 잎사귀의 찢어진 도시의 니코틴을 본다
'교신하는 소리 들리지 않고 나'는 두렵도록 이 내향은 미련을 만들고서 아아 저만큼 아무렇게 나를 떠날 때마다 나는 가끔은 바람에 밀리고 단정의 비명을 덮치고 얇은 혹여 큰 하늘이 보였다 밤이 요고 세아 한 턱밑씩 삭히었다 불타는 구두 위로 붉은 피톨 안개들이 왔다
'작은 사람은 큰 사람'을 사랑하고 있다 유난히 가볍게도 사랑이라는 줄 모르는 이 세상을 사랑합니다 그대가 당신을 사랑하는 사람은 서로의 온기에서 불러 봐 내가 그대를 사랑하는 그대가 사랑했던 사랑이기에 잊어버리면 그 사람이 있어 가슴이 조각조각 부서진다 달빛 스며드는 가을 내음이 핏빛으로 다가와 무창포의 모습을 만져 보며 추억의 사랑앓이 흔적이여 눈시울을 희게 당겨 보던 물소리 듣지 못한 그 님의 아지랭이
Epoch 20/20 (190에폭)
396/396 [==============================] - 134s 337ms/step - loss: 1.9494 - accuracy: 0.5745
'저 생명을 능가할 것은 이'여름에서 자란 병의 붕대로 슬며시 바늘이 된 소리를 저기 먼 돛단배의 종소리가 식어 져요 무딘 여물을 쥔 것이 지나가겠다 내 삶의 휴전선 교과서이 박혀 지고 하고 나오는 바퀴서 쪽빛이라 했지요
'이 밤은 여느 때 마냥 춥'고 마침내 나는 감아 가고 오렌지를 그리워할 수 있는 것으로 우리가 가장 어려운 자연을 만날까 주신 따로 나의 사랑은 짧다 나는 나를 사랑하는 일 입니다 당신의 웃음꽃 그대의 감상한 지류에 한이나 눈물 나는 곳에서 방황하는 그대를 위하여 함께 할 수 있는 그대의 모습이 있었을 뿐이였나 봅니다
Epoch 20/20 (210에폭)
396/396 [==============================] - 135s 341ms/step - loss: 1.8306 - accuracy: 0.5989
'손 흔들' 수 있을까 놀이의 뜨거운 정적을 찍어 냈다 제발 돌아간다 굽어 씻는 골짜기에 스며 달이 엉망인가 그래 거꾸로 몸살을 앓고 있었다 내새해 나는 무슨 색으로 살아 있는 방에서 횡포의 빈자리도 있었다 병이 그제야 더듬거리 때되는 걸까 낡은 곳의 해방을 울리고 있다 청바지가 떠밀려 가다가 머물러야 직전이고 먼지들의 목소리에 피었다
'옛 애인이 전화한 날의 저녁은 폭설과 허공 사이에서' 방황하고 과외하는 친구의 문자를 온몸 쓸어 보아요 이젠 지난 양씩 다 빠져나왔는데 여기 나로 용서하라 말한 다달이 다 소리치는 태양뿐 인 세월 모를 불행 과금을 가지런히 보고 있지만 멍들어 살고 싶은 자의 미소가 있어 행복한 것은 언제나 내게 쓸쓸히 바라보는 것이 다흉악하다거나 야속한 데들이 휘감는 것이라고
* 특별히 문장이 좋아지지는 않네요.
형태소 분석을 제가 바라는 방향으로 해주는 분석기를 찾아봐야겠습니다.
아래는 수정된 문장 생성 코드입니다.
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
from random import randint
import pickle
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.sequence import pad_sequences
from konlpy.tag import Mecab
# 문서를 메모리로 불러오기
def load_doc(filename):
# 파일을 읽기 모드로 열기
with open(filename, 'r') as f:
text = f.read()
return text
# generate a sequence from a language model
def generate_seq(model, tokenizer, seq_length, seed_text, n_words):
result = []
in_text = seed_text
# generate a fixed number of words
for _ in range(n_words):
# encode the text as integer
encoded = tokenizer.texts_to_sequences([in_text])[0]
# truncate sequences to a fixed length
encoded = pad_sequences([encoded], maxlen=seq_length, truncating='pre')
# predict probabilities for each word
yhat = model.predict_classes(encoded, verbose=0)
# map predicted word index to word
out_word = ''
for word, index in tokenizer.word_index.items():
if index == yhat:
out_word = word
break
# append to input
in_text += ' ' + out_word
result.append(out_word)
return ' '.join(result)
def spacing_mecab(sentence):
mecab = Mecab()
tagged = mecab.pos(sentence)
corrected = ""
for tag in tagged:
if tag[1][0] in "JEXS": # S는 부호 포함, SL외국어, SH한자, SN숫자
corrected += tag[0]
elif tag[1] == "VCP":
corrected += tag[0]
else:
corrected += " " + tag[0]
if corrected[0] == " ":
corrected = corrected[1:] # 문장 처음의 공백을 제거
return corrected
# load cleaned text sequences
#in_filename = "republic_sequences.txt"
in_filename = "poems_sequences.txt"
doc = load_doc(in_filename)
lines = doc.split('\n')
seq_length = len(lines[0].split()) - 1 # 50
# load the model
model = load_model('model.h5')
# load the tokenizer
with open('tokenizer.pkl', 'rb') as f:
tokenizer = pickle.load(f)
# select a seed text
seed_text = lines[randint(0, len(lines))]
print(seed_text + '\n')
# generate new text
generated = generate_seq(model, tokenizer, seq_length, seed_text, 100)
generated = generated.replace(' ', '')
# print(generated)
print("------------------")
print(spacing_mecab(generated))
# 생성된 문장이 기존 문장과 얼마나 닮았는지 평가하는 (표절 평가) 기능 코드.
# 단어 네 개가 (예를 들면) 연속으로 같으면 표절 점수를 1을 올리고, 계속 한단어씩 shift 해가면서
# 표절 점수를 계산한다.
# 점수 합계를 검사 횟수와 전체 단어 개수로 평균을 낸다.
# 혹은 표절한 문장과 표절 횟수를 출력 (원 시의 앞뒤 단어 몇 개를 더 보여줌)