0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

深層学習を用いたトランスクリプトームの分類(実践編)

Last updated at Posted at 2025-02-01

BioinfoにおけるPandas,Matplotlibの基礎

この記事は、Pythonで実践 生命科学データの機械学習 (https://www.yodosha.co.jp/yodobook/book/9784758122634/) の内容を含んでいます。

私は現在バイオインフォマティクス研究室に所属する学生です。
勉強した事をアウトプットする場として用いていますため、何卒ご理解のほどよろしくお願いいたします。
(>人<;)

PyTorchでニューラルネットワークを構築する

⇧前回の記事では、深層学習の基本知識に深掘りを行ないました。
この知識を踏まえて、今回は実際にPuTorchを扱ってみました。

ベースとなる進め方は、

  • モデル構築
  • 訓練データセットで学習
  • 検証データセットで過学習の確認
  • データセットのスコアの確認

この手順になっていきます。
以下は学習段階で疑問に思ったこと、より調べたくなったことを記載していきます!
最初に行ったこと、
1️⃣ データ読み込み
2️⃣ クラスラベル追加
3️⃣ データ分割(学習・検証・テスト)
4️⃣ 特徴量・ラベルの分割
5️⃣ データ標準化

データセットの仕上げとして、データの標準化を行いました。

# 標準化する
from sklearn.preprocessing import StandardScaler

標準化(Standardization)の目的と具体的な処理

標準化の目的

標準化(Standardization)は、機械学習モデルの 学習を安定させる ために重要な前処理です。特に、異なるスケールの特徴量を持つデータを扱う際に役立ちます。

1. 学習の安定化

  • 特徴量のスケールが異なると、モデルが適切に学習できず、特定の特徴量に偏った重みが学習される 可能性がある。
  • :
    • 身長(150〜180cm)
    • 体重(50〜80kg)
    • スケールが異なるため、大きな値の特徴(身長)が学習を支配してしまう。

2. 勾配降下法の最適化

  • ニューラルネットワークや線形回帰などで使用される 勾配降下法(Gradient Descent) の収束を早める。
  • スケールがバラバラだと、学習が非効率になり、最適解への収束が遅くなる。

3. モデルの精度向上

  • 多くの機械学習アルゴリズム(ロジスティック回帰・SVM・k-NN・ニューラルネットワークなど)は、データのスケールに敏感。
  • 標準化を行うことで、モデルの性能が向上する可能性が高い。

具体的に何をしているのか?

① 平均を 0、標準偏差を 1 にする

標準化では、各特徴量を以下の式に従って変換します:

$$
X' = \frac{X - \mu}{\sigma}
$$

  • $(X)$:元の特徴量
  • $(\mu) $:その特徴量の平均
  • $(\sigma) $:その特徴量の標準偏差
  • $(X') $:標準化後の特徴量

② Python(scikit-learn)での標準化の実装

Pythonでは、StandardScaler を使って簡単に標準化できます。

from sklearn.preprocessing import StandardScaler

sc = StandardScaler()  # StandardScalerのインスタンスを作成

# 学習データの平均と標準偏差を計算
sc.fit(X_train)

# トレーニングデータの標準化
X_train_std = sc.transform(X_train)

# 検証データ・テストデータにも同じ変換を適用
X_val_std = sc.transform(X_val)
X_test_std = sc.transform(X_test)

具体例

例:標準化前と標準化後の比較
標準化前

身長 (cm) | 体重 (kg)
---------------------
170      |  65
160      |  55
180      |  75

問題点

身長と体重のスケールが異なる
大きい値(身長)が学習に大きな影響を与える可能性がある
標準化後

身長 (標準化) | 体重 (標準化)
---------------------
 0.0         |  0.0
-1.0         | -1.0
 1.0         |  1.0

すべての特徴量のスケールが揃い、学習が安定!

標準化が必要なアルゴリズム

  • 標準化が重要なモデル
  • ロジスティック回帰
  • SVM(サポートベクターマシン)
  • k近傍法(k-NN)
  • ニューラルネットワーク
  • 主成分分析(PCA)
  • 線形回帰(勾配降下法を用いる場合)

標準化が不要なモデル

  • 決定木(Decision Tree)
  • ランダムフォレスト(Random Forest)
  • XGBoost, LightGBM(勾配ブースティング系)
  • k-means(ただし、特徴量のスケールが大きく異なる場合は必要)

コードの再現性と乱数

# コードに再現性を持たせるために乱数を固定
torch.manual_seed(42)
torch.cuda.manual_seed(42)
torch.backends.cudnn.deterministic = True
torch.use_deterministic_algorithms = True

PyTorch で乱数を固定する方法とその目的

なぜ乱数を固定するのか?

機械学習・ディープラーニングのモデルをトレーニングする際、以下の理由から 乱数の固定(シード設定) は重要です:

1. 再現性の確保
同じコードを実行しても、常に同じ結果が得られるようにする。
モデルの学習結果の一貫性を保ち、デバッグや比較を容易にする。

2. 実験の公平性
複数のモデルを比較する際、ランダムな初期値による影響を排除し、公平な比較を可能にする。
3. バグの発見
結果が毎回変わると、予期しない挙動が起きても原因を特定しづらい。
乱数を固定することで、問題の切り分けがしやすくなる。

次に、PyTorchを学ぶ上での基本文法を示す。

PyTorchのDatasetを使ってデータを管理する

1. Dataset クラスとは?

PyTorchのDatasetクラスを継承して、独自のデータセットを作成します。
これにより、データを簡単に管理でき、DataLoader を使ってバッチ単位でデータを取得できます。


2. クラスの詳細説明

① 訓練 & 検証データ (TrainValData)

class TrainValData(Dataset):
    def __init__(self, X_data, y_data):
        self.X_data = X_data
        self.y_data = y_data
    
    def __getitem__(self, index):
        return self.X_data[index], self.y_data[index]
    
    def __len__(self):
        return len(self.X_data)

X_data (特徴量) と y_data (ラベル) を受け取る
__getitem__index 番目のデータを取得
__len__ でデータの総数を返す

② テストデータ (TestData)

class TestData(Dataset):
    def __init__(self, X_data):
        self.X_data = X_data
    
    def __getitem__(self, index):
        return self.X_data[index]
    
    def __len__(self):
        return len(self.X_data)

y_data (ラベル) を持たない
X_data のみを管理
テストデータを誤って訓練に使用しないための対策


3. データセットの作成

train_data = TrainValData(torch.FloatTensor(X_train_std), torch.FloatTensor(y_train))
val_data = TrainValData(torch.FloatTensor(X_val_std), torch.FloatTensor(y_val))
test_data = TestData(torch.FloatTensor(X_test_std))

torch.FloatTensor(...) に変換し、PyTorchで扱いやすい形に
train_data → 訓練用
val_data → 検証用
test_data → テスト用(ラベルなし)


PyTorch の学習ステップ

PyTorchを用いた学習プロセスは 5 ステップの繰り返し です!

PyTorch における学習の流れ

機械学習の学習ステップは、次の 5つのステップ に分かれます。

  1. 順伝播(forward propagation)
  2. 損失計算(loss calculation)
  3. 勾配の初期化(zero gradients)
  4. 誤差逆伝播(backpropagation)
  5. パラメータ更新(update parameters)

それぞれ わかりやすく 解説していきます!


ステップ1:順伝播(Forward Propagation)

何をするの?

モデルに入力データを与え、ニューラルネットワークを通して 予測値 を計算します。

イメージ

人間の脳に例えると、「問題(入力)」を見て「答え(出力)」を考えるステップです。

PyTorchコード

outputs = model(inputs)  # モデルにデータを入力し、出力を得る

ポイント

  • model(inputs) で、ニューラルネットワークがデータを処理し、予測値を出す。
  • 「前回の学習結果をもとに、どのように予測するか」をニューラルネットワークが考える。

ステップ2:損失計算(Loss Calculation)

何をするの?

モデルの予測 (outputs) と正解ラベル (targets) を比べて、どれだけ間違っているか(損失) を計算します。

イメージ

テストの答案を採点して、「何点間違えたか?」を測るステップ。

PyTorchコード

loss = loss_function(outputs, targets)  # 損失関数で誤差を計算

ポイント

  • loss_function は、例えば MSE(平均二乗誤差)クロスエントロピー損失 を使う。
  • 目標は 損失(誤差)を小さくすること


もし猫の画像を入力したとき、モデルが 「犬」 と予測したら 損失は大きく なります。
逆に 「猫」 と正しく予測したら、損失は 小さく なります。


ステップ3:勾配の初期化(Zero Gradients)

何をするの?

前回の学習の影響を消して、新しく勾配を計算できるようにします。

イメージ

ホワイトボードに前回の計算式が残っていたら、新しい計算ができませんよね?
だから、一旦ホワイトボードを消す ステップです。

PyTorchコード

optimizer.zero_grad()  # 勾配を初期化

ポイント

  • PyTorch は 勾配を累積 する性質があるので、毎回リセットが必要!
  • zero_grad() を忘れると、前の計算の影響で 間違った学習 になる。

ステップ4:誤差逆伝播(Backpropagation)

💡 何をするの?

損失を小さくするために、どの重み(パラメータ)をどれくらい調整すればよいか? を計算します。

イメージ

試験の点数が悪かったとき、「どの問題を間違えたか?」を分析し、次に何を勉強すれば点数が上がるか? を考えるステップ。

PyTorchコード

loss.backward()  # 誤差逆伝播で勾配を計算

ポイント

  • .backward() で、各パラメータが どれくらい損失に影響しているか を計算。
  • これにより、「どの重みをどれくらい変更すればよいか」が分かる。

ステップ5:パラメータ更新(Update Parameters)

何をするの?

計算した勾配を使って、モデルのパラメータ(重み)を更新し、より良い予測ができるようにします。

イメージ

間違えた問題を復習して、次は より良い回答ができるように改善 するステップ。

PyTorchコード

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

ポイント

  • .step() を実行すると、学習率 (lr) に基づいて、パラメータが調整される。
  • これにより、次回の予測が より正しくなる可能性 が高まる。

まとめ:PyTorch の学習プロセス

for epoch in range(num_epochs):  # 学習を複数回繰り返す
    outputs = model(inputs)  # (1) 順伝播
    loss = loss_function(outputs, targets)  # (2) 損失計算

    optimizer.zero_grad()  # (3) 勾配初期化
    loss.backward()  # (4) 誤差逆伝播
    optimizer.step()  # (5) パラメータ更新

PyTorchでニューラルネットワークを作る方法

1. どんなニューラルネットワークを作るの?

今回は 2値分類(Binary Classification) を行う ニューラルネットワーク を定義します!

具体的には、以下の構造を持つ 4層のモデル になります。

入力特徴量 出力特徴量 処理内容
入力層 13 32 線形変換 + Batch Normalization + ReLU
隠れ層1 32 128 線形変換 + Batch Normalization + ReLU
隠れ層2 128 64 線形変換 + Batch Normalization + ReLU
出力層 64 1 線形変換(シグモイドは不要)

特徴

  • nn.Sequential を使って、レイヤーを 簡潔に定義
  • BatchNorm1d を追加して、学習の安定化
  • ReLU を使って 活性化関数 を適用!
  • Binary Classification のため、出力は1つの値(0 or 1 の確率)

2. ニューラルネットワークの定義

では、PyTorchでニューラルネットワークを定義 してみましょう!

torch.nn.Module を継承した BinaryClassificationNet クラスを作成します。

import torch.nn as nn

# 各層のノード数を定義
num_layers = 3
num_features = [32, 128, 64]

# ニューラルネットワークの定義
class BinaryClassificationNet(nn.Module):
    def __init__(self):
        super(BinaryClassificationNet, self).__init__()

        # 入力層(13 -> 32)
        self.layers1 = nn.Sequential(
            nn.Linear(in_features=13, out_features=num_features[0]),
            nn.BatchNorm1d(num_features[0]),  # バッチ正規化
            nn.ReLU(),  # 活性化関数
        )

        # 隠れ層1(32 -> 128)
        self.layers2 = nn.Sequential(
            nn.Linear(in_features=num_features[0], out_features=num_features[1]),
            nn.BatchNorm1d(num_features[1]),
            nn.ReLU(),
        )

        # 隠れ層2(128 -> 64)
        self.layers3 = nn.Sequential(
            nn.Linear(in_features=num_features[1], out_features=num_features[2]),
            nn.BatchNorm1d(num_features[2]),
            nn.ReLU(),
        )

        # 出力層(64 -> 1)
        self.layers_out = nn.Linear(in_features=num_features[2], out_features=1)

    # 順伝播の処理を定義
    def forward(self, x):
        x = self.layers1(x)
        x = self.layers2(x)
        x = self.layers3(x)
        x = self.layers_out(x)
        return x

コードのポイント

  • __init__()各層を定義
  • forward()データを順番に流す処理を記述
  • nn.Sequential を使って、簡潔に記述

3. まとめ

  • nn.Module を継承してニューラルネットワークを定義する方法!
  • nn.Sequential を使って コードを簡潔にするテクニック
  • 2値分類用のモデル構築 に必要なレイヤー(Linear, BatchNorm1d, ReLU)の役割!
  • 順伝播(forward)でデータを流す処理を記述する方法

学習率0.001のAdamオプティマイザとは?

Adamオプティマイザとは?

Adam(Adaptive Moment Estimation)は、機械学習・深層学習で広く使われている最適化アルゴリズムです。
勾配降下法の一種で、学習の進み方を適応的に調整 する特徴があります。

Adamの主なメリット

  • 学習率の調整が不要(自動的に適応)
  • SGD(確率的勾配降下法)より収束が速い
  • 慣性(Momentum)と適応学習率(Adaptive Learning Rate)を組み合わせている

学習率(Learning Rate)とは?

学習率(lr)は、ニューラルネットワークのパラメータ(重み)をどれくらい更新するかを決めるハイパーパラメータです。

学習率 特徴
大きすぎる(例: 0.1) 収束が早いが、最適解を飛び越えてしまい、精度が安定しない可能性がある。
小さすぎる(例: 0.00001) 収束が遅くなり、学習に時間がかかる。最適解にたどり着かないことも。
適切(例: 0.001) 速く安定して学習できる。一般的に推奨される値。

optim.Adam(model.parameters(), lr=0.001) の意味

LEARNING_RATE = 0.001
optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE)

このコードは、以下のような意味を持ちます。

  1. model.parameters():モデルのパラメータ(重み)を最適化の対象とする
  2. optim.Adam(...):Adamオプティマイザを使用する
  3. lr=0.001:学習率を 0.001 に設定(一般的な初期値)

なぜ0.001なのか?

  • Adamオプティマイザのデフォルトの学習率が 0.001 であり、一般的に良い結果が得られるため。
  • 多くの研究・実験で 最適な初期値 として使われている。
  • 必要に応じて 0.00010.01 などに変更してチューニング可能。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?