概要

numpyを使用した重回帰分析scikit-learnを使用した重回帰分析 で実装した賃貸価格の推論と同じ事を Chainer を使用してやってみる。
※ 1層、2入力、1出力のシンプルなネットワークとする。
※ 使用するデータは numpyを使用した重回帰分析 と同じ。

目次

実装

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import chainer
import chainer.links as L
import chainer.functions as F
from chainer import Chain, Variable
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler


class MyModel(Chain):
    def __init__(self):
        super().__init__(
            l1=L.Linear(2, 1)
        )
    def __call__(self, x):
        return self.l1(x)


# 学習率、学習回数
alpha = 0.01
iter_num = 1000

# データ読み込み
data = np.loadtxt("data/sample_rent1.csv", delimiter=",", skiprows=1)
x = data[:, 1:3].astype("float32")  # 広さ, 築年数
t = data[:, 3:4].astype("float32")  # 家賃

# 訓練データとテストデータに分割
x_train, x_test, t_train, t_test = train_test_split(x, t, test_size=0.3, random_state=0)

# 標準化用
scaler = StandardScaler()
scaler.fit(x)

# モデルのインスタンス化
net = MyModel()
optimizer = chainer.optimizers.SGD(lr=alpha)  # 最適化手法には確率的勾配降下法 (SGD) を利用
optimizer.setup(net)

# ログの保存用
loss_history = []

# 精度向上の可視化用に任意の1レコードをサンプルとして抽出
x_sample = np.array([[60, 10]]).astype("float32")
sample_history = []
print("## サンプル ...  広さ: {}, 築年数: {}年 ##".format(x_sample[0,0], x_sample[0,1]))

for epoch in range(iter_num):

    # 正規化(標準化)
    x_train_scaled = scaler.transform(x_train)
    x_test_scaled  = scaler.transform(x_test)

    # モデルの訓練
    y_train = net(x_train_scaled)

    # 精度を計算
    loss = F.mean_squared_error(y_train, t_train)  # 平均二乗誤差
    loss_history.append(loss.item())

    # 勾配のリセットと勾配の計算
    net.cleargrads()
    loss.backward()

    #  パラメータの更新
    optimizer.update()

    # サンプルデータの推論
    with chainer.using_config('train', False), chainer.using_config('enable_backprop', False):
        # chainer.using_config('train', False) ... 対象のデータを使用した訓練を行わない
        # chainer.using_config('enable_backprop', False) ... 計算グラフの構築を行わない
        x_sample_scaled = scaler.transform(x_sample)
        y_sample = net(x_sample_scaled)
        sample_history.append(y_sample.item())

    # 100件ごとにサンプルの推論結果 及び 精度を表示
    if (epoch + 1) % 100 == 0:
        print("## {}: loss: {}, sample_result: {} ##".format(epoch + 1, loss.item(),  y_sample.item()))

print("## 訓練済みネットワークを使用して任意の値を推論してみる ##")
with chainer.using_config('train', False), chainer.using_config('enable_backprop', False):
    #x_tmp = x_test[:5]
    x_tmp = np.array([[60.0, 10.0],[50.0, 10.0],[40.0, 10.0]]).astype("float32")
    y_tmp = net(scaler.transform(x_tmp))
    [print("広さ: {:.1f}, 築年数: {}年 => 家賃: {:.1f}万円".format(x_tmp[i,0], x_tmp[i,1], y_tmp.array[i,0])) for i in range(x_tmp.shape[0])]

# 訓練済みネットワークの保存
chainer.serializers.save_npz('sample1.net', net)

# 訓練済みネットワークの利用
#loaded_net = MyModel()
#chainer.serializers.load_npz('sample1.net', loaded_net)
#with chainer.using_config('train', False), chainer.using_config('enable_backprop', False):
#    y_test = loaded_net(x_test)

# 日本語フォントを利用可能にしておく
plt.rcParams['font.sans-serif'] = ['Hiragino Maru Gothic Pro', 'Yu Gothic', 'Meirio', 'Takao', 'IPAexGothic', 'IPAPGothic', 'Noto Sans CJK JP']

#fig = plt.figure()
fig = plt.figure(figsize=(10, 5))
x1 = fig.add_subplot(1, 2, 1)
x1.set_title("訓練回数毎の精度")
x1.plot(loss_history)
x1.set_xlabel("学習回数")
x1.set_ylabel("精度(Loss)")
x1.grid(True)

x2 = fig.add_subplot(1, 2, 2)
x2.set_title("広さ: 60  築年数: 10年の場合の家賃")
x2.set_xlabel("学習回数")
x2.set_ylabel("家賃")
x2.plot(sample_history)
x1.grid(True)

plt.show()

結果

numpyを使用した重回帰分析scikit-learnを使用した重回帰分析 の結果とほぼ同じ。
左のグラフから訓練毎に精度が上がっている事が分かる。
また、右のグラフからはサンプルデータ(広さ:60屐築年数: 10年) の家賃が学習毎に約8万円あたりに収束していっている事が分かる。

## サンプル ...  広さ: 60.0, 築年数: 10.0年 ##
## 100: loss: 1.2375797033309937, sample_result: 6.949620246887207 ##
## 200: loss: 0.5576881170272827, sample_result: 7.930976867675781 ##
## 300: loss: 0.5441631078720093, sample_result: 8.066993713378906 ##
## 400: loss: 0.5438786745071411, sample_result: 8.086057662963867 ##
## 500: loss: 0.5438722372055054, sample_result: 8.088766098022461 ##
## 600: loss: 0.5438721179962158, sample_result: 8.089155197143555 ##
## 700: loss: 0.5438721179962158, sample_result: 8.08920669555664 ##
## 800: loss: 0.5438721179962158, sample_result: 8.089208602905273 ##
## 900: loss: 0.5438721179962158, sample_result: 8.089208602905273 ##
## 1000: loss: 0.5438721179962158, sample_result: 8.089208602905273 ##
## 訓練済みネットワークを使用して任意の値を推論してみる ##
広さ: 60.0, 築年数: 10.0年 => 家賃: 8.1万円
広さ: 50.0, 築年数: 10.0年 => 家賃: 7.2万円
広さ: 40.0, 築年数: 10.0年 => 家賃: 6.2万円

sample_rent1_chainer.png


添付ファイル: filesample_rent1_chainer.png 5件 [詳細]

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019-11-22 (金) 08:07:51 (20d)