- 投稿日:2020-08-24T13:30:38+09:00
tensorfow を使い複数入力、複数出力を持つモデルの作成方法(mulitple input , output)
multiple input, outputとは
multiple inputとは
全く違うデータ、あるいは形状の違うデータを一つのモデルに入力する、入力層自体が複数あるモデルを言います。
multiple outputとは
multiclassのように出力層に複数の出力を持つのではなく、出力層がそもそも複数あるモデルを言います。
modelの定義部
modelの定義の際に気をつけなければいけないところは、複数の入力が結合するlayerの形状と、複数の出力が分岐される箇所のlayerの形です。当たり前と言えばそれまでですが、ミスしやすいところだと思います。
書き方的には単純なモデルと同じにできるのでこの部分のコードは省きます。from tensorflow.keras import Model の部分
次に詰まるのはmodelの宣言だと思います。multiple input output modelの宣言は以下のようにすれば可能です。
model = Model(inputs=[input_1,input_2], outputs=[output_1,output_2])リスト形式で宣言することができます。
今回の場合の入力層
- input_1
- input_2
今回の場合の出力層
- output_1
- output_2
compile 部分の書き方
compileではlossと、metricsにおいて各出力層ごとに別の関数を割り当てることができます。
model.compile(optimizer='adam', loss={"output_1":"mse","output_2":"categorical_crossentropy"}, metrics={"output_2":"acc"})lossもmetricsもdict形式で与えてやることでcompile可能です出力層の指定にはnameを使うのでmodel定義の際にnameを決めてやる必要があります。
学習の書き方
compile同様にdict形式で各層ごとに別のものを与えてやることができます。
model.fit(x = {"input_1":x_train_1,"input_2":x_train_2}, y={"output_1":x_train_1,"output_2":y_train}, epochs=10000, batch_size=8, shuffle=True, validation_data=({"input_1":x_val_1,"input_12":x_val_2}, {"output_1":x_val_1,"output_2":y_val}), callbacks=[early_stopping] )predictの際の注意点
predictをする際には出力は当たり前ですが定義した出力層の数だけ出てきます。そのため返り値を受け取る変数はその分用意しなければならないわけです。(例 : 出力層が2種類の場合は2つの変数が必要)
入力もdict形式で与えてやる必要があります。pred_1 , pred_2 = model.predict({"input_1":x_test_1,"input_2":x_test_2})以上でmultiple input outputなmodelの作成方法となります。
- 投稿日:2020-08-24T12:58:58+09:00
[tensorflow , keras , mnist] mnistのデータから各ラベルごとにn枚ずつ取り出し10*n枚のデータを作成する
前置き
なぜわざわざデータ量を少なく取りたいのか
- データ量が少ない場合にも良い精度が出るモデルを考えたいため
- 各ラベルごとに偏りをなくしたいため
コード
github
mnistのロードを行う(x_train, y_train), (x_test, y_test) = mnist.load_data()y_trainをpandasのdataframeに一度格納し、そこからdataframeを分割、indexを取り出す。という流れでn=100で取り出します。
#各label100枚ずつ足りだすためのコード、pandasを用いて行う df = pd.DataFrame(columns=["label"]) df["label"] = y_train.reshape([-1]) list_0 = df.loc[df.label==0].sample(n=100)#n=100でsampling list_1 = df.loc[df.label==1].sample(n=100) list_2 = df.loc[df.label==2].sample(n=100) list_3 = df.loc[df.label==3].sample(n=100) list_4 = df.loc[df.label==4].sample(n=100) list_5 = df.loc[df.label==5].sample(n=100) list_6 = df.loc[df.label==6].sample(n=100) list_7 = df.loc[df.label==7].sample(n=100) list_8 = df.loc[df.label==8].sample(n=100) list_9 = df.loc[df.label==9].sample(n=100) label_list = pd.concat([list_0,list_1,list_2,list_3,list_4,list_5,list_6,list_7,list_8, list_9]) label_list = label_list.sort_index() label_idx = label_list.index.values train_label = label_list.label.values """ x_trainからlabel用のdataframe.indexを取り出すことでlabelに対応したデータを取り出す。 """ x_train = x_train[label_idx] y_train= train_label x_train = x_train / 255 x_test = x_test / 255これで各ラベル100枚ごとにサンプリングできました。
- 投稿日:2020-08-24T12:01:08+09:00
PythonによるAI作成入門!その2 ニューラルネットワークでボストン市の住宅価格を予測してみた
本記事について
深層学習の基本である「回帰」を使って、
住宅価格を予測するプログラムを作ってみようと思います。
出来るだけ初心者目線で書いていきます。
前回記事はこちらです。回帰ってなに?
回帰とは、特徴的なデータをもとに数値を予測するタスクのことを言います。
今回は住宅価格を予測するプログラムを作りますが、株やFX(外国為替取引)の値動きの予測も可能です。import
インポートは↓です。
今回はデータの確認用にpandasをインポートしましょう。ちなみに、pandasは非常に扱いやすいですが速度はとても遅いです。
学習の際にはnumpyを使い、目視確認やデータの前処理段階でpandasを使うのが一般的です。from tensorflow.keras.datasets import boston_housing from tensorflow.keras.layers import Activation, Dense, Dropout from tensorflow.keras.models import Sequential from tensorflow.keras.callbacks import EarlyStopping from tensorflow.keras.optimizers import Adam import pandas as pd import numpy as np import matplotlib.pyplot as plt %matplotlib inline住宅価格のダウンロード
今回、住宅価格を予測するにあたって、boston_housingというライブラリを使います。
boston_housingには、米国ボストンの住宅を決めるにあたっての特徴的な情報とその正解ラベルが入っています。
特徴的な情報(以下、説明変数)には、その地域の犯罪率とかアクセスの良さとかが入ってます。当然ですが、この説明変数にいい加減な情報が入っていると、予測の精度が悪くなります。
例えば、周辺にあるパチンコ店の数を説明変数に加えても
パチンカーしか価値を感じないので、予測の邪魔になるでしょう。
万人が価値を感じるようなものを加えなければいけません。回帰予測で最も難しいのはこの説明変数の定義なのですが、
今回はダウンロードしたデータに含まれるので楽ですね。ダウンロードは以下のコードです。
ダウンロードした説明変数は正解ラベルを学習用と検証用で分けています。
(train_data, train_labels)が学習用で、(test_data, test_labels)が検証用です。
この辺は前回記事の分類と同じです。(train_data, train_labels), (test_data, test_labels) = boston_housing.load_data()shape数を確認します。
学習用データは404件、検証用データが102件。
前回記事の分類と比べてやたらと少ないですね。本当に予測できるのか不安になる件数です。
データの前処理
続いて、最も地味で最も重要な作業、データの前処理です。
今回の住宅価格の予測は時系列データではないので、連続性がありません。
そんなデータを予測する場合は、データをシャッフルしておいた方が無難です。
※株やFXなどの時系列データ予測の際にはシャッフルは厳禁です。
random.random()
で乱数を作り、np.argsort()
でインデックスを作ってソートします。order = np.argsort(np.random.random(train_labels.shape)) train_data = train_data[order] train_labels = train_labels[order]続いて、住宅価格を決める説明変数を正規化します。
今回は正規化で説明変数を平均0の分散1の数値にします。回帰予測では大きい数値の説明変数に予測が引っ張られることがあるため、
このように正規化しておくと良いと言われています。正規化は、正規化したいデータから平均を引いて標準偏差で割ると算出できます。
コードは↓です。mean = train_data.mean(axis=0) std = train_data.std(axis=0) train_data = (train_data - mean) / std test_data = (test_data - mean) / stdpandasを使って、説明変数が正規化されていることを確認しましょう。
# データセットの前処理後のデータの確認 column_names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT'] df = pd.DataFrame(train_data, columns=column_names) df.head()モデルの作成
ニューラルネットワークのモデルを作成します。
今回は全総結合の層を3つ用意します。
※今回はDropoutはありませんmodel = Sequential() model.add(Dense(64, activation='relu', input_shape=(13,))) model.add(Dense(64, activation='relu')) model.add(Dense(1)) model.compile(loss='mse', optimizer=Adam(lr=0.001), metrics=['mae']) # コンパイル1つ1つ解説します。
まず、model = Sequential()
でシーケンシャルモデルを作成します。
model.add(Dense(64, activation='relu', input_shape=(13,)))
は入力層です。
Dense:全総結合、ユニット数:64、活性化関数:ReLU、説明変数:13個
model.add(Dense(64, activation='relu'))
は隠れ層です。
Dense:全総結合、ユニット数:64、活性化関数:ReLU
model.add(Dense(1))
は出力層です。
今回は数値の予測なので、ユニット(出力数)は1つだけです。モデルのコンパイル
model.compile(loss='mse', optimizer=Adam(lr=0.001), metrics=['mae'])
でコンパイルします。
loss='mse'で予測値と実際の値の誤差の求めるための損失関数をセットします。
回帰に向いているといわれるmseをセットしましょう。optimizer=Adam(lr=0.001)で誤差を小さくするための最適化関数にAdam、学習率は0.01をセットします。
metrics=['mae']でモデルの性能を評価するための評価関数のmaeをセットします。
学習
今回はEarlyStoppingを使って学習をしたいと思います。
EarlyStoppingを使うと、指定のエポック数で学習の改善が見られなかった場合、自動で止めてくれます。
今回は20エポックで改善が見られなかった場合、止めたいと思います。学習は、最大エポック数を500、検証用データは2割にセット、callbacks=[early_stop]でEarlyStoppingを有効化します。
# EarlyStoppingを準備 early_stop = EarlyStopping(monitor='val_loss', patience=30) # 学習の実行 history = model.fit(train_data, train_labels, epochs=500, validation_split=0.2, callbacks=[early_stop])学習状況の説明です。
lossは訓練データの誤差です。0に近いほど良い結果です。
maeは訓練データの平均絶対誤差です。0に近いほど良い結果です。
val_lossは検証データの誤差です。0に近いほど良い結果です。
val_maeは検証データの平均絶対誤差です。0に近いほど良い結果です。エポック数を500でセットしていますが、途中で改善が見られなくなって打ち切られているかと思います。
学習結果をグラフで表示
学習結果が保存されているhistory.historyをmatplotlibで描画します。
plt.plot(history.history['mae'], label='train mae') plt.plot(history.history['val_mae'], label='val mae') plt.xlabel('epoch') plt.ylabel('mae [1000$]') plt.legend(loc='best') plt.ylim([0,5]) plt.show()学習の評価
model.evaluteで学習データを評価します。
test_loss, test_mae = model.evaluate(test_data, test_labels) print('loss:{:.3f}\nmae: {:.3f}'.format(test_loss, test_mae))学習データより結果が悪いですが、概ね近い結果が出せました。
400件程度の少ない件数でもここまで近い数値が出せるのはすごいですね。
おそらく説明変数の定義が優秀なんでしょう。推論
最後に予測データを出力して確認してみましょう。
最初に正解ラベルを表示して、そのあと推論します。
推論の出力結果は2次元なので、flatten()
で1次元に変換しておきましょう。# 正解ラベルを表示 print(np.round(test_labels[0:10])) # 推論した値段の表示 test_predictions = model.predict(test_data[0:10]).flatten() print(np.round(test_predictions))この予測値より下回っている物件は相場よりも安く売られている可能性があるということです。
ただ、説明変数で表現できない理由(幽霊が出る等)で安くなっている場合もあります。
この予測結果だけで売買をするのは危険ですが、参考にはなるかと思います。
- 投稿日:2020-08-24T12:01:08+09:00
PythonによるAI作成入門!その2 ニューラルネットワークでボストン市の住宅価格を予測してみた
本記事について
深層学習の基本である「回帰」を使って、
住宅価格を予測するプログラムを作ってみようと思います。
出来るだけ初心者目線で書いていきます。
前回記事はこちらです。回帰ってなに?
回帰とは、特徴的なデータをもとに数値を予測するタスクのことを言います。
今回は住宅価格を予測するプログラムを作りますが、株やFX(外国為替取引)の値動きの予測も可能です。import
インポートは↓です。
今回はデータの確認用にpandasをインポートしましょう。ちなみに、pandasは非常に扱いやすいですが速度はとても遅いです。
学習の際にはnumpyを使い、目視確認やデータの前処理段階でpandasを使うのが一般的です。from tensorflow.keras.datasets import boston_housing from tensorflow.keras.layers import Activation, Dense, Dropout from tensorflow.keras.models import Sequential from tensorflow.keras.callbacks import EarlyStopping from tensorflow.keras.optimizers import Adam import pandas as pd import numpy as np import matplotlib.pyplot as plt %matplotlib inline住宅価格のダウンロード
今回、住宅価格を予測するにあたって、boston_housingというライブラリを使います。
boston_housingには、米国ボストンの住宅を決めるにあたっての特徴的な情報とその正解ラベルが入っています。
特徴的な情報(以下、説明変数)には、その地域の犯罪率とかアクセスの良さとかが入ってます。当然ですが、この説明変数にいい加減な情報が入っていると、予測の精度が悪くなります。
例えば、周辺にあるパチンコ店の数を説明変数に加えても
パチンカーしか価値を感じないので、予測の邪魔になるでしょう。
万人が価値を感じるようなものを加えなければいけません。回帰予測で最も難しいのはこの説明変数の定義なのですが、
今回はダウンロードしたデータに含まれるので楽ですね。ダウンロードは以下のコードです。
ダウンロードした説明変数は正解ラベルを学習用と検証用で分けています。
(train_data, train_labels)が学習用で、(test_data, test_labels)が検証用です。
この辺は前回記事の分類と同じです。(train_data, train_labels), (test_data, test_labels) = boston_housing.load_data()shape数を確認します。
学習用データは404件、検証用データが102件。
前回記事の分類と比べてやたらと少ないですね。本当に予測できるのか不安になる件数です。
データの前処理
続いて、最も地味で最も重要な作業、データの前処理です。
今回の住宅価格の予測は時系列データではないので、連続性がありません。
そんなデータを予測する場合は、データをシャッフルしておいた方が無難です。
※株やFXなどの時系列データ予測の際にはシャッフルは厳禁です。
random.random()
で乱数を作り、np.argsort()
でインデックスを作ってソートします。order = np.argsort(np.random.random(train_labels.shape)) train_data = train_data[order] train_labels = train_labels[order]続いて、住宅価格を決める説明変数を正規化します。
今回は正規化で説明変数を平均0の分散1の数値にします。回帰予測では大きい数値の説明変数に予測が引っ張られることがあるため、
このように正規化しておくと良いと言われています。正規化は、正規化したいデータから平均を引いて標準偏差で割ると算出できます。
コードは↓です。mean = train_data.mean(axis=0) std = train_data.std(axis=0) train_data = (train_data - mean) / std test_data = (test_data - mean) / stdpandasを使って、説明変数が正規化されていることを確認しましょう。
# データセットの前処理後のデータの確認 column_names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT'] df = pd.DataFrame(train_data, columns=column_names) df.head()モデルの作成
ニューラルネットワークのモデルを作成します。
今回は全総結合の層を3つ用意します。
※今回はDropoutはありませんmodel = Sequential() model.add(Dense(64, activation='relu', input_shape=(13,))) model.add(Dense(64, activation='relu')) model.add(Dense(1)) model.compile(loss='mse', optimizer=Adam(lr=0.001), metrics=['mae']) # コンパイル1つ1つ解説します。
まず、model = Sequential()
でシーケンシャルモデルを作成します。
model.add(Dense(64, activation='relu', input_shape=(13,)))
は入力層です。
Dense:全総結合、ユニット数:64、活性化関数:ReLU、説明変数:13個
model.add(Dense(64, activation='relu'))
は隠れ層です。
Dense:全総結合、ユニット数:64、活性化関数:ReLU
model.add(Dense(1))
は出力層です。
今回は数値の予測なので、ユニット(出力数)は1つだけです。モデルのコンパイル
model.compile(loss='mse', optimizer=Adam(lr=0.001), metrics=['mae'])
でコンパイルします。
loss='mse'で予測値と実際の値の誤差の求めるための損失関数をセットします。
回帰に向いているといわれるmseをセットしましょう。optimizer=Adam(lr=0.001)で誤差を小さくするための最適化関数にAdam、学習率は0.01をセットします。
metrics=['mae']でモデルの性能を評価するための評価関数のmaeをセットします。
学習
今回はEarlyStoppingを使って学習をしたいと思います。
EarlyStoppingを使うと、指定のエポック数で学習の改善が見られなかった場合、自動で止めてくれます。
今回は20エポックで改善が見られなかった場合、止めたいと思います。学習は、最大エポック数を500、検証用データは2割にセット、callbacks=[early_stop]でEarlyStoppingを有効化します。
# EarlyStoppingを準備 early_stop = EarlyStopping(monitor='val_loss', patience=30) # 学習の実行 history = model.fit(train_data, train_labels, epochs=500, validation_split=0.2, callbacks=[early_stop])学習状況の説明です。
lossは訓練データの誤差です。0に近いほど良い結果です。
maeは訓練データの平均絶対誤差です。0に近いほど良い結果です。
val_lossは検証データの誤差です。0に近いほど良い結果です。
val_maeは検証データの平均絶対誤差です。0に近いほど良い結果です。エポック数を500でセットしていますが、途中で改善が見られなくなって打ち切られているかと思います。
学習結果をグラフで表示
学習結果が保存されているhistory.historyをmatplotlibで描画します。
plt.plot(history.history['mae'], label='train mae') plt.plot(history.history['val_mae'], label='val mae') plt.xlabel('epoch') plt.ylabel('mae [1000$]') plt.legend(loc='best') plt.ylim([0,5]) plt.show()学習の評価
model.evaluteで学習データを評価します。
test_loss, test_mae = model.evaluate(test_data, test_labels) print('loss:{:.3f}\nmae: {:.3f}'.format(test_loss, test_mae))学習データより結果が悪いですが、概ね近い結果が出せました。
400件程度の少ない件数でもここまで近い数値が出せるのはすごいですね。
おそらく説明変数の定義が優秀なんでしょう。推論
最後に予測データを出力して確認してみましょう。
最初に正解ラベルを表示して、そのあと推論します。
推論の出力結果は2次元なので、flatten()
で1次元に変換しておきましょう。# 正解ラベルを表示 print(np.round(test_labels[0:10])) # 推論した値段の表示 test_predictions = model.predict(test_data[0:10]).flatten() print(np.round(test_predictions))この予測値より下回っている物件は相場よりも安く売られている可能性があるということです。
ただ、説明変数で表現できない理由(幽霊が出る等)で安くなっている場合もあります。
この予測結果だけで売買をするのは危険ですが、参考にはなるかと思います。