CNN

卷积神经网络(Convolutional Neural Network,CNN)是一种专门设计用于处理图像数据的深度学习模型。它的设计灵感来自于生物学中对动物视觉系统的理解,特别是动物视觉皮层中的神经元对视觉刺激的处理方式。

CNN的核心思想是通过卷积层和池化层来提取图像中的特征,并通过全连接层将这些特征映射到输出类别。下面是CNN的主要组成部分:

  1. 卷积层(Convolutional Layer):卷积层是CNN中最重要的部分之一。它通过使用一系列可学习的滤波器(也称为卷积核)对输入图像进行卷积操作。每个滤波器会在输入图像上滑动,并计算滤波器与图像局部区域的卷积,生成特征图。这些特征图捕获了输入图像中的不同特征,如边缘、纹理等。
  2. 池化层(Pooling Layer):池化层用于减少特征图的尺寸,并增强模型的平移不变性(即特征的位置不会影响识别结果)。常用的池化操作包括最大池化和平均池化。最大池化取局部区域的最大值作为池化后的值,而平均池化取局部区域的平均值。
  3. 激活函数(Activation Function):通常在卷积层之后会使用非线性的激活函数,如ReLU(Rectified Linear Unit),用于引入非线性特征。ReLU函数能够将负数值映射为0,保留正数值不变,有助于网络学习更复杂的特征。
  4. 全连接层(Fully Connected Layer):在卷积层和池化层提取图像特征后,全连接层将这些特征映射到输出类别。全连接层中的每个神经元与前一层中的所有神经元都有连接关系,因此称为全连接。

CNN通过堆叠多个卷积层、池化层和全连接层来构建深度网络,从而学习图像数据中更高级别的抽象特征,如物体形状、结构等。这种层级结构使得CNN在图像分类、目标检测、图像分割等任务中取得了很好的表现,并成为图像处理领域的重要工具。

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
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms

# 定义CNN模型
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5) # 输入通道数为3,输出通道数为6,卷积核大小为5x5
self.pool = nn.MaxPool2d(2, 2) # 最大池化层,池化窗口大小为2x2
self.conv2 = nn.Conv2d(6, 16, 5) # 输入通道数为6,输出通道数为16,卷积核大小为5x5
self.fc1 = nn.Linear(16 * 5 * 5, 120) # 全连接层,输入大小为16*5*5,输出大小为120
self.fc2 = nn.Linear(120, 84) # 全连接层,输入大小为120,输出大小为84
self.fc3 = nn.Linear(84, 10) # 全连接层,输入大小为84,输出大小为10(类别数)

def forward(self, x):
x = self.pool(nn.functional.relu(self.conv1(x))) # 第一层卷积 -> 激活 -> 池化
x = self.pool(nn.functional.relu(self.conv2(x))) # 第二层卷积 -> 激活 -> 池化
x = x.view(-1, 16 * 5 * 5) # 将特征张量展平
x = nn.functional.relu(self.fc1(x)) # 第一层全连接 -> 激活
x = nn.functional.relu(self.fc2(x)) # 第二层全连接 -> 激活
x = self.fc3(x) # 第三层全连接
return x

# 加载数据集
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, 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=4, shuffle=False, num_workers=2)

# 定义类别标签
classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

# 初始化模型、损失函数和优化器
net = CNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

# 训练网络
for epoch in range(2): # 训练数据集迭代两次
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 2000 == 1999: # 每2000个小批量数据打印一次损失值
print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000))
running_loss = 0.0

print('Finished Training')

# 保存训练好的模型
PATH = './cifar_net.pth'
torch.save(net.state_dict(), PATH)

# 测试网络
dataiter = iter(testloader)
images, labels = dataiter.next()

# 输出图像
print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))

# 加载模型
net = CNN()
net.load_state_dict(torch.load(PATH))

# 计算模型预测
outputs = net(images)

# 获取最大预测值的索引
_, predicted = torch.max(outputs, 1)

# 输出预测结果
print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(4)))

RNN

循环神经网络(Recurrent Neural Network,RNN)是一种专门用于处理序列数据的神经网络模型。与传统的前馈神经网络不同,RNN具有循环结构,能够通过时间步连接自身,从而使得信息可以在网络中持续传递。

RNN的主要特点是它可以接受任意长度的输入序列,并且在处理序列数据时能够考虑上下文信息。这使得RNN在自然语言处理(如语言建模、机器翻译)、时间序列分析(如股票预测、天气预测)等任务中得到广泛应用。

RNN的基本结构包括:

  1. 循环连接(Recurrent Connection):RNN中的循环结构允许信息从当前时间步传递到下一个时间步。这种连接允许RNN对序列数据进行处理,并保留了序列中的顺序信息。
  2. 隐藏状态(Hidden State):在每个时间步,RNN都会输出一个隐藏状态,用于捕获序列数据中的特征和信息。隐藏状态会被传递到下一个时间步,并参与到下一步的计算中。
  3. 循环神经元(Recurrent Neurons):RNN中的循环神经元是网络的核心组件,负责接收输入和隐藏状态,并生成新的隐藏状态。通常,循环神经元会使用激活函数来引入非线性,以便网络能够学习复杂的序列模式。

RNN虽然具有处理序列数据的能力,但也存在一些问题,比如长期依赖(Long-Term Dependencies)问题,即当序列长度较长时,RNN很难捕捉到远处时间步的信息,导致性能下降。为了解决这个问题,出现了长短期记忆网络(LSTM)和门控循环单元(GRU)等变种结构,它们通过引入门控机制来更好地捕捉长期依赖关系,从而提高了模型的性能。

总之,RNN是一种能够处理序列数据的神经网络模型,通过循环连接和隐藏状态的传递,在序列数据的建模和预测任务中取得了广泛的应用。

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
import torch
import torch.nn as nn
import torch.optim as optim

# 定义RNN模型
class RNN(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(RNN, self).__init__()
self.hidden_size = hidden_size
self.i2h = nn.Linear(input_size + hidden_size, hidden_size)
self.i2o = nn.Linear(input_size + hidden_size, output_size)
self.softmax = nn.LogSoftmax(dim=1)

def forward(self, input, hidden):
combined = torch.cat((input, hidden), 1)
hidden = self.i2h(combined)
output = self.i2o(combined)
output = self.softmax(output)
return output, hidden

def init_hidden(self):
return torch.zeros(1, self.hidden_size)

# 数据准备
input_size = 3
hidden_size = 5
output_size = 2
rnn = RNN(input_size, hidden_size, output_size)

# 定义损失函数和优化器
criterion = nn.NLLLoss()
optimizer = optim.SGD(rnn.parameters(), lr=0.01)

# 训练模型
def train(input_tensor, target_tensor):
hidden = rnn.init_hidden()
optimizer.zero_grad()
loss = 0

for i in range(input_tensor.size(0)):
output, hidden = rnn(input_tensor[i], hidden)
loss += criterion(output, target_tensor[i])

loss.backward()
optimizer.step()

return output, loss.item() / input_tensor.size(0)

# 示例训练过程
input_tensor = torch.tensor([[0.1, 0.2, 0.3], [0.2, 0.3, 0.4], [0.3, 0.4, 0.5]])
target_tensor = torch.tensor([0, 1, 0])
output, loss = train(input_tensor, target_tensor)
print("Output:", output)
print("Loss:", loss)

LSTM

长短期记忆网络(Long Short-Term Memory,LSTM)是一种特殊的循环神经网络(RNN)变体,设计用于解决传统RNN中的长期依赖问题。长期依赖问题是指在传统RNN中,当序列长度较长时,难以有效捕捉到远距离时间步的依赖关系,导致模型性能下降。

LSTM通过引入特殊的记忆单元(memory cell)和门控机制来解决这个问题。它的核心思想是通过三个门控单元来控制信息的流动:遗忘门(forget gate)、输入门(input gate)和输出门(output gate)。这些门控单元能够选择性地记住或忘记之前的信息,从而更好地处理序列数据中的长期依赖关系。

以下是LSTM的主要组成部分:

  1. 记忆单元(Memory Cell):记忆单元是LSTM的核心组件,用于存储和传递信息。记忆单元允许网络在长序列中保持信息,并且可以选择性地忘记或存储信息。
  2. 遗忘门(Forget Gate):遗忘门决定了在当前时间步应该保留多少之前的记忆。它根据当前输入和前一个隐藏状态来计算一个介于0和1之间的值,表示需要保留的之前的记忆信息。
  3. 输入门(Input Gate):输入门决定了当前时间步应该更新多少新的记忆。它根据当前输入和前一个隐藏状态来计算一个介于0和1之间的值,表示需要更新的新信息。
  4. 输出门(Output Gate):输出门决定了当前时间步记忆单元中的信息应该输出多少到当前时间步的隐藏状态中。它根据当前输入和前一个隐藏状态来计算一个介于0和1之间的值,表示输出的信息量。

通过这些门控机制,LSTM能够更有效地处理序列数据中的长期依赖关系,使得模型在处理时间序列数据、自然语言处理等任务中取得了更好的效果。

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
# 不使用nn.LSTM
import torch
import torch.nn as nn
import torch.optim as optim

# 定义LSTM模型
class CustomLSTM(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(CustomLSTM, self).__init__()
self.hidden_size = hidden_size
self.W_i = nn.Parameter(torch.randn(input_size, hidden_size * 4))
self.W_h = nn.Parameter(torch.randn(hidden_size, hidden_size * 4))
self.b = nn.Parameter(torch.randn(hidden_size * 4))
self.fc = nn.Linear(hidden_size, output_size)
self.sigmoid = nn.Sigmoid()
self.tanh = nn.Tanh()

def forward(self, input):
batch_size = input.size(0)
seq_len = input.size(1)
hidden_state = torch.zeros(batch_size, self.hidden_size)
cell_state = torch.zeros(batch_size, self.hidden_size)
for i in range(seq_len):
combined = torch.matmul(input[:, i, :], self.W_i) + torch.matmul(hidden_state, self.W_h) + self.b
gates = combined[:, :3 * self.hidden_size].sigmoid()
input_gate = gates[:, :self.hidden_size]
forget_gate = gates[:, self.hidden_size:2 * self.hidden_size]
output_gate = gates[:, -self.hidden_size:]
cell_input = combined[:, 3 * self.hidden_size:].tanh()
cell_state = forget_gate * cell_state + input_gate * cell_input
hidden_state = output_gate * cell_state.tanh()
output = self.fc(hidden_state)
return output

# 数据准备
input_size = 3
hidden_size = 5
output_size = 2
lstm = CustomLSTM(input_size, hidden_size, output_size)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(lstm.parameters(), lr=0.01)

# 训练模型
def train(input_tensor, target_tensor):
optimizer.zero_grad()
output = lstm(input_tensor)
loss = criterion(output, target_tensor)
loss.backward()
optimizer.step()
return output, loss.item()

# 示例训练过程
input_tensor = torch.tensor([[[0.1, 0.2, 0.3], [0.2, 0.3, 0.4], [0.3, 0.4, 0.5]]])
target_tensor = torch.tensor([0])
output, loss = train(input_tensor, target_tensor)
print("Output:", output)
print("Loss:", loss)
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
#使用nn.LSTM
import torch
import torch.nn as nn
import torch.optim as optim

# 定义LSTM模型
class LSTM(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(LSTM, self).__init__()
self.hidden_size = hidden_size
self.lstm = nn.LSTM(input_size, hidden_size)
self.fc = nn.Linear(hidden_size, output_size)

def forward(self, input):
lstm_out, _ = self.lstm(input.view(len(input), 1, -1))
output = self.fc(lstm_out[-1])
return output

# 数据准备
input_size = 3
hidden_size = 5
output_size = 2
lstm = LSTM(input_size, hidden_size, output_size)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(lstm.parameters(), lr=0.01)

# 训练模型
def train(input_tensor, target_tensor):
optimizer.zero_grad()
output = lstm(input_tensor)
loss = criterion(output, target_tensor)
loss.backward()
optimizer.step()
return output, loss.item()

# 示例训练过程
input_tensor = torch.tensor([[0.1, 0.2, 0.3], [0.2, 0.3, 0.4], [0.3, 0.4, 0.5]])
target_tensor = torch.tensor([0, 1])
output, loss = train(input_tensor, target_tensor)
print("Output:", output)
print("Loss:", loss)