#はじめに
この記事ではWindowsでのPyTorchのインストールから、Irisの分類をざっくりやっていきます。
#関連リンク
PyTorch v0.4 導入
PyTorch-NLPを使ってみる
skorch入門
#環境
- python 3.6.2
- Anaconda 4.3.27
- Windows10
#PyTorch
ざっくり説明すると、Facebookが開発していてChainerの様にコードが書け、
Tensorflowとは異なり研究向けのディープラーニングライブラリです。
#Install
※2018年7月12日追記
Windowsも公式からインストールができるようになりました。
Windowsは公式からはインストールできないので、Anaconda Cloudから、
コマンドプロンプトを開いて下のようにインストールします。
conda install -c peterjc123 pytorch
※追記
Bash on Windowsにインストールする方法
Bash on WindowsでPyTorchを使えるようにする。
#Iris
ここからはPyTorchを使ったIrisデータセットの分類をざっくり書いていきます。
##データセット
Irisデータセットとは150件の花のデータセットで、setosa, versicolor, virginicaという3つのクラスに分類されていて、それぞれがく片(Sepal)と花弁(Petal)の長さと幅の4つの特徴量をもっています。
##データセットの準備
scikit-learnからデータを読み込んだあと正規化し、訓練データとテストデータに分けます。
~~後ほど説明しますが、~~誤差関数にはCrossEntropyLossを使います。CrossEntropyLossの入力の型はFloatTensor, 出力はLongTensorである必要があります。出力のtargetの型はnp.int32になっているので、targetの型をnp.int64に変換します。詳しいことはこちらを参考にしてください。
target(クラス)はone-hotではなくラベルで与えます。
# Load dataset...
iris_dataset = datasets.load_iris()
data = iris_dataset.data
# Normalization...
data = sp.stats.zscore(data, axis=0)
# 0 -> setosa
# 1 -> versicolor
# 2 -> virginica
target = iris_dataset.target
# np.int64 -> Longtensor
target = target.astype(np.int64)
# Split data into train and test set...
# Training size -> 120
# Test size -> 30
train_X, test_X, train_Y, test_Y = train_test_split(data, target, test_size=0.2)
##モデル
入力層、隠れ層、出力層からなるニューラルネットワークです。
Chainerの様にモデルを書くことができます。
class NeuralNetwork(nn.Module):
def __init__(self, n_in, n_units, n_out):
super(NeuralNetwork, self).__init__()
self.l1 = nn.Linear(n_in, n_units)
self.l2 = nn.Linear(n_units, n_out)
def forward(self, x):
h = F.relu(self.l1(x))
y = self.l2(h)
return y
##学習
訓練データを使ってミニバッチ学習をします。
学習部分もChainerの様に書けます。
# Training...
for epoch in range(epochs):
train_X, train_Y = shuffle(train_X, train_Y)
for i in range(n_batch):
start = i * batch_size
end = start + batch_size
x = Variable(torch.FloatTensor(train_X[start:end]))
t = Variable(torch.LongTensor(train_Y[start:end]))
optimizer.zero_grad()
y = model(x)
loss = criterion(y, t)
loss.backward()
optimizer.step()
##モデルのテスト
テストデータを使って学習したモデルのテストをします。
テストデータをFloatTensorにした後、Variableに変換します。
それをモデルに渡すことでモデルからの出力を得られます。
torch.maxを使うことにより一つの入力に対する出力の中で最も高い値のindexを得ることができ、それがモデルの予測したラベルとなります。詳しいことはこちらを参考してください。
# Test...
test_case = Variable(torch.FloatTensor(test_X), requires_grad=False)
result = model(test_case)
predicted = torch.max(result, 1)[1]
print("{:.2f}".format(sum(p == t for p, t in zip(predicted.data, test_Y)) / len(test_X)))
40epochで9割を超える正答率を得ることができました。
0.93
#全体のコード
import argparse
import torch
import numpy as np
import matplotlib.pyplot as plt
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as O
import scipy.stats as sp
from torch.autograd import Variable
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.utils import shuffle
class NeuralNetwork(nn.Module):
def __init__(self, n_in, n_units, n_out):
super(NeuralNetwork, self).__init__()
self.l1 = nn.Linear(n_in, n_units)
self.l2 = nn.Linear(n_units, n_out)
def forward(self, x):
h = F.relu(self.l1(x))
y = self.l2(h)
return y
parser = argparse.ArgumentParser()
parser.add_argument('--batchsize', '-b', type=int, default=20,
help="Number of minibatch size...")
parser.add_argument('--epochs', '-e', type=int, default=40,
help="Number of epochs...")
parser.add_argument('--learning_rate', '-lr', type=float, default=0.1,
help="Learning rate...")
args = parser.parse_args()
batch_size = args.batchsize
epochs = args.epochs
learning_rate = args.learning_rate
# Load dataset...
iris_dataset = datasets.load_iris()
# data type -> numpy.ndarray
data = iris_dataset.data
# Normalization...
data = sp.stats.zscore(data, axis=0)
# 0 -> setosa
# 1 -> versicolor
# 2 -> virginica
target = iris_dataset.target
# np.float32 -> FloatTensor
# np.int64 -> Longtensor
target = target.astype(np.int64)
# Split data into train and test set...
# Training size -> 120
# Test size -> 30
train_X, test_X, train_Y, test_Y = train_test_split(data, target, test_size=0.2)
n_in = len(data[0])
n_units = 5
n_out = len(iris_dataset.target_names)
n_batch = len(train_X) // batch_size
history = {"loss": []}
# Model + Loss + Optimizer
model = NeuralNetwork(n_in, n_units, n_out)
criterion = nn.CrossEntropyLoss()
optimizer = O.Adam(model.parameters(), lr=learning_rate)
# Training...
for epoch in range(epochs):
train_X, train_Y = shuffle(train_X, train_Y)
for i in range(n_batch):
start = i * batch_size
end = start + batch_size
x = Variable(torch.FloatTensor(train_X[start:end]))
t = Variable(torch.LongTensor(train_Y[start:end]))
optimizer.zero_grad()
y = model(x)
loss = criterion(y, t)
loss.backward()
optimizer.step()
history["loss"].append(loss.data[0])
#print(history["loss"][-1])
plt.title("loss")
plt.plot(range(epochs), history["loss"])
plt.show()
# Test...
test_case = Variable(torch.FloatTensor(test_X), requires_grad=False)
result = model(test_case)
predicted = torch.max(result, 1)[1]
print("{:.2f}".format(sum(p == t for p, t in zip(predicted.data, test_Y)) / len(test_X)))