• 深度学习10——卷积神经网络


    目录

    1.全连接网络复习 

     2.卷积

     2.1 卷积核​

     2.2 卷积层的基本实现

     2.3 padding填充

     2.4 stride步长

     2.5 池化层

     3. CNN实例

    3.1 完整代码:

    3.1.1 cpu训练

    3.1.2 GPU上训练

    4. 卷积神经网络进阶

     4.1 GoogLeNet

    4.2 inception Module

    4.2.1  1*1卷积及其作用

     4.2.2 implemetaion of inception Module​编辑

    4.2.3 Inception Module 以及模型构建的实现代码

     完整代码:

    4.3 residual Network 

    4.3.1 Residual Block的代码实现


    参考文章: 

    PyTorch 深度学习实践 第10讲_错错莫的博客-CSDN博客

    1.全连接网络复习 

     2.卷积

     

     

     2.1 卷积核

     

     

     

     

     2.2 卷积层的基本实现

    1. import torch
    2. in_channels, out_channels = 5, 10 #定义输入输出的通道数
    3. width, hight = 100, 100 #定义图片的大小
    4. kernel_size = 3 # 定义的卷积核是一个3*3的
    5. batch_size = 1
    6. #输入层
    7. input = torch.randn(batch_size,
    8. in_channels,
    9. width,
    10. hight
    11. )
    12. # 定义卷积层
    13. conv_layer = torch.nn.Conv2d(
    14. in_channels,
    15. out_channels,
    16. kernel_size=kernel_size
    17. )
    18. #定义输出层
    19. output = conv_layer(input)
    20. print(input.shape)
    21. print(output.shape)
    22. print(conv_layer.weight.shape)
    1. torch.Size([1, 5, 100, 100])
    2. torch.Size([1, 10, 98, 98])
    3. torch.Size([10, 5, 3, 3])

     2.3 padding填充

     

     

     

    1. import torch
    2. #以下数据假设是输入的图像像素点
    3. input =[
    4. 3,4,6,5,7,
    5. 2,4,6,8,2,
    6. 1,6,7,8,4,
    7. 9,7,4,6,2,
    8. 3,7,5,4,1
    9. ]
    10. input = torch.Tensor(input).view(1,1,5,5) #将input的数据转化为tensor类型,并设置B,C,W,H为1,1,5,5
    11. #padding填充
    12. conv_layer = torch.nn.Conv2d(1,1,kernel_size=3,padding=1,bias=False) #前两个数字对应的是输入与输出对应的通道数
    13. kernel = torch.Tensor([1,2,3,4,5,6,7,8,9]).view(1,1,3,3) # 构造卷积核,view(输出的通道(卷积核的个数),输入的通道数(卷积核的通道数),3*3)
    14. conv_layer.weight.data = kernel.data # 将卷积核的权重赋给卷积层
    15. output = conv_layer(input) #做卷积运算
    16. print(output)

     2.4 stride步长

     

    1. import torch
    2. #以下数据假设是输入的图像像素点
    3. input =[
    4. 3,4,6,5,7,
    5. 2,4,6,8,2,
    6. 1,6,7,8,4,
    7. 9,7,4,6,2,
    8. 3,7,5,4,1
    9. ]
    10. input = torch.Tensor(input).view(1,1,5,5) #将input的数据转化为tensor类型,并设置B,C,W,H为1,1,5,5
    11. #stride步长
    12. conv_layer = torch.nn.Conv2d(1,1,kernel_size=3,stride=2,bias=False)
    13. kernel = torch.Tensor([1,2,3,4,5,6,7,8,9]).view(1,1,3,3) # 构造卷积核,view(输出的通道(卷积核的个数),输入的通道数(卷积核的通道数),3*3)
    14. conv_layer.weight.data = kernel.data # 将卷积核的权重赋给卷积层
    15. output = conv_layer(input) #做卷积运算
    16. print(output)

     

     2.5 池化层

     

    1. import torch
    2. #以下数据假设是输入的图像像素点
    3. input =[
    4. 3,4,6,5,7,
    5. 2,4,6,8,2,
    6. 1,6,7,8,4,
    7. 9,7,4,6,2,
    8. 3,7,5,4,1
    9. ]
    10. input = torch.Tensor(input).view(1,1,5,5) #将input的数据转化为tensor类型,并设置B,C,W,H为1,1,5,5
    11. #池化层
    12. maxpooling_layer = torch.nn.MaxPool2d(kernel_size=2)
    13. output = maxpooling_layer(input) #做卷积运算
    14. print(output)

     3. CNN实例

     

     

     

     

     

                                                                                                

     

     

     

    3.1 完整代码:

    代码说明:

    1、torch.nn.Conv2d(1,10,kernel_size=3,stride=2,bias=False)

          1是指输入的Channel,灰色图像是1维的;10是指输出的Channel,也可以说第一个卷积层需要10个卷积核;kernel_size=3,卷积核大小是3x3;stride=2进行卷积运算时的步长,默认为1;bias=False卷积运算是否需要偏置bias,默认为False。padding = 0,卷积操作是否补0。

    2、self.fc = torch.nn.Linear(320, 10),这个320获取的方式,可以通过x = x.view(batch_size, -1) # print(x.shape)可得到(64,320),64指的是batch,320就是指要进行全连接操作时,输入的特征维度。


    3.1.1 cpu训练

    1. import torch
    2. from torchvision import transforms
    3. from torchvision import datasets
    4. from torch.utils.data import DataLoader
    5. import torch.nn.functional as F
    6. import torch.optim as optim
    7. # prepare dataset
    8. batch_size = 64
    9. transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
    10. train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, download=True, transform=transform)
    11. train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
    12. test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, download=True, transform=transform)
    13. test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)
    14. # design model using class 构建网络模型
    15. class Net(torch.nn.Module):
    16. def __init__(self):
    17. super(Net, self).__init__()
    18. self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5) #卷积核为5*5
    19. self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5)
    20. self.pooling = torch.nn.MaxPool2d(2)
    21. self.fc = torch.nn.Linear(320, 10) #全连接层,320 = 20*4*4
    22. def forward(self, x):
    23. # flatten data from (n,1,28,28) to (n, 784)
    24. batch_size = x.size(0) #样本的数据量
    25. x = F.relu(self.pooling(self.conv1(x))) #执行第一层卷积运算
    26. x = F.relu(self.pooling(self.conv2(x)))
    27. # 以下两步用于全连接运算
    28. x = x.view(batch_size, -1) # -1 此处自动算出的是320
    29. x = self.fc(x)
    30. return x
    31. model = Net()
    32. # construct loss and optimizer
    33. criterion = torch.nn.CrossEntropyLoss()
    34. optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    35. # training cycle forward, backward, update
    36. def train(epoch):
    37. running_loss = 0.0
    38. for batch_idx, data in enumerate(train_loader, 0):
    39. inputs, target = data
    40. optimizer.zero_grad()
    41. outputs = model(inputs)
    42. loss = criterion(outputs, target)
    43. loss.backward()
    44. optimizer.step()
    45. running_loss += loss.item()
    46. if batch_idx % 300 == 299:
    47. print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
    48. running_loss = 0.0
    49. def test():
    50. correct = 0
    51. total = 0
    52. with torch.no_grad():
    53. for data in test_loader:
    54. images, labels = data
    55. outputs = model(images)
    56. _, predicted = torch.max(outputs.data, dim=1)
    57. total += labels.size(0)
    58. correct += (predicted == labels).sum().item()
    59. print('accuracy on test set: %d %% ' % (100 * correct / total))
    60. if __name__ == '__main__':
    61. for epoch in range(10):
    62. train(epoch)
    63. test()
    1. C:\Users\ZARD\anaconda3\envs\PyTorch\python.exe C:/Users/ZARD/PycharmProjects/pythonProject/机器学习库/PyTorch实战课程内容/lecture10/CNN01.py
    2. Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
    3. Using downloaded and verified file: ../dataset/mnist/MNIST\raw\train-images-idx3-ubyte.gz
    4. Extracting ../dataset/mnist/MNIST\raw\train-images-idx3-ubyte.gz to ../dataset/mnist/MNIST\raw
    5. Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz
    6. Using downloaded and verified file: ../dataset/mnist/MNIST\raw\train-labels-idx1-ubyte.gz
    7. Extracting ../dataset/mnist/MNIST\raw\train-labels-idx1-ubyte.gz to ../dataset/mnist/MNIST\raw
    8. Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz
    9. Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz to ../dataset/mnist/MNIST\raw\t10k-images-idx3-ubyte.gz
    10. 100%|██████████| 1648877/1648877 [00:30<00:00, 53892.68it/s]
    11. Extracting ../dataset/mnist/MNIST\raw\t10k-images-idx3-ubyte.gz to ../dataset/mnist/MNIST\raw
    12. Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz
    13. Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz to ../dataset/mnist/MNIST\raw\t10k-labels-idx1-ubyte.gz
    14. 100%|██████████| 4542/4542 [00:03<00:00, 1153.06it/s]
    15. Extracting ../dataset/mnist/MNIST\raw\t10k-labels-idx1-ubyte.gz to ../dataset/mnist/MNIST\raw
    16. [1, 300] loss: 0.737
    17. [1, 600] loss: 0.213
    18. [1, 900] loss: 0.147
    19. accuracy on test set: 96 %
    20. [2, 300] loss: 0.118
    21. [2, 600] loss: 0.105
    22. [2, 900] loss: 0.084
    23. accuracy on test set: 97 %
    24. [3, 300] loss: 0.080
    25. [3, 600] loss: 0.071
    26. [3, 900] loss: 0.075
    27. accuracy on test set: 98 %
    28. [4, 300] loss: 0.065
    29. [4, 600] loss: 0.060
    30. [4, 900] loss: 0.064
    31. accuracy on test set: 98 %
    32. [5, 300] loss: 0.058
    33. [5, 600] loss: 0.054
    34. [5, 900] loss: 0.050
    35. accuracy on test set: 98 %
    36. [6, 300] loss: 0.046
    37. [6, 600] loss: 0.051
    38. [6, 900] loss: 0.049
    39. accuracy on test set: 98 %
    40. [7, 300] loss: 0.044
    41. [7, 600] loss: 0.046
    42. [7, 900] loss: 0.043
    43. accuracy on test set: 98 %
    44. [8, 300] loss: 0.040
    45. [8, 600] loss: 0.044
    46. [8, 900] loss: 0.038
    47. accuracy on test set: 98 %
    48. [9, 300] loss: 0.039
    49. [9, 600] loss: 0.037
    50. [9, 900] loss: 0.038
    51. accuracy on test set: 98 %
    52. [10, 300] loss: 0.038
    53. [10, 600] loss: 0.035
    54. [10, 900] loss: 0.034
    55. accuracy on test set: 98 %
    56. Process finished with exit code 0

    3.1.2 GPU上训练

    1. import torch
    2. from torchvision import transforms
    3. from torchvision import datasets
    4. from torch.utils.data import DataLoader
    5. import torch.nn.functional as F
    6. import torch.optim as optim
    7. import matplotlib.pyplot as plt
    8. # prepare dataset
    9. batch_size = 64
    10. transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
    11. train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, download=True, transform=transform)
    12. train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
    13. test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, download=True, transform=transform)
    14. test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)
    15. # design model using class
    16. class Net(torch.nn.Module):
    17. def __init__(self):
    18. super(Net, self).__init__()
    19. self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
    20. self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5)
    21. self.pooling = torch.nn.MaxPool2d(2)
    22. self.fc = torch.nn.Linear(320, 10)
    23. def forward(self, x):
    24. # flatten data from (n,1,28,28) to (n, 784)
    25. batch_size = x.size(0)
    26. x = F.relu(self.pooling(self.conv1(x)))
    27. x = F.relu(self.pooling(self.conv2(x)))
    28. x = x.view(batch_size, -1) # -1 此处自动算出的是320
    29. # print("x.shape",x.shape)
    30. x = self.fc(x)
    31. return x
    32. model = Net()
    33. device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    34. model.to(device)
    35. # construct loss and optimizer
    36. criterion = torch.nn.CrossEntropyLoss()
    37. optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    38. # training cycle forward, backward, update
    39. def train(epoch):
    40. running_loss = 0.0
    41. for batch_idx, data in enumerate(train_loader, 0):
    42. inputs, target = data
    43. inputs, target = inputs.to(device), target.to(device)
    44. optimizer.zero_grad()
    45. outputs = model(inputs)
    46. loss = criterion(outputs, target)
    47. loss.backward()
    48. optimizer.step()
    49. running_loss += loss.item()
    50. if batch_idx % 300 == 299:
    51. print('[%d, %5d] loss: %.3f' % (epoch+1, batch_idx+1, running_loss/300))
    52. running_loss = 0.0
    53. def test():
    54. correct = 0
    55. total = 0
    56. with torch.no_grad():
    57. for data in test_loader:
    58. images, labels = data
    59. images, labels = images.to(device), labels.to(device)
    60. outputs = model(images)
    61. _, predicted = torch.max(outputs.data, dim=1)
    62. total += labels.size(0)
    63. correct += (predicted == labels).sum().item()
    64. print('accuracy on test set: %d %% ' % (100*correct/total))
    65. return correct/total
    66. if __name__ == '__main__':
    67. epoch_list = []
    68. acc_list = []
    69. for epoch in range(10):
    70. train(epoch)
    71. acc = test()
    72. epoch_list.append(epoch)
    73. acc_list.append(acc)
    74. plt.plot(epoch_list,acc_list)
    75. plt.ylabel('accuracy')
    76. plt.xlabel('epoch')
    77. plt.show()

    4. 卷积神经网络进阶

     4.1 GoogLeNet

    4.2 inception Module

    4.2.1  1*1卷积及其作用

     

     

     4.2.2 implemetaion of inception Module

     

     

     

    如上class Net网络结构的第二层卷积的输入为88,是因为在其 froward()函数中,在调用第二层卷积self.conv2之前已经调用了InceptionA类的实例,而InceptionA类实例返回的结果是各网络分支所得的通道数之和,即24*3+16=88.

     

    4.2.3 Inception Module 以及模型构建的实现代码

    1. #将某分支网络抽象为一个Inception类
    2. class Inception(nn.Module):
    3. def __init__(self,in_channels):
    4. super(Inception,self).__init__()
    5. #定义如下4个分支结构
    6. self.branch1x1 = nn.Conv2d(in_channels,16,kernel_size=1) # 该分支为一层卷积核为1*1的16通道的卷积层
    7. #该分支为由两层构成,第一层卷积核1*1,输出通道为16;第二层卷积核为5*5,输出通道为24
    8. self.branch5x5_1 = nn.Conv2d(in_channels,16,kernel_size=1)
    9. self.branch5x5_2 = nn.Conv2d(16,24,kernel_size=5,padding=2)
    10. #第三分支
    11. self.branch3x3_1 = nn.Conv2d(in_channels,16,kernel_size=1)
    12. self.branch3x3_2 = nn.Conv2d(16,24,kernel_size=3,padding=1)
    13. self.branch3x3_3 = nn.Conv2d(24,24,kernel_size=3,padding=1)
    14. #第四分支:池化分支
    15. self.branch_pool = nn.Conv2d(in_channels,24,kernel_size=1)
    16. #计算各层分支的卷积和
    17. def forward(self,x):
    18. branch1x1 = self.branch1x1(x)
    19. branch5x5 = self.branch5x5_1(x)
    20. branch5x5 = self.branch5x5_2(branch5x5)
    21. branch3x3 = self.branch3x3_1(x)
    22. branch3x3 = self.branch3x3_3(branch3x3)
    23. branch3x3 = self.branch3x3_3(branch3x3)
    24. branch_pool = F.avg_pool2d(x,kernel_size=3,stride=1,padding=1)
    25. branch_pool = self.branch_pool(branch_pool)
    26. output = [branch1x1,branch5x5,branch3x3,branch_pool]
    27. return torch.cat(output,dim=1)
    28. class Net(nn.Module):
    29. def __init__(self):
    30. super(Net, self).__init__()
    31. self.conv1 = nn.Conv2d(1,10,kernel_size=5)
    32. self.conv2 = nn.Conv2d(88,20,kernel_size=5)
    33. #实例化分支网络结构Inception
    34. self.incep1 = Inception(in_channels=10)
    35. self.incep2 = Inception(in_channels=20)
    36. self.mp = nn.MaxPool2d(2) #池化
    37. self.fc = nn.Linear(1408,10) #实例化全连接层,全连接层的实质就是一个线性层
    38. def forward(self,x):
    39. in_side = x.size(0)
    40. x = F.relu(self.mp(self.conv1(x)))
    41. x = self.incep1(x)
    42. x = F.relu(self.mp(self.conv2(x)))
    43. x = self.incep2(x)
    44. #全连接层
    45. x = x.view(in_side,-1)
    46. x = self.fc(x)
    47. return x

     完整代码:

    1. import torch
    2. import torch.nn as nn
    3. from torchvision import transforms
    4. from torchvision import datasets
    5. from torch.utils.data import DataLoader
    6. import torch.nn.functional as F
    7. import torch.optim as optim
    8. # prepare datasets 数据集的准备
    9. batch_size = 64
    10. transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]) # 归一化,均值和方差
    11. train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, download=True, transform=transform)
    12. train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
    13. test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, download=True, transform=transform)
    14. test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)
    15. #将某分支网络抽象为一个Inception类
    16. class Inception(nn.Module):
    17. def __init__(self,in_channels):
    18. super(Inception,self).__init__()
    19. #定义如下4个分支结构
    20. self.branch1x1 = nn.Conv2d(in_channels, 16, kernel_size=1) # 该分支为一层卷积核为1*1的16通道的卷积层
    21. #该分支为由两层构成,第一层卷积核1*1,输出通道为16;第二层卷积核为5*5,输出通道为24
    22. self.branch5x5_1 = nn.Conv2d(in_channels, 16, kernel_size=1)
    23. self.branch5x5_2 = nn.Conv2d(16, 24, kernel_size=5, padding=2)
    24. #第三分支
    25. self.branch3x3_1 = nn.Conv2d(in_channels, 16, kernel_size=1)
    26. self.branch3x3_2 = nn.Conv2d(16, 24, kernel_size=3, padding=1)
    27. self.branch3x3_3 = nn.Conv2d(24, 24, kernel_size=3, padding=1)
    28. #第四分支:池化分支
    29. self.branch_pool = nn.Conv2d(in_channels,24,kernel_size=1)
    30. #计算各层分支的卷积和
    31. def forward(self,x):
    32. branch1x1 = self.branch1x1(x)
    33. branch5x5 = self.branch5x5_1(x)
    34. branch5x5 = self.branch5x5_2(branch5x5)
    35. branch3x3 = self.branch3x3_1(x)
    36. branch3x3 = self.branch3x3_2(branch3x3)
    37. branch3x3 = self.branch3x3_3(branch3x3)
    38. branch_pool = F.avg_pool2d(x,kernel_size=3,stride=1,padding=1)
    39. branch_pool = self.branch_pool(branch_pool)
    40. output = [branch1x1,branch5x5,branch3x3,branch_pool]
    41. return torch.cat(output,dim=1)
    42. class Net(nn.Module):
    43. def __init__(self):
    44. super(Net, self).__init__()
    45. self.conv1 = nn.Conv2d(1,10,kernel_size=5)
    46. self.conv2 = nn.Conv2d(88,20,kernel_size=5)
    47. #实例化分支网络结构Inception
    48. self.incep1 = Inception(in_channels=10)
    49. self.incep2 = Inception(in_channels=20)
    50. self.mp = nn.MaxPool2d(2) #池化
    51. self.fc = nn.Linear(1408,10) #实例化全连接层,全连接层的实质就是一个线性层
    52. def forward(self,x):
    53. in_side = x.size(0)
    54. x = F.relu(self.mp(self.conv1(x)))
    55. x = self.incep1(x)
    56. x = F.relu(self.mp(self.conv2(x)))
    57. x = self.incep2(x)
    58. #全连接层
    59. x = x.view(in_side,-1)
    60. x = self.fc(x)
    61. return x
    62. model = Net()
    63. # construct loss and optimizer
    64. criterion = torch.nn.CrossEntropyLoss()
    65. optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    66. # training cycle forward, backward, update
    67. def train(epoch):
    68. running_loss = 0.0
    69. for batch_idx, data in enumerate(train_loader, 0):
    70. inputs, target = data
    71. optimizer.zero_grad()
    72. outputs = model(inputs)
    73. loss = criterion(outputs, target)
    74. loss.backward()
    75. optimizer.step()
    76. running_loss += loss.item()
    77. if batch_idx % 300 == 299:
    78. print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
    79. running_loss = 0.0
    80. def test():
    81. correct = 0
    82. total = 0
    83. with torch.no_grad():
    84. for data in test_loader:
    85. images, labels = data
    86. outputs = model(images)
    87. _, predicted = torch.max(outputs.data, dim=1)
    88. total += labels.size(0)
    89. correct += (predicted == labels).sum().item()
    90. print('accuracy on test set: %d %% ' % (100 * correct / total))
    91. if __name__ == '__main__':
    92. for epoch in range(10):
    93. train(epoch)
    94. test()

    结果:

    1. C:\Users\ZARD\anaconda3\envs\PyTorch\python.exe C:/Users/ZARD/PycharmProjects/pythonProject/机器学习库/PyTorch实战课程内容/lecture10/CNN_plus.py
    2. [1, 300] loss: 0.884
    3. [1, 600] loss: 0.224
    4. [1, 900] loss: 0.144
    5. accuracy on test set: 96 %
    6. [2, 300] loss: 0.108
    7. [2, 600] loss: 0.095
    8. [2, 900] loss: 0.087
    9. accuracy on test set: 97 %
    10. [3, 300] loss: 0.077
    11. [3, 600] loss: 0.068
    12. [3, 900] loss: 0.069
    13. accuracy on test set: 98 %
    14. [4, 300] loss: 0.060
    15. [4, 600] loss: 0.060
    16. [4, 900] loss: 0.062
    17. accuracy on test set: 98 %

     

    4.3 residual Network 

     

     

     

    4.3.1 Residual Block的代码实现

     

     代码:
     

    1. # design model using class
    2. class ResidualBlock(nn.Module):
    3. def __init__(self, channels):
    4. super(ResidualBlock, self).__init__()
    5. self.channels = channels
    6. self.conv1 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
    7. self.conv2 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
    8. def forward(self, x):
    9. y = F.relu(self.conv1(x))
    10. y = self.conv2(y)
    11. return F.relu(x + y)
    12. class Net(nn.Module):
    13. def __init__(self):
    14. super(Net, self).__init__()
    15. self.conv1 = nn.Conv2d(1, 16, kernel_size=5)
    16. self.conv2 = nn.Conv2d(16, 32, kernel_size=5) # 88 = 24x3 + 16
    17. self.rblock1 = ResidualBlock(16)
    18. self.rblock2 = ResidualBlock(32)
    19. self.mp = nn.MaxPool2d(2)
    20. self.fc = nn.Linear(512, 10) # 暂时不知道1408咋能自动出来的
    21. def forward(self, x):
    22. in_size = x.size(0)
    23. x = self.mp(F.relu(self.conv1(x)))
    24. x = self.rblock1(x)
    25. x = self.mp(F.relu(self.conv2(x)))
    26. x = self.rblock2(x)
    27. x = x.view(in_size, -1)
    28. x = self.fc(x)
    29. return x

     完整代码:
     

    1. import torch
    2. import torch.nn as nn
    3. from torchvision import transforms
    4. from torchvision import datasets
    5. from torch.utils.data import DataLoader
    6. import torch.nn.functional as F
    7. import torch.optim as optim
    8. # prepare dataset
    9. batch_size = 64
    10. transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]) # 归一化,均值和方差
    11. train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, download=True, transform=transform)
    12. train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
    13. test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, download=True, transform=transform)
    14. test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)
    15. # design model using class
    16. class ResidualBlock(nn.Module):
    17. def __init__(self, channels):
    18. super(ResidualBlock, self).__init__()
    19. self.channels = channels
    20. self.conv1 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
    21. self.conv2 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
    22. def forward(self, x):
    23. y = F.relu(self.conv1(x))
    24. y = self.conv2(y)
    25. return F.relu(x + y)
    26. class Net(nn.Module):
    27. def __init__(self):
    28. super(Net, self).__init__()
    29. self.conv1 = nn.Conv2d(1, 16, kernel_size=5)
    30. self.conv2 = nn.Conv2d(16, 32, kernel_size=5) # 88 = 24x3 + 16
    31. self.rblock1 = ResidualBlock(16)
    32. self.rblock2 = ResidualBlock(32)
    33. self.mp = nn.MaxPool2d(2)
    34. self.fc = nn.Linear(512, 10) # 暂时不知道1408咋能自动出来的
    35. def forward(self, x):
    36. in_size = x.size(0)
    37. x = self.mp(F.relu(self.conv1(x)))
    38. x = self.rblock1(x)
    39. x = self.mp(F.relu(self.conv2(x)))
    40. x = self.rblock2(x)
    41. x = x.view(in_size, -1)
    42. x = self.fc(x)
    43. return x
    44. model = Net()
    45. # construct loss and optimizer
    46. criterion = torch.nn.CrossEntropyLoss()
    47. optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    48. # training cycle forward, backward, update
    49. def train(epoch):
    50. running_loss = 0.0
    51. for batch_idx, data in enumerate(train_loader, 0):
    52. inputs, target = data
    53. optimizer.zero_grad()
    54. outputs = model(inputs)
    55. loss = criterion(outputs, target)
    56. loss.backward()
    57. optimizer.step()
    58. running_loss += loss.item()
    59. if batch_idx % 300 == 299:
    60. print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
    61. running_loss = 0.0
    62. def test():
    63. correct = 0
    64. total = 0
    65. with torch.no_grad():
    66. for data in test_loader:
    67. images, labels = data
    68. outputs = model(images)
    69. _, predicted = torch.max(outputs.data, dim=1)
    70. total += labels.size(0)
    71. correct += (predicted == labels).sum().item()
    72. print('accuracy on test set: %d %% ' % (100 * correct / total))
    73. if __name__ == '__main__':
    74. for epoch in range(10):
    75. train(epoch)
    76. test()

     运行结果:
     

    1. C:\Users\ZARD\anaconda3\envs\PyTorch\python.exe C:/Users/ZARD/PycharmProjects/pythonProject/机器学习库/PyTorch实战课程内容/lecture10/aaa.py
    2. [1, 300] loss: 0.509
    3. [1, 600] loss: 0.155
    4. [1, 900] loss: 0.107
    5. accuracy on test set: 97 %
    6. [2, 300] loss: 0.087
    7. [2, 600] loss: 0.076
    8. [2, 900] loss: 0.073
    9. accuracy on test set: 98 %
    1. import torch
    2. from torch.utils.data import DataLoader #我们要加载数据集的
    3. from torchvision import transforms #数据的原始处理
    4. from torchvision import datasets #pytorch十分贴心的为我们直接准备了这个数据集
    5. import torch.nn.functional as F#激活函数
    6. import torch.optim as optim
    7. batch_size = 64
    8. #我们拿到的图片是pillow,我们要把他转换成模型里能训练的tensor也就是张量的格式
    9. transform = transforms.Compose([transforms.ToTensor()])
    10. #加载训练集,pytorch十分贴心的为我们直接准备了这个数据集,注意,即使你没有下载这个数据集
    11. #在函数中输入download=True,他在运行到这里的时候发现你给的路径没有,就自动下载
    12. train_dataset = datasets.MNIST(root='../data', train=True, download=True, transform=transform)
    13. train_loader = DataLoader(dataset=train_dataset, shuffle=True, batch_size=batch_size)
    14. #同样的方式加载一下测试集
    15. test_dataset = datasets.MNIST(root='../data', train=False, download=True, transform=transform)
    16. test_loader = DataLoader(dataset=test_dataset, shuffle=False, batch_size=batch_size)
    17. #接下来我们看一下模型是怎么做的
    18. class Net(torch.nn.Module):
    19. def __init__(self):
    20. super(Net, self).__init__()
    21. #定义了我们第一个要用到的卷积层,因为图片输入通道为1,第一个参数就是1
    22. #输出的通道为10,kernel_size是卷积核的大小,这里定义的是5x5的
    23. self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
    24. #看懂了上面的定义,下面这个你肯定也能看懂
    25. self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5)
    26. #再定义一个池化层
    27. self.pooling = torch.nn.MaxPool2d(2)
    28. #最后是我们做分类用的线性层
    29. self.fc = torch.nn.Linear(320, 10)
    30. #下面就是计算的过程
    31. def forward(self, x):
    32. # Flatten data from (n, 1, 28, 28) to (n, 784)
    33. batch_size = x.size(0) #这里面的0是x大小第1个参数,自动获取batch大小
    34. #输入x经过一个卷积层,之后经历一个池化层,最后用relu做激活
    35. x = F.relu(self.pooling(self.conv1(x)))
    36. #再经历上面的过程
    37. x = F.relu(self.pooling(self.conv2(x)))
    38. #为了给我们最后一个全连接的线性层用
    39. #我们要把一个二维的图片(实际上这里已经是处理过的)20x4x4张量变成一维的
    40. x = x.view(batch_size, -1) # flatten
    41. #经过线性层,确定他是0~9每一个数的概率
    42. x = self.fc(x)
    43. return x
    44. model = Net()#实例化模型
    45. #把计算迁移到GPU
    46. device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    47. model.to(device)
    48. #定义一个损失函数,来计算我们模型输出的值和标准值的差距
    49. criterion = torch.nn.CrossEntropyLoss()
    50. #定义一个优化器,训练模型咋训练的,就靠这个,他会反向的更改相应层的权重
    51. optimizer = optim.SGD(model.parameters(),lr=0.1,momentum=0.5)#lr为学习率
    52. def train(epoch):
    53. running_loss = 0.0
    54. for batch_idx, data in enumerate(train_loader, 0):#每次取一个样本
    55. inputs, target = data
    56. inputs, target = inputs.to(device), target.to(device)
    57. #优化器清零
    58. optimizer.zero_grad()
    59. # 正向计算一下
    60. outputs = model(inputs)
    61. #计算损失
    62. loss = criterion(outputs, target)
    63. #反向求梯度
    64. loss.backward()
    65. #更新权重
    66. optimizer.step()
    67. #把损失加起来
    68. running_loss += loss.item()
    69. #每300次输出一下数据
    70. if batch_idx % 300 == 299:
    71. print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 2000))
    72. running_loss = 0.0
    73. def test():
    74. correct = 0
    75. total = 0
    76. with torch.no_grad():#不用算梯度
    77. for data in test_loader:
    78. inputs, target = data
    79. inputs, target = inputs.to(device), target.to(device)
    80. outputs = model(inputs)
    81. #我们取概率最大的那个数作为输出
    82. _, predicted = torch.max(outputs.data, dim=1)
    83. total += target.size(0)
    84. #计算正确率
    85. correct += (predicted == target).sum().item()
    86. print('Accuracy on test set: %d %% [%d/%d]' % (100 * correct / total, correct, total))
    87. if __name__=='__main__':
    88. for epoch in range(10):
    89. train(epoch)
    90. if epoch % 10 == 9:
    91. test()

     

    深度学习10—卷积神经网络(复盘总结)

    1. 先要掌握全连接网络。定义一个全连接网络:class Net(torch.nn.Module),其中包含def __init__()和def forward()的设置;

    卷积:
    (1) 辨析“一个卷积核”和“一个卷积核的一个通道”。一个卷积核可能包含多个通道。卷积核的通道数cahnnel是由被其处理的数据决定的。比如,被做卷积处理的数据的channel=3,那么就需要一个3通道的卷积核来进行卷积操作。将这3通道处理的数据对应相加,就变成了1通道,这样就实现了降维操作。

    1. 若要将一个输入为n通道的数据,转化为m通道的数据,则需要通道为n的m个卷积核;
    2. 在程序中实现输入层、卷积层torch.nn.Conv2d(输入通道n,输出通道m,卷积核大小)、输出层;
    3. 对卷积核的定义:kernel = torch.Tensor([1,2,3,4,5,6,7,8,9]).view(1,1,3,3);将卷积核作为权重赋值给卷积层中对应的数据:conv_layer.weight.data = kernel.data
    4. Padding填充:比如,输入一个5*5的数据,通过3*3的卷积核,得到的是3*3的输出。如果想要得到也是5*5的输出,就得在原输入数据的基础上做一个填充处理。关于在原输入数据外围填充多少圈的计算方法是:若卷积核是a*a的,那么就填充(a/2得到的整数部分数值)的圈数。
    5. Stride步长
    6. 池化层,下采样。通道数不变。Torch.nn.MaxPool2d(kernel_size=n)。其中分最大池化和平均池化两类;
    7. 最后以全连接层作为输出;

    卷积神经网络进阶:
    (1)1*1卷积的作用在于改变输入数据的通道。其好处在于,使用1*1卷积后,会极大降低计算周期。

    (2)将不同的网络结构抽象为Inception类,即将不同的网络分支定义在一个class Inception(nn.Module)中,并将计算得到的值通过torch.cat()进行拼接,并作为forward()函数的返回值。(将某分支网络抽象为一个Inception类,然后计算各层分支的卷积和)

    (3)在构造的网络class Net(nn.Module)中调用如上定义的Inception类,要注意的是,调用Inception类的实例后,数据的通道数就变成了Inception类实例返回的各个网络分支结构的通道数之和,因此在调用Inception类的实例后,下一网络层的输入通道数就应该是各个网络分支结构的通道数之和。

    (4)residual Network:在训练网络的过程中,在回传时可能会存在梯度消失的问题。解决的方法是先将F(x)与x相加,再通过激活函数去激活。(其实这一部分了解得还还不够丰富,后续学习需要注意)

      


     

  • 相关阅读:
    齐岳|近红外染料CY7.5标记PCL聚已内酯纳米载体CY7.5-PCL|PCL-CY7.5|CY7.5-PEG-PCL
    字符串函数
    Vue axios和vue-axios的关系及使用区别
    Linux 完整 Redis 安装配置教程(可用远程连接)
    面试官:说一下网络数据传输的具体流程
    c++------类和对象(下)包含了this指针、构造函数、析构函数、拷贝构造等
    【shell学习】企业运维工作中常用的shell脚本
    异构AI算力操作平台的架构设计与优化策略
    马达步进机工作原理
    自定义springboot-start
  • 原文地址:https://blog.csdn.net/m0_55196097/article/details/127137067