numpyのエラー

tensorflowのサンプルを動かそうとしたときのエラー

4$ python fully_connected_feed.py 
RuntimeError: module compiled against API version 0xc but this version of numpy is 0xb
ImportError: numpy.core.multiarray failed to import
ImportError: numpy.core.umath failed to import
ImportError: numpy.core.umath failed to import
2019-11-15 09:55:15.959592: F tensorflow/python/lib/core/bfloat16.cc:675] Check failed: PyBfloat16_Type.tp_base != nullptr 
中止 (コアダンプ)

どうやら、numpyが壊れているらしい?

$ pip install -U numpy 

これで解決

Rstudioの環境変数

RStudioを好んで使っています。

Mac版RStudioはHomeBrewでインストールすることができます

brew cask install rstudio

この時、アプリケーションフォルダ内にRStudioのアイコンが表示されます。
このアイコンをクリックして起動すると、Bashシェルの環境変数を読み込んでくれません。

自分の場合、データフォルダをDATA環境変数に入れることにより、大学で使っている
サーバのデータフォルダとの物理ディレクトリの違いを吸収するようにしています。
例えば


data.file<-paste(Sys.getenv("DATA"),"/sample.txt",sep="")

こんな感じで記述しておけば、
サーバでは /work/user/data/sample.txtのディレクトリにあるファイル
ローカルPCでは /home/user/data/sample.txtのディレクトリにあるファイルでも、
環境変数DATAにサーバでは/work/user/data/、ローカルPCでは/home/user/data/
を設定しておけば、プログラムを変更する必要がありません。

しかし、Rstudioを入れたそのままではこの環境変数が使えません。

これを解決するには、~/.Renvironに環境変数を記述しておけばOKです。

~/.Renviron

DATA=${HOME}/data

chainerでCRFを用いて固有表現抽出

このあたりを参考に書き直してみました。
CRFなどの解説はリンク先を参照のこと

仕様

単語列から名詞の塊を抜き出す。
英語で複合名詞など複数の名詞で構成される名詞の塊にフラグをつける。
下記の例では、Oが名詞以外、Bが名詞の開始位置、Iが複合名詞の2個目以降を示している。

 the wall street journal reported today that apple corporation made money 
O    B   I      I      I      O        O    O     B     I          O    O      O

これを、Linearの1層で学習し、CRFで出力する

コード



import numpy as np
import argparse
import os
import chainer
import chainer.functions as F
import chainer.links as L
from chainer import training, optimizers, initializers,reporter
from chainer.training import extensions
import random
from itertools import chain


# my model
class IconDetector(chainer.Chain):

    def __init__(self, n_vocab, window, n_label, n_unit):
        super().__init__()
        with self.init_scope():
            self.embed=L.EmbedID(n_vocab, n_unit)
            self.lin=L.Linear(n_unit , n_label)
            self.crf=L.CRF1d(n_label=n_label)
        self.window=window

    def forward(self, xs):
        l = xs.shape[1]
        ys = []
        # 1 wordづつ
        for i in range(l):
            x = self.embed(xs[:,i])
            h = F.tanh(x)
            y = self.lin(h)
            ys.append(y)
        return ys #[window, batchsize, n_label]

    def __call__(self, xs, ts):
        """error function"""
        ys = self.forward(xs)
        ts = [ts[:, i] for i in range(ts.data.shape[1])] # [window,batchsize]
        loss = self.crf(ys, ts)
        reporter.report({'loss': loss}, self)
        return loss

    def predict(self, xs):
        ts = self.forward(xs)
        _, ys = self.crf.argmax(ts)
        return ys

class WindowIterator(chainer.dataset.Iterator):

    def __init__(self, text, label, window, batch_size, shuffle= True,repeat=True):
        self.text = np.asarray(text, dtype=np.int32)
        self.label = np.asarray(label, dtype=np.int32)
        self.window = window
        self.batch_size = batch_size
        self._repeat = repeat
        self._shuffle=shuffle

        if self._shuffle:
            self.order = np.random.permutation(
                len(text) - window ).astype(np.int32)

        else:
            self.order=np.array(list(range(len(text) - window )))
        self.current_position = 0
        self.epoch = 0
        self.is_new_epoch = False

    def __next__(self):
        if not self._repeat and self.epoch > 0:
            raise StopIteration

        i = self.current_position
        i_end = i + self.batch_size
        position = self.order[i: i_end]
        offset = np.concatenate([np.arange(0, self.window )])
        pos = position[:, None] + offset[None, :]
        context = self.text.take(pos)
        doc = self.label.take(pos)

        if i_end >= len(self.order):
            np.random.shuffle(self.order)
            self.epoch += 1
            self.is_new_epoch = True
            self.current_position = 0
        else:
            self.is_new_epoch = False
            self.current_position = i_end

        return  context, doc

    @property
    def epoch_detail(self):
        return self.epoch + float(self.current_position) / len(self.order)

@chainer.dataset.converter()
def convert(batch, device):
    context, doc = batch
    xp = device.xp
    doc = xp.asarray(doc)
    context = xp.asarray(context)
    return context, doc


def main():

    parser = argparse.ArgumentParser()
    parser.add_argument('--device', '-d', type=str, default='-1',
                        help='Device specifier. Either ChainerX device '
                        'specifier or an integer. If non-negative integer, '
                        'CuPy arrays with specified device id are used. If '
                        'negative integer, NumPy arrays are used')
    parser.add_argument('--window', '-w', default=5, type=int,
                        help='window size')
    parser.add_argument('--batchsize', '-b', type=int, default=2,
                        help='learning minibatch size')
    parser.add_argument('--epoch', '-e', default=100, type=int,
                        help='number of epochs to learn')
    parser.add_argument('--out', default=os.environ["WORK"]+"/summarization/sm_icgw/result",
                        help='Directory to output the result')

    args = parser.parse_args()

    random.seed(12345)
    np.random.seed(12345)

    device = chainer.get_device(args.device)

    training_data = [(
        " the wall street journal reported today that apple corporation made money ".split(),
        "O B I I I O O O B I O O O".split()
    ), (
        " georgia tech is a university in georgia ".split(),
        "O B I O O O O B O".split()
    )]

    validation_data = [(' georgia tech reported today '.split(),"O B I O O O".split())]

    word2id={"":0,"":1,"":2,"":3}
    label2id={"B":0,"I":1,"O":2}

    def get_dataset(data,is_train=True):
        texts=[]
        labels=[]
        for word,attrib in data:
            for w,a in zip(word,attrib):
                if w not in word2id:
                    if is_train:
                        word2id[w]=len(word2id)
                    else:
                        w=""
                texts.append(word2id[w])
                labels.append(label2id[a])
        return texts,labels

    train_text,train_label=get_dataset(training_data)
    valid_text,valid_label=get_dataset(validation_data,False)

    n_vocab=len(word2id)
    n_label=len(label2id)
    n_unit=n_vocab//2
    model=IconDetector(n_vocab=n_vocab, window=args.window,n_label=n_label,n_unit=n_unit)

    model.to_device(device)
    optimizer = optimizers.Adam()
    optimizer.setup(model)

    train_iter = WindowIterator(train_text, train_label, args.window, args.batchsize)
    valid_iter = WindowIterator(valid_text, valid_label, args.window,args.batchsize, repeat=False, shuffle=False)

    updater = training.StandardUpdater(train_iter, optimizer, converter=convert, device=device)
    trainer = training.Trainer(updater, (args.epoch, 'epoch'), out=args.out)
    trainer.extend(extensions.LogReport(),trigger=(10, 'epoch'))
    trainer.extend(extensions.PrintReport(['epoch', 'main/loss','validation/main/loss']))
    #trainer.extend(extensions.ProgressBar())

    trainer.extend(extensions.Evaluator(valid_iter, model,converter=convert, device=device),trigger=(10, 'epoch'))
    trainer.run()

    # testing
    testing_data = [(' the street journal is a university '.split(),"O B I I O O O O".split())]
    test_text,test_label=get_dataset(testing_data,False)
    with chainer.using_config('train', False), \
            chainer.using_config('enable_backprop', False):
        ys=model.predict(np.array([test_text],dtype=np.int32))

        ys=list(chain.from_iterable(ys))
        print(ys)
        print(test_label)

if __name__ == '__main__':
    main()

実行結果

epoch       main/loss   validation/main/loss
10          6.24186     7.77101               
20          5.43089     6.29938               
30          3.16409     5.09233               
40          2.68146     4.02053               
50          1.47248     3.07853               
60          1.63073     2.28975               
70          1.13568     1.67798               
80          0.842947    1.22796               
90          0.364242    0.912943              
100         0.658557    0.692736              
[2, 0, 1, 1, 2, 2, 2, 2]
[2, 0, 1, 1, 2, 2, 2, 2]

ちゃんと学習できているようです

LSTMでSIN波を学習させる

このあたりを参考に書き直してみました。

プログラム


import chainer
import chainer.links as L
import chainer.functions as F
import numpy as np
from chainer import optimizers
from chainer.datasets import tuple_dataset
from chainer import reporter
import matplotlib.pyplot as plt

class MyClassifier(chainer.Chain):

    def __init__(self, seqlen, out_units=1, dropout=0.1):
        super(MyClassifier, self).__init__()
        with self.init_scope():
            self.encoder = L.LSTM(seqlen, out_units)
        self.dropout = dropout

    def forward(self, xs, ys):
        concat_outputs =F.concat( self.predict(xs), axis=0)
        concat_truths = F.concat(ys, axis=0)

        loss = F.mean_squared_error(concat_outputs, concat_truths)
        reporter.report({'loss': loss}, self)
        return loss

    def predict(self, xs, softmax=False, argmax=False):
        concat_encodings = F.dropout(self.encoder(xs), ratio=self.dropout)
        if softmax:
            return F.softmax(concat_encodings).array
        elif argmax:
            return self.xp.argmax(concat_encodings.array, axis=1)
        else:
            return concat_encodings

    def reset_state(self):
        self.encoder.reset_state()


# main
if __name__ == "__main__":

    # データ
    def get_dataset(N,st=0,ed=2*np.pi):
        xval = np.linspace(st,ed, N)  # x軸の値
        y = np.sin(xval)              # y軸の値
        return y,xval

    # 0-2piまでを100等分
    N = 100
    train_ds,train_xval = get_dataset(N)

    # valid
    N_valid = 50
    valid_ds,valid_xval = get_dataset(N_valid,2*np.pi,3*np.pi)


    # 学習パラメータ
    batchsize = 10
    n_epoch = 1000
    seqlen=10
    gpu = -1

    def seq_split(seqlen,ds,xval):
        X=[]    # seqlen 分Y軸の値を取り出し
        y=[]    # seqlen+1のY軸の値を正解として格納
        ret_xval=[]   # その時のX軸の値
        for i in range(len(ds)-seqlen-1):
            X.append(np.array(ds[i:i+seqlen]))
            y.append(np.array([ds[i+seqlen]]))
            ret_xval.append(xval[i+seqlen])
        return X,y,ret_xval


    X_train,y_train,_=seq_split(seqlen,train_ds,train_xval)
    train=tuple_dataset.TupleDataset(np.array(X_train, dtype=np.float32), np.array(y_train, dtype=np.float32))

    X_valid,y_valid,_=seq_split(seqlen,valid_ds,valid_xval)
    valid=tuple_dataset.TupleDataset(np.array(X_valid, dtype=np.float32), np.array(y_valid, dtype=np.float32))

    # モデル作成
    model = MyClassifier(seqlen=seqlen)
    optimizer = optimizers.Adam()
    optimizer.setup(model)

    train_iter = chainer.iterators.SerialIterator(train, batchsize)
    valid_iter = chainer.iterators.SerialIterator(valid, batchsize, repeat=False, shuffle=False)

    updater = chainer.training.updaters.StandardUpdater(train_iter, optimizer, device=gpu)
    trainer = chainer.training.Trainer(updater, (n_epoch, 'epoch'), out="snapshot")

    trainer.extend(chainer.training.extensions.Evaluator(valid_iter, model, device=gpu))
    trainer.extend(chainer.training.extensions.dump_graph('main/loss'))

    # Take a snapshot for each specified epoch
    frequency = 10
    trainer.extend(chainer.training.extensions.snapshot(filename="snapshot_cureent"), trigger=(frequency, 'epoch'))

    trainer.extend(chainer.training.extensions.LogReport(trigger=(10, "epoch")))
    trainer.extend(chainer.training.extensions.PrintReport(
        ["epoch", "main/loss", "validation/main/loss", "elapsed_time"]))
    # trainer.extend(chainer.training.extensions.ProgressBar())
    trainer.extend(chainer.training.extensions.PlotReport(['main/loss', 'validation/main/loss'], trigger=(10, "epoch"),
                                                          filename="loss.png"))
    trainer.run()


    # テストデータ
    N_test = 50
    test_ds,test_xval = get_dataset(N_test,3*np.pi,4*np.pi)
    X_test,y_test,x=seq_split(seqlen,test_ds,test_xval)

    with chainer.using_config("train", False), chainer.using_config('enable_backprop', False):
        model_predict=[]
        for xt in X_test:
            model_predict.append(model.predict(np.array([xt],dtype=np.float32)))
        y=F.concat(y_test,axis=0).data
        p=F.concat(model_predict, axis=0).data
        plt.plot(x,y,color="b")
        plt.plot(x,p,color="r")
        plt.show()

xが0から2πまでをN=100等分し、その時のyの値を学習します

出力

epoch       main/loss   validation/main/loss  elapsed_time
10          0.412313    0.22419               0.680705      
20          0.34348     0.176668              1.45632       
30          0.322577    0.157206              2.21422       
40          0.313264    0.142921              3.01513       
50          0.286482    0.156473              3.79678       
60          0.271693    0.145663              4.5567        
70          0.26161     0.153716              5.27208       
80          0.249188    0.148146              6.01087       
90          0.229289    0.135516              6.7483        
100         0.235577    0.135556              7.4885        
110         0.210943    0.122771              8.23302       
120         0.206481    0.125734              8.96983       
130         0.199006    0.110476              9.70469       
140         0.185752    0.105235              10.443        
150         0.170962    0.0997412             11.2183       
160         0.17236     0.0935808             11.9595       
170         0.159314    0.08463               12.7018       
180         0.159687    0.0768325             13.4395       
190         0.137582    0.0830929             14.18         
200         0.146723    0.0774658             14.9236       
210         0.144295    0.0731078             15.6569       
220         0.137017    0.0640324             16.3937       
230         0.120282    0.0675966             17.1413       
240         0.122946    0.065422              17.886        
250         0.112485    0.0601812             18.6319       
260         0.115785    0.0622176             19.3996       
270         0.108337    0.0572397             20.1444       
280         0.113232    0.0529092             20.8836       
290         0.111058    0.0531542             21.6315       
300         0.0978656   0.0537841             22.367        
310         0.107318    0.0500048             23.1059       
320         0.100115    0.0471024             23.8513       
330         0.0941351   0.0466782             24.6336       
340         0.0992865   0.0462204             25.4045       
350         0.0909913   0.0444264             26.1611       
360         0.0862495   0.04312               26.9144       
370         0.0855708   0.0425527             27.7444       
380         0.0872798   0.0402729             28.5102       
390         0.0902846   0.0412268             29.265        
400         0.0840953   0.0421445             30.0178       
410         0.0782678   0.0389577             30.7646       
420         0.0813485   0.0383136             31.5095       
430         0.0892697   0.0380051             32.2756       
440         0.0784913   0.0378043             33.0377       
450         0.077315    0.0382185             33.7859       
460         0.0797667   0.0370378             34.5328       
470         0.085258    0.0353085             35.2766       
480         0.0904794   0.0364417             36.0569       
490         0.0760617   0.0347273             36.7939       
500         0.0776822   0.0349566             37.5342       
510         0.0753997   0.0348118             38.2753       
520         0.084298    0.0351735             39.0137       
530         0.0827682   0.0336927             39.7616       
540         0.0885914   0.032941              40.4968       
550         0.0755433   0.0328157             41.2496       
560         0.0864087   0.0329004             41.9931       
570         0.0696817   0.0333915             42.7455       
580         0.0673041   0.0310085             43.4925       
590         0.0695492   0.0322058             44.2814       
600         0.0626493   0.0321012             45.0249       
610         0.0780004   0.0311171             45.7709       
620         0.0842924   0.0313559             46.5104       
630         0.0869392   0.0310007             47.253        
640         0.0807384   0.0300728             48.0017       
650         0.061898    0.0308209             48.799        
660         0.0656733   0.0304086             49.5613       
670         0.0785108   0.0301482             50.3314       
680         0.0748608   0.0305042             51.1063       
690         0.0720685   0.0300295             51.874        
700         0.071668    0.0300219             52.6741       
710         0.0577448   0.0295377             53.4246       
720         0.07059     0.0295795             54.1749       
730         0.0677278   0.0291774             54.9278       
740         0.0747214   0.0296802             55.6766       
750         0.0796093   0.0296162             56.4188       
760         0.0659514   0.0292572             57.1649       
770         0.0651634   0.0294423             57.9178       
780         0.0732363   0.0291244             58.6651       
790         0.0750731   0.0292386             59.54         
800         0.0768709   0.0289816             60.4078       
810         0.0712155   0.0293295             61.1858       
820         0.0613775   0.0290006             62.1138       
830         0.0674119   0.0289881             62.9673       
840         0.0720593   0.0289764             63.7099       
850         0.0653162   0.028784              64.4681       
860         0.0873163   0.0285498             65.2305       
870         0.0674722   0.0286272             65.9901       
880         0.0718548   0.0282714             66.7374       
890         0.0659643   0.028604              67.5049       
900         0.0790577   0.0286806             68.2621       
910         0.0734288   0.028266              69.0192       
920         0.0664547   0.0282677             69.7996       
930         0.0799885   0.0284383             70.5581       
940         0.0687402   0.0284575             71.3119       
950         0.0721005   0.0282444             72.0637       
960         0.0750532   0.0282908             72.8485       
970         0.0663102   0.0282821             73.6094       
980         0.0807248   0.0281474             74.3701       
990         0.0730301   0.0283711             75.155        
1000        0.0674249   0.0282971             75.9349    

テスト結果

青い線が正解で赤い線が学習したのちの予測結果です。
Xの値を与えて、Yを予測した結果ですが、あまりうまく予測できていませんね

VAEを用いたなりすまし検知を書き直してみる

こちらの記事「VAEを用いたUNIXセッションのなりすまし検出」はソースコードが完全に公開されていないので、補完してみました。

環境

  • macOS 10.14
  • python 3.7

データ準備

まず、データを準備します。こちらからダウンロードします。ダウンロードしたら、解凍し、Fasttext用にデータを結合します。各ユーザの前半の5000は訓練用のデータで、なりすましがないデータですので、これをすべてのユーザから抽出します。ユーザごとに一行にコマンドをスペースでつないで作成します。全部で五十行になります。

for f in masquerade-data/*;do head -n 5000 $f|perl -pe 's/\n/ /g'|perl -pe 's/$/\n/'>> train.txt; done

Fasttextによるベクトル化

単語をfasttextによりベクトル化します。50次元を使っています。fasttextはpipでインストールしたものでもOKです。


import numpy as np
import os
import fasttext

model = fasttext.train_unsupervised("train.txt", "skipgram", dim=50, minCount=1)

UMAPによる可視化

元記事では出現頻度の高いコマンドから200取り出して、可視化していますが、面倒なので、modelの単語列から上位50単語を抜き出して可視化します。


%matplotlib inline
import matplotlib.pyplot as plt

import umap
import matplotlib.cm as cm
np.random.seed(12345)
x_word=[model[w] for w in model.words]
y_word=model.words
embedding = umap.UMAP().fit_transform(x_word[:50])
for emb,lbl in zip(embedding,y_word[:50]):
    plt.plot(emb[0],emb[1],marker=".")
    plt.annotate(lbl,(emb[0],emb[1]))
# https://teratail.com/questions/110775
plt.show()

モデル

元記事のものではそのままでは動かなかったので多少修正しています。


import numpy as np
import keras
from keras import layers
from keras import backend as K
from keras.models import Model
from keras.layers.core import Lambda
from keras.optimizers import Adam
 
#K.clear_session()
 
shape = (100, 50, 1)
epochs = 120
batch_size = 16
latent_dim = 2
 
input_cmd = keras.Input(shape=shape)
 
x = layers.Conv2D(32, 3,
                  padding='same', activation='relu')(input_cmd)
x = layers.Conv2D(64, 3,
                  padding='same', activation='relu',
                  strides=(2, 2))(x)
x = layers.Dropout(0.1)(x)
x = layers.Conv2D(64, 3,
                  padding='same', activation='relu')(x)
x = layers.Dropout(0.2)(x)
x = layers.Conv2D(64, 3,
                  padding='same', activation='relu')(x)
x = layers.Dropout(0.2)(x)
 
shape_before_flattening = K.int_shape(x)
 
x = layers.Flatten()(x)
x = layers.Dense(32, activation='relu')(x)
 
z_mean = layers.Dense(latent_dim)(x)
z_log_var = layers.Dense(latent_dim)(x)
 
def sampling(args):
    z_mean, z_log_var = args
    epsilon = K.random_normal(shape=(K.shape(z_mean)[0], latent_dim),
                              mean=0., stddev=1.)
    return z_mean + K.exp(z_log_var) * epsilon
 
z = Lambda(sampling)([z_mean, z_log_var])
 
decoder_input = layers.Input(K.int_shape(z)[1:])
 
x = layers.Dense(np.prod(shape_before_flattening[1:]),
                 activation='relu')(decoder_input)
 
x = layers.Reshape(shape_before_flattening[1:])(x)
 
x = layers.Conv2DTranspose(32, 3, strides=(2, 2),
                           padding='same', activation='relu')(x)
x = layers.Conv2D(1, 3,
                  padding='same', activation='sigmoid')(x)
 
decoder = Model(decoder_input, x)
 
z_decoded = decoder(z)
 
class CustomVariationalLayer(keras.layers.Layer):
 
    def vae_loss(self, x, z_decoded):
        x = K.flatten(x)
        z_decoded = K.flatten(z_decoded)
        xent_loss = keras.metrics.binary_crossentropy(x, z_decoded)
        kl_loss = -5e-4 * K.mean(
            1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1)
        return K.mean(xent_loss + kl_loss)
 
    def call(self, inputs):
        x = inputs[0]
        z_decoded = inputs[1]
        loss = self.vae_loss(x, z_decoded)
        self.add_loss(loss, inputs=inputs)
        return x
 
y = CustomVariationalLayer()([input_cmd, z_decoded])


vae = Model(input_cmd, y)
vae.compile(optimizer=Adam(), loss=None)
vae.summary()

入力データ

入力データを作成します。ファイルから再度読み込んで、訓練データを上位4000コマンド、テストデータを4001から5000コマンドで作成します。また、元記事と同様にUser2を使っています。


with open("masquerade-data/User2") as f:
    cmds=[l.rstrip() for l in f.readlines()]

x=[model[cmd] for cmd in cmds]
x_train=np.reshape(np.array(x[:4000]),(40,100,50,1))
x_valid=np.reshape(np.array(x[4000:5000]),(10,100,50,1))

訓練

Earlystoppingを入れました。訓練は100コマンドをひとかたまりとして訓練しています。


from keras.callbacks import EarlyStopping
es_cb = EarlyStopping(monitor='val_loss', patience=50, verbose=1, mode='auto')
history = vae.fit(x=x_train, y=None,
        shuffle=True,
        epochs=epochs,
        batch_size=batch_size,
        validation_data=(x_valid, None),
        callbacks=[ es_cb])

結果の可視化

訓練データでのLossを可視化します


%matplotlib inline
import matplotlib.pyplot as plt
plt.plot(history.history["loss"],label="training loss")
plt.plot(history.history["val_loss"],label="validation loss")
plt.title("model loss")
plt.xlabel("epoch")
plt.ylabel("loss")
plt.legend(loc="upper right")
plt.show()

テスト

最後に、1%の確率でなりすましが入っているという各ユーザの5001行目からのデータをつかって、Lossを可視化します。同様に100コマンドをひとかたまりとして、100個分をテストしています


x_test=np.reshape(np.array(x[5000:]),(100,100,50,1))
loss_test=[]
for i in range(len(x_test)):
    loss_test.append((vae.evaluate(x=np.reshape(x_test[i],(1,100,50,1)),y=None)))
    

%matplotlib inline
import matplotlib.pyplot as plt
plt.plot(loss_test,label="test loss")
plt.title("test loss")
plt.xlabel("epoch")
plt.ylabel("loss")
plt.legend(loc="upper right")
plt.show()

chainerでsin関数を学習させてみたをtrainerで書き直す

chainerのサンプルを探していると,古いものではtrainerを使っていないものも結構あります。
そこで,chainerでsin関数を学習させてみた
を書き直してみました。




# https://qiita.com/hikobotch/items/018808ef795061176824
# https://github.com/kose/chainer-linear-regression/blob/master/train.py

# とりあえず片っ端からimport
import numpy as np
import chainer
from chainer import cuda, Function, gradient_check, Variable, optimizers, serializers, utils
from chainer import Link, Chain, ChainList
import chainer.functions as F
import chainer.links as L
import time
import matplotlib
matplotlib.use('Agg')
from matplotlib import pyplot as plt
import os
# データ
def get_dataset(N):
    x = np.linspace(0, 2 * np.pi, N)
    y = np.sin(x)
    dataset=[]
    for xx,yy in zip(x,y):
        dataset.append((xx,yy))
    return dataset

# ニューラルネットワーク
class MyChain(Chain):
    def __init__(self, n_units=10):
        super(MyChain, self).__init__(
             l1=L.Linear(1, n_units),
             l2=L.Linear(n_units, n_units),
             l3=L.Linear(n_units, 1))

    def __call__(self, x_data, y_data):
        x = Variable(x_data.astype(np.float32).reshape(len(x_data),1)) # Variableオブジェクトに変換
        y = Variable(y_data.astype(np.float32).reshape(len(y_data),1)) # Variableオブジェクトに変換
        loss= F.mean_squared_error(self.predict(x), y)
        chainer.reporter.report({
            'loss': loss
        }, self)

        return loss

    def  predict(self, x):
        h1 = F.relu(self.l1(x))
        h2 = F.relu(self.l2(h1))
        h3 = self.l3(h2)
        return h3

    def get_predata(self, x):
        return self.predict(Variable(x.astype(np.float32).reshape(len(x),1))).data

from chainer.training import trigger as trigger_module
class MyChartReport(chainer.training.extension.Extension):

    #trigger = (1, 'epoch')

    def __init__(self,model,N_test=900,trigger = (1, 'epoch')):
        self.N_test=N_test
        self.model=model
        self._trigger = trigger_module.get_trigger(trigger)

    def __call__(self,trainer):
        if self._trigger(trainer):
            with chainer.configuration.using_config('train', False):
                theta = np.linspace(0, 2 * np.pi, self.N_test)
                sin = np.sin(theta)
                test = self.model.get_predata(theta)
                plt.plot(theta, sin, label="sin")
                plt.plot(theta, test, label="test")
                plt.legend()
                plt.grid(True)
                plt.xlim(0, 2 * np.pi)
                plt.ylim(-1.2, 1.2)
                plt.title("sin")
                plt.xlabel("theta")
                plt.ylabel("amp")
                plt.savefig("fig_sin_epoch{}.png".format(trainer.updater.epoch)) 
                plt.clf()



# main
if __name__ == "__main__":

    # 学習データ
    N = 1000
    train = get_dataset(N)

    # テストデータ
    N_test = 900
    test = get_dataset(N_test)

    # 学習パラメータ
    batchsize = 10
    n_epoch = 500
    n_units = 100
    gpu=-1

    # モデル作成
    model = MyChain(n_units)
    optimizer = optimizers.Adam()
    optimizer.setup(model)

    train_iter = chainer.iterators.SerialIterator(train, batchsize)
    test_iter = chainer.iterators.SerialIterator(test, batchsize, repeat=False, shuffle=False)

    updater = chainer.training.updaters.StandardUpdater(train_iter, optimizer, device=gpu)
    trainer = chainer.training.Trainer(updater, (n_epoch, 'epoch'), out="snapshot")

    trainer.extend(chainer.training.extensions.Evaluator(test_iter, model, device=gpu))
    trainer.extend(chainer.training.extensions.dump_graph('main/loss'))

    # Take a snapshot for each specified epoch
    frequency = 10
    trainer.extend(chainer.training.extensions.snapshot(filename="snapshot_cureent"),trigger=(frequency, 'epoch'))


    # Write a log of evaluation statistics for each epoch
    #trainer.extend(chainer.training.extensions.LogReport())

    trainer.extend(MyChartReport(model,trigger=(10, "epoch")))

    trainer.extend(chainer.training.extensions.LogReport(trigger=(10, "epoch")))
    trainer.extend(chainer.training.extensions.PrintReport(
        ["epoch", "main/loss", "validation/main/loss", "elapsed_time"]))
    #trainer.extend(chainer.training.extensions.ProgressBar())
    trainer.extend(chainer.training.extensions.PlotReport(['main/loss', 'validation/main/loss'],trigger=(10, "epoch"),filename="loss.png"))
    trainer.run()

    model.to_cpu()
    chainer.serializers.save_npz("model.h5",model)


ポイントは,extensionを使って,エポックごとにsinの学習結果を画像で保存しているところです。
結構いい加減に作っているので,画像保存ディレクトリやファイル名などは外から与えるようにするといいでしょう。

chainerでattentionモデルを実装

chainerで実装してみた

こちらを参考に,実装してみた。


train_pair = [
    ["初めまして。", "初めまして。よろしくお願いします。"],
    ["どこから来たんですか?", "日本から来ました。"],
    ["日本のどこに住んでるんですか?", "東京に住んでいます。"],
    ["仕事は何してますか?", "私は会社員です。"],
    ["お会いできて嬉しかったです。", "私もです!"],
    ["おはよう。", "おはようございます。"],
    ["いつも何時に起きますか?", "6時に起きます。"],
    ["朝食は何を食べますか?", "たいていトーストと卵を食べます。"],
    ["朝食は毎日食べますか?", "たまに朝食を抜くことがあります。"],
    ["野菜をたくさん取っていますか?", "毎日野菜を取るようにしています。"],
    ["週末は何をしていますか?", "友達と会っていることが多いです。"],
    ["どこに行くのが好き?", "私たちは渋谷に行くのが好きです。"]
]
test_pair = [
    ["初めまして。", "初めまして。よろしくお願いします。"],
    ["どこから来たんですか?", "米国から来ました。"],
    ["米国のどこに住んでるんですか?", "ニューヨークに住んでいます。"],
    ["おはよう。", "おはよう。"],
    ["いつも何時に起きますか?", "7時に起きます。"],
    ["夕食は何を食べますか?", "たいていトーストと卵を食べます。"],
    ["夕食は毎日食べますか?", "たまに朝食を抜くことがあります。"],
    ["肉をたくさん取っていますか?", "毎日インクを取るようにしています。"],
    ["週頭は何をしていますか?", "友達と会っていることが多いです。"],
]



# https://nojima.hatenablog.com/entry/2017/10/10/023147


import MeCab
import chainer
import chainer.links as L
import chainer.functions as F
import random
import numpy as np

SIZE=10000
EOS=1
UNK=0


class EncoderDecoder(chainer.Chain):
    def __init__(self, n_layer,n_vocab, n_out, n_hidden,dropout):
        super(EncoderDecoder,self).__init__()

        with self.init_scope():
            self.embed_x = L.EmbedID(n_vocab, n_hidden)
            self.embed_y = L.EmbedID(n_out,n_hidden)

            self.encoder = L.NStepLSTM(
                n_layers=n_layer,
                in_size=n_hidden,
                out_size=n_hidden,
                dropout=dropout)
            self.decoder = L.NStepLSTM(
                n_layers=n_layer,
                in_size=n_hidden,
                out_size=n_hidden,
                dropout=dropout)

            self.W_C = L.Linear(2*n_hidden, n_hidden)
            self.W_D = L.Linear(n_hidden, n_out)

    def __call__(self, xs , ys ):
        xs = [x[::-1] for x in xs]

        eos = self.xp.array([EOS], dtype=np.int32)
        ys_in = [F.concat((eos, y), axis=0) for y in ys]
        ys_out = [F.concat((y, eos), axis=0) for y in ys]

        # Both xs and ys_in are lists of arrays.
        exs = [self.embed_x(x) for x in xs]
        eys = [self.embed_y(y) for y in ys_in]

        # hx:dimension x batchsize
        # cx:dimension x batchsize
        # yx:batchsize x timesize x dimension
        hx, cx, yx = self.encoder(None, None, exs)  # yxに全T方向ステップのyの出力,数はxsの長さと同じ,バッチごとにバラバラ

        _, _, os = self.decoder(hx, cx, eys)

        loss=0
        for o,y,ey in zip(os,yx,ys_out): # バッチごとに処理
            op=self._calculate_attention_layer_output(o,y)
            loss+=F.softmax_cross_entropy(op,ey)
        loss/=len(yx)

        chainer.report({'loss': loss}, self)
        return loss

    def _calculate_attention_layer_output(self, embedded_output, attention):
        inner_prod = F.matmul(embedded_output, attention, transb=True)
        weights = F.softmax(inner_prod)
        contexts = F.matmul(weights, attention)
        concatenated = F.concat((contexts, embedded_output))
        new_embedded_output = F.tanh(self.W_C(concatenated))
        return self.W_D(new_embedded_output)

    def translate(self,xs,max_length=30):
        with chainer.no_backprop_mode(),chainer.using_config("train",False):
            xs=xs[::-1] # reverse list
            #exs = [self.embed_x(x) for x in xs]
            exs = self.embed_x(xs)
            hx, cx, yx = self.encoder(None, None, [exs])

            predicts=[]
            eos = self.xp.array([EOS], dtype=np.int32)
            # EOSだけ入力,あとは予想した出力を入力にして繰り返す
            for y in yx:  # バッチ単位
                predict=[]
                ys_in=[eos]
                for i in range(max_length):
                    eys = [self.embed_y(y) for y in ys_in]
                    _, _, os = self.decoder(hx, cx, eys)
                    op=self._calculate_attention_layer_output(os[0], y)
                    word_id=int(F.argmax(F.softmax(op)).data) # 単語IDに戻す

                    if word_id == EOS:break
                    predict.append(word_id)
                    ys_in=[self.xp.array([word_id], dtype=np.int32)]
                predicts.append(np.array(predict))
            return predict

class Data(chainer.dataset.DatasetMixin):
    def __init__(self):
        mecab = MeCab.Tagger("-Owakati")

        self.vocab={"eos":0,"unk":1}
        def to_dataset(source,target,train=True):
            swords = to_number(mecab.parse(source).strip().split(" "),train)
            twords = to_number(mecab.parse(target).strip().split(" "),train)
            return (np.array(swords).astype(np.int32),np.array(twords).astype(np.int32))

        def to_number(words,train):
            ds=[]
            for w in words:
                if w not in self.vocab:
                    if train:
                        self.vocab[w]=len(self.vocab)
                    else:
                        w="unk"
                ds.append(self.vocab[w])
            return ds

        self.train_data=[]
        self.test_data=[]
        for source,target in train_pair:
            self.train_data.append(to_dataset(source,target))

        for source,target in test_pair:
            self.test_data.append(to_dataset(source,target,False))


        self.vocab_inv={}
        for w in self.vocab.keys():
            self.vocab_inv[self.vocab[w]]=w

def convert(batch, device):
    def to_device_batch(batch):
        return [chainer.dataset.to_device(device, x) for x in batch]

    res= {'xs': to_device_batch([x for x, _ in batch]),
            'ys': to_device_batch([y for _, y in batch])}
    return res




seed = 12345
random.seed(seed)
np.random.seed(seed)

data = Data()

batchsize=5
train_iter = chainer.iterators.SerialIterator(data.train_data,batchsize)
test_iter=chainer.iterators.SerialIterator(data.test_data,len(data.test_data))


n_vocab=len(data.vocab)
n_out=len(data.vocab)
n_hidden=300
n_layer=1
dropout=0.3
print("n_vocab:",n_vocab)

optimizer=chainer.optimizers.Adam()

mlp=EncoderDecoder(n_layer,n_vocab,n_out,n_hidden,dropout)
optimizer.setup(mlp)

updater=chainer.training.StandardUpdater(train_iter,optimizer,converter=convert,device=-1)

#train
epochs=20
trainer=chainer.training.Trainer(updater,(epochs,"epoch"),out="dialog_result")
trainer.extend(chainer.training.extensions.LogReport())
trainer.extend(chainer.training.extensions.PrintReport(['epoch', 'main/loss', 'main/accuracy']))

trainer.run()
mlp.to_cpu()
chainer.serializers.save_npz("attention.model",mlp)




# https://nojima.hatenablog.com/entry/2017/10/17/034840
mlp=EncoderDecoder(n_layer,n_vocab,n_out,n_hidden,dropout)
chainer.serializers.load_npz("attention.model",mlp,path="")

for source,target in data.test_data:
    predict=mlp.translate(np.array(source))
    print("-----")
    print("source:",[data.vocab_inv[w] for w in source])
    print("predict:",[data.vocab_inv[w] for w in predict])
    print("target:",[data.vocab_inv[w] for w in target])


実行結果

n_vocab: 71
epoch       main/loss   main/accuracy
1           4.00112                    
2           3.148                      
3           2.33681                    
4           1.62404                    
5           1.30338                    
6           0.93243                    
7           0.6091                     
8           0.3701                     
9           0.233166                   
10          0.202335                   
11          0.119416                   
12          0.0804442                  
13          0.0629114                  
14          0.0467078                  
15          0.032828                   
16          0.0285745                  
17          0.0225082                  
18          0.0183743                  
19          0.0152494                  
20          0.0140195                  
-----
source: ['初め', 'まして', '。']
predict: ['初め', 'まして', '。', 'よろしくお願いします', '。', 'よろしくお願いします', '。', 'よろしくお願いします', '。', 'よろしくお願いします', '。', 'よろしくお願いします', '。', 'よろしくお願いします', '。', 'よろしくお願いします', '。', 'よろしくお願いします', '。', 'よろしくお願いします', '。', 'よろしくお願いします', '。', 'よろしくお願いします', '。', 'よろしくお願いします', '。', 'よろしくお願いします', '。', 'よろしくお願いします']
target: ['初め', 'まして', '。', 'よろしくお願いします', '。']
-----
source: ['どこ', 'から', '来', 'た', 'ん', 'です', 'か', '?']
predict: ['日本', 'から', '来', '日本', 'から', '来', '日本', 'から', '来', '日本', 'から', '来', '日本', 'から', '来', '日本', 'から', '来', '日本', 'から', '来', '日本', 'から', '来', '日本', 'から', '来', '日本', 'から', '来']
target: ['unk', 'から', '来', 'まし', 'た', '。']
-----
source: ['unk', 'の', 'どこ', 'に', '住ん', 'でる', 'ん', 'です', 'か', '?']
predict: ['東京', 'に', '住ん', 'で', 'い', 'ます', '。']
target: ['unk', 'に', '住ん', 'で', 'い', 'ます', '。']
-----
source: ['おはよう。']
predict: ['おはよう', 'ござい', 'ます', '。']
target: ['おはよう。']
-----
source: ['いつも', '何', '時', 'に', '起き', 'ます', 'か', '?']
predict: ['6', '時', 'に', '6', '時', 'に', '6', '時', 'に', '6', '時', 'に', '6', '時', 'に', '6', '時', 'に', '6', '時', 'に', '6', '時', 'に', '6', '時', 'に', '6', '時', 'に']
target: ['unk', '時', 'に', '起き', 'ます', '。']
-----
source: ['unk', 'は', '何', 'を', '食べ', 'ます', 'か', '?']
predict: ['たいてい', 'トースト', 'と', 'たいてい', 'トースト', 'と', 'たいてい', 'トースト', 'と', 'たいてい', 'トースト', 'と', 'たいてい', 'トースト', 'と', 'たいてい', 'トースト', 'と', 'たいてい', 'トースト', 'と', 'たいてい', 'トースト', 'と', 'たいてい', 'トースト', 'と', 'たいてい', 'トースト', 'と']
target: ['たいてい', 'トースト', 'と', '卵', 'を', '食べ', 'ます', '。']
-----
source: ['unk', 'は', '毎日', '食べ', 'ます', 'か', '?']
predict: ['たまに', '朝食', '抜く', 'たまに', '朝食', '抜く', 'たまに', '朝食', '抜く', 'たまに', '朝食', '抜く', 'たまに', '朝食', '抜く', 'たまに', '朝食', '抜く', 'たまに', '朝食', '抜く', 'たまに', '朝食', '抜く', 'たまに', '朝食', '抜く', 'たまに', '朝食', '抜く']
target: ['たまに', '朝食', 'を', '抜く', 'こと', 'が', 'あり', 'ます', '。']
-----
source: ['unk', 'を', 'たくさん', '取っ', 'て', 'い', 'ます', 'か', '?']
predict: ['毎日', '野菜', 'を', '取る', 'よう', 'に', 'し', 'て', 'い', 'ます', '。']
target: ['毎日', 'unk', 'を', '取る', 'よう', 'に', 'し', 'て', 'い', 'ます', '。']
-----
source: ['unk', 'unk', 'は', '何', 'を', 'し', 'て', 'い', 'ます', 'か', '?']
predict: ['友達', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と', 'と']
target: ['友達', 'と', '会っ', 'て', 'いる', 'こと', 'が', '多い', 'です', '。']

あまり,結果が良くないが,訓練データを増やし,Epochを増やすと良くなるかもしれない。

chainer.functions.pad_sequence

chainer.functions.pad_sequenceのサンプル


import chainer.functions as F
import chainer 
import numpy as np

a=chainer.Variable(np.array([[1],[2],[3]],dtype=np.float32))
b=chainer.Variable(np.array([[11],[12]],dtype=np.float32))
c=chainer.Variable(np.array([[21]],dtype=np.float32))

tpl=(a,b,c)
F.pad_sequence(tpl)

variable([[[ 1.],
           [ 2.],
           [ 3.]],

          [[11.],
           [12.],
           [ 0.]],

          [[21.],
           [ 0.],
           [ 0.]]])

chainerによるSeq2Seq

こちら
で紹介しているSeq2Seqを動く形で作成しなおしてみました。


train_pair = [
    ["初めまして。", "初めまして。よろしくお願いします。"],
    ["どこから来たんですか?", "日本から来ました。"],
    ["日本のどこに住んでるんですか?", "東京に住んでいます。"],
    ["仕事は何してますか?", "私は会社員です。"],
    ["お会いできて嬉しかったです。", "私もです!"],
    ["おはよう。", "おはようございます。"],
    ["いつも何時に起きますか?", "6時に起きます。"],
    ["朝食は何を食べますか?", "たいていトーストと卵を食べます。"],
    ["朝食は毎日食べますか?", "たまに朝食を抜くことがあります。"],
    ["野菜をたくさん取っていますか?", "毎日野菜を取るようにしています。"],
    ["週末は何をしていますか?", "友達と会っていることが多いです。"],
    ["どこに行くのが好き?", "私たちは渋谷に行くのが好きです。"]
]
test_pair = [
    ["初めまして。", "初めまして。よろしくお願いします。"],
    ["どこから来たんですか?", "米国から来ました。"],
    ["米国のどこに住んでるんですか?", "ニューヨークに住んでいます。"],
    ["おはよう。", "おはよう。"],
    ["いつも何時に起きますか?", "7時に起きます。"],
    ["夕食は何を食べますか?", "たいていトーストと卵を食べます。"],
    ["夕食は毎日食べますか?", "たまに朝食を抜くことがあります。"],
    ["肉をたくさん取っていますか?", "毎日インクを取るようにしています。"],
    ["週頭は何をしていますか?", "友達と会っていることが多いです。"],
]



# https://nojima.hatenablog.com/entry/2017/10/10/023147


import nltk
import MeCab
import chainer
from chainer.datasets import split_dataset_random , cifar
import chainer.links as L
import chainer.functions as F
import random
import numpy as np
import codecs

SIZE=10000
EOS=1
UNK=0


class EncoderDecoder(chainer.Chain):
    def __init__(self, n_vocab, n_out, n_hidden):
        super(EncoderDecoder,self).__init__()

        with self.init_scope():
            self.embed_x = L.EmbedID(n_vocab, n_hidden)
            self.embed_y = L.EmbedID(n_out,n_hidden)

            self.encoder = L.NStepLSTM(
                n_layers=1,
                in_size=n_hidden,
                out_size=n_hidden,
                dropout=0.1)
            self.decoder = L.NStepLSTM(
                n_layers=1,
                in_size=n_hidden,
                out_size=n_hidden,
                dropout=0.1)

            self.W = L.Linear(n_hidden, n_out)

    def __call__(self, xs , ys ):
        xs = [x[::-1] for x in xs]

        eos = self.xp.array([EOS], dtype=np.int32)
        ys_in = [F.concat((eos, y), axis=0) for y in ys]
        ys_out = [F.concat((y, eos), axis=0) for y in ys]

        # Both xs and ys_in are lists of arrays.
        exs = [self.embed_x(x) for x in xs]
        eys = [self.embed_y(y) for y in ys_in]

        hx, cx, _ = self.encoder(None, None, exs)
        _, _, os = self.decoder(hx, cx, eys)

        batch = len(xs)
        concat_os = F.concat(os, axis=0)
        concat_ys_out = F.concat(ys_out, axis=0)
        loss = F.sum(F.softmax_cross_entropy(self.W(concat_os), concat_ys_out, reduce='no')) / batch

        chainer.report({'loss': loss}, self)
        n_words = concat_ys_out.shape[0]
        perp = self.xp.exp(loss.array * batch / n_words)
        chainer.report({'perp': perp}, self)
        return loss

    def translate(self,xs,max_length=30):
        with chainer.no_backprop_mode(),chainer.using_config("train",False):
            xs=xs[::-1] # reverse list
            #exs = [self.embed_x(x) for x in xs]
            exs = self.embed_x(xs)
            hx, cx, _ = self.encoder(None, None, [exs])

            result=[]
            word_id=EOS
            for i in range(max_length):
                os,cs=self._translate_word(word_id,hx,cx)
                word_id=int(F.argmax(os).data)
                if word_id==EOS:break
                result.append(word_id)
            return result

    def _translate_word(self,word_id,hx,cx):
        y=np.array([word_id],dtype=np.int32)
        ey=self.embed_y(y)
        _, cs, os = self.decoder(hx, cx, [ey])
        fos=F.softmax(self.W(os[0]))
        return fos,cs

class Data(chainer.dataset.DatasetMixin):
    def __init__(self):
        mecab = MeCab.Tagger("-Owakati")

        self.vocab={"":0,"":1}
        def to_dataset(source,target,train=True):
            swords = to_number(mecab.parse(source).strip().split(" "),train)
            twords = to_number(mecab.parse(target).strip().split(" "),train)
            return (np.array(swords).astype(np.int32),np.array(twords).astype(np.int32))

        def to_number(words,train):
            ds=[]
            for w in words:
                if w not in self.vocab:
                    if train:
                        self.vocab[w]=len(self.vocab)
                    else:
                        w=""
                ds.append(self.vocab[w])
            return ds

        self.train_data=[]
        self.test_data=[]
        for source,target in train_pair:
            self.train_data.append(to_dataset(source,target))

        for source,target in test_pair:
            self.test_data.append(to_dataset(source,target,False))


        self.vocab_inv={}
        for w in self.vocab.keys():
            self.vocab_inv[self.vocab[w]]=w

def convert(batch, device):
    def to_device_batch(batch):
        return [chainer.dataset.to_device(device, x) for x in batch]

    res= {'xs': to_device_batch([x for x, _ in batch]),
            'ys': to_device_batch([y for _, y in batch])}
    return res




seed = 12345
random.seed(seed)
np.random.seed(seed)

data = Data()

batchsize=128
#train_iter = chainer.iterators.MultithreadIterator(train,batchsize,n_threads=4)
#test_iter=chainer.iterators.MultithreadIterator(test,len(test),repeat=False,shuffle=False,n_threads=4)
train_iter = chainer.iterators.SerialIterator(data.train_data,batchsize)
test_iter=chainer.iterators.SerialIterator(data.test_data,len(data.test_data))




n_vocab=len(data.vocab)
n_out=len(data.vocab)
n_hidden=300
print("n_vocab:",n_vocab)

optimizer=chainer.optimizers.Adam()

mlp=EncoderDecoder(n_vocab,n_out,n_hidden)
optimizer.setup(mlp)

updater=chainer.training.StandardUpdater(train_iter,optimizer,converter=convert,device=-1)

#train
epochs=1000
trainer=chainer.training.Trainer(updater,(epochs,"epoch"),out="dialog_result")
trainer.extend(chainer.training.extensions.LogReport())
trainer.extend(chainer.training.extensions.PrintReport(['epoch', 'main/loss', 'main/accuracy']))

trainer.run()
mlp.to_cpu()
chainer.serializers.save_npz("dialog.model",mlp)




# https://nojima.hatenablog.com/entry/2017/10/17/034840
mlp=EncoderDecoder(n_vocab,n_out,n_hidden)
chainer.serializers.load_npz("dialog.model",mlp,path="")

for source,target in data.test_data:
    predict=mlp.translate(np.array(source))
    print("source:",[data.vocab_inv[w] for w in source])
    print("predict:",[data.vocab_inv[w] for w in predict])
    print("target:",[data.vocab_inv[w] for w in target])

結果

n_vocab: 71
epoch       main/loss   main/accuracy
1           34.5502                    
2           31.7847                    
3           29.1603                    
4           26.6713                    
5           24.3079                    
6           22.0612                    
7           19.9224                    
8           17.8789                    
9           15.919                     
10          14.0387                    
11          12.2457                    
12          10.5555                    
13          8.98597                    
14          7.55335                    
15          6.26964                    
16          5.14105                    
17          4.16823                    
18          3.34746                    
19          2.67084                    
20          2.12592                    
21          1.69575                    
22          1.36043                    
23          1.10025                    
24          0.898079                   
25          0.740202                   
26          0.616168                   
27          0.518174                   
28          0.44032                    
29          0.378046                   
30          0.327818                   
31          0.286931                   
32          0.253339                   
33          0.225496                   
34          0.202227                   
35          0.18263                    
36          0.166004                   
37          0.151796                   
38          0.139575                   
39          0.128993                   
40          0.119775                   
41          0.1117                     
42          0.104586                   
43          0.09829                    
44          0.0926925                  
45          0.0876961                  
46          0.0832203                  
47          0.0791977                  
48          0.0755707                  
49          0.0722914                  
50          0.0693159                  
51          0.0666087                  
52          0.0641389                  
53          0.0618778                  
54          0.0598021                  
55          0.0578909                  
56          0.0561267                  
57          0.0544931                  
58          0.0529775                  
59          0.051567                   
60          0.0502504                  
61          0.0490188                  
62          0.0478641                  
63          0.0467791                  
64          0.0457571                  
65          0.0447925                  
66          0.0438801                  
67          0.0430147                  
68          0.0421937                  
69          0.0414122                  
70          0.0406681                  
71          0.039957                   
72          0.0392778                  
73          0.0386279                  
74          0.0380038                  
75          0.037405                   
76          0.0368287                  
77          0.0362744                  
78          0.0357389                  
79          0.0352229                  
80          0.0347236                  
81          0.0342409                  
82          0.0337726                  
83          0.0333189                  
84          0.0328779                  
85          0.0324506                  
86          0.0320346                  
87          0.0316298                  
88          0.0312351                  
89          0.0308511                  
90          0.0304759                  
91          0.0301098                  
92          0.0297521                  
93          0.0294023                  
94          0.0290616                  
source: ['初め', 'まして', '。']
predict: ['初め', 'まして', '。', '初め', 'まして', '。', '初め', 'まして', '。', '初め', 'まして', '。', '初め', 'まして', '。', '初め', 'まして', '。', '初め', 'まして', '。', '初め', 'まして', '。', '初め', 'まして', '。', '初め', 'まして', '。']
target: ['初め', 'まして', '。', 'よろしくお願いします', '。']
source: ['どこ', 'から', '来', 'た', 'ん', 'です', 'か', '?']
predict: ['日本', 'から', '来', '日本', 'から', '来', '日本', 'から', '来', '日本', 'から', '来', '日本', 'から', '来', '日本', 'から', '来', '日本', 'から', '来', '日本', 'から', '来', '日本', 'から', '来', '日本', 'から', '来']
target: ['', 'から', '来', 'まし', 'た', '。']
source: ['', 'の', 'どこ', 'に', '住ん', 'でる', 'ん', 'です', 'か', '?']
predict: ['東京', 'に', '住ん', '東京', 'に', '住ん', '東京', 'に', '住ん', '東京', 'に', '住ん', '東京', 'に', '住ん', '東京', 'に', '住ん', '東京', 'に', '住ん', '東京', 'に', '住ん', '東京', 'に', '住ん', '東京', 'に', '住ん']
target: ['', 'に', '住ん', 'で', 'い', 'ます', '。']
source: ['おはよう。']
predict: ['おはよう', 'ござい', 'ます', '。']
target: ['おはよう。']
source: ['いつも', '何', '時', 'に', '起き', 'ます', 'か', '?']
predict: ['6', '時', 'に', '6', '時', 'に', '6', '時', 'に', '6', '時', 'に', '6', '時', 'に', '6', '時', 'に', '6', '時', 'に', '6', '時', 'に', '6', '時', 'に', '6', '時', 'に']
target: ['', '時', 'に', '起き', 'ます', '。']
source: ['', 'は', '何', 'を', '食べ', 'ます', 'か', '?']
predict: ['たいてい', 'トースト', 'と', '卵', 'を', '抜く', 'たいてい', 'トースト', 'と', '卵', 'を', '抜く', 'たいてい', 'トースト', 'と', '卵', 'を', '抜く', 'たいてい', 'トースト', 'と', '卵', 'を', '抜く', 'たいてい', 'トースト', 'と', '卵', 'を', '抜く']
target: ['たいてい', 'トースト', 'と', '卵', 'を', '食べ', 'ます', '。']
source: ['', 'は', '毎日', '食べ', 'ます', 'か', '?']
predict: ['たまに', '朝食', 'を', '抜く', 'たまに', '朝食', 'を', '抜く', 'たまに', '朝食', 'を', '抜く', 'たまに', '朝食', 'を', '抜く', 'たまに', '朝食', 'を', '抜く', 'たまに', '朝食', 'を', '抜く', 'たまに', '朝食', 'を', '抜く', 'たまに', '朝食']
target: ['たまに', '朝食', 'を', '抜く', 'こと', 'が', 'あり', 'ます', '。']
source: ['', 'を', 'たくさん', '取っ', 'て', 'い', 'ます', 'か', '?']
predict: ['毎日', '野菜', 'を', '取る', 'よう', 'に', '毎日', '野菜', 'を', '取る', 'よう', 'に', '毎日', '野菜', 'を', '取る', 'よう', 'に', '毎日', '野菜', 'を', '取る', 'よう', 'に', '毎日', '野菜', 'を', '取る', 'よう', 'に']
target: ['毎日', '', 'を', '取る', 'よう', 'に', 'し', 'て', 'い', 'ます', '。']
source: ['', '', 'は', '何', 'を', 'し', 'て', 'い', 'ます', 'か', '?']
predict: ['友達', 'と', '会っ', 'て', 'いる', 'と', '会っ', 'て', 'いる', 'と', '会っ', 'て', 'いる', 'と', '会っ', 'て', 'いる', 'と', '会っ', 'て', 'いる', 'と', '会っ', 'て', 'いる', 'と', '会っ', 'て', 'いる', 'と']
target: ['友達', 'と', '会っ', 'て', 'いる', 'こと', 'が', '多い', 'です', '。']
トレイニングデータは収束しているようですが,結果はまだまだダメそうですね。

ワンライナーで拡張子を変更

Bashの変数から拡張子を除いたファイル名を取得するには

a="file.txt"
echo ${a%%.txt}  # aと表示

これをうまく利用すると一気にディレクトリ内のファイルの拡張子を変更できます。txtをjsonに変更する例はこれ。

for f in *.txt;do mv $f ${f%%.*}.json; done