概要
元は1次元スペクトルを入力データとする学習モデルを作成したかった。
入力データが1次元データの場合はLSTMなりDenseが使われるが、今やりたいのは時系列データではないのでLSTMは使う意味はないし、1次元スペクトルも長さが65536なのでこれを全結合してもメモリが不足する。
Conv1Dを使うのが正しい答えだがどういう風にモデル作成をすればいいのか情報が少ない。
そこで1次元スペクトルデータを2次元データに並び替えて既存の2次元データ用(画像用)モデルを学習させてみる。
並べ方①
import numpy as np
X = np.asarray(list(range(65536)))
X = np.reshape(X,(256,256))
print(X)
[[ 0 1 2 ... 253 254 255]
[ 256 257 258 ... 509 510 511]
[ 512 513 514 ... 765 766 767]
...
[64768 64769 64770 ... 65021 65022 65023]
[65024 65025 65026 ... 65277 65278 65279]
[65280 65281 65282 ... 65533 65534 65535]]
単純に*np.reshape()*を用いて1次元データを2次元データに変換する方法を並べ方①とする。
順に並べているだけだが行列の2次元目方向には連続データだが1次元目には連続データではない。
こういうデータに二次元モデルのConv2DやPooling2Dが正しいのかという疑問がある。
並べ方②
import numpy as np
X = np.asarray(list(range(65536)))
X = np.reshape(X,(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2))
transpose_tuple = (0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15)
X = X.transpose(transpose_tuple)
X = np.reshape(X,(256,256))
print(X)
[[ 0 1 4 ... 21841 21844 21845]
[ 2 3 6 ... 21843 21846 21847]
[ 8 9 12 ... 21849 21852 21853]
...
[43682 43683 43686 ... 65523 65526 65527]
[43688 43689 43692 ... 65529 65532 65533]
[43690 43691 43694 ... 65531 65534 65535]]
次にConv2DやPooling2Dを掛けるのに適した並べ方を並べ方②とする。
Conv2Dで計算する近接にあるデータは自分の前後のデータで、Pooling2D後にデータサイズの縦横を1/2に縮小した後もその前後のデータが必ず近接に存在するような並べ方を考える。
この並び替えは*np.reshape()とtranspose()*を使って実装できる。
学習
Kerasにおいて1次元データを2次元データに変換してXceptionモデルを用いて学習を行ってみる。
いま入力1次元スペクトルの形は$(32768,2)$なので、これを$(256,128,2)$の二次元画像データのように変換して入力データにする。出力は分子構造を表現するMorganfingerprintで$1024$bitの0,1配列である。
学習のlossは**'binary_crossentropy'**を使う。
X = np.asarray(X)
Y = np.asarray(Y)
data_num = X.shape[0]
channel_num = X.shape[-1]
X = np.reshape(X,(data_num,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,channel_num))
transpose_tuple = (0,1,3,5,7,9,11,13,15,2,4,6,8,10,12,14,16)
X = X.transpose(transpose_tuple)
X = np.reshape(X,(data_num, 256, 128, channel_num))
from keras.applications.xception import Xception
inputs = Input(shape=(256,128,2))
x = Xception(weights=None,input_shape=(256,128,2), include_top=False, pooling='avg')(inputs)
y = Dense(fingerprint_bits, activation='sigmoid')(x)
model = Model(inputs, y)
精度はテストデータにおいて予測される出力配列と実際のfingerprintとのtanimoto係数の値で評価を行う。
結果
各並び方においてepoch150回で3回学習させてみて最後にtanimoto係数を計算させた。
結果は並び方②の方がほんのちょっとだけ良かった。
ただ、実際には1次元スペクトルデータに普通にConv1DとPooling1Dを使ったモデルの方がtanimoto係数は良かったので、1次元データを並び替えて画像用の学習モデルで学習させるメリットはありませんでした。
並び方①の場合
tanimoto_ave = 0.299359707004864
tanimoto_ave = 0.29289148614259464
tanimoto_ave = 0.30107553163958395
並び方②の場合
tanimoto_ave = 0.30911110569123995
tanimoto_ave = 0.30068866803832783
tanimoto_ave = 0.3035398883085789