Python

わかりやすいPyTorch入門②(ニューラルネットワークによる分類)

ニューラルネットワークを使ってワインの種類を分類する

今回はscikit-learnに含まれるワインのデータセットを使って、ニューラルネットワーク(以下、NNと呼ぶ)による分類を学んでいきます。
大まかな流れは以下の通りです。

  1. 13個の特徴量(input layer)を持つワインのデータセットを用意
  2. 隠れ層(hidden layer)を通して、出力(output layer)を計算
  3. 出力値と正解値から誤差を計算
  4. 誤差を逆伝搬し、重み(パラメータ)を更新
  5. 処理を繰り返し最適解(モデル)を探す

では早速、コードを書いて実行していきましょう。

'''ライブラリの準備'''
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
import pandas as pd
'''データセットの準備'''
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split


まずは学習に必要なライブラリとデータセットを読み込みます。
ライブラリに関する説明は前回の記事で説明したので、今回は割愛いたします。

'''データの読み込み'''
wine = load_wine()


まずは今回利用するデータセットの中身を確認します。
ここではデータセットをwineという名前で登録しました。

wine_df = pd.DataFrame(wine.data, columns=wine.feature_names)


先ほど取り込んだワインデータをデータフレーム型(DataFrame)に変更します。
データフレーム型は、加工や抽出などデータ解析に必要な操作ができるのでとても便利です。
wine.dataでwineというデータセットの「data」を参照し、カラム名(列名)には「feature_names」をセットしました。
※この「data」「feature_names」はデータセットによって名前が異なります。

wine_class = pd.DataFrame(wine.target, columns=['class'])


先ほど作成したwine_df(ワインの特徴が入ったデータ)とwine_class(ワインの種類:0 or 1)を結合するために、DataFrame型に変換しました。

'''学習データの準備'''
wine_cat = pd.concat([wine_df, wine_class], axis=1)
wine_cat.drop(wine_cat[wine_cat['class'] == 2].index, inplace=True)
wine_data = wine_cat.values[:,:13]
wine_target = wine_cat.values[:,13]


pd.concatでデータを結合。axis=1は横方向を意味します。
.indexは行番号を示しており、dropでそのデータを削除することができます。
また、inplace=Trueで結果をそのままwine_catに代入しました。
.valuesを使うとDataFrameの値を配列として取得でき、wine_data.values[行, 列]で任意の行・列を参照します。
※[:, :13]=[全行, 0~12列目]。[:, 13]=[全行, 13列目]。
※print()内の「’\n’」は改行を意味します。

'''データセットの分割'''
Train_X, Test_X, Train_Y, Test_Y = train_test_split(wine_data, wine_target, test_size=0.25)
'''PyTorch tensorへ変換(型指定)'''
train_X = torch.FloatTensor(Train_X)
train_Y = torch.LongTensor(Train_Y)
test_X = torch.FloatTensor(Test_X)
test_Y = torch.LongTensor(Test_Y)
train = TensorDataset(train_X, train_Y)


◆データセットの準備
まずは、train_test_splitで学習用データとテスト用データに分割します。
(ここでは25%をテスト用データとしました)
◆PyTorch tensorへ変換(型変換)
ただ、これはまだtensor型ではないので、FloatTensorなどを用いてTensor型に変換します。
※メモリの負荷を下げるために今回は32bit小数のfloatを採用しました。
tensor型に変換できたらTensorDatasetを使って、train_Xとtrain_Yを一つにしたtensor型データセットを作成します。

train_loader = DataLoader(train, batch_size=8, shuffle=True)


DataLoader:データセット(train)からサンプルを取得してミニバッチを作成。
「batch_size=8」「shuffle=True」とすることで、データをシャッフルし、8個のデータをまとめて学習できるようにしました。

'''モデルの定義'''
class Net(nn.Module):
  def __init__(self):
    super(Net, self).__init__()
    self.fc1 = nn.Linear(13, 128)
    self.fc2 = nn.Linear(128, 2)
  def forward(self, x):
    x = F.relu(self.fc1(x))
    x = self.fc2(x)
    return x
net = Net()
'''最適化手法の定義'''
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.01)


◆モデルの定義
PyTorchでクラスを作成するときは通常、nn.Moduleを継承します。
※すでに存在するクラスを継承すると何かと楽です。
<クラス作成時の公式>

結合層(入力層・隠れ層・出力層)のイメージはこちらです。
結合層では主に「nn.Linear:線型結合」「Conv2d:画像データの畳み込み計算」などが使われます。

toward data scienceより引用
そして順伝搬の処理(forward内)では、活性化関数「ReLU」を使用しました。
活性化関数とは数値をその関数に取り込んで計算結果を返すというものです。
※例えばReLUは「y=x(x>=0)、y=0(x<0)」という関数です。
◆最適化手法
評価方法には「CrossEntropyLoss(交差エントロピー誤差)」を採用しました。
前回の記事では「MSELoss(平均二乗誤差)」を用いたのですが、SGD(確率的勾配降下法)との相性の良さから、実際には交差エントロピー誤差が使われることが多いです。
※確率的勾配降下法は「微分から傾きを求めて損失関数が小さくなる方向に進むことで最適化を図る」という手法なので、微分計算が楽なlog(x)やe^xを含む交差エントロピー誤差は相性が良いのです。
※学習率とは、最適化の際にどのくらいパラメータを動かすかを決めるもので「0.01~0.03」あたりがよく使われます。

'''学習'''
for epoch in range(100):
  total_loss = 0
  for train_x, train_y in train_loader:
    optimizer.zero_grad()
    loss = criterion( net(train_x), train_y )
    loss.backward()
    optimizer.step()
    total_loss += loss.data


今回はデータを500回学習させます。
1回の学習でtrain_loaderのミニバッチからデータを取り出し、予測値(net(train_x))と正解値(train_y)の損失を計算することで、最適なパラメータを探していきます。
学習がうまく進んでいるか確認したいので、50回に1回の頻度で結果を表示させました。
微小ではありますが少しずつ学習が進んでいる様子が観察できます。

test_net = net(test_X).detach()


先ほど学習が完了したので、実際にテストしていきたいと思います。
net(test_X)の値を取得するために、勾配を計算する演算情報を.detechで削除しました。

'''精度を計算'''
result = torch.max(test_net, 1)[1]
accuracy = sum(test_Y.data.numpy() == result.numpy()) / len(test_Y.data.numpy())
accuracy


2つの特徴量を持つtest_netの配列で*torch.max(詳細は後述)を用います。
そしてデータ型をtensorからnumpyに変換し、「torch.maxで求めた値(result)」と「test_Yの値(test_Y.data)」の一致率を求め、それを正解率としました。
◆torch.max
torch.maxは配列内のある方向で「最大値とそのインデックス」を取得することができます。
※torch.max(x, 0)で列方向。torch.max(x, 1)で行方向。

◆test_Yとresultの中身

今回はニューラルネットワークの雰囲気を感じてもらいましたが、次回は画像識別データを使ってその精度を上げる方法について学びたいと思います。

参考文献

pytorchを用いたワイン分類
PyTorchでCNNsを徹底解説
Qiita – 交差エントロピー誤差をわかりやすく説明してみる

ピックアップ記事

  1. 最速で理解したい人のためのIT用語集

関連記事

  1. Python

    わかりやすいPyTorch入門④(CNN:畳み込みニューラルネットワーク)

    MNISTの手書き数字画像をCNNで分類前回の記事でも利用したMNI…

  2. Python

    Streamlit in Snowflakeによるダッシュボード作成

    こんにちは、エクスチュアの石原です。前回に引き続き、Stre…

  3. Python

    モダンデータスタックなワークフローオーケストレーションツール「Prefect」 試してみた

    こんにちは!みなさんPrefectについて知っていますでしょうか?…

  4. Python

    回帰分析はかく語りき Part1 単回帰分析

    こんにちは、小郷です。回帰と言えばフリードリヒ・ニーチェの永劫回帰を…

  5. Adobe Analytics

    Google Analytics検証を効率的に進める方法

    0.初めにGoogle Analyticsがデータをとれているか検証…

コメント

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

CAPTCHA


最近の記事

  1. 回帰分析はかく語りき Part3 ロジスティック回帰
  2. GCSへのSnowflake Open Catalogによる…
  3. VPC Service Controlsで「NO_MATCH…
  4. モダンデータスタックなワークフローオーケストレーションツール…
  5. Streamlit in Snowflakeによるダッシュボ…
  1. Adobe Analytics

    再来訪頻度とは-Adobe Analyticsの指標説明
  2. Tableau

    【TC19ブログ】エクスチュアの海外カンファレンス参加支援制度
  3. ブログ

    IPアドレスとは
  4. Tableau

    TableauでTreasure Data上のデータへ接続する方法(2023/0…
  5. ヒートマップ

    【Tips】ヒートマップ機能について②~ムーブメント、アテンション編~
PAGE TOP