【OUCディープラーニング入門】第2週学習記録:畳み込みニューラルネットワークの基礎

目次

Part1 ビデオ学習

1 従来のニューラル ネットワークと畳み込みニューラル ネットワーク

2 基本構造

3 畳み込みニューラルネットワークの典型的な構造

Part2 コード演習

1 MNIST データセットの分類

2 CIFAR10 データセットの分類

3 VGG16 を使用して CIFAR10 を分類する

Part3 問題思考

1 データローダーのシャッフルのさまざまな値の違いは何ですか?

2 変換では異なる値が取られますが、その違いは何ですか?

3 エポックとバッチの違いは何ですか?

4 1x1 コンボリューションと FC の違いは何ですか? 主な役割は何ですか?

5 残留リーンリングにより精度が向上するのはなぜですか?

6 2 番目のコード演習では、ネットワークと 1989 年に Lecun によって提案された LeNet の違いは何ですか?

7 2 番目のコード演習では、畳み込み後に特徴マップのサイズが小さくなります。残差学習を適用するにはどうすればよいですか?

8 精度をさらに向上させる方法はありますか?


Part1 ビデオ学習

1 従来のニューラル ネットワークと畳み込みニューラル ネットワーク

畳み込みニューラル ネットワークの基本的なアプリケーション: 分類、検索、検出、セグメンテーション、認識、画像生成、スタイル転送、自動運転など。

1.1 深層学習三部作

  1. ニューラルネットワークを構築する
  2. 適切な損失関数を選択します: クロス エントロピー損失 (クロス エントロピー損失)、平均二乗誤差 (MSE) など。
  3. バックプロパゲーション (BP)、確率的勾配降下法 (SGD) など、パラメーターを更新するための適切な最適化関数を選択します。

1.2 損失関数

損失関数は、予測結果と実際の結果の間の一致度を測定するために使用され、畳み込みニューラル ネットワークがパラメータ/重み W を調整してより良いトレーニング結果を達成するのに役立ちます。

1.3 両者の比較

従来のニューラル ネットワーク カーネルの畳み込みニューラル ネットワークは階層構造を採用していますが、従来のニューラル ネットワークは完全接続ネットワークであり、ほぼすべてのニューロンが画像のすべてのピクセル情報に接続されているため、重み行列のパラメーターが多すぎて、 ; 畳み込みネットワークはローカルな関連付けとパラメータ共有を通じてこの問題を解決しますが、その各ニューロンは画像内の特定の領域にのみ接続されており、畳み込みカーネルのパラメータはスライディング プロセス中に変更されず、さらにパラメータのサイズを小さくします

2 基本構造

2.1 畳み込み

1 次元畳み込み: 信号処理で信号の遅延累積を計算するために使用されます。

畳み込み: 畳み込みは 2 つの実変数関数に対する数学的演算です。画像処理では、画像が 2 次元形式でニューラル ネットワークに入力されるため、2 次元の畳み込みが必要です

畳み込み関連の概念

  • 基本形式: y=Wx+b、x は指定された画像、W はフィルターです。
  • コンボリューションカーネル/フィルター (カーネル/フィルター)
  • 重さ
  • 受容野(受容野):畳み込み演算に相当する領域の大きさ
  • 特徴マップ (アクティベーション マップ/特徴マップ): 畳み込み演算の後に取得されるマップ。サイズは畳み込みカーネルのサイズ、ステップ サイズ、およびマップ (N+パディング*2-F)/ストライド+1 に関連します。
  • 塗りつぶし (パディング): 畳み込み演算で画像のエッジを考慮できるように、画像の周囲に 0 をパディングします。
  • ステップ サイズ (ストライド): コンボリューション カーネルが 1 回スライドする長さ
  • 深さ (深さ/チャンネル)

畳み込みの可視化: 特定の層の特徴マップを出力し、その層がどのような特徴を学習したかを観察します

2.2 プーリング

プーリング: 構造と動作は畳み込みに似ています. 通常、畳み込み層と畳み込み層の間、または全結合層と全結合層の間に配置されます. 主な機能を維持しながらパラメータと計算を削減します. 改善のためのオーバーフィッティングモデルの汎化能力

プーリングの種類

  • 最大プーリング (最大プーリング): 分類認識タスクでより一般的に使用されます。
  • 平均プーリング

2.3 完全接続

全結合層 (FC 層) : 通常、畳み込みニューラル ネットワークの最後に、2 つの層間のすべてのニューロンに重み結合があり、パラメーターの数が多くなります。

3 畳み込みニューラルネットワークの典型的な構造

3.1 アレックスネット

モデル構造: CONV1 + MAXPOOL1 +NORM1+ CONV2 + MAXPOOL2 +NORM2+ CONV3 + CONV4 + CONV5 + MAXPOOL3 + FC6+FC7+FC8

 モデルの特徴

  • ビッグデータ トレーニング: ImageNet
  • 非線形活性化関数: ReLU。シグモイドよりも速い計算速度と速い収束速度で、正の区間での勾配の消失の問題を解決します。
  • 過学習の防止: ドロップアウト (ランダムな非アクティブ化) + データ拡張 (変換、反転、ガウス摂動などのデータ拡張)
  • デュアルGPU実装

層ごとの分析

  1. 畳み込み-ReLU-プーリング
  2. 畳み込み-ReLU-プーリング
  3. 畳み込み ReLU
  4. 畳み込み ReLU
  5. 畳み込み-ReLU-プーリング
  6. フルコネクション-ReLU-ドロップアウト
  7. フルコネクション-ReLU-ドロップアウト
  8. 完全に接続された-SoftMax

3.2 ZFネット

ネットワーク構造は AlexNet と同じですが、畳み込み層 1 の受容野サイズが 11*11 から 7*7 に、ステップサイズが 4 から 2 に変更され、畳み込み層 3、4、および 3 のフィルター数が変更されています。 5 は 384 、 384、 256 から 512、 512、 1024 に変更されます

3.3 VGG

VGG はより深いネットワークで、AlexNet には 8 層、VGG には 16 ~ 19 層があり、VGG は転移学習で一般的に使用されます。

ネットワーク構造:

 16層ネットワークのノード情報:

  • 01:64個のフィルターを使用したコンボリューション
  • 02: 64 フィルター + 最大プーリングを使用したコンボリューション
  • 03: 128 フィルターを使用したコンボリューション
  • 04: 128 フィルター + 最大プーリングを使用したコンボリューション
  • 05: 256 フィルターを使用したコンボリューション
  • 06: 256 フィルターを使用したコンボリューション
  • 07: 256 フィルター + 最大プーリングを使用したコンボリューション
  • 08: 512 フィルターを使用したコンボリューション
  • 09: 512 フィルターを使用したコンボリューション
  • 10: 512 フィルター + 最大プーリングを使用したコンボリューション
  • 11: 512 フィルターを使用したコンボリューション
  • 12: 512 フィルターを使用したコンボリューション
  • 13: 512 フィルター + 最大プーリングを使用したコンボリューション
  • 14: 4096 ノードで完全接続
  • 15: 4096 ノードで完全接続
  • 16:ソフトマックス

 

3.4 グーグルネット

全体的なネットワーク構造: パラメータ付きの 22 層 (プーリング層が 27 層であることを考慮)、合計約 100 の独立したブロック層が含まれ、パラメータの数は AlexNet の約半分であり、完全に接続された層はありません

インセプション モジュールの役割: マルチコンボリューション カーネルにより機能の多様性が向上

Inception V2 : 次元削減のために 1*1 畳み込みを挿入します。これにより、深度深化パラメータの数が急速に増加する問題が解決されます。

インセプション V3 : 大きなコンボリューション カーネルを小さなコンボリューション カーネルに置き換え、パラメーターの数をさらに削減します。同時に、非線形活性化関数を増やすことで、ネットワークがより独立した特徴を生成し、表現能力が強化され、トレーニングが高速化されます。

 ステム部分 (ステム ネットワーク) : 畳み込み-プーリング-畳み込み-畳み込み-プーリング

3.5 レスネット

残差学習ネットワーク (深層残差学習ネットワーク)。出力層以外に完全に接続された層はなく、構造が柔軟で、非常に深いネットワークを訓練できます。

 残差の考え方: 同じ主要部分を削除し、小さな変化を強調表示します。

Part2 コード演習

1 MNIST データセットの分類

コードリンク: (colab)MNIST データセット分類

ディープ畳み込みニューラル ネットワークには次の特性があります。

  • 多くの層: 構成性
  • 卷积: 画像の局所性 + 定常性
  • 池化: 翻訳に対するオブジェクトクラスの不変性

1.1 MNISTデータのロード

PyTorch には、MNIST や CIFAR10 などの共通データ セットが含まれています。torchvision.datasets を呼び出して、これらのデータをリモートからローカルにダウンロードします。MNIST の使用を例に挙げます。

torchvision.datasets.MNIST(root、train=True、transform=None、target_transform=None、download=False)

  • root: データ セットがローカルにダウンロードされた後のルート ディレクトリ (training.pt および test.pt ファイルを含む)
  • train: True に設定すると、training.pt からデータセットを作成し、それ以外の場合は test.pt からデータセットを作成します。
  • download: True に設定すると、インターネットからデータをダウンロードし、ルート フォルダーに置きます。
  • 変換: PIL イメージを入力し、変換されたデータを返す関数または変換
  • target_transform: 関数または変換、入力ターゲット、変換

DataLoader は比較的重要なクラスであり、提供される一般的な操作は次のとおりです。

  • batch_size: 各バッチのサイズ
  • shuffle: 順序をランダムにシャッフルする操作を実行するかどうか
  • num_workers: データをロードするときに複数のサブプロセスを使用します
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets,transforms
import matplotlib.pyplot as plt
import numpy

# 计算模型中有多少参数
def get_n_params(model):
    np=0
    for p in list(model.parameters()):
        np += p.nelement()
    return np

# 使用GPU训练
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(device)
# out: cude:0

input_size = 28*28  # MNIST上的图像尺寸
output_size = 10  # 类别为0到9的数字

train_loader = torch.utils.data.DataLoader(datasets.MNIST('./data',train=True,download=True,
                      transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.1307,),(0.3081,))])),
                      batch_size=64,shuffle=True)

test_loader = torch.utils.data.DataLoader(datasets.MNIST('./data',train=False,
                      transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.1307,),(0.3081,))])),
                      batch_size=1000,shuffle=True)

# 显示数据集中的部分图像
plt.figure(figsize=(8,5))
for i in range(20):
    plt.subplot(4,5,i+1)
    image,_ = train_loader.dataset.__getitem__(i)
    plt.imshow(image.squeeze().numpy(), 'gray')
    plt.axis('off');

1.2 ネットワークを作成する

ネットワークを定義するときは、nn.Module を継承し、その forward メソッドを実装する必要があります。ネットワーク内の学習可能なパラメータを持つ層を、コンストラクターの init に配置します。forward 関数が nn.Module のサブクラスに定義されている限り、backward 関数は、関数は自動的に実装されます (autograd を使用)

# 网络结构

class FC2Layer(nn.Module):
  def __init__(self,input_size,n_hidden,output_size):
    # nn.Module子类的函数必须在构造函数中执行父类的构造函数
    # 下式等价于nn.Module.__init__(self)        
    super(FC2Layer,self).__init__()
    self.input_size = input_size
    # 这里直接用Sequential定义网络,注意要和下面CNN的代码区分开
    self.network = nn.Sequential(
        nn.Linear(input_size,n_hidden), 
        nn.ReLU(), 
        nn.Linear(n_hidden,n_hidden), 
        nn.ReLU(), 
        nn.Linear(n_hidden,output_size), 
        nn.LogSoftmax(dim=1)
    )
  # forward函数用于指定网络的运行过程
  def forward(self,x):
    # view一般出现在model类的forward函数中,用于改变输入或输出的形状
    # 代码指定二维数据的列数为input_size=784,行数-1表示由电脑自己计算对应的数字
    # batch_size是64,所以x的行数是64
    x = x.view(-1,self.input_size) # 多维的数据展成二维
    # print(x.cpu().numpy().shape)  # 输出(64,784)
    return self.network(x)
    


class CNN(nn.Module):
  def __init__(self,input_size,n_feature,output_size):
    # 执行父类的构造函数
    super(CNN,self).__init__()
    # 池化、ReLU一类的不用在这里定义
    self.n_feature = n_feature
    self.conv1 = nn.Conv2d(in_channels=1,out_channels=n_feature,kernel_size=5)
    self.conv2 = nn.Conv2d(n_feature,n_feature,kernel_size=5)
    self.fc1 = nn.Linear(n_feature*4*4,50)
    self.fc2 = nn.Linear(50,10)    

  # 下面的forward函数定义了网络的结构
  # conv1,conv2等等可以多次重用
  def forward(self,x,verbose=False):
    x = self.conv1(x)
    x = F.relu(x)
    x = F.max_pool2d(x,kernel_size=2)
    x = self.conv2(x)
    x = F.relu(x)
    x = F.max_pool2d(x,kernel_size=2)
    x = x.view(-1,self.n_feature*4*4)
    x = self.fc1(x)
    x = F.relu(x)
    x = self.fc2(x)
    x = F.log_softmax(x,dim=1)
    return x

1.3 完全に接続された小規模ネットワークでのトレーニング

関数のトレーニングとテスト:

# 训练函数
def train(model):
  model.train()
  # 从train_loader里,64个样本一个batch为单位提取样本进行训练
  for batch_idx,(data,target) in enumerate(train_loader):
    # 把数据送到GPU中
    data,target = data.to(device),target.to(device)

    optimizer.zero_grad()
    output = model(data)
    loss = F.nll_loss(output,target)
    loss.backward()
    optimizer.step()
    if batch_idx%100==0:
      print('Train: [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
        batch_idx*len(data),len(train_loader.dataset),
        100.*batch_idx/len(train_loader),loss.item()))

# 测试函数
def test(model):
  model.eval()
  test_loss = 0
  correct = 0
  for data, target in test_loader:
    # 把数据送到GPU中
    data,target = data.to(device),target.to(device)
    # 把数据送入模型,得到预测结果
    output = model(data)
    # 计算本次batch的损失,并加到test_loss中
    test_loss += F.nll_loss(output,target,reduction='sum').item()
    # 值最大的那个即对应着分类结果,然后把分类结果保存在pred里
    pred = output.data.max(1,keepdim=True)[1]
    # 将pred与target相比,得到正确预测结果的数量,并加到correct中
    # view_as:把target变成维度和pred一样                                                
    correct += pred.eq(target.data.view_as(pred)).cpu().sum().item()

  test_loss /= len(test_loader.dataset)
  accuracy = 100.*correct/len(test_loader.dataset)
  print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
      test_loss,correct,len(test_loader.dataset),
      accuracy))
# 全连接层网络训练

n_hidden = 8 # number of hidden units

model_fnn = FC2Layer(input_size,n_hidden,output_size)
model_fnn.to(device)
optimizer = optim.SGD(model_fnn.parameters(),lr=0.01,momentum=0.5)
print('Number of parameters: {}'.format(get_n_params(model_fnn)))

train(model_fnn)
test(model_fnn)

1.4 畳み込みニューラル ネットワークのトレーニング

# 卷积神经网络训练

# Training settings 
n_features = 6 # number of feature maps

model_cnn = CNN(input_size,n_features,output_size)
model_cnn.to(device)
optimizer = optim.SGD(model_cnn.parameters(),lr=0.01,momentum=0.5)
print('Number of parameters: {}'.format(get_n_params(model_cnn)))

train(model_cnn)
test(model_cnn)

パラメータの数が同程度の場合、CNN は畳み込みカーネル プーリングを通じてより適切に情報を抽出できるため、CNN の効果は単純な完全接続ネットワークの効果よりも優れていることがわかります。

1.5 ピクセルの順序をシャッフルし、2 つのネットワークで再度トレーニングしてテストする

畳み込み演算もプーリング演算も画像上で局所的に行うことで画素の位置関係を抽出することができますが、このとき画像内の画素の順序を乱すようにしてください。

# 打乱像素顺序的演示

perm = torch.randperm(784)  # 给定参数n,返回一个从0到n-1的随机整数排列
plt.figure(figsize=(8,4))
for i in range(10):
    image,_ = train_loader.dataset.__getitem__(i)
    # permute pixels
    image_perm = image.view(-1,28*28).clone()
    image_perm = image_perm[:,perm]
    image_perm = image_perm.view(-1,1,28,28)
    plt.subplot(4,5,i+1)
    plt.imshow(image.squeeze().numpy(), 'gray')
    plt.axis('off')
    plt.subplot(4,5,i+11)
    plt.imshow(image_perm.squeeze().numpy(),'gray')
    plt.axis('off')

ピクセルの順序をシャッフルした後の効果:

ピクセルをシャッフルする関数:

# 对每个batch里的数据,打乱像素顺序的函数
def perm_pixel(data,perm):
  # 转化为二维矩阵
  data_new = data.view(-1,28*28)
  # 打乱像素顺序
  data_new = data_new[:,perm]
  # 恢复为原来4维的tensor
  data_new = data_new.view(-1,1,28,28)
  return data_new

完全に接続されたネットワーク上でトレーニングとテストを行います。

# 打乱像素顺序训练全连接网络

perm = torch.randperm(784)
n_hidden = 8  # number of hidden units

model_fnn = FC2Layer(input_size,n_hidden,output_size)
model_fnn.to(device)
optimizer = optim.SGD(model_fnn.parameters(),lr=0.01,momentum=0.5)
print('Number of parameters: {}'.format(get_n_params(model_fnn)))

train_perm(model_fnn,perm)
test_perm(model_fnn,perm)

畳み込みニューラル ネットワークでトレーニングしてテストします。

# 打乱像素顺序训练卷积神经网络

perm = torch.randperm(784)
n_features = 6  # number of feature maps

model_cnn = CNN(input_size,n_features,output_size)
model_cnn.to(device)
optimizer = optim.SGD(model_cnn.parameters(),lr=0.01,momentum=0.5)
print('Number of parameters: {}'.format(get_n_params(model_cnn)))

train_perm(model_cnn,perm)
test_perm(model_cnn,perm)

ピクセルの順序が崩れると、畳み込みニューラル ネットワークのパフォーマンスが低下し、ピクセル間の局所的な関係が畳み込みニューラル ネットワークにとって非常に重要なトレーニング情報であることがわかります。

2 CIFAR10 データセットの分類

コードリンク: (colab) CIFAR10 データセット分類

CIFAR10 データセットには 10 のカテゴリが含まれており、画像サイズは 3*32*32 です。torchsivion を使用してロードできます。torchvision データセットの出力範囲は [0,1] PILImage です。使用する前に、正規化して、 [ -1,1] テンソルに変換

import torch
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

# 使用GPU训练
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

transform = transforms.Compose([transforms.ToTensor(),
                transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))])

# 训练的shuffle是True,打乱顺序增加样本多样性,测试的shuffle是false
trainset = torchvision.datasets.CIFAR10(root='./data',train=True,download=True,transform=transform)
trainloader = torch.utils.data.DataLoader(trainset,batch_size=64,shuffle=True,num_workers=2)

testset = torchvision.datasets.CIFAR10(root='./data',train=False,download=True,transform=transform)
testloader = torch.utils.data.DataLoader(testset,batch_size=8,shuffle=False,num_workers=2)

classes = ('plane','car','bird','cat','deer','dog','frog','horse','ship','truck')

def imshow(img):
  plt.figure(figsize=(8,8))
  img = img/2+0.5 # 转换为[0,1]
  npimg = img.numpy()
  plt.imshow(np.transpose(npimg,(1,2,0)))
  plt.show()

# 得到一组图像
images,labels = iter(trainloader).next()
# 展示图像
imshow(torchvision.utils.make_grid(images))
# 展示第一行图像的标签
for j in range(8):
  print(classes[labels[j]])

2.1 ネットワーク、損失関数、オプティマイザーを定義する

class Net(nn.Module):
  def __init__(self):
    super(Net,self).__init__()
    self.conv1 = nn.Conv2d(3,6,5)
    self.pool = nn.MaxPool2d(2,2)
    self.conv2 = nn.Conv2d(6,16,5)
    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 = self.pool(F.relu(self.conv1(x)))
    x = self.pool(F.relu(self.conv2(x)))
    x = x.view(-1,16*5*5)
    x = F.relu(self.fc1(x))
    x = F.relu(self.fc2(x))
    x = self.fc3(x)
    return x

# 在GPU上训练
net = Net().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(),lr=0.001)

2.2 研修ネットワーク

for epoch in range(10):  # 重复多轮训练
    for i,(inputs,labels) in enumerate(trainloader):
        inputs = inputs.to(device)
        labels = labels.to(device)
        # 优化器梯度归零
        optimizer.zero_grad()
        # 正向传播+反向传播+优化 
        outputs = net(inputs)
        loss = criterion(outputs,labels)
        loss.backward()
        optimizer.step()
        # 输出统计信息
        if i%200==0:   
            print('Epoch: %d Minibatch: %5d loss: %.3f' %(epoch+1,i+1,loss.item()))

print('Finished Training')

 トレーニング結果:

2.3 認識効果の観察

# 得到一组图像
images,labels = iter(testloader).next()
# 展示图像
imshow(torchvision.utils.make_grid(images))
# 展示图像的标签
for j in range(8):
    print(classes[labels[j]])

outputs = net(images.to(device))
_,predicted = torch.max(outputs,1)

print("预测结果:")

# 展示预测的结果
for j in range(8):
    print(classes[predicted[j]])

 

 少数の認識エラーが見つかりました

2.4 統計的な全体的な精度

 正解率が低いので改善が必要

3 VGG16 を使用して CIFAR10 を分類する

コードリンク: (colab)VGG_CIFAR10

3.1 データローダーの定義

コード演習 2 と比較すると、ここでの正規化操作のパラメーターにはいくつかの変更があります。

import torch
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

# 使用GPU训练
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

transform_train = transforms.Compose([
    transforms.RandomCrop(32, padding=4),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize((0.4914,0.4822,0.4465),(0.2023,0.1994,0.2010))])

transform_test = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.4914,0.4822,0.4465),(0.2023,0.1994,0.2010))])

trainset = torchvision.datasets.CIFAR10(root='./data',train=True,download=True,transform=transform_train)
testset = torchvision.datasets.CIFAR10(root='./data',train=False,download=True,transform=transform_test)

trainloader = torch.utils.data.DataLoader(trainset,batch_size=128,shuffle=True,num_workers=2)
testloader = torch.utils.data.DataLoader(testset,batch_size=128,shuffle=False,num_workers=2)

classes = ('plane','car','bird','cat','deer','dog','frog','horse','ship','truck')

3.2 VGG ネットワークの定義

ここでは、次の構造を持つ単純な VGG ネットワークが定義されています。

  • 64 コンバージョン、マックスプーリング

  • 128 コンバージョン、マックスプーリング

  • 256 コンバージョン、256 コンバージョン、マックスプーリング

  • 512 コンバージョン、512 コンバージョン、マックスプーリング

  • 512 コンバージョン、512 コンバージョン、マックスプーリング

  • ソフトマックス

# 简化版的VGG

class VGG(nn.Module):
  def __init__(self):
    super(VGG,self).__init__()
    self.cfg = [64,'M',128,'M',256,256,'M',512,512,'M',512,512,'M']
    self.features = self._make_layers(self.cfg)
    self.classifier = nn.Linear(2048,10)  # 根据分类任务的类别数量确定

  def forward(self,x):
    out = self.features(x)
    out = out.view(out.size(0),-1)
    out = self.classifier(out)
    return out

  def _make_layers(self,cfg):
    layers = []
    in_channels = 3
    for x in cfg:
      if x=='M':
        layers += [nn.MaxPool2d(kernel_size=2,stride=2)]
      else:
        layers += [nn.Conv2d(in_channels,x,kernel_size=3,padding=1),nn.BatchNorm2d(x),nn.ReLU(inplace=True)]
        in_channels = x
    layers += [nn.AvgPool2d(kernel_size=1,stride=1)]
    return nn.Sequential(*layers)


# 网络放到GPU上
net = VGG().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(),lr=0.001)

3.3 ネットワークトレーニング

for epoch in range(10):  # 重复多轮训练
  for i,(inputs,labels) in enumerate(trainloader):
    inputs = inputs.to(device)
    labels = labels.to(device)
    # 优化器梯度归零
    optimizer.zero_grad()
    # 正向传播+反向传播+优化 
    outputs = net(inputs)
    loss = criterion(outputs,labels)
    loss.backward()
    optimizer.step()
    # 输出训练信息
    if i%100==0:   
      print('Epoch: %d Minibatch: %5d loss: %.3f' %(epoch+1,i+1,loss.item()))

print('Finished Training')

トレーニングプロセスの損失:

3.4 テスト検証精度

 コード演習 2 で CNN トレーニングを使用して得られた正解率と比較して、VGG を使用して得られた正解率は 20 ポイント向上しました。VGG はコード演習 2 の CNN よりも深く、非線形変換の可能性がより多くなっています。非線形変換をフィッティングしてデータ分類問題を解決する

Part3 問題思考

1 データローダーのシャッフルのさまざまな値の違いは何ですか?

Shuffle は bool 型のパラメータです。shuffle が True の場合、データ セット データをロードするときにデータがスクランブルされます。shuffle が False の場合、スクランブルされません。順序をスクランブルすると、トレーニングの各ラウンドでのデータ シーケンスが異なります。 、データ配置によるトレーニング効果への影響を排除

2 変換では異なる値が取られますが、その違いは何ですか?

ここでの変換は、データ正規化、ランダム クロッピング、反転などの一般的に使用されるデータ前処理操作を定義します。これらはデータ強化に使用でき、データ サンプルを最大限に活用し、トレーニング モデルの汎化能力を向上させることができます。

コード演習で使用されるtransforms.normalize() は、画像をチャネルごとに正規化するために使用され、データが平均 0、標準偏差 1 の分布に従い、モデルの収束が高速化されます。基本的な実現式は x=(x-mean )/std です。ここで、mean はデータ自体の平均であり、std はデータ自体の標準偏差です。これら 2 つの値は事前に計算する必要があります。

正規化する前はデータは[0,1]で、正規化する場合はnormalize((0.5,0.5,0.5),(0.5,0.5,0.5))の場合はデータを正規化することになり、normalize(平均、標準偏差) は、平均が 0、標準偏差が 1 の分布としてデータを処理します。

3 エポックとバッチの違いは何ですか?

エポックはトレーニング データ セットのラウンド数です。1 エポックはすべてのデータ セットを 1 回実行することに相当します。バンチは 1 エポック内のバッチ トレーニングのサンプル数です。

4 1x1 コンボリューションと FC の違いは何ですか? 主な役割は何ですか?

1*1 畳み込みは 2 次元畳み込みの特殊なケースであり、次元削減の役割を果たすことができます。多次元入力を処理する場合、チャネル数を調整し、パラメータを削減し、パターンを深く捕捉し、増加させることができます。分類子として FC の代わりに非線形。1*1畳み込みはFCと比べて重み共有が可能であり、同機能のfc層よりもパラメータ量が少なく、位置情報を利用するため、学習サンプルのサイズが均一である必要があるが、 1*1 畳み込みはこの規定の対象外

5 残留リーンリングにより精度が向上するのはなぜですか?

ネットワークの学習過程では、深さが深くなるほどパラメータが複雑になり、ネットワークはより複雑になりますが、分類タスクはプロセス未知であり、ディープ ニューラル ネットワークが同一性マッピングを達成することは困難です。ネットワークがより良いパラメータを学習することが困難になりますが、残差学習を導入した後、ネットワークはアイデンティティマッピングを実現できます。トレーニングプロセス中に、実際の効果に応じていくつかの層をスキップでき、より柔軟であるため、精度率が向上します。改善されること。

6 2 番目のコード演習では、ネットワークと 1989 年に Lecun によって提案された LeNet の違いは何ですか?

LeNet の構造はおおよそ次のとおりです。

コード演習 2 では、最大プーリング関数と ReLU アクティベーション関数が使用されますが、LeNet は平均プーリングを使用し、アクティベーション関数はシグモイドです。

7 2 番目のコード演習では、畳み込み後に特徴マップのサイズが小さくなります。残差学習を適用するにはどうすればよいですか?

50 層を超える ResNet ネットワークの BottleNeck 設計を参照し、1*1 畳み込みを使用してディメンションと機能マップのサイズを調整できます。

8 精度をさらに向上させる方法はありますか?

  1. ドロップアウト操作の追加
  2. さまざまなネットワーク構造を試し、層の数を適切に調整してください
  3. さまざまな活性化関数を試してみる
  4. L1/L2 正則化を使用する
  5. 事前トレーニングを使用し、事前トレーニングから取得したパラメータを正式なトレーニングに使用します
  6. さまざまなオプティマイザと損失関数を試し、ハイパーパラメータを調整してみる

おすすめ

転載: blog.csdn.net/qq_55708326/article/details/125831268