Chainer&LSTM에서'만담 마음'체험

9800 단어 LSTM
개시하다
만담 으로 순정 하다
최근에 나는 《소화원록 낙담의 마음》이라는 애니메이션에 푹 빠졌다.
조사해보니'클래식 낙하물'이라는 텍스트 데이터가 공개된 것 같아서 이를 바탕으로 체어의 LSTM에 낙하물이 생성되면 흥미로운 결과가 나올 것 같다는 생각에 해봤다.
Chainer의 설치에 관해서는 과거 기사에 썼기 때문에 저쪽을 참조하세요.
http://qiita.com/oggata/items/22e4512821a3ce2590d0
고전 단일 만담 텍스트 데이터
http://www.asahi-net.or.jp/~ee4y-nsn/rakugo/00menu.htm
FeedForward Neural Network와 Recurent Neural Network의 차이
일반적인 NeuralNetwork에서는 출력이 특정한 입력으로 내보내지지만 RNN에서는 중성 네트워크를 역귀적으로 처리하고 시간 서열의 모델을 분석할 수 있다.
예컨대'탕'에서 연상되는 동사는'음해'로 추정된다
"목욕하러 가자, 목욕하러 가자..."위와 같은 상하문이 있다면 끓는 것이 더 좋은 추측이라고 할 수 있다.
이렇게 과거의 정보를 기억하고 결과를 출력하며 LSTM은 주로 글을 만드는 데 쓰인다.

사전의 생성은 문자 단위입니까?단어 단위로?
LSTM이 글을 배울 때 기본적으로 입력한 정답은 (이하 문자나 단어)이다.
문자 단위로 사전을 생성하는 경우 정답은 다음과 같습니다.
사전을 단어 단위로 만들려면 다음 단어가 정답입니다.
예제
(문자 단위)
나/대/고양이/아
(단어 단위)
우리는 고양이
절차.
코드
chainer에서 LSTM을 사용하는 방법을 많이 찾아봤는데 이쪽 코드를 사용하는 사람이 많아요.
나도 참고했어.
$ git clone https://github.com/yusuketomoto/chainer-char-rnn.git rakugo
$ cd rakugo
$ python train.py
input.txt에 데이터 쓰기
vim data/rakugo/input.txt
훈련하다
$ python train.py --data_dir data/rakugo --checkpoint_dir cv/rakugo --gpu -1
train_로스 끝났어.
1/8038, train_loss = 7.84989990234, time = 0.61
2/8038, train_loss = 7.71635498047, time = 0.99
3/8038, train_loss = 6.4572869873, time = 1.03
..
8037/8038, train_loss = 2.20953674316, time = 1.33
8038/8038, train_loss = 2.19822174072, time = 1.22
vocab 및 모델
훈련을 진행하면 사전 데이터와 모델 데이터가 완성됩니다.
(사전 데이터)
일부분 Pirnt는 단번에 알 수 있어요.
text <--> id
그렇습니다.
글을 공부할 때 입력 벡터와 정해 벡터를 소량으로 만들 때
정답 벡터는 문자의 한 문자 뒤에 있습니다. (단어 구분자라면 한 단어 뒤에 있습니다.)
이 때, 양적 데이터와 실제 문자 (단어) 사이의 관계는voocab (사전) 가 필요합니다.
(모델 데이터)
훈련의 데이터를 가리킨다.
(이미지)
기사->(vocal)vector&word->xbatch,y_batch(<-vector)-> 결과(vector)-> 사전으로vector->word 되돌려주기
생성을 시도하다
$ python sample.py --vocabulary data/rakugo/vocab.bin --model cv/rakugo/latest.chainermodel --primetext "落語心中" --gpu -1 --length 100
모든 EPoch는 모델 데이터를 증가시키기 위해 버젼 번호를 추가합니다.
반복 학습이 더 좋은 데이터가 될 거라고 믿습니다. 여기는latest입니다.chainermodel을 지정했지만 점점 똑똑해지는 모습은 중도 모델을 사용해서 확인할 수 있습니다.
내용을 대강대강 이해하다
네트워크 설계
입력 차원에서 사전(voocab)의 길이(예를 들어 10개 문자의 사전이면 10개 단원이 입력 차원이 된다)
(중간층의 단원수(신경원수), 중간층의 층수를 어떻게 설계하는지,
아직 잘 이해되지는 않지만 인터넷 디자이너들이 끊임없이 모색하면서 신경원수의 변화는 보편적인 것 같다.)
train.py
model = CharRNN(len(vocab), n_units

여기 3단 LSTM 사용.
CharRNN.py
super(CharRNN, self).__init__(
            embed = F.EmbedID(n_vocab, n_units),
            l1_x = L.Linear(n_units, 4*n_units),
            l1_h = L.Linear(n_units, 4*n_units),
            l2_h = L.Linear(n_units, 4*n_units),
            l2_x = L.Linear(n_units, 4*n_units),
            l3   = L.Linear(n_units, n_vocab),
        )
optimizer의 결정
RMSProp, Ada Delta, Adam 등 몇 가지 유명한 것이 있기 때문에 사용하기로 했습니다.
optimizer = optimizers.RMSprop(lr=args.learning_rate, alpha=args.decay_rate, eps=1e-8)
입력 및 정답 데이터 만들기
소량을 생성하다.여기 +1 문자의 데이터를 y로 변환합니다batch로 공부하게 하다
x_batch = np.array([train_data[(jump * j + i) % whole_len]
                        for j in xrange(batchsize)])
y_batch = np.array([train_data[(jump * j + i + 1) % whole_len]
                        for j in xrange(batchsize)])
입력 값과 정답을 배우다
train.py
state, loss_i = model.forward_one_step(x_batch, y_batch, state, dropout_ratio=args.dropout)
과도한 학습을 방지하기 위해dropout율을 설정합니다
CharRNN.py
h1_in   = self.l1_x(F.dropout(h0, ratio=dropout_ratio, train=train)) + self.l1_h(state['h1'])
c1, h1  = F.lstm(state['c1'], h1_in)
역방향 전파
accum_loss.backward()
truncated backprop
truncated backprop이라는 수법으로
스토리지에 저장할 수 없을 정도로 입력 및 상태 시퀀스가 긴 경우
짧은 시간 동안 역방향 속성 중지
accum_loss.unchain_backward()
optimizer.update()
일내 이율의 방법
state, prob = model.forward_one_step(prev_char, prev_char, state, train=False)
probability = cuda.to_cpu(prob.data)[0].astype(np.float64)
probability /= np.sum(probability)
index = np.random.choice(range(len(probability)), p=probability)
결과 내보내기
落語心中が計って開け聞けるというものは」
ね「年見合われると何か先者の町内でございます。酒は」
辰「左らかありません。それが急う者が参ろうに申しますよ」
客「ウム、この通りじゃァ皆な御前《めふ》がノシンといってるんだすね」
権「そんなどでも方のんや/\と言う訳もあるものか。女房は起ころこれな事を申す事にする 馬鹿な小《めき》でもゝう、モウ一遍留めて、女房どんに人間の面《から》をして逃げなければ、私は病気になりますそうに着きます。そないにお気が出て火の玉へ寝ていて
甚「そうね、お“先方に平伏は好《い》いね。じゃァいねえだ、我々は瓦ァと何よくなるから遊びにそういうんだ、いう御暇分な事を申すな」
泥「オイ/\此は運かジズ/\と着けてッたらねえ事をしなさった。アヽ御更に替え方が礼に有りと言われるもんだが」
伝「じゃァお前の所で彼《あ》れき先《かち》だって只今」
富「アハヽヽ」
八「モさ、お忙しいなはお前途中に買ってしまったんで、買うなら知って来たんだ」
熊「ちょっと御酒《おとら》をお出しをした」
清「そんな事を吐《くれ》えたから……」
まっけたらば、稲上をくれなかったら、寝ておるのだ」
甚の泥「魚を言
끝맺다
고찰하다.
원래 데이터는 대화 형식이거나 가명을 읽는다고 쓰여 있기 때문이다
이번 출력의 결과는 같은 회화 형식이고 가명(유사한) 단어를 읽는 것도 포함돼 있다. 이런 결과가 나올 것 같지만 뜻을 전혀 이해할 수 없다.
그나저나 등장인물이 너무 많아서...
참고로 학습 데이터를 늘리면 방법이 있을 것 같아요.
"간단한 RNN/LSTM만으로는 제대로 된 글을 쓸 수 없어요".
http://studylog.hateblo.jp/entry/2015/08/31/225124
그냥 막 늘어나는 게 아니라.
"앞의 문자열을 출발점으로 하는 것이 아니라 문법적 성격과 언어 자원을 대량으로 투입한다."
이 근처가 관건이 될 것 같아서요.
일본어 자료 라이브러리
그러면 이번에 우리는 낙오된 데이터를 어료 라이브러리에 썼다
말하자면 LSTM을 사용하여 실험적인 기억을 하고 싶어도 사용하는 일본어 어료 라이브러리 자체가 매우 적다.다른 LSTM의 문헌을 조사한 결과 다음과 같은 어료 라이브러리를 사용하는 예가 많이 발견되었다.
wikipedia
LiveDoor 자료 라이브러리
청공 문고
스마일 데이터 세트
일본어를 잘 배우려면 시간이 좀 걸리겠지만, 어쨌든 먼저 LSTM을 대충 배웠다.

JavaScript로 LSTM을 사용할 수 있는 프로그램 라이브러리가 있는 것 같아서 다음에는 이 일대를 이용해서 뭔가를 해보고 싶어요.
https://github.com/karpathy/recurrentjs

좋은 웹페이지 즐겨찾기