祭囃子は遠く、

理系大学生のハッピーエヴリディを書いていきます。

LSTMっていうオモチャを見付けました

はじめに

これはぼくのインターンメモです。

LSTM

標語的にはリカレントニューラルネットワーク(RNN)の一種でLong short-term memoryの略だとか言われてますね。

この手法の何が他と違うかというと、ある決められた(人の手で入れる)長さのデータを保持しつつ(たまに忘却しつつ)

学習していくというところみたいですね、すごそう。下のリンクの記事は読んだ事ないですが貼ります

qiita.com


何に強いかというと時系列データだとか、文章(前後の繋がりがあるため)でその辺メインで使われてるらしい。

qiita.com
deepage.net


画像認識もいけるみたいだけど、わざわざやる意味はいまいち分かりません。

動かしてみた

株価予想とか腐る程出てくるので他のでやりたい、文章どうこうはあんまり興味がない

んで、今回は


素数予想」


やります。

CNNで素数判定!みたいな話は結構出てくるんですが、時系列データとして生成するってのはあんまり出てこなかったんで。

まぁ多分やった結果面白くなかったから誰も言ってないないとか、数学的に不可能と証明されているとかそんな感じでしょう。

とりあえず素数をDLしましょう

素数2357: 素数一覧ダウンロード

10000個のやつでやりました、計算重いからね。

毎回思うんですが、こういうcsvファイルってプログラムに読み込ませる以外の用途思いつかないのに、なんで余計なヘッダー付いてるんでしょう。

エクセルで編集はあまりいい思い出が無いので、エディタで消しましょう。

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import math
from keras.models import Sequential
from keras.models import load_model
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error


#データ読み込み
dataframe = pd.read_table('primelist10000.txt')

#変数の抽出ためのデータフレーム作成
df = pd.DataFrame()

#目的変数
df['prime'] = dataframe['Number']#csvのカラム名をぼくが勝手に変えました
max_prime = max(df.prime)#データ範囲での最大値を取得
df.prime = df.prime/max_prime#絶対値0~1でスケール、LSTMはこれが推奨されてるらしい

#説明変数+上と同じ操作
df['index'] = dataframe.index
max_index = max(df.index)
df.index = df.index/max_index

#ここでnumpy-arrayにする。型は適当に設定
df = df.values
df = df.astype('float32')

#データ分割
train_size = int(len(df) * 0.9)#データの9割で学習、1割でテスト
train, test = df[0:train_size,:], df[train_size:len(df),:]

#LSTMが受け取れる形にしましょう、[データ行数][変数の個数][ルックバックの個数]みたいな形でしか受け取れない
def make_dataset(dataset, look_back=1):
    dataX, dataY = [], []
    for i in range(len(dataset)-look_back-1):
        xset = []
        for j in range(dataset.shape[1]):
            a = dataset[i:(i+look_back), j]
            xset.append(a)
        dataY.append(dataset[i + look_back, 0])
        dataX.append(xset)
    return np.array(dataX), np.array(dataY)


look_back = 10#上で出てきましたが、保持しておくデータ数で今回は適当に10とおいた
trainX, trainY = make_dataset(train, look_back)#訓練データリシェープ
testX, testY = make_dataset(test, look_back)#テストデータリシェープ

Hidden_Layer = 300#隠れ層の数、多いほどコスト上がるけど多いほどいいとかなんとか
Epochs = 1000#学習回数
Batch_Size = 10#バッチサイズ(まとまった単位で最適化する感じかな?よくわかってなさそう)

#モデル作成
model = Sequential()
model.add(LSTM(Hidden_Layer, input_shape=(testX.shape[1], look_back)))#隠れ層の指定とインプットデータの指定、ルックバックの指定
model.add(Dense(1))#出力の数
model.compile(loss='mean_squared_error', optimizer='adam')#損失関数と最適化法の指定
model.fit(trainX, trainY, epochs=Epochs, batch_size=Batch_Size)#学習開始
model.save("prime_LSTM2.h5")#学習したモデル保存
#model = load_model("prime_LSTM.h5")#読み込む時はこっち

#予測値
trainPredict = model.predict(trainX)
testPredict = model.predict(testX)

#リスケール
trainPredict = trainPredict * max_prime
trainY = trainY * max_prime
testPredict = testPredict * max_prime
testY = testY * max_prime


# 誤差率評価
err_rate_train = (abs(trainPredict-trainY)/trainY)
err_rate_test = (abs(testPredict-testY)/testY)

#以下予測と実際の素数のプロット
test_len = len(testY)
x_pl = np.arange(test_len)
plt.scatter(x_pl,testY,label="actual")
plt.scatter(x_pl,testPredict,label="predict",color="r")
plt.legend()
plt.xlim([0,50])
plt.savefig("ac_pre.png")

#予測された数値を整数として吐き出し
np.savetxt('pre_train.csv',trainPredict.astype("int"),delimiter=',')
np.savetxt('pre_test.csv',(testPredict.astype("int")),delimiter=',')
np.savetxt('test.csv',testY.astype("int"),delimiter=',')

結果

f:id:ta_ichi:20180215231609p:plain

うーん、微妙そうだけど素数が書く軌跡?みたいなのは若干拾えてそう。わからん!

というか予測した値が実際素数かどうか判定しなきゃ意味がないですね!このプロットはなんなんだ!(一応平行移動して心眼で見る事は可能)

そのプログラムは面倒なのでまた今度回しておきます・・・。

まとめ

よくわからん。

というか、int型での推定(離散的な推定)ってそれ用に何かあるのかな

色々改善できそうだけどもうやらなさそうです。

おしまい