技術共有

Pytorch (ノート 8 ニューラル ネットワーク nn)

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

1、nn.モジュール

torch.nn は、ディープラーニング用に特別に設計されたモジュールです。 torch.nn の中核となるデータ構造はモジュールです。これは、ニューラル ネットワーク内の特定の層、または多くの層を含むニューラル ネットワークを表すことができる抽象的な概念です。実際に使用する場合、最も一般的なアプローチは、nn.Module を継承し、独自のネットワーク/レイヤーを記述することです。まず、nn.Module を使用して独自の完全接続層を実装する方法を見てみましょう。Y=AX+B

import torch as t
import torch.nn as nn

class network(nn.Module):
    def __init__(self, input, output):
        super().__init__()
        # 定义权重矩阵a,它是一个可训练的参数,形状为(input, output)
        self.a = nn.Parameter(t.randn(input, output))
        # 定义偏置向量b,它也是一个可训练的参数,形状为(output,)
        # 注意:偏置向量的长度应与输出特征的维度相匹配
        self.b = nn.Parameter(t.randn(output))

    def forward(self, x):
        """
        定义前向传播过程

        参数:
            x (torch.Tensor): 输入数据,形状应为(batch_size, input)

        返回:
            torch.Tensor: 输出数据,形状为(batch_size, output)
        """
        # 首先,使用权重矩阵a对输入x进行线性变换
        # [email protected]执行矩阵乘法,x的每一行与a相乘,结果形状为(batch_size, output)
        x = x @ self.a
        # 然后,将偏置向量b扩展(通过broadcasting)到与x相同的形状,并加到x上
        # self.b.expand_as(x)将b的形状从(output,)扩展到(batch_size, output)
        # x + self.b.expand_as(x)将偏置加到每个样本的输出上
        x = x + self.b.expand_as(x)
        # 返回变换后的输出
        return x


a = network(4, 3)
# 创建输入数据,形状为(6, 4),表示有6个样本,每个样本有4个特征
input = t.rand(6, 4)
# 通过网络前向传播得到输出
output = a(input)
# 打印输出,形状应为(6, 3),表示有6个样本,每个样本的输出特征维度为3
print(output)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • カスタム層ネットワークは nn.Module を継承する必要があり、nn.Module のコンストラクターはそのコンストラクター、つまり super() で呼び出す必要があります。初期化() または nn.Module。初期化(自分自身)、最初の使用をお勧めします。
  • コンストラクター __init__ では、学習可能なパラメーターを自分で定義し、パラメーターにカプセル化する必要があります。たとえば、この例では、w と b をパラメーターにカプセル化します。 パラメータは特別な Tensor ですが、デフォルトで導関数が必要です (requires_grad
    = 本当)
  • forward 関数は順伝播プロセスを実装し、その入力は 1 つ以上の Tensor にすることができます。
  • バックプロパゲーション関数を記述する必要はありません。nn.Module は autograd を使用してバックプロパゲーションを自動的に実装できます。これは Function よりもはるかに簡単です。
  • モジュールの学習可能なパラメータは、named_pa​​rameters() またはparameters() を通じてイテレータを返すことができ、前者は各パラメータに名前を付けて識別しやすくします。

2. 一般的に使用されるニューラル ネットワーク層

2.1 画像関連レイヤー

画像関連の層には主に畳み込み層(Conv)、プーリング層(Pool)などがあり、実際にはこれらの層は1次元(1D)、2次元(2D)、3次元(3D)に分けられます。プーリング方式も平均プーリング(AvgPool)、最大プーリング(MaxPool)、適応プーリング(AdaptiveAvgPool)などに分かれます。畳み込み層には一般的に使用される順畳み込みの他に、逆畳み込み(TransposeConv)などもあります。以下に例を示す。

  • 特徴抽出
  • データスペース構造を維持する
  • 非線形変換の導入 畳み込み演算の後、通常、活性化関数 (ReLU、Sigmoid、Tanh など) を適用して非線形変換を導入します。これらの活性化関数により、CNN の表現力が向上し、より複雑な非線形関係を学習できるようになります。
  • 計算効率の向上 畳み込み演算とプーリング層を組み合わせて使用​​することで、畳み込み層は特徴マップの空間次元を削減でき、それによって計算量が削減され、モデルの計算効率が向上します。同時に、プーリング層は特徴の変換不変性も強化し、入力データの小さな変化に対するモデルの堅牢性を高めることもできます。

畳み込み層

深層学習において、画像処理に関連する最も重要なネットワーク構造は畳み込み層 (Conv) です。畳み込みニューラル ネットワークの本質は、畳み込み層、プーリング層、活性化層、その他の層の重ね合わせです。したがって、畳み込み層の動作原理を理解することが非常に重要です。以下に、畳み込み層の具体的なプロセスの例を示します。畳み込み演算。
ここに画像の説明を挿入します

# 导入PyTorch库  
import torch  
import torch.nn as nn  
  
# 从torchvision.transforms导入ToTensor和ToPILImage,用于图像张量和PIL图像之间的转换  
from torchvision.transforms import ToTensor, ToPILImage  
  
# 从PIL(Python Imaging Library,Pillow是其一个分支)导入Image模块,用于处理图像文件  
from PIL import Image  
  
# 使用PIL的Image.open函数打开指定路径的图片文件,并通过.convert("L")将其转换为灰度图像(单通道)  
img = Image.open("H:\PYTHON_Proj\handlearnpytorch\OIP-C.jpg").convert("L")  
  
# 实例化ToTensor转换对象,用于将PIL图像转换为PyTorch张量  
to_tensor = ToTensor()  
  
# 实例化ToPILImage转换对象,用于将PyTorch张量转换回PIL图像  
to_PIL = ToPILImage()  
  
# 使用to_tensor将PIL图像转换为PyTorch张量,并通过.unsqueeze(0)在批次大小维度上增加一个维度,使其形状变为(1, 1, H, W)  
img = to_tensor(img).unsqueeze(0)  
  
# 创建一个3x3的卷积核(滤波器),初始时所有元素都被设置为-1/9,然后将中心元素设置为1  
kernel = torch.ones(3, 3) / (-9.0)  
kernel[1][1] = 1  
  
# 创建一个Conv2d层,指定输入通道数为1(因为是灰度图像),输出通道数也为1,卷积核大小为3x3,步长为1,填充为1(保持输出尺寸与输入相同),且不使用偏置项  
conv = nn.Conv2d(1, 1, 3, 1, 1, bias=False)  
  
# 将之前定义的卷积核赋值给Conv2d层的权重,注意要调整形状以匹配Conv2d层的期望(out_channels, in_channels, kernel_size[0], kernel_size[1])  
conv.weight.data = kernel.reshape(1, 1, 3, 3)  
  
# 对图像应用卷积操作,此时img是一个四维张量,Conv2d层会处理它并返回一个新的四维张量  
img = conv(img)  
  
# 使用to_PIL将卷积后的PyTorch张量转换回PIL图像,并通过.squeeze(0)移除批次大小维度  
img = to_PIL(img.squeeze(0))  
  
# 使用PIL的.show()方法显示图像  
img.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

プーリング層

プーリング層は、主にダウンサンプリングに使用される特別な畳み込み層とみなすことができ、プーリング層を追加すると、主な機能を維持しながらパラメータの数を削減できるため、ある程度の過学習を防ぐことができます。プーリング層には学習可能なパラメータがなく、重みは固定されています。 torch.nn ツールボックスには、最大プーリング (MaxPool) と平均プーリング (AvgPool) などのさまざまなプーリング レイヤーがパッケージ化されています。プーリング レイヤーは、畳み込みニューラル ネットワーク (CNN) で非常に重要な役割を果たします。その主な用途は次のように要約できます。

  • 次元削減 (計算量の削減): プーリング層は、データの空間サイズ (つまり、高さと幅) を削減することで、後続の層の計算量とパラメーターの数を削減します。これは、過学習を防止し、計算を高速化するのに非常に有益です。
  • 特徴の不変性: プーリング層により、モデルはより堅牢な特徴表現、つまり入力データの小さな変化 (平行移動、回転など) に対して不変であることを学習できるようになります。これは、プーリング操作 (最大プーリング、平均プーリングなど) が、特定の位置情報に依存するのではなく、エリア内の代表的なフィーチャを選択するためです。
  • 主要な特徴の抽出: プーリング操作により、いくつかの重要でない詳細を無視しながら、画像内の最も重要な特徴を抽出できます。これは、後続の畳み込み層で高レベルの特徴をさらに抽出するのに役立ちます。
  • 受容野の拡張: ネットワーク層の数が増加するにつれて、プーリング層は後続の層の各ニューロンに対応する入力領域 (つまり、受容野) を徐々に拡張できます。これは、ネットワークがより多くのグローバル機能情報を学習するのに役立ちます。
  • 過学習の削減: プーリング層はデータの空間次元を削減することでパラメーターの数を減らすため、モデルの複雑さをある程度軽減でき、過学習の防止に役立ちます。

一般的なプーリング操作には次のものがあります。

  • 最大プーリング: プーリング ウィンドウ内の最大値を出力として選択します。このアプローチは、画像のエッジとテクスチャ情報を保存するのに役立ちます。
  • 平均プーリング: プーリング ウィンドウ内のすべての値の平均を出力として計算します。このアプローチは、画像の背景情報を保持するのに役立ちます。
  • 確率的プーリング: プーリング ウィンドウ内の各要素の値に基づいて、確率に従って要素が出力としてランダムに選択されます。この方法は、最大プーリングと平均プーリングの利点を組み合わせたものですが、計算の複雑さが高くなります。

つまり、プーリング層は畳み込みニューラル ネットワークの不可欠な部分であり、データの空間次元を削減し、主な特徴を抽出し、受容野を拡張し、過剰適合を防止することにより、ネットワーク全体の学習能力とパフォーマンスを提供します。サポート。

# 导入PyTorch库  
import torch  
  
# 导入PyTorch的神经网络模块,用于构建和训练神经网络  
import torch.nn as nn  
  
# 从torchvision.transforms模块导入ToTensor和ToPILImage,这两个转换工具用于图像数据的预处理和后处理  
from torchvision.transforms import ToTensor, ToPILImage  
  
# 从PIL库导入Image模块,用于图像的打开、显示等操作  
from PIL import Image  
  
# 创建一个ToTensor的实例,用于将PIL图像或numpy.ndarray转换为FloatTensor,并归一化到[0.0, 1.0]  
to_tensor = ToTensor()  
  
# 创建一个ToPILImage的实例,用于将Tensor或ndarray转换为PIL图像  
to_pil = ToPILImage()  
  
# 使用PIL的Image.open方法打开指定路径的图像文件,并将其转换为灰度图像('L'模式)  
img = Image.open("H:\PYTHON_Proj\handlearnpytorch\OIP-C.jpg").convert('L')  
  
# 使用PIL的show方法显示图像  
img.show()  
  
# 使用ToTensor转换将PIL图像转换为Tensor,并增加一个维度使其成为[1, H, W]形状,即增加一个批次维度  
img = to_tensor(img).unsqueeze(0)  
  
# 创建一个平均池化层实例,使用2x2的窗口大小和步长为2进行池化  
pool = nn.AvgPool2d(2, 2)  
  
# 对图像Tensor应用平均池化层,然后移除批次维度(squeeze(0)),使其变回[H', W']形状  
img = pool(img).squeeze(0)  
  
# 将Tensor转换回PIL图像以便显示  
img = to_pil(img)  
  
# 再次使用PIL的show方法显示经过池化处理的图像  
img.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

他の層

畳み込み層とプーリング層に加えて、次の層も深層学習でよく使用されます。

  • 線形: 完全に接続された層。
  • BatchNorm: 1D、2D、3D に分割されたバッチ正規化レイヤー。標準の BatchNorm に加えて、スタイルの移行で一般的に使用される InstanceNorm レイヤーもあります。
  • ドロップアウト: オーバーフィッティングを防ぐために使用されるドロップアウト レイヤーも 1D、2D、3D に分割されます。

3. 初期化戦略

パラメーターの初期化はディープ ラーニングにおいて非常に重要です。適切な初期化により、モデルがより速く収束し、より高いレベルに到達する可能性があります。一方、初期化が不十分な場合は、モデルがすぐに崩壊する可能性があります。 PyTorch の nn.Module のモジュール パラメーターは、より合理的な初期化戦略を採用しているため、通常はそれを考慮する必要はありません。もちろん、カスタム初期化を使用してシステムのデフォルトの初期化を置き換えることもできます。パラメータを使用する場合、カスタム初期化は特に重要です。これは、torch.Tensor() がメモリ内の乱数を返すため、実際のトレーニング ネットワークでオーバーフローやオーバーフローが発生する可能性があります。 。 PyTorch の nn.init モジュールは、初期化用に特別に設計されたモジュールで、一般的に使用される初期化戦略を実装します。特定の初期化戦略が nn.init で提供されていない場合は、ユーザーが自分で直接初期化することもできます。

import torch  
from torch.nn import init  
from torch import nn  
  
# 创建一个线性层,其权重和偏置会被随机初始化(与torch.manual_seed无关,因为这是在调用torch.manual_seed之前发生的)  
linear = nn.Linear(3, 4)  
  
# 打印层创建时默认初始化的权重  
print("默认初始化的权重:")  
print(linear.weight)  
  
# 设置随机数生成的种子,以确保接下来的随机数生成是可重复的  
torch.manual_seed(2021)  
  
# 使用Xavier正态分布重新初始化权重  
# 这个初始化是受torch.manual_seed(2021)影响的  
init.xavier_normal_(linear.weight)  
  
# 打印重新初始化后的权重  
print("Xavier正态分布初始化后的权重:")  
print(linear.weight)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21