学習時期:2022.04.12~2022.04.14
環境構成:Anaconda(Python 3.8) + PyCharm
記事ディレクトリ
3. 畳み込みニューラルネットワーク CNN
上記「 学習メモ:深層学習(3) - 畳み込みニューラルネットワーク(CNN)理論 」の続きです。
3.5 PyTorch を使用した深層学習モデルの構築
このセクションは大きく 3 つの部分で構成されており、最初はモデルを構築するための PyTorch の一般的な理解、次に PyTorch を使用した簡単な CV プロジェクトの実行、最後に CNN を使用したタイタニック号の予測を試してみます。
この部分の主な情報源:深層学習モデルを構築するにはどのような手順が必要ですか? 、pytorch、quickstart_tutorialを学ぶのに1時間。
PyTorch: これは、次の 2 種類のユーザーにサービスを提供することに特化した Python ベースの科学計算ライブラリです。
- ニューラル ネットワークを構築するために Numpy の代替手段を探している一部のユーザー。
- 極めて優れたスケーラビリティとスピードを提供する深層学習研究プラットフォームを探しています。
3.5.1 テンソル
PyTorch のテンソルの概念は、Numpy の N 次元配列 (ndarray) の概念に非常に似ており、これを基礎として、テンソルを GPU 上で実行して計算を高速化することもできます。
テンソル、行列、ベクトルの違い:
まず、テンソルの次元数はテンソルの次数と同等です。
0 次元テンソルはスカラー、1 次元テンソルはベクトル、2 次元テンソルは行列、3 次元以上のテンソルには名前がなく、総称してテンソルと呼ばれます。以下に例を示します。
- スカラー: 非常に単純で、1、2、5、108 などの数値です。
- ベクトル: [1,2]、[1,2,3]、[1,2,3,4]、[3,5,67,....................,n] はすべてベクトルです
- マトリックス: [[1,3],[3,5]]、[[1,2,3]、[2,3,4]、[3,4,5]]、[[4,5,6, 7,8]、[3,4,7,8,9]、[2,11,34,56,18]] は行列です
- 3 次元テンソル: [[[1,2],[3,4]],[[1,2],[3,4]]]
しかし、ここで混乱が生じます、つまり、数学では 3 次元ベクトルと n 次元ベクトルが使用されますが、これは実際には 1 次元テンソル (つまりベクトル) の形状、つまり次の数を指します。含まれるコンポーネント
([ 1 ,3] など) このベクトルの次元は 2 で、1 と 3 の 2 つのコンポーネントがあります。[1,2,3, …,4096] このベクトルの次元は次のとおりです。4096, it has 1, 2 ......4096 4096 の成分は
すべてベクトルの形状です。「テンソル」[1,3] の次元が 2 であるとは言えず、「1 次元テンソル」[1,3] の次元が 2 であるとしか言えません。
次元は、テンソルの左端にある左括弧の数によって決まります。n 個ある場合、このテンソルは n 次元テンソルです
(1) テンソルの生成
- torch.empty は、初期化されていないデータで満たされたテンソルを作成します。(すべて0ではありません)
torch.empty(*size, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False, pin_memory=False, memory_format=torch.contiguous_format)
このうちサイズは(1, 2, 3, ...)のような形式で指定され、最初の数字は最外層の番号、2番目の数字は2番目の外層の番号を表します、そして 3 番目の数字は 3 番目の層の番号を表します...
dtype はテンソルの必要なデータ型を指定します (「torch.dtype」の形式で); device はテンソルの必要なデバイスを指定します (デフォルトは設定されています)現在のデバイスに応じて)
import torch
x = torch.empty(5, 3)
print(x)
'''
tensor([[2.7712e+35, 4.5886e-41, 7.2927e-04],
[3.0780e-41, 3.8725e+35, 4.5886e-41],
[4.4446e-17, 4.5886e-41, 3.9665e+35],
[4.5886e-41, 3.9648e+35, 4.5886e-41],
[3.8722e+35, 4.5886e-41, 4.4446e-17]])
'''
- torch.rand は、各要素が 0 から 1 の範囲にある、初期化された均一に分散されたテンソルを生成します。
torch.rand(*size, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
x = torch.rand(2, 3, 2)
print(x)
'''
tensor([[[0.7350, 0.1058],
[0.1558, 0.3330],
[0.9874, 0.9351]],
[[0.6613, 0.4773],
[0.9103, 0.2991],
[0.6107, 0.5941]]])
'''
- torch.zeros は、すべてゼロの初期化されたテンソルを生成します。
torch.zeros(*size, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
x = torch.zeros(3, 2, 4, dtype=torch.long)
print(x)
'''
tensor([[[0, 0, 0, 0],
[0, 0, 0, 0]],
[[0, 0, 0, 0],
[0, 0, 0, 0]],
[[0, 0, 0, 0],
[0, 0, 0, 0]]])
'''
- torch.tensor はコピーしてテンソルを作成します。
torch.tensor(data, *, dtype=None, device=None, requires_grad=False, pin_memory=False)
data はテンソルの初期データです。リスト、タプル、NumPy、スカラー、その他の型を使用できます。
x = torch.tensor([[5, 3], [6, 8], [7, 1]])
print(x)
'''
tensor([[5, 3],
[6, 8],
[7, 1]])
'''
- Tensor.new_ones(既存のテンソルから) は、1 で満たされたテンソルを返します。
Tensor.new_ones(size, dtype=None, device=None, requires_grad=False)
size は、出力テンソルの形状を定義するリスト、タプル、または整数です。デフォルトでは、返される Tensor は既存の Tensor と同じ torch.dtype および torch.device を持ちます。
x = torch.tensor([[2, 2, 2], [2, 2, 2]])
x = x.new_ones(2, 3)
print(x)
'''
tensor([[1, 1, 1],
[1, 1, 1]])
'''
- torch.randn_like は、平均 0、分散 1 の正規分布からの乱数で満たされた入力テンソルと同じサイズのテンソルを生成します。
torch.randn_like(input, *, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preserve_format)
x = torch.tensor([[2, 2, 2], [2, 2, 2]])
x = torch.rand_like(x, dtype=torch.float)
print(x)
'''
tensor([[0.9673, 0.5070, 0.2757],
[0.0980, 0.1018, 0.4406]])
'''
(2) テンソル演算
このセクションでは 4 つの基本操作を示します。詳細なリンクはここにあります。
- Tensor.size はテンソルの形状を取得します。
Tensor.size(dim=None)
ヒント: torch.Size はタプルなので、タプル操作もサポートします。
x = torch.tensor([[2, 2, 2], [2, 2, 2]])
print(x.size())
'''
torch.Size([2, 3])
'''
- Tensor.item は、テンソルの値 (テンソルのサイズ) を表示する
ときに、単一のテンソルの値のみを表示できます。
x = torch.randn(1)
print(x.item())
y = torch.randn(4)
print(x[:2].item())
'''
-0.2167293280363083
-0.2167293280363083
'''
- テンソルを再形成する Tensor.view は、
Tensor.view(*shape)
テンソルと同じデータを持つ新しいテンソルを返しますが、形状は異なります。
返されるテンソルは同じデータを共有し、同じ数の要素を持つ必要がありますが、異なるサイズを持つ可能性があります。
x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8) # -1是由别的维度推断出来的
f = x.view(2, 8)
print(x.size(), y.size(), z.size(), f.size())
'''
torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8]) torch.Size([2, 8])
'''
- torch.add 加算演算
torch.add(input, other, *, alpha=1, out=None)
input は加算されるテンソル、other は加算されるテンソルまたは数値、alpha は other のスケーリング比 (デフォルトではスケーリングなし)、out は出力に対して追加で指定できるパラメータです結果の。
さらに、tensor は次のような演算子もサポートしています。print(x + y)
x = torch.zeros(5, 3)
y = torch.ones_like(x)
z = torch.empty(5, 3)
torch.add(x, y, out=z)
print('-------------\n', z)
torch.add(x, 20, out=z)
print('-------------\n', z)
'''
-------------
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
-------------
tensor([[20., 20., 20.],
[20., 20., 20.],
[20., 20., 20.],
[20., 20., 20.],
[20., 20., 20.]])
Process finished with exit code 0
'''
または、追加のバリアントを使用します。Tensor.add_(other, *, alpha=1)
すべての自己置換演算子の末尾にある「_」に注意してください。
また、出力方法もPython風にすることも可能です。
x.add_(y)
print(x)
'''
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
'''
print(x[:, 1])
'''
tensor([1., 1., 1., 1., 1.])
'''
- Tensor と Numpy の間の変換
- テンソルから Nump:
Tensor.numpy()
。 - Numpy から Tensor:
torch.from_numpy(ndarray)
。
CPU を使用する場合、テンソルと配列は物理的な位置を共有し、一方の値を変更すると他方も変更されます。
a = torch.ones(5) # torch.ones返回一个填充有标量值1的张量,其形状由变量参数size定义。
b = a.numpy()
print(a, '\n', b)
'''
tensor([1., 1., 1., 1., 1.])
[1. 1. 1. 1. 1.]
'''
c = torch.from_numpy(b)
print(b, '\n', c)
'''
[1. 1. 1. 1. 1.]
tensor([1., 1., 1., 1., 1.])
'''
3.5.2 自動微分
pytorch では、ニューラル ネットワークの中心となるのは自動微分であり、このセクションではこの部分を検討し、小さなニューラル ネットワークをトレーニングします。
自動微分パッケージは自動微分操作を提供します。これは各ラウンドの操作に依存するライブラリです。次の結果は、最後のラウンドで実行したコードに関連します。したがって、各ラウンドの結果は次のとおりになる可能性があります。違う。
torch.Tensor はこのパッケージのコア クラスであり、パラメータを設定すると.requires_grad=true
、この tensor に対するすべての操作の追跡が開始されます。計算が完了したら、呼び出してbackwward()
すべての導関数を計算できます。このベクトルの勾配は、grad
このプロパティに自動的に保存されます。
テンソルが履歴データを追跡しないようにしたい場合は、テンソルを呼び出してdetach()
計算履歴から分離することができます。もちろん、将来の計算データはすべて保存されません。with torch.no_grad()
または、 を使用してコード ブロックを呼び出すことができます。これにより、勾配計算が阻止されるだけでなく、記憶域の使用も回避されます。モデル勾配計算のこのプロパティはデフォルトで有効になっているため、これはモデルを計算するときに非常に役立ちます。、そして私たちはおそらくそうではありません。
2 番目の非常に重要なクラスは Function、Tensor、および Function です。これら 2 つは相互接続されており、非周期操作グラフを構築できます。
各 tensor にはgrad_fn
プロパティがあり、Function を呼び出して Tensor を作成できます。もちろん、ユーザーが自分で Tensor を作成する場合、このプロパティは自動的に None に設定されます。
導出された量を計算したい場合は、.backward()
Tensor でそれを呼び出すことができます。Tensor が純粋な数値である場合は、パラメーターを指定する必要はありません。純粋な数値でない場合は、パラメーターを指定する必要があります。テンソルの形状と一致する 勾配パラメータ。いくつかの例を見てみましょう。
import torch
x = torch.ones(2, 2, requires_grad=True)
print(x)
"""
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
"""
y = x + 2
print(y)
"""
tensor([[3., 3.],
[3., 3.]], grad_fn=<AddBackward0>)
"""
print(y.grad_fn)
"""
<AddBackward0 object at 0x7fc6bd199ac8>
"""
z = y * y * 3
out = z.mean()
print(z, out)
"""
tensor([[27., 27.],
[27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)
"""
a = torch.randn(2, 2)
a = ((a * 3) / (a - 1))
print(a.requires_grad)
a.requires_grad_(True)
print(a.requires_grad)
b = (a * a).sum()
print(b.grad_fn)
"""
False
True
<SumBackward0 object at 0x7fc6bd1b02e8>
"""
3.5.3 オプティマイザークラス
オプティマイザーは、一般的な確率的勾配降下法 (SGD) など、パラメーターを更新するためにトーチがカプセル化するメソッドとして理解できます。
オプティマイザー クラスはtorch.optim
、たとえば次のように提供されます。
- torch.optim.SGD(パラメータ、学習率)
- torch.optim.Adam(パラメータ、学習率)
知らせ:
model.parameters()
パラメータは、モデル内のすべてのrequires_grad=True
パラメータを取得するために使用して取得できます。- 最適化クラスの使用方法: インスタンス化 → すべてのパラメーターの勾配、値を 0 に設定 → バックプロパゲーションで勾配を計算 → パラメーター値を更新
from torch import optim
optimizer = optim.SGD(model.parameters(), lr=1e-3) # 1. 实例化
optimizer.zero_grad() # 2. 梯度置为0
loss.backward() # 3. 计算梯度
optimizer.step() # 4. 更新参数的值
3.5.4 損失関数
torch では、回帰問題でよく使用される平均二乗誤差: nn.MSELoss()
、分類問題でよく使用されるクロスエントロピー損失:などnn.CrossEntropyLoss()
、多くの損失関数も予測されます。
手順:
model = Lr() #1. 实例化模型
criterion = nn.MSELoss() # 2. 实例化损失函数
optimizer = optim.SGD(model.parameters(), lr=1e-3) #3. 实例化优化器类
for i in range(100):
y_predict = model(x_true) # 4. 向前计算预测值
loss = criterion(y_true,y_predict) # 5. 调用损失函数传入真实值和预测值,得到损失结果
optimizer.zero_grad() # 5. 当前循环参数梯度置为0
loss.backward() # 6. 计算梯度
optimizer.step() # 7. 更新参数的值
3.5.5 GPU でのコードの実行
モデルが大きすぎる場合やパラメータが多すぎる場合、トレーニングを高速化するために GPU がトレーニングに使用されることがよくあります。この時点で、コードを少し調整する必要があります。
- GPU が利用可能かどうかを確認します
torch.cuda.is_available()
。
import torch
print(torch.device("cuda:0" if torch.cuda.is_available() else "cpu"))
'''
输出:
cuda:0 # 是使用gpu
cpu # 是使用cpu
'''
- モデルパラメーターと入力データを cuda サポートタイプに変換します。
model.to(device) # device是cpu或cuda
x_true.to(device)
- GPU 上の計算結果も cuda のデータ型なので、これを numpy または torch の CPU のテンソル型に変換する必要があります。
predict = predict.cpu().detach().numpy()
3.5.6 深層学習モデルの構築
深層学習モデルの構築は、データセットの準備、モデル定義、モデルのトレーニングの 3 つのステップに分けることもできます。
(1) データセットの準備
理論的には、ディープ ラーニングでのデータ セットの準備と古典的な機械学習でのデータ セットの準備の間に本質的な違いはありません。これは一般に、特定のデータに基づいてサンプルとラベルを構築するプロセスです。ここでのサンプルは、さまざまなアプリケーション シナリオに応じて異なります。さまざまなスタイルたとえば、CV 分野では写真が一般的ですが、NLP 分野ではテキストの段落が一般的です。
ただし、元のサンプルが何であっても、最終的には数値テンソルに変換する必要があります。
もちろん、データ セットを Tensor に変換した後、理論的には深層学習モデルの入力とトレーニングに使用できますが、大規模なデータ セットでのモデル トレーニングとバッチ トレーニングをより適切にサポートするために、PyTorch は標準のデータ セット タイプ (Dataset) を提供します。であり、通常はこのクラスを継承してこの形式を提供します。一般的に使用される 3 つのデータセット関連クラスを次に示します。
- データセット: すべてのカスタム データセットの基本クラス。
- TensorDataset: Dataset のラッパー (カプセル化)。Dataset を迅速に構築するために使用されます。
- DataLoader: Dataset を複数のバッチに自動的に分割する Dataset のラッパー
1. データセット
Dataset は PyTorch で提供されるデータセットの基本クラスですが、まず Dataset の署名ドキュメントを以下のように確認します。
[docs]class Dataset(Generic[T_co]):
r"""An abstract class representing a :class:`Dataset`.
All datasets that represent a map from keys to data samples should subclass
it. All subclasses should overwrite :meth:`__getitem__`, supporting fetching a
data sample for a given key. Subclasses could also optionally overwrite
:meth:`__len__`, which is expected to return the size of the dataset by many
:class:`~torch.utils.data.Sampler` implementations and the default options
of :class:`~torch.utils.data.DataLoader`.
.. note::
:class:`~torch.utils.data.DataLoader` by default constructs a index
sampler that yields integral indices. To make it work with a map-style
dataset with non-integral indices/keys, a custom sampler must be provided.
"""
def __getitem__(self, index) -> T_co:
raise NotImplementedError
def __add__(self, other: 'Dataset[T_co]') -> 'ConcatDataset[T_co]':
return ConcatDataset([self, other])
# No `def __len__(self)` default?
# See NOTE [ Lack of Default `__len__` in Python Abstract Base Classes ]
# in pytorch/torch/utils/data/sampler.py
torch.utils.data.Dataset(*args, **kwds)
データセットを表す抽象クラス。
このことから、すべてのカスタム データ セットはこのクラスを継承し、__getitem__ と __len__ の 2 つのメソッドをオーバーロードする必要があることがわかります。後者はデータ全体のサイズを取得し、前者はインデックスに相当するデータを取得します。
もちろん、ロードするデータはクラス初期化メソッド __init__ を通じて設定する必要があります。データセットのカスタマイズの一般的な実装は次のとおりです。
class MyDataset(Dataset):
def __init__(self, x, y):
super().__init__()
……
def __getitem__(self):
return ……
def __len__(self):
return ……
2. TensorDataset
Dataset の上記のメソッドは標準的なカスタム データ セットの構築を実現できますが、比較的単純なデータ セットに対してステレオタイプのように __getitem__ と __len__ の 2 つのメソッドをオーバーロードする必要がある場合、必然的に少し複雑で決まり文句になります。TensorDataset は上記の要件を簡素化したものです。つまり、特定のテンソルをカスタム データセットとして Dataset 型にラップする必要がある場合のみ、TensorDataset を直接使用できます。
ここではまだその署名文書が最初に示されています。
[docs]class TensorDataset(Dataset[Tuple[Tensor, ...]]):
r"""Dataset wrapping tensors.
Each sample will be retrieved by indexing tensors along the first dimension.
Args:
*tensors (Tensor): tensors that have the same size of the first dimension.
"""
tensors: Tuple[Tensor, ...]
def __init__(self, *tensors: Tensor) -> None:
assert all(tensors[0].size(0) == tensor.size(0) for tensor in tensors), "Size mismatch between tensors"
self.tensors = tensors
def __getitem__(self, index):
return tuple(tensor[index] for tensor in self.tensors)
def __len__(self):
return self.tensors[0].size(0)
torch.utils.data.TensorDataset(*tensors)
*tensors
最初の次元と同じサイズのテンソルが必要です。
特定のアプリケーションでは、いくつかのテンソル形式の入力をパラメーターとして TensorDataset に渡し、その結果を標準の Dataset タイプのデータセットとして返すだけで済みます。標準的な使用方法は次のとおりです。
my_dataset = TensorDataset(tenso_x, tensor_y)
3. データローダー
ディープ ラーニングは大規模なデータ セットのシナリオに適用できることが多く、成熟したディープ ラーニング モデルのトレーニングには通常、十分な量のデータが必要です。
したがって、深層学習トレーニングのプロセスでは、一般に、毎回一度にすべてのトレーニング セット データをモデルにフィードするのではなく、小さなバッチとバッチでトレーニングします。各バッチはバッチと呼ばれ、完全なトレーニングはセットは 1 回だけ参加します。トレーニングはエポックと呼ばれます。小さなバッチや複数のバッチを実装するにはさまざまな方法があります。たとえば、この作業はインデックス フラグメントをランダムに選択することで実現できますが、より標準的で洗練された方法は、データローダーを使用することです。
それによって与えられた署名文書は次のように抜粋されます。
[docs]class DataLoader(Generic[T_co]):
r"""
Data loader. Combines a dataset and a sampler, and provides an iterable over
the given dataset.
The :class:`~torch.utils.data.DataLoader` supports both map-style and
iterable-style datasets with single- or multi-process loading, customizing
loading order and optional automatic batching (collation) and memory pinning.
See :py:mod:`torch.utils.data` documentation page for more details.
……
torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False, sampler=None, batch_sampler=None, num_workers=0, collate_fn=None, pin_memory=False, drop_last=False, timeout=0, worker_init_fn=None, multiprocessing_context=None, generator=None, *, prefetch_factor=2, persistent_workers=False)
データローダー。データセットとサンプラーを結合し、指定されたデータセットに対して反復可能を提供します。
DataLoader は、単一または複数プロセスの読み込み、カスタム読み込み順序、およびオプションの自動バッチ処理 (照合) とメモリ固定を備えた、マップ スタイルおよび反復可能スタイルのデータセットをサポートします。
-
batch_size (整数、オプション) – バッチごとにロードするサンプルの数 (デフォルト: 1)。
-
shuffle (bool、オプション) – 反復ごとにデータをシャッフルする場合は True (デフォルト: False)。
DataLoader は、データセットのランダム サンプリング (サンプラー) を実装し、指定されたデータセットに反復可能な型を提供することとほぼ同等であることがわかります。それに応じて、その使用法は比較的簡単です。Dataset タイプのデータセットをパラメータとして DataLoader に直接渡すだけです。
簡単な使用例は次のとおりです。
dataloader = DataLoader(MyDataset, batch_size=128, shuffle=True)
上記は、PyTorch を使用してデータ セットを構築するときに一般的に使用される 3 つの操作であり、基本的に日常使用のニーズのほとんどをカバーできます。後で実際のケースで十分に説明します。
(2) ネットワークアーキテクチャの定義
深層学習と古典的機械学習の最大の違いの 1 つは、モデルの構造にあります。古典的な機械学習モデルは、多くの場合、固定されたパラダイムと構造を持っています。たとえば、ランダム フォレストは、指定された数の決定木で構成されます。ただし、ここでの n_estimators は、オプションにすることもできますが、全体として、ランダム フォレスト モデルの構造は明確です。一方、深層学習モデルの基礎はニューラル ネットワークにあり、複数のニューラル ネットワーク層とニューラル ネットワーク モジュールの種類で構成されます。各層で使用されるニューロンは異なる場合があり (完全接続層、畳み込み層など)、含まれるニューロンの数の違いも大きな違いを生む可能性があります。
このため、ディープラーニングはユーザーに設計革新のためのより大きなスペースを提供します。
もちろん、ネットワークアーキテクチャ(Architecture)の設計をゼロから始める必要はなく、PyTorchなどのディープラーニングフレームワークの主な機能は、基本的なニューラルネットワークモジュール(Module)を提供することであり、ユーザーはそれを柔軟に組み立てるだけで済みます。積み木のように、ただ立ち上がるだけです。PyTorch のすべてのネットワーク モジュールは、torch.nn モジュール (nn=nueral network) の下にあります。詳細については、 https://pytorch.org/docs/stable/nn.htmlを参照してください。
これらのモジュールは膨大な数があり、さまざまな機能を持ち、深層学習モデルの中核を形成します。ただし、その機能に関しては、次のカテゴリに大別できます。
- モデル関数クラス: Linear、Conv2d、RNN など、全結合層、畳み込み層、サイクリック ニューラル ネットワーク層に対応します。
- 活性化関数: Sigmoid、Tanh、ReLU など。
- 損失関数: CrossEntropyLoss、MSELoss など。前者は分類によく使用される損失関数であり、後者は回帰によく使用される損失関数です。
- 正規化: LayerNorm など。
- オーバーフィッティングを防止: ドロップアウトなど。
- 他の。
これらの基本的なネットワークモジュールとそれぞれの機能や利用方法を理解し、使いこなすことがディープラーニングの学習の主体となり、これをベースに、データやシナリオの理解に合わせてネットワークアーキテクチャの設計をカスタマイズすることができます。 、期待されるモデル効果を達成するために。
これらの個々のネットワーク モジュールに基づいて、構築された完全なネットワーク モデルは、PyTorch で Module クラスを継承することによって実装する必要があります (このプロセスは、カスタム データセットを実装するための Dataset クラスの継承に似ています)。モジュールの署名ドキュメントは次のとおりです。まだここに与えられています:
class Module:
r"""Base class for all neural network modules.
Your models should also subclass this class.
Modules can also contain other Modules, allowing to nest them in
a tree structure. You can assign the submodules as regular attributes::
import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 20, 5)
self.conv2 = nn.Conv2d(20, 20, 5)
def forward(self, x):
x = F.relu(self.conv1(x))
return F.relu(self.conv2(x))
Submodules assigned in this way will be registered, and will have their
parameters converted too when you call :meth:`to`, etc.
.. note::
As per the example above, an ``__init__()`` call to the parent class
must be made before assignment on the child.
:ivar training: Boolean represents whether this module is in training or
evaluation mode.
:vartype training: bool
"""
このことから、すべてのカスタム ネットワーク モデルは Module クラスを継承する必要があり、一般に、たとえば次のように、forward 関数 (ニューラル ネットワークの順伝播プロセスの実装に使用される) を書き直す必要があることがわかります。
その後、モデルが登録され、対応するトレーニング可能なパラメーターが設定されます。
ネットワークをカスタマイズする場合、特別な注意が必要な方法が 2 つあります。
- __init__ は、親クラスのプロパティとメソッドを継承するためにスーパー メソッドを呼び出す必要があります。
- ネットワークの前方計算プロセスを定義するには、farward メソッドを実装する必要があります。
import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 20, 5)
self.conv2 = nn.Conv2d(20, 20, 5)
def forward(self, x):
x = F.relu(self.conv1(x))
return F.relu(self.conv2(x))
(3) モデルのトレーニング
古典的な機械学習モデルのトレーニングとは依然として異なります。深層学習モデルのネットワーク アーキテクチャは一般にカスタム設計されているため、一般に、単純に Fit/
Predict を呼び出して簡潔なモデルのトレーニング/予測プロセスを実現することはできず、多くの場合ハンドオーバーが実装されます。ユーザー自身による。
一般に、モデル トレーニングの実装には主に次の要素が含まれます。
- データセットの準備を完了します。
- ネットワークモデルを定義します。
- 損失関数を指定して、指定したデータセットで現在のモデルのパフォーマンスを評価します。
- モデルを望ましい方向に「ガイド」するオプティマイザーを指定します。
- モデルトレーニングの反復と進化を実現するサイクルスケジュールを作成します。
データセットの準備とモデルの定義は前の 2 つのセクションで説明した内容ですが、損失関数については、単純な要件は PyTorch が提供する共通の損失関数に基づくことができ、より複雑で個別の損失関数は
、関数は、Module クラスを継承することでカスタマイズできます。実装を定義します。オプティマイザ部分には、説明するほど多くの「トリック」はありません。通常は
、Adam、SGD などの組み込みオプティマイザを直接呼び出すだけです。これらの操作を実際の事例とともに紹介します。
(4) 単純な深層学習のケース
前のセクションの理論的基礎を使用して、ディープ ラーニングの実践ケースを開始できます。ここでは、sklearn に付属する手書きの数字分類を練習の目標として使用します。
- まずデータをロードします。
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
X, y = load_digits(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y)
- Dataset タイプのデータセットを構築します。
import torch
from torch.utils.data import TensorDataset, DataLoader
X_train_tensor = torch.Tensor(X_train)
y_train_tensor = torch.Tensor(y_train).long() # 主要标签需要用整数形式,否则后续用于计算交叉熵损失时报错
dataset = TensorDataset(X_train_tensor, y_train_tensor) # 直接调用TensorDataset加以包裹使用
dataloader = DataLoader(dataset, batch_size=128, shuffle=True) # 每128个样本为一个batch,训练时设为随机
X_test_tensor = torch.Tensor(X_test) # 测试集只需转化为tensor即可
y_test_tensor = torch.Tensor(y_test).long()
- 線形ネットワーク層のみを使用するネットワーク モデルをカスタマイズします。
from torch import nn, optim
class Model(nn.Module): # 继承Module基类
def __init__(self, n_input=64, n_hidden=32, n_output=10):
# 定义一个含有单隐藏层的全连接网络,其中输入64为手写数字数据集的特征数,输出10为类别数,隐藏层神经元数量设置32
super().__init__() # 对继承自父类nn.Module的属性进行初始化。而且是用nn.Module的初始化方法来初始化继承的属性。(也可用自己的方法)
# 使用全连接层和ReLU激活函数搭建网络模型
self.dnn = nn.Sequential(
nn.Linear(n_input, n_hidden), # nn.Linear为torch预定义好的线性模型,也被称为全链接层,
nn.ReLU(),
nn.Linear(n_hidden, n_output) # Linear传入的参数为输入的数量(特征数、列数),输出的数量(in_features, out_features)
)
def forward(self, x):
# 重载forward函数,从输入到输出
return self.dnn(x)
- ステレオタイプ スタイルの深層学習トレーニング プロセス:
model = Model() # 初始化模型
creterion = nn.CrossEntropyLoss() # 选用交叉熵损失函数
optimizer = optim.Adam(model.parameters(), lr=0.001) # 选用Adam优化器,传入模型参数,设置学习率
for epoch in range(50): # 50个epoch
for data, label in dataloader: # DataLoader是一个可迭代对象
optimizer.zero_grad() # 待优化参数梯度清空
prob = model(data) # 执行一次前向传播,计算预测结果
loss = creterion(prob, label) # 评估模型损失
loss.backward() # 损失反向传播,完成对待优化参数的梯度求解
optimizer.step() # 参数更新
if (epoch + 1) % 5 == 0: # 每隔5个epoch打印当前模型训练效果
with torch.no_grad():
train_prob = model(X_train_tensor)
train_pred = train_prob.argmax(dim=1)
acc_train = (train_pred == y_train_tensor).float().mean()
test_prob = model(X_test_tensor)
test_pred = test_prob.argmax(dim=1)
acc_test = (test_pred == y_test_tensor).float().mean()
print(f"epoch: {
epoch}, train_accuracy: {
acc_train}, test_accuracy: {
acc_test} !")
出力:
epoch: 4, train_accuracy: 0.8507795333862305, test_accuracy: 0.8577777743339539 !
epoch: 9, train_accuracy: 0.948775053024292, test_accuracy: 0.9200000166893005 !
epoch: 14, train_accuracy: 0.9717891812324524, test_accuracy: 0.9444444179534912 !
epoch: 19, train_accuracy: 0.9799554347991943, test_accuracy: 0.9577777981758118 !
epoch: 24, train_accuracy: 0.9866369962692261, test_accuracy: 0.9644444584846497 !
epoch: 29, train_accuracy: 0.9925761222839355, test_accuracy: 0.9644444584846497 !
epoch: 34, train_accuracy: 0.9925761222839355, test_accuracy: 0.9644444584846497 !
epoch: 39, train_accuracy: 0.9962880611419678, test_accuracy: 0.9666666388511658 !
epoch: 44, train_accuracy: 0.9970304369926453, test_accuracy: 0.9711111187934875 !
epoch: 49, train_accuracy: 0.9970304369926453, test_accuracy: 0.9711111187934875 !
3.6 LeNet-5 を使用した手書き数字の分類
上記の部分に基づいて、LeNet5 を選択して手書き数字分類タスクを試し、モデルがこの畳み込み演算をどのように使用するかを確認します。
- 1 つ目は mnist データ セットの準備です。これは、torchvision パッケージを使用してオンラインで直接ダウンロードできます。
from torchvision import datasets
from torch.utils.data import DataLoader, TensorDataset
train = datasets.MNIST('data/', download=True, train=True) # 从库中导出数据
test = datasets.MNIST('data/', download=True, train=False)
X_train = train.data.unsqueeze(1) / 255.0
y_train = train.targets
trainloader = DataLoader(TensorDataset(X_train, y_train), batch_size=256, shuffle=True)
X_test = test.data.unsqueeze(1) / 255.0
y_test = test.targets
- 次に、LeNet5 のネットワーク モデルがあります (いくつかの古典的なモデルは torchvision に組み込まれていますが、LeNet5 は比較的単純であるため含まれていません)。
import torch
from torch import nn, optim
import torch.nn.functional as F
class LeNet5(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 6, 5, padding=2)
self.pool1 = nn.MaxPool2d((2, 2))
self.conv2 = nn.Conv2d(6, 16, 5)
self.pool2 = nn.MaxPool2d((2, 2))
self.fc1 = nn.Linear(16*5*5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = F.relu(self.conv1(x))
x = self.pool1(x)
x = F.relu(self.conv2(x))
x = self.pool2(x)
x = x.view(len(x), -1)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
- 最後に、モデルのトレーニング プロセス:
model = LeNet5()
optimizer = optim.Adam(model.parameters())
criterion = nn.CrossEntropyLoss()
for epoch in range(10):
for X, y in trainloader:
pred = model(X)
loss = criterion(pred, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
with torch.no_grad():
y_pred = model(X_train)
acc_train = (y_pred.argmax(dim=1) == y_train).float().mean().item()
y_pred = model(X_test)
acc_test = (y_pred.argmax(dim=1) == y_test).float().mean().item()
print(epoch, acc_train, acc_test)
出力:
0 0.9371833205223083 0.9401000142097473
1 0.9669833183288574 0.9700000286102295
2 0.9770166873931885 0.9786999821662903
3 0.9809166789054871 0.9832000136375427
4 0.9846000075340271 0.9857000112533569
5 0.9866999983787537 0.9868000149726868
6 0.9891166687011719 0.9873999953269958
7 0.989983320236206 0.9882000088691711
8 0.9918333292007446 0.989799976348877
9 0.9908999800682068 0.9890000224113464
最後に、torchinfo パッケージを使用してモデルの構造を表示できます。
from torchinfo import summary
model = LeNet5()
batch_size = 256
summary(model, input_size=(batch_size, 1, 28, 28))
出力:
==========================================================================================
Layer (type:depth-idx) Output Shape Param #
==========================================================================================
LeNet5 -- --
├─Conv2d: 1-1 [256, 6, 28, 28] 156
├─MaxPool2d: 1-2 [256, 6, 14, 14] --
├─Conv2d: 1-3 [256, 16, 10, 10] 2,416
├─MaxPool2d: 1-4 [256, 16, 5, 5] --
├─Linear: 1-5 [256, 120] 48,120
├─Linear: 1-6 [256, 84] 10,164
├─Linear: 1-7 [256, 10] 850
==========================================================================================
Total params: 61,706
Trainable params: 61,706
Non-trainable params: 0
Total mult-adds (M): 108.30
==========================================================================================
Input size (MB): 0.80
Forward/backward pass size (MB): 13.35
Params size (MB): 0.25
Estimated Total Size (MB): 14.40
==========================================================================================
3.7 宇宙船タイタニック号の事例演習
宇宙船タイタニック号の具体的な背景情報は、 Kaggle 公式 Web サイトでご覧いただけます。
トレーニング セット (train.csv) には、次の 12 フィールドがあります。
- PassengerId: 乗客 ID (合計 8693 項目)。
- ホームプラネット: 乗客が去った惑星、通常は彼らが永住する惑星、機密データ、201 個のアイテムが欠落している。
- CryoSleep: 睡眠をフリーズするかどうか、二項分類 (ブール値)、217 項目が欠落しています。
- キャビン: キャビン番号 (デッキ/番号/サイドの形式)、文字列、199 個の項目がありません。
- 宛先: 宛先、機密データ、182 項目が欠落しています。
- 年齢: 年齢、数値データ、179 項目が欠落、178 項目が 0。
- VIP: VIP かどうか、二項分類 (ブール値)、203 項目が欠落しています。
- ルームサービス: サービスによって支払われた料金、数値データ、181 項目が欠落しています。
- FoodCourt: このサービスによって支払われた料金、数値データ、183 項目が欠落しています。
- ShoppingMall: このサービスによって支払われた料金、数値データ、208 項目が不足しています。
- スパ: このサービスによって支払われた料金、数値データ、183 項目が欠落しています。
- VRDeck: サービスによって支払われた料金、数値データ、188 項目が欠落しています。
- 名前: 名前、文字列、200 項目がありません。
- 転送済み: 転送済みかどうか、予測値、2 つの分類。
- まずデータをロードし、値間の基本的な状況を確認して、データを探索します。
import pandas as pd
import pandas_profiling as pp
df = pd.read_csv('train.csv')
report = pp.ProfileReport(df)
report.to_file('report.html') # 读取数据报告,研究怎么进行数据预处理
- データの処理方法を考えてみましょう。
- 旅客 ID: インデックス、削除;
- HomePlanet: 機密データ (3 カテゴリ)、欠落している 201 項目、「Earth」 (モード) で埋められ、ワンホット エンコーディング (get_dummies()) に変換されました。
- CryoSleep: バイナリ分類 (ブール値)、217 項目欠落、astype() は最初に str に変換され、次に False (mode) で埋められ、onehot エンコーディング (get_dummies()) に変換されます。
- Cabin: (デッキ/番号/サイドの形式)、文字列。「/」を使用して列を区切ってから、キャビンを削除します。199 個の項目が欠落しており、モードが最初に入力されます。
- デッキ列、ラベルエンコーディング (LabelEncoder()) を使用。
- num 列、文字列から整数データに変換 (astype());
- サイド列、ワンホット エンコーディング (get_dummies()) に変換されます。
- 宛先: カテゴリカル データ、欠落 182 項目、モード 'TRAPPIST-1e' で埋められ、ワンホット エンコーディング (get_dummies()) に変換されました。
- 年齢: 数値データ、179 個の項目が欠落しており、178 個の項目が 0 です。
- VIP: バイナリ分類 (ブール値)、203 項目が欠落しています。astype() は最初に str に変換され、次に False (mode) で埋められます。ワンホット エンコーディング (get_dummies()) に変換されます。
- RoomService: サービスによって支払われた料金、数値データ、181 項目が欠落しており、モードで満たされています。
- FoodCourt: サービスによって支払われた料金、数値データ、183 個の不足アイテム、モードで満たされた;
- ShoppingMall: このサービスによって支払われた料金、数値データ、208 項目が不足しており、モードで満たされています。
- スパ: サービスによって支払われた料金、数値データ、183 個の欠落項目、モードで満たされています。
- VRDeck: サービスによって支払われた料金、数値データ、188 個の欠落項目、モードで満たされたもの。
- 名前: 名前、文字列、200 個の項目がありませんが、予測とは関係ありません。削除します。
- 転送済み: 転送済みかどうか、予測値、2 つの分類。
- データの前処理を実行する
# 数据预处理:列出需要用众数处理的列的列表
missing_column = ['HomePlanet', 'CryoSleep', 'Cabin', 'Destination', 'VIP', 'RoomService', 'FoodCourt', 'ShoppingMall', 'Spa', 'VRDeck']
# 列出要弃掉的列的列表
drop_column = ['PassengerId', 'Cabin', 'Name']
# 创建一个填充缺失值的函数,填充完整所有需要的数据
def missing_fill(df):
for feature in missing_column: # 循环missing_column列表
df[feature] = df[feature].fillna(df[feature].mode()[0]) # 用众数填充缺失值
df['Age'] = df['Age'].fillna(df['Age'].mean()) # 用平均值填充Age
return df
# 创建一个用于Cabin分列和数据类型转换的函数
def column_split_trans(df):
# 将布尔类型转换成字符串类型
bool_features = ['CryoSleep', 'VIP']
for bool_ft in bool_features:
df[bool_ft] = df[bool_ft].astype('str')
# 拆分'Cabin'列
column = 'Cabin'
df['Deck'] = df['Cabin'].str.split('/').str[0]
df['Num'] = df[column].str.split('/').str[1]
df['Num'] = df['Num'].astype('int') # 将num列从字符转化成整数
df['Side'] = df[column].str.split('/').str[2]
return df
# 定义一个删除列的函数
def drop_features(df):
drop_feature = ['PassengerId', 'Cabin', 'Name']
for ft in drop_feature:
df = df.drop(ft, axis=1) # 当axis=1时,数组的变化是横向的,而体现出来的是列的增加或者减少
return df
# 定义一个编码的函数
from sklearn.preprocessing import LabelEncoder
def encoder(df):
# 对'Deck'采用LabelEncoder编码
label_en = LabelEncoder()
label_en.fit(df['Deck'])
df['Deck'] = label_en.transform(df['Deck'])
# 对剩下的所有字符数据进行OneHot编码
df = pd.get_dummies(df) # 当应用于DataFrame数据时,get_dummies方法只对字符串列进行转换,而其它的列保持不变
return df
# 将所有的数据处理流程合并,组成一个新函数
def data_processing(df):
df = missing_fill(df)
df = column_split_trans(df)
df = drop_features(df)
df = encoder(df)
return df
# 对数据集应用数据处理方法
train_df_after = data_processing(train_df)
valid_df_after = data_processing(valid_df)
print(train_df_after.info()) # 查看转换后的数据情况
# 划分数据集(x)和预测值(y)。 由于读入的numpy数组里的元素是object类型,无法将这种类型转换成tensor。所以强制转换格式:
from torch.utils.data import TensorDataset
import torch
train_df_x = train_df_after.drop('Transported', axis=1).astype(float)
train_df_y = train_df_after.Transported.astype(float)
# 将训练数据集划分为训练集和验证集,并将其转为tensor格式
from sklearn.model_selection import train_test_split
import numpy as np
x_train, x_test, y_train, y_test = train_test_split(train_df_x, train_df_y, test_size=0.2, random_state=42)
x_train = np.array(x_train)
x_test = np.array(x_test)
y_train = np.array(y_train)
y_test = np.array(y_test)
x_train_tensor, x_test_tensor, y_train_tensor, y_test_tensor = map(torch.tensor, (x_train, x_test, y_train, y_test))
# 将数据维度从2D升维到4D
x_train_tensor = x_train_tensor.view(6954, 1, 1, 20)
x_test_tensor = x_test_tensor.view(1739, 1, 1, 20)
# 将标签转为long格式
y_train_tensor = y_train_tensor.long()
y_test_tensor = y_test_tensor.long()
# 类似处理验证集(只有数据,没有标签)
valid_df_x = valid_df_after.astype(float)
valid_tensor_x = torch.tensor(valid_df_x.values)
x_valid_tensor = valid_tensor_x.view(4277, 1, 1, 20)
# 将训练集放进的dataset,然后转换成dataloader
from torch.utils.data import DataLoader
train_dataset = TensorDataset(x_train_tensor, y_train_tensor)
train_dr = DataLoader(train_dataset, batch_size=128, shuffle=True)
- モデルを構築する
# 定义网络模型
from torch import nn
import torch.nn.functional as F
class LeNet5(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 16, (1, 2)) # 输入数据:输入通道数(1)×输出通道数(16)×卷积核大小((1×2))
self.pool1 = nn.MaxPool2d((1, 2))
self.conv2 = nn.Conv2d(16, 32, (1, 2))
self.pool2 = nn.MaxPool2d((1, 2))
self.fc1 = nn.Linear(8*4*4, 128) # 输入数据:输入特征数(8*4*4)×输出特征数(128)
self.fc2 = nn.Linear(128, 32)
self.fc3 = nn.Linear(32, 2)
def forward(self, out):
out = out.to(torch.float32) # 解决数据类型的问题
out = F.relu(self.conv1(out))
out = self.pool1(out)
out = F.relu(self.conv2(out))
out = self.pool2(out)
out = out.view(len(out), -1) # 光栅化
out = F.relu(self.fc1(out))
out = F.relu(self.fc2(out))
out = self.fc3(out)
return out
- トレーニングモデル
# 设置随机数种子,保证结果可复现
seed = 548
torch.manual_seed(seed) # 设置CPU
# torch.cuda.manual_seed(seed) # 设置GPU
# 训练模型
from torch import optim
model = LeNet5() # 实例化模型
optimizer = optim.Adam(model.parameters()) # 选择优化器
criterion = nn.CrossEntropyLoss() # 选用交叉熵作为损失函数Loss
epoch = 30 # 设定迭代次数
for epoch in range(epoch+1): # 开始迭代循环
for x, y in train_dr: # 从dataloader中取x,y
pred = model(x) # 正向传播
loss = criterion(pred, y) # 计算损失函数
optimizer.zero_grad() # 优化器的梯度清零
loss.backward() # 反向传播
optimizer.step() # 参数更新
# 计算准确率
with torch.no_grad(): # 在该模块下,所有计算得出的tensor的requires_grad都自动设置为False。
y_pred = model(x_train_tensor) # 得到训练集的预测标签
acc_train = (y_pred.argmax(dim=1) == y_train_tensor).float().mean().item() # 计算训练集的准确率
y_pred = model(x_test_tensor) # 得到测试集的预测标签
acc_test = (y_pred.argmax(dim=1) == y_test_tensor).float().mean().item() # 计算训练集的准确率
print('epoch:', epoch, ' Accuracy for train:', acc_train, ' Accuracy for test:', acc_test)
- モデルの概要
# 模型总结
from torchinfo import summary
model = LeNet5()
batch_size = 128
summary(model, input_size=(batch_size, 1, 1, 20))
7. 出力:
RangeIndex: 8693 entries, 0 to 8692
Data columns (total 21 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Age 8693 non-null float64
1 RoomService 8693 non-null float64
2 FoodCourt 8693 non-null float64
3 ShoppingMall 8693 non-null float64
4 Spa 8693 non-null float64
5 VRDeck 8693 non-null float64
6 Transported 8693 non-null bool
7 Deck 8693 non-null int32
8 Num 8693 non-null int32
9 HomePlanet_Earth 8693 non-null uint8
10 HomePlanet_Europa 8693 non-null uint8
11 HomePlanet_Mars 8693 non-null uint8
12 CryoSleep_False 8693 non-null uint8
13 CryoSleep_True 8693 non-null uint8
14 Destination_55 Cancri e 8693 non-null uint8
15 Destination_PSO J318.5-22 8693 non-null uint8
16 Destination_TRAPPIST-1e 8693 non-null uint8
17 VIP_False 8693 non-null uint8
18 VIP_True 8693 non-null uint8
19 Side_P 8693 non-null uint8
20 Side_S 8693 non-null uint8
dtypes: bool(1), float64(6), int32(2), uint8(12)
memory usage: 585.9 KB
None
epoch: 0 Accuracy for train: 0.6711245179176331 Accuracy for test: 0.6589994430541992
epoch: 1 Accuracy for train: 0.7778257131576538 Accuracy for test: 0.76365727186203
epoch: 2 Accuracy for train: 0.7920621037483215 Accuracy for test: 0.77400803565979
epoch: 3 Accuracy for train: 0.7877480387687683 Accuracy for test: 0.7694076895713806
epoch: 4 Accuracy for train: 0.791343092918396 Accuracy for test: 0.7711328268051147
epoch: 5 Accuracy for train: 0.7929249405860901 Accuracy for test: 0.7717078924179077
epoch: 6 Accuracy for train: 0.7981017827987671 Accuracy for test: 0.78435879945755
epoch: 7 Accuracy for train: 0.7976704239845276 Accuracy for test: 0.7728579640388489
epoch: 8 Accuracy for train: 0.7995398044586182 Accuracy for test: 0.7768832445144653
epoch: 9 Accuracy for train: 0.7963761687278748 Accuracy for test: 0.7774583101272583
epoch: 10 Accuracy for train: 0.791630744934082 Accuracy for test: 0.7803335189819336
epoch: 11 Accuracy for train: 0.7965199947357178 Accuracy for test: 0.7797584533691406
epoch: 12 Accuracy for train: 0.8016968369483948 Accuracy for test: 0.78435879945755
epoch: 13 Accuracy for train: 0.7988207936286926 Accuracy for test: 0.7809085845947266
epoch: 14 Accuracy for train: 0.7950819730758667 Accuracy for test: 0.7803335189819336
epoch: 15 Accuracy for train: 0.800690233707428 Accuracy for test: 0.78435879945755
epoch: 16 Accuracy for train: 0.7996836304664612 Accuracy for test: 0.7791834473609924
epoch: 17 Accuracy for train: 0.8031348586082458 Accuracy for test: 0.7797584533691406
epoch: 18 Accuracy for train: 0.8029910922050476 Accuracy for test: 0.7780333757400513
epoch: 19 Accuracy for train: 0.8050042986869812 Accuracy for test: 0.7860839366912842
epoch: 20 Accuracy for train: 0.8015530705451965 Accuracy for test: 0.7809085845947266
epoch: 21 Accuracy for train: 0.8025596737861633 Accuracy for test: 0.7860839366912842
epoch: 22 Accuracy for train: 0.8025596737861633 Accuracy for test: 0.7895342111587524
epoch: 23 Accuracy for train: 0.7999712228775024 Accuracy for test: 0.7832087278366089
epoch: 24 Accuracy for train: 0.8031348586082458 Accuracy for test: 0.7826337218284607
epoch: 25 Accuracy for train: 0.802128255367279 Accuracy for test: 0.7814835906028748
epoch: 26 Accuracy for train: 0.8041415214538574 Accuracy for test: 0.78435879945755
epoch: 27 Accuracy for train: 0.802128255367279 Accuracy for test: 0.78435879945755
epoch: 28 Accuracy for train: 0.7989646196365356 Accuracy for test: 0.7803335189819336
epoch: 29 Accuracy for train: 0.8034225106239319 Accuracy for test: 0.78435879945755
epoch: 30 Accuracy for train: 0.7989646196365356 Accuracy for test: 0.784933865070343
==========================================================================================
Layer (type:depth-idx) Output Shape Param #
==========================================================================================
LeNet5 -- --
├─Conv2d: 1-1 [128, 16, 1, 19] 48
├─MaxPool2d: 1-2 [128, 16, 1, 9] --
├─Conv2d: 1-3 [128, 32, 1, 8] 1,056
├─MaxPool2d: 1-4 [128, 32, 1, 4] --
├─Linear: 1-5 [128, 128] 16,512
├─Linear: 1-6 [128, 32] 4,128
├─Linear: 1-7 [128, 2] 66
==========================================================================================
Total params: 21,810
Trainable params: 21,810
Non-trainable params: 0
Total mult-adds (M): 3.85
==========================================================================================
Input size (MB): 0.01
Forward/backward pass size (MB): 0.74
Params size (MB): 0.09
Estimated Total Size (MB): 0.84
==========================================================================================
Finish!!
Process finished with exit code 0
要約: CNN を使用して宇宙船タイタニック号 次に、他のネットワークを使用してそれを実行してみることができます。