【Python】 PyTorch ~ 深層学習ライブラリ ~

■ はじめに

ディープラーニングライブラリ である PyTorch(パイトーチ)について学ぶ

目次

【1】環境設定
【2】関連用語
 1)確率的勾配降下法(SGC)
【3】サンプル
 例1:偏微分
 例2:勾配降下法
 例3:確率的勾配降下法(SGC)
 例4:ニューラルネットワーク対応版

【1】環境設定

Anaconda をインストール

トラブル:Anaconda入れているのにモジュールないって怒られる

Anaconda入れているのに、
~~~~
import torch
~~~~
で、エラー「ModuleNotFoundError: No module named 'torch'」になる

解決案
https://github.com/pytorch/pytorch/issues/4827

より抜粋
~~~~~
# torch に関するモジュールがあるか確認
conda list | grep torch

# 念のため、モジュール削除
conda uninstall torchvision-cpu pytorch-cpu
# 再インストール
conda install pytorch-cpu torchvision-cpu -c pytorch
~~~~~

【2】関連用語

1)確率的勾配降下法(SGC)

* SGD = Stochastic Gradient Descent

基本的な仕組み

ランダムに学習データを1つ選び、
そのデータの変化させた場合に
損失関数が最小になるように求める

【3】サンプル

例1:偏微分
例2:勾配降下法
例3:確率的勾配降下法(SGC)
例4:ニューラルネットワーク対応版

例1:偏微分

import torch

x1 = torch.tensor([2.0], requires_grad=True)
x2 = torch.tensor([1.0], requires_grad=True)
# 対象関数
function = x1**2 - 4*x1 + x2**2 - 2*x2 + 5

# 微分して勾配を計算
function.backward()

# 出力
# dy/dx1 = 2*x1 - 4 = 2*2 - 4 = 0.0
# dy/dx2 = 2*x2 - 2 = 2*1 - 2 = 0.0
print("{}, {}".format(
  x1.grad.item(),
  x2.grad.item()))

出力結果

0.0, 0.0

例2:勾配降下法(Gradient descent)

import torch
from torch.utils.data import TensorDataset, DataLoader

# カリフォルニアの住宅価格のデータセット
# https://scikit-learn.org/stable/modules/generated/sklearn.datasets.fetch_california_housing.html
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_absolute_error


# データセット を訓練データとテストデータに分割
housing = fetch_california_housing()
x_train, x_test, y_train, y_test = \
  train_test_split(housing.data, housing.target)

# データの正規化
# 正規化 = データの最大値と最小値を制限する変換
normalizer = MinMaxScaler()
# x_trainに対して、平均と分散を計算(fit)して
# 変換(transform)する
x_train = normalizer.fit_transform(x_train)
x_test = normalizer.transform(x_test)

# データをTensor形式に変換する
x = torch.tensor(x_train, dtype=torch.float32)
y = torch.tensor(y_train, dtype=torch.float32)
dataset = TensorDataset(x, y)
loader = DataLoader(dataset, batch_size=40, shuffle=True)

# 勾配降下法(Gradient descent)

# requires_grad=True : 自動微分ON
w = torch.randn(9, requires_grad=True)
# 学習係数
learning_coeff = 0.01

for i in range(10):
  for batch_x, batch_y in loader:
    # Tensorの連結
    x = torch.cat(
      [torch.ones(batch_x.shape[0], 1), batch_x],
      dim=1)
    # 勾配リセット
    w.grad = None
    # 予想値を計算
    y_product = torch.matmul(x, w)
    # 平均二乗誤差
    loss = torch.mean((y_product - batch_y) ** 2)
    # 微分して勾配を計算
    loss.backward()
    # パラメータを更新
    w.data = w.data - learning_coeff * w.grad.data

# テストデータで予想値と実測値とのズレを計算する

x = torch.cat(
  [torch.ones(x_test.shape[0], 1),
  torch.tensor(x_test, dtype=torch.float32)], dim=1)
# 予想値
y_product = torch.matmul(x, w).detach().numpy()
# 予想値 y_product と実測値 y_test とのズレを計算
print(mean_absolute_error(y_test, y_product))

出力結果

0.6326653451121648

例3:確率的勾配降下法(SGC)

import torch
from torch import nn, optim
from torch.utils.data import TensorDataset, DataLoader

# カリフォルニアの住宅価格のデータセット
# https://scikit-learn.org/stable/modules/generated/sklearn.datasets.fetch_california_housing.html
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_absolute_error


# データセット を訓練データとテストデータに分割
housing = fetch_california_housing()
x_train, x_test, y_train, y_test = \
  train_test_split(housing.data, housing.target)

# データの正規化
# 正規化 = データの最大値と最小値を制限する変換
normalizer = MinMaxScaler()
# x_trainに対して、平均と分散を計算(fit)して
# 変換(transform)する
x_train = normalizer.fit_transform(x_train)
x_test = normalizer.transform(x_test)

# データをTensor形式に変換する
x = torch.tensor(x_train, dtype=torch.float32)
y = torch.tensor(y_train, dtype=torch.float32)
dataset = TensorDataset(x, y)
loader = DataLoader(dataset, batch_size=40, shuffle=True)

# 確率的勾配降下法(Stochastic Gradient Desent; SGD)

model = nn.Linear(in_features=8, out_features=1)
# 確率的勾配降下法(lr : 学習率(learning rate))
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 平均二乗誤差
mse = nn.MSELoss()

for i in range(10):
  for batch_x, batch_y in loader:
    # 勾配リセット
    optimizer.zero_grad()
    # 予想値を計算
    y_product = model(batch_x)
    # 平均二乗誤差
    loss = mse(y_product.view_as(batch_y), batch_y)
    # 微分して勾配を計算
    loss.backward()
    # パラメータを更新
    optimizer.step()

x = torch.tensor(x_test, dtype=torch.float32)
y_product = model(x).detach().numpy()
print(mean_absolute_error(y_test, y_product))

出力結果

0.6150867488364139

例4:ニューラルネットワーク対応版

import torch
from torch import nn, optim
from torch.utils.data import TensorDataset, DataLoader

# カリフォルニアの住宅価格のデータセット
# https://scikit-learn.org/stable/modules/generated/sklearn.datasets.fetch_california_housing.html
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_absolute_error


# データセット を訓練データとテストデータに分割
housing = fetch_california_housing()
x_train, x_test, y_train, y_test = \
  train_test_split(housing.data, housing.target)

# データの正規化
# 正規化 = データの最大値と最小値を制限する変換
normalizer = MinMaxScaler()
# x_trainに対して、平均と分散を計算(fit)して
# 変換(transform)する
x_train = normalizer.fit_transform(x_train)
x_test = normalizer.transform(x_test)

# データをTensor形式に変換する
x = torch.tensor(x_train, dtype=torch.float32)
y = torch.tensor(y_train, dtype=torch.float32)
dataset = TensorDataset(x, y)
loader = DataLoader(dataset, batch_size=40, shuffle=True)

# 確率的勾配降下法(Stochastic Gradient Desent; SGD)

# ★例3と異なるのはここだけ★
model = nn.Sequential(
  # 入力層から隠れ層
  nn.Linear(8, 10),
  # 活性化関数
  nn.ReLU(),
  # 隠れ層から出力層
  nn.Linear(10, 1)
)
# 確率的勾配降下法(lr : 学習率(learning rate))
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 平均二乗誤差
mse = nn.MSELoss()

for i in range(10):
  for batch_x, batch_y in loader:
    # 勾配リセット
    optimizer.zero_grad()
    # 予想値を計算
    y_product = model(batch_x)
    # 平均二乗誤差
    loss = mse(y_product.view_as(batch_y), batch_y)
    # 微分して勾配を計算
    loss.backward()
    # パラメータを更新
    optimizer.step()

x = torch.tensor(x_test, dtype=torch.float32)
y_product = model(x).detach().numpy()
print(mean_absolute_error(y_test, y_product))

出力結果(精度がよくなっている)

0.5363054261147532

関連記事

PyTorch ~ CNN編 ~
https://dk521123.hatenablog.com/entry/2020/07/13/000000
NumPy ~ 数値計算ライブラリ ~
https://dk521123.hatenablog.com/entry/2018/03/28/224532
Pandas ~ データ解析支援ライブラリ ~
https://dk521123.hatenablog.com/entry/2019/10/22/014957
TensorFlow ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2018/02/16/103500
Keras ~ 深層学習用ライブラリ ~
https://dk521123.hatenablog.com/entry/2020/03/03/235302
Matplotlib ~ グラフ描画ライブラリ ~
https://dk521123.hatenablog.com/entry/2020/03/01/000000
scikit-learn ~ 機械学習用ライブラリ・入門編 ~
https://dk521123.hatenablog.com/entry/2020/03/02/233902
scikit-learn ~ 機械学習用ライブラリ・基本編 ~
https://dk521123.hatenablog.com/entry/2020/03/08/113356
scikit-learn ~ 決定木 / ランダムフォレスト ~
https://dk521123.hatenablog.com/entry/2020/04/04/021413
scikit-learn ~ 線形回帰 ~
https://dk521123.hatenablog.com/entry/2020/07/04/000000
scikit-learn ~ リッジ回帰 ~
https://dk521123.hatenablog.com/entry/2020/04/25/174503