Titanicのデータを使ってPytorchを試してみた
(9/23 修正)NetクラスのNNの数を圧縮
評価基準を正解率、適合率、再現率、f1値に修正
タイタニックのデータを使ってPyTorchの実装をしてみました。
なお、PyTorchのコードは、こちらのサイトから拝借させていただきました、ありがとうございます。
本ブログのコードはこちらからダウンロードできます。
タイタニックのデータについてはkaggleのタイタニックコンペを参照するとよいかと思います。
import pandas as pd import numpy as np from IPython.display import display from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score # 正解率 from sklearn.metrics import precision_score # 適合率 from sklearn.metrics import recall_score # 再現率 from sklearn.metrics import f1_score # F1値 # pytorch import torch from torch.autograd import Variable import torch.nn as nn import torch.nn.functional as F import torch.optim as optim pd.set_option('max_columns', 500) pd.set_option('max_rows', 500) # タイタニックのデータの読込 url = "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/raw/titanic.csv" df = pd.read_csv(url) display(df.head()) display(df.tail()) display(df.shape)
# 特徴量を適当に指定 feature = ["pclass", "sibsp", "parch", "fare"] X_train, X_test, y_train, y_test = train_test_split(df[feature], df["survived"], test_size=0.3, random_state=42) display(X_train.shape) # (623, 4)
PyTorchのデータセットは、numpy型を取り込んで、tensor型でする必要があります。
そこで、.valuesを使ってDataFrame型からnumpy.ndarray型に変換して、torch.Tesor()、LongTensor()でtensor型に変換しています。
また、説明変数をTensor()、目的変数をLongTensor()で変換しないと、RuntimeErrorが発生しますので間違えないようにしましょう。
Longというのは、PyTorchで使われる64bitの整数の型のようです。
X_train = torch.Tensor(X_train.values) X_test = torch.Tensor(X_test.values) y_train = torch.LongTensor(y_train.values) y_test = torch.LongTensor(y_test.values) # シードを固定 torch.manual_seed(42)
ニューラルネットの関数です。
class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.fc1 = nn.Linear(4, 20) # (X_train.shape[1], X) self.fc2 = nn.Linear(20, 10) # (X, Y) self.fc3 = nn.Linear(10, 2) # (Y, Z) def forward(self, x): x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = F.relu(self.fc3(x)) return F.log_softmax(x, dim = 1)
関数の中に設定されている数値が気になりますね。
self.fc1 = nn.Linear(4, 20)
self.fc2 = nn.Linear(20, 10)
self.fc3 = nn.Linear(10, 2)
self.fc1 の1番目の数値 X_trainの次元数 4
(参考)X_train.shape → (623, 4)
self.fc1 の2番目の数値と、self.fc2 の1番目の数値を同じにする
self.fc2 の2番目の数値と、self.fc3 の1番目の数値を同じにする
2クラス分類なので、self.fc3 の2番目の数値を 2 にする
数学よわよわ勢なので間違っているかもしれませんが・・・行列の積ができるようにそろえているんでしょう。
model = Net() print(model) optimizer = optim.SGD(model.parameters(), lr=0.02) train_loss = [] train_accu = [] i = 0 model.train() #学習モードに切り替え for epoch in range(2000): # 数字は適当 data, target = Variable(X_train), Variable(y_train) optimizer.zero_grad() output = model(data) loss = F.nll_loss(output, target) loss.backward() train_loss.append(loss.data.item()) optimizer.step() prediction = output.data.max(1)[1] accuracy = prediction.eq(target.data).sum().numpy() / len(X_train) train_accu.append(accuracy) if i % 10 == 0: print('Train Step: {}\tLoss: {:.3f}\tAccuracy: {:.3f}'.format(i, loss.data.item(), accuracy)) i += 1 print('Train Step: {}\tLoss: {:.3f}\tAccuracy: {:.3f}'.format(i, loss.data.item(), accuracy)) model.eval() #推論モードに切り替え outputs = model(Variable(X_test)) _, predicted = torch.max(outputs.data, 1) # 誤差算定 print(f"正解率 :{accuracy_score(y_test, predicted)}") print(f"適合率 :{precision_score(y_test, predicted)}") print(f"再現率 :{recall_score(y_test, predicted)}") print(f"F1スコア :{f1_score(y_test, predicted)}")
精度は以下のとおりでした。
正解率 :0.7238805970149254
適合率 :0.6907216494845361
再現率 :0.6036036036036037
F1スコア :0.6442307692307693
以上になります、最後までお読みいただきありがとうございました。