assignment_2_DNN网络搭建

DNN的定义

深度神经网络(Deep Neural Network,简称DNN)是一种包含多个隐藏层的神经网络。与传统的浅层神经网络相比,DNN能够学习更复杂的数据特征和模式,这使得它们在处理高维度数据和解决复杂问题方面表现出色。

pk4Bk8g.png

DNN原理

DNN的原理基于以下几个关键概念:

  1. 层次结构:DNN由多个层次组成,包括输入层、多个隐藏层和输出层。每个层次包含多个神经元。
    • 多层次非线性变换: 每一层神经元通过接收前一层的输出,并通过非线性激活函数(如sigmoid、ReLU等)进行处理,将原始数据逐步转化为更抽象和复杂的特征表示。在图像识别任务中,底层神经元可能学习到边缘、纹理等低级特征,而高层神经元则能够捕捉到更高级别的特征,如物体的部件和整体形态。
  2. 参数化:每个神经元与前一个层次的神经元通过权重连接,并且每个神经元有一个偏置项。
  3. 前向传播:输入数据在网络中前向传递,每层的输出是下一层的输入。
  4. 激活函数:在每层的输出上应用非线性激活函数,以引入非线性特性,使网络能够学习复杂的函数。
  5. 损失函数:定义一个损失函数来衡量模型预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)和交叉熵损失。
  6. 反向传播:利用链式法则计算损失函数对每个参数的梯度,从而更新网络的权重和偏置。
    • 反向传播与优化:DNN的训练采用反向传播算法(Backpropagation)配合梯度下降(Gradient Descent)或其他优化算法(如Adam、Adagrad等),通过计算损失函数相对于权重的梯度,更新网络权重以最小化损失函数,从而实现对训练数据的良好拟合。
  7. 优化算法:使用梯度下降或其变体(如Adam、RMSprop等)来更新网络的参数,以最小化损失函数。

DNN模型构建步骤

构建DNN模型通常遵循以下步骤:

  1. 定义网络结构:确定网络的层数、每层的神经元数量以及激活函数。
  2. 初始化参数:为网络中的权重和偏置分配初始值,通常使用随机初始化。
  3. 选择损失函数:根据任务类型(如分类或回归)选择合适的损失函数。
  4. 选择优化器:选择一个优化算法来更新网络的参数。
  5. 前向传播:在训练数据上执行前向传播,计算预测输出。
  6. 计算损失:使用损失函数计算预测输出与真实标签之间的差异。
  7. 反向传播:执行反向传播算法,计算损失相对于每个参数的梯度。
  8. 参数更新:根据计算出的梯度和选择的学习率更新网络的参数。
  9. 迭代训练:重复步骤5到8,直到模型在验证集上的性能不再显著提升或达到预定的迭代次数。
  10. 评估和调优:在测试集上评估模型性能,根据需要调整网络结构或训练过程。
  11. 应用模型:将训练好的模型应用于实际问题或数据。

DNN模型的构建和训练是一个迭代和试错的过程,可能需要多次调整和优化以达到最佳性能。

代码实现

下面用一个识别手写数字的例子来搭建深度神经网络(DNN)

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets,transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt

torch.manual_seed(1024)
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,),(0.5,))
])
train_dataset = datasets.MNIST(root='./data',train=True,transform=transforms.ToTensor(),download=False)
# load test set
test_dataset = datasets.MNIST(root='./data',train=False,transform=transforms.ToTensor(),download=False)
train_loader = DataLoader(train_dataset,batch_size=64,shuffle=True)
test_loader = DataLoader(test_dataset,batch_size=64,shuffle=False)
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(28 * 28, 256)
self.fc2 = nn.Linear(256, 128)
self.fc3 = nn.Linear(128, 64)
self.fc4 = nn.Linear(64, 10)

def forward(self,x):
x = torch.flatten(x,start_dim=1)
x = torch.relu(self.fc1(x))
x = torch.relu(self.fc2(x))
x = torch.relu(self.fc3(x))
x = self.fc4(x)
return x
net = Net()
print(net)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), lr=0.001)
train_losses = []
train_accuracies = []
test_accuracies = []
epochs = 10
best_accuracy = 0.0
best_model_path = 'best_mnist_path.pth'

for epoch in range(epochs):
running_loss = 0.0
correct_train = 0
total_train = 0

# 训练过程
net.train()
for inputs,labels in train_loader:
optimizer.zero_grad() # 梯度清零
outputs = net(inputs) # 前向传播
loss = criterion(outputs,labels) # 计算损失
loss.backward() # 反向传播
optimizer.step() # 更新参数
running_loss += loss.item() # 累加损失

_,predicted = torch.max(outputs,1)
total_train += labels.size(0) # 累加样本数量
correct_train += (predicted == labels).sum().item()
train_accuracy = correct_train / total_train
train_losses.append(running_loss / len(train_loader))
train_accuracies.append((train_accuracy))

print(f"Epoch {epoch + 1} / {epochs}, Loss: {running_loss / len(train_loader):.4f},Train Accuracy :{train_accuracy:.2%}")
net.eval()
correct = 0
total = 0
with torch.no_grad():
for inputs,labels in test_loader:
outputs = net(inputs)
_,predicted = torch.max(outputs,1)
total += labels.size(0)
correct += (predicted == labels).sum().item()

test_accuracy = correct / total
test_accuracies.append(test_accuracy)
print(f"Epoch {epoch+1}/{epochs},Test Accuracy:{test_accuracy:.2%}")
if test_accuracy > best_accuracy:
best_accuracy = test_accuracy
torch.save(net.state_dict(),best_model_path)
print(f"Best model saved with accuracy:{best_accuracy:.2%}")
print(f"Best Accuracy on test set:{best_accuracy:.2%}")
plt.figure(figsize=(12,5))
plt.subplot(1,2,1)
plt.plot(train_losses,label='Training Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training Loss over Epochs')
plt.legend()
plt.grid(True)
plt.subplot(1,2,2)
plt.plot(train_accuracies,label='Train Accuracy')
plt.plot(test_accuracies,label='Test Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.title('Train and Test Accuracy over Epochs')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.savefig('loss_and_accuracy_curves.png')
plt.show()

实现细节注释

参考


assignment_2_DNN网络搭建
https://fu-jingqi.github.io/2024/07/12/assignment-2-DNN网络搭建/
作者
coderfjq
发布于
2024年7月12日
许可协议