Pytorch学习笔记
1. 整个过程的学习思路将按照是什么、怎么用、为什么这样用来学习
2.本篇基于chatGPT完成学习
3.部分为什么在代码注释中已有体现,故不再赘述
第一课 安装
按照这一篇就可以了
(135条消息) Pytorch安装,这一篇就够了,绝不踩坑_孔德浩的博客-优快云博客
第二课 线性回归
2.1是什么
线性回归是一种广泛应用于机器学习和统计学中的监督学习算法。它用于对两个或更多变量之间的线性关系进行建模,通常用于预测或解释一个因变量(或响应变量)与一个或多个自变量(或预测变量)之间的关系。
公式:y = w*x + b
2.2怎么用
import torch
# 生成数据,x是输入,y是输出
x = torch.randn(100, 1) # 生成100个标准正态分布的随机数作为输入
y = 3 * x + 1 + 0.2 * torch.randn(100, 1) # y = 3x + 1 + 噪声,其中噪声服从标准正态分布
# 定义模型,这里使用一层线性层作为模型
model = torch.nn.Linear(1, 1)
# 定义损失函数,这里使用均方误差作为损失函数
loss_fn = torch.nn.MSELoss()
# 定义优化器,这里使用随机梯度下降作为优化器
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
# 训练模型
for epoch in range(1000): # 迭代1000次
y_pred = model(x) # 使用模型进行预测
loss = loss_fn(y_pred, y) # 计算损失值
optimizer.zero_grad() # 清空上一次迭代的梯度
loss.backward() # 计算梯度
optimizer.step() # 更新模型参数
if epoch % 100 == 0: # 每迭代100次输出一次损失值
print(f"Epoch {epoch}, Loss {loss.item():.4f}")
# 测试模型
x_test = torch.tensor([[1.0], [2.0], [3.0]])
y_pred = model(x_test)
print(y_pred)
2.3为什么这样用
因为在线性回归中,假设因变量与自变量之间存在线性关系。因此,算法将寻找一条最优拟合直线来表示这种关系。这条直线可以表示为 y = β 0 + β 1 x 1 + . . . + β n x n y = \beta_0 + \beta_1 x_1 + ... + \beta_n x_n y=β0+β1x1+...+βnxn,其中 y y y 表示因变量, x 1 , x 2 , . . . , x n x_1, x_2, ..., x_n x1,x2,...,xn 表示自变量, β 0 , β 1 , . . . , β n \beta_0, \beta_1, ..., \beta_n β0,β1,...,βn 是回归系数。这些系数用于计算预测值,从而使得预测值与实际值之间的差距最小化。
通常使用最小二乘法(loss函数)来确定这些系数的值。这意味着要找到一组系数,使得所有数据点到回归线的距离的平方和最小。不断迭代求得最优参数值。
第三课 初始化模型、损失函数、优化方法
3.1是什么
深度学习是一种机器学习方法,其核心是构建深度神经网络模型。在深度学习中,模型、损失函数和优化方法是三个重要的概念。
-
模型:深度神经网络模型是深度学习中的核心组件。它由多层神经网络组成,每一层都包含多个神经元。在训练过程中,数据通过网络进行传递和处理,最终输出预测结果。不同的神经网络结构和层数可以应用于不同的问题和数据集,例如卷积神经网络(CNN)用于图像识别,循环神经网络(RNN)用于序列数据,等等。
-
损失函数:在深度学习中,损失函数是用来衡量模型预测结果和实际结果之间的差距的函数。通常使用**均方误差(MSE)、交叉熵(cross-entropy)**等损失函数来训练深度学习模型。优化目标是最小化损失函数,以提高模型的预测能力。
-
优化方法:优化方法是用来调整模型参数以最小化损失函数的方法。深度学习中广泛使用的优化方法包括梯度下降(gradient descent)、Adam、Adagrad等。梯度下降是一种基本的优化方法,它通过计算损失函数的梯度并沿着负梯度的方向更新参数。Adam和Adagrad是一些更高级的优化方法,它们能够自适应地调整学习率以更好地训练深度学习模型。
综上所述,深度学习中的模型、损失函数和优化方法是三个密切相关的概念,它们共同作用于训练深度神经网络模型,并在不同领域取得了广泛应用。
3.2怎么用
import torch
import torch.nn as nn
import torch.optim as optim
# 定义一个简单的线性回归模型
class LinearRegression(nn.Module):
def __init__(self, input_dim, output_dim):
super(LinearRegression, self).__init__()
self.linear = nn.Linear(input_dim, output_dim)
def forward(self, x):
out = self.linear(x)
return out
# 定义模型的输入和输出维度
input_dim = 1
output_dim = 1
# 创建模型实例
model = LinearRegression(input_dim, output_dim)
# 定义损失函数
criterion = nn.MSELoss()
# 定义优化方法
learning_rate = 0.01
optimizer = optim.SGD(model.parameters(), lr=learning_rate)
# 假设有一组输入和输出数据
x = torch.tensor([1.0, 2.0, 3.0, 4.0])
y = torch.tensor([2.0, 4.0, 6.0, 8.0])
# 迭代训练模型
num_epochs = 1000
for epoch in range(num_epochs):
# 前向传播计算模型输出
outputs = model(x)
# 计算损失函数值
loss = criterion(outputs, y)
# 反向传播更新模型参数
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 打印每轮迭代的损失函数值
if (epoch+1) % 100 == 0:
print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item()))
"'
第 1-3 行:导入必要的PyTorch库。
第 5-11 行:定义一个简单的线性回归模型,包括构造函数 __init__ 和前向传播函数 forward。
第 14-15 行:定义模型的输入和输出维度。
第 17 行:创建模型实例。
第 20 行:定义损失函数为均方误差(MSE)。
第 23-24 行:定义优化方法为随机梯度下降(SGD),学习率为0.01。
第 27-28 行:定义训练数据 x 和 y。
第 31-39 行:迭代训练模型,每轮迭代包括以下步骤:
前向传播计算模型输出;
计算损失函数值;
反向传播更新模型参数;
打印每轮迭代的损失函数值。
'"
3.3为什么这样用
因为模型本身就是由一层一层的网络组成的,我们目前用的是比较基础的网络。选择了nn.MSELoss()损失函数和一般的优化方法SGD
第四课 模型训练、结果可视化
4.1是什么
深度学习中的模型训练是指通过优化模型参数来最小化损失函数,以使模型能够对输入数据进行准确的预测。训练通常包括以下步骤:
- 准备数据集:包括将数据集分成训练集、验证集和测试集,以及进行数据预处理和数据增强等操作。
- 定义模型:选择合适的网络结构、激活函数、损失函数和优化器等,并将其组装成一个完整的模型。
- 训练模型:迭代地将训练数据输入到模型中,计算损失函数并反向传播更新模型参数,直到达到预设的训练轮数或满足停止训练的条件为止。
- 评估模型:使用验证集评估模型的性能,调整模型参数以提高模型的泛化性能。
- 测试模型:最终使用测试集评估模型的性能,检查模型是否能够对新数据进行准确的预测。
结果可视化是指通过可视化工具将训练和测试结果呈现出来,以便更好地理解和分析模型的性能和行为。通常使用的可视化方法包括:
- 训练曲线:绘制损失函数随着训练轮数的变化曲线,以便了解模型在训练期间的收敛情况。
- 预测结果可视化:将模型的预测结果可视化,以便了解模型在不同数据上的表现。
- 特征可视化:可视化神经网络中的卷积层或其他层的激活值,以便了解模型对不同特征的响应情况。
- 梯度可视化:可视化模型中的梯度,以便了解模型中每个参数的影响和重要性。
- 参数可视化:可视化模型的参数,以便了解模型中每个参数的取值和变化情况。
结果可视化可以帮助我们更好地了解和调整模型,从而提高模型的性能和泛化能力。
4.2怎么用
import torch
import torchvision
import matplotlib.pyplot as plt
# 1. 数据加载和预处理
transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize((0.5,), (0.5,))])
trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
# 2. 模型定义
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = torch.nn.Conv2d(1, 32, 3, 1)
self.conv2 = torch.nn.Conv2d(32, 64, 3, 1)
self.dropout1 = torch.nn.Dropout2d(0.25)
self.dropout2 = torch.nn.Dropout2d(0.5)
self.fc1 = torch.nn.Linear(9216, 128)
self.fc2 = torch.nn.Linear(128, 10)
def forward(self, x):
x = self.conv1(x)
x = torch.nn.functional.relu(x)
x = self.conv2(x)
x = torch.nn.functional.relu(x)
x = torch.nn.functional.max_pool2d(x, 2)
x = self.dropout1(x)
x = torch.flatten(x, 1)
x = self.fc1(x)
x = torch.nn.functional.relu(x)
x = self.dropout2(x)
x = self.fc2(x)
output = torch.nn.functional.log_softmax(x, dim=1)
return output
# 3. 损失函数和优化器定义
model = Net()
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
# 4. 模型训练
for epoch in range(10):
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 100 == 99:
print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 100))
running_loss = 0.0
print('Finished Training')
# 5. 结果可视化
images, labels = iter(trainloader).next()
outputs = model(images)
_, predicted = torch.max(outputs, 1)
fig, ax = plt.subplots(figsize=(8, 8))
for i in range(16):
ax = plt.subplot(4, 4, i+1)
ax.imshow(images[i][0], cmap='gray')
ax.set_title("Predicted: {}".format(predicted[i].item()))
ax.axis('off')
plt.show()
4.3为什么这样用
我们简单地完成了模型训练功能和结果可视化工作,代码如上
第五课 张量(Tensor)
5.1是什么
在深度学习中,张量是一种多维数组,类似于向量和矩阵,但可以有任意数量的维度。在PyTorch中,张量是一个torch.Tensor对象,可以用于存储和操作数据。
5.2怎么用
import torch
# 创建一个2x3的浮点型张量
a = torch.FloatTensor([[1, 2, 3], [4, 5, 6]])
print(a)
# tensor([[1., 2., 3.],
# [4., 5., 6.]])
# 创建一个3x2的整型张量
b = torch.IntTensor([[7, 8], [9, 10], [11, 12]])
print(b)
# tensor([[ 7, 8],
# [ 9, 10],
# [11, 12]], dtype=torch.int32)
# 创建一个随机的3x3的张量
c = torch.randn(3, 3)
print(c)
# tensor([[-1.6661, 0.7482, 0.2695],
# [ 1.3691, -0.0424, -0.3479],
# [-1.1927, 1.0337, -0.5743]])
# 将a和b张量相乘,结果为一个2x2的张量
d = torch.mm(a, b)
print(d)
# tensor([[ 58., 64.],
# [139., 154.]])
# 将a和d张量相加,结果为一个2x2的张量
e = a + d
print(e)
# tensor([[ 59., 66.],
# [143., 159.]])
# 将e张量转化为一个numpy数组
f = e.numpy()
print(f)
# array([[ 59., 66.],
# [143., 159.]], dtype=float32)
第六课 numpy
6.1是什么
NumPy是一个Python包,提供了处理多维数组和矩阵的功能,也包含了一些数学函数库,是进行科学计算的基础库之一。
6.2怎么用
import numpy as np
# 创建一个3x3的数组
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(a)
# array([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9]])
# 打印数组的形状和数据类型
print(a.shape)
# (3, 3)
print(a.dtype)
# int32
# 创建一个3x3的全0数组
b = np.zeros((3, 3))
print(b)
# array([[0., 0., 0.],
# [0., 0., 0.],
# [0., 0., 0.]])
# 创建一个3x3的全1数组
c = np.ones((3, 3))
print(c)
# array([[1., 1., 1.],
# [1., 1., 1.],
# [1., 1., 1.]])
# 将a和c数组相加,结果为一个3x3的数组
d = a + c
print(d)
# array([[ 2., 3., 4.],
# [ 5., 6., 7.],
# [ 8., 9., 10.]])
# 将a数组转化为一个列表
e = a.tolist()
print(e)
# [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
第七课 panda
7.1是什么
Pandas是一个Python的第三方库,用于数据处理和数据分析,主要提供了两个重要的数据结构:Series和DataFrame。
7.2怎么用
import pandas as pd
# 创建一个Series对象
s = pd.Series([1, 3, 5, np.nan, 6, 8])
print(s)
# 0 1.0
# 1 3.0
# 2 5.0
# 3 NaN
# 4 6.0
# 5 8.0
# dtype: float64
# 创建一个DataFrame对象
dates = pd.date_range('20220101', periods=6)
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD'))
print(df)
# A B C D
# 2022-01-01 -0.266826 -0.190583 -1.717356 -1.166508
# 2022-01-02 0.056252 0.141524 0.451517 0.277314
# 2022-01-03 -0.278475 0.244017 0.775764 -0.024066
# 2022-01-04 -1.018408 -0.668607 -0.401710 1.471810
# 2022-01-05 0.004640 -0.019361 1.388217 -0.446747
# 2022-01-06 -0.523668 0.925784 0.347915 -0.011667
# 查看DataFrame的列标签和行标签
print(df.columns)
# Index(['A', 'B', 'C', 'D'], dtype='object')
print(df.index)
# DatetimeIndex(['2022-01-01', '2022-01-02', '2022-01-03', '2022-01-04',
# '2022-01-05', '2022-01-06'],
# dtype='datetime64[ns]', freq='D')
# 对DataFrame进行描述性统计
print(df.describe())
# A B C D
# count 6.000000 6.000000 6.000000 6.000000
# mean -0.283520 0.064649 0.192541 0.145495
# std 0.446812 0.519024 1.058564 0.959843
# min -1.018408 -0.668607 -1.717356 -1.166508
# 25% -0.442203 -0.160100 -0.248885 -0.345843
# 50% -0.272150 0.061082 0.399716 -0.017867
# 75% -0.002698 0.225932 0.704260 0.231547
# max 0.056252 0.925784 1.388217 1.471810
三者转化:
import numpy as np
import pandas as pd
import torch
# 创建一个numpy数组
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr)
# [[1 2 3]
# [4 5 6]]
# 将numpy数组转化为tensor类型数据
tensor = torch.from_numpy(arr)
print(tensor)
# tensor([[1, 2, 3],
# [4, 5, 6]])
# 将tensor类型数据转化为numpy数组
arr = tensor.numpy()
print(arr)
# [[1 2 3]
# [4 5 6]]
# 创建一个pandas DataFrame
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
print(df)
# A B
# 0 1 4
# 1 2 5
# 2 3 6
# 将pandas DataFrame转化为tensor类型数据
tensor = torch.from_numpy(df.values)
print(tensor)
# tensor([[1, 4],
# [2, 5],
# [3, 6]])
# 将tensor类型数据转化为pandas DataFrame
df = pd.DataFrame(tensor.numpy(), columns=['A', 'B'])
print(df)
# A B
# 0 1 4
# 1 2 5
# 2 3 6
"'注释如下:
第5-7行创建一个numpy数组,并使用print函数打印数组。
第10行将numpy数组转换为tensor类型数据,并使用print函数打印tensor。
第14行将tensor类型数据转换为numpy数组,并使用print函数打印数组。
第17-19行创建一个pandas DataFrame,并使用print函数打印DataFrame。
第22行将pandas DataFrame转化为tensor类型数据,并使用print函数打印tensor。
第26-28行将tensor类型数据转化为pandas DataFrame,并使用print函数打印DataFrame。'"
第八课 梯度求导
8.1是什么
在机器学习和深度学习中,梯度是指函数在某一点处的变化率,也可以理解为函数在该点处的导数。梯度在深度学习中常常用于求解模型参数的更新方向和步长,以最小化损失函数。
8.2怎么用
import torch
# 定义一个tensor变量x,并使其requires_grad=True以启用自动求导
x = torch.tensor([2.0], requires_grad=True)
# 定义一个函数f(x) = x^2 + 2x + 1
def f(x):
return x**2 + 2*x + 1
# 在x处计算函数f的值
y = f(x)
print(y) # tensor([9.], grad_fn=<AddBackward0>)
# 使用autograd库自动求解y关于x的梯度
y.backward()
# 输出x的梯度
print(x.grad) # tensor([6.])
"
这段代码首先定义了一个tensor变量x,并使用requires_grad=True来启用自动求导。接着定义了一个函数f(x) = x^2 + 2x + 1,并在x=2的位置计算了函数的值,结果为y=9。接着使用PyTorch自带的autograd库自动计算了y关于x的梯度,并使用x.grad来获取梯度值,结果为6。
"
第九课 激活函数
9.1是什么
在深度学习中,激活函数是指在神经网络的每个节点上对输入进行非线性转换的函数。激活函数的作用是增强神经网络的表达能力,使其能够学习更为复杂的特征。
9.2怎么用
- Sigmoid函数
Sigmoid函数的公式为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e8T83Caf-1682268742069)(pytorch/1682261529895.png)]
Sigmoid函数的输出值在0到1之间,可以将任何实数值映射到0到1的范围内。它的特点是在输入值较大或较小的情况下,输出值趋近于0或1,导致梯度消失的问题。
import torch.nn.functional as F
x = torch.randn(3, 3)
y = F.sigmoid(x)
- Tanh函数
Tanh函数的公式为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PQSKg2mm-1682268742070)(pytorch/1682261577551.png)]
Tanh函数的输出值在-1到1之间,可以将任何实数值映射到**-1到1**的范围内。它的特点是在输入值较大或较小的情况下,输出值趋近于-1或1,也会导致梯度消失的问题。
import torch.nn.functional as F
x = torch.randn(3, 3)
y = F.tanh(x)
- ReLU函数
ReLU函数的公式为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X3D4LJgo-1682268742070)(pytorch/1682261628461.png)]
ReLU函数的输出值在输入值大于0时等于输入值,小于等于0时等于0,可以将输入值非线性地映射到0到正无穷的范围内。它的特点是在输入值大于0时没有梯度消失的问题,但在小于等于0时梯度为0,可能导致神经元无法更新。
import torch.nn.functional as F
x = torch.randn(3, 3)
y = F.relu(x)
第十课 反向传播
10.1是什么
反向传播是深度学习中用于计算梯度以便更新模型参数的一种有效方法。
10.2怎么用
import torch
# 定义输入、参数和目标
x = torch.tensor([1.0, 2.0, 3.0, 4.0], requires_grad=True) # 输入张量,开启梯度跟踪
w = torch.tensor([2.0, 3.0, 4.0, 5.0], requires_grad=True) # 模型参数,开启梯度跟踪
y_true = torch.tensor([2.0])
# 前向传播
y_pred = torch.dot(x, w) # 计算预测值
# 计算损失函数
loss = (y_true - y_pred) ** 2
# 反向传播
loss.backward()
# 打印梯度
print(x.grad) # tensor([-8., -12., -16., -20.])
print(w.grad) # tensor([-2., -4., -6., -8.])
"'注释如下:
导入 PyTorch 库
定义输入张量 x,并开启梯度跟踪
定义模型参数 w,并开启梯度跟踪
定义目标值 y_true
进行前向传播,计算预测值 y_pred
计算损失函数,这里使用了均方误差(MSE)作为损失函数
调用 backward() 方法,自动计算所有张量的梯度
打印输入张量 x 的梯度
打印模型参数 w 的梯度
在这个示例中,我们首先定义了输入张量 x、模型参数 w 和目标值 y_true。然后我们进行前向传播,计算出模型的预测值 y_pred,并计算出损失函数。接着我们调用 backward() 方法,自动计算出所有张量的梯度。最后,我们打印出输入张量 x 和模型参数 w 的梯度,可以看到它们的值分别为 [-8., -12., -16., -20.] 和 [-2., -4., -6., -8.]。这些梯度可以用于更新模型参数,使得模型的预测结果更加接近真实值。'"
第十一课 优化
11.1是什么
在深度学习中,优化算法是用于调整模型参数以最小化损失函数的一种重要技术。
11.2怎么用
- 随机梯度下降(SGD)
随机梯度下降是深度学习中最基本的优化算法之一,其思想是在每次迭代中使用一小部分数据来计算梯度并更新模型参数。以下是使用 SGD 进行模型训练的示例代码:
import torch
import torch.nn as nn
import torch.optim as optim
# 定义模型、损失函数和优化器
model = nn.Linear(2, 1) # 线性模型,输入特征维度为 2,输出特征维度为 1
criterion = nn.MSELoss() # 均方误差损失函数
optimizer = optim.SGD(model.parameters(), lr=0.01) # 随机梯度下降优化器,学习率为 0.01
# 训练模型
for epoch in range(100):
# 生成随机数据
x = torch.randn(10, 2) # 输入数据,大小为 (10, 2)
y_true = torch.matmul(x, torch.tensor([2.0, 3.0]).reshape(-1, 1)) # 目标数据,大小为 (10, 1)
# 前向传播
y_pred = model(x)
# 计算损失
loss = criterion(y_pred, y_true)
# 反向传播
optimizer.zero_grad() # 清空梯度缓存
loss.backward() # 反向传播计算梯度
optimizer.step() # 更新模型参数
# 打印训练过程中的损失值
print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, 100, loss.item()))
- Adam
Adam 是一种基于梯度的优化算法,可以自适应地调整学习率。以下是使用 Adam 进行模型训练的示例代码:
import torch
import torch.nn as nn
import torch.optim as optim
# 定义模型、损失函数和优化器
model = nn.Linear(2, 1) # 线性模型,输入特征维度为 2,输出特征维度为 1
criterion = nn.MSELoss() # 均方误差损失函数
optimizer = optim.Adam(model.parameters(), lr=0.01) # Adam 优化器,学习率为 0.01
# 训练模型
for epoch in range(100):
# 生成随机数据
x = torch.randn(10, 2) # 输入数据,大小为 (10, 2)
y_true = torch.matmul(x, torch.tensor([2.0, 3.0]).reshape(-1
第十二课 逻辑回归
12.1是什么
逻辑回归(Logistic Regression)是一种常见的分类算法,它基于输入特征的线性组合进行分类,常用于二分类问题。
12.2怎么用
import torch
import torch.nn as nn
import torch.optim as optim
# 定义逻辑回归模型
class LogisticRegression(nn.Module):
def __init__(self, input_dim):
super(LogisticRegression, self).__init__()
self.linear = nn.Linear(input_dim, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
out = self.linear(x)
out = self.sigmoid(out)
return out
# 构建数据集
x_train = torch.Tensor([[1.0, 2.0], [2.0, 3.0], [3.0, 1.0], [4.0, 3.0], [5.0, 3.0], [6.0, 2.0]])
y_train = torch.Tensor([[0.0], [0.0], [0.0], [1.0], [1.0], [1.0]])
# 定义模型、损失函数和优化器
model = LogisticRegression(input_dim=2)
criterion = nn.BCELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 训练模型
num_epochs = 1000
for epoch in range(num_epochs):
# 前向传播
y_pred = model(x_train)
# 计算损失
loss = criterion(y_pred, y_train)
# 反向传播和优化
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 每训练100次输出一次损失
if (epoch+1) % 100 == 0:
print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item()))
12.3为什么这样用
- 定义逻辑回归模型,该模型包括一个线性层和一个 sigmoid 激活函数。
- 构建数据集,包括输入数据 x_train 和目标标签 y_train。
- 定义模型、损失函数和优化器,使用 BCELoss(二元交叉熵损失函数)和 SGD(随机梯度下降优化器)。
- 在训练过程中,对每个 epoch 进行以下操作:
- 前向传播得到预测值 y_pred。
- 计算损失。
- 反向传播和优化,使用 optimizer 对模型参数进行更新。
- 每100个 epoch 输出一次损失。
第十三课 交叉熵
13.1是什么
在深度学习中,交叉熵是一种常用的损失函数,通常用于分类任务中的模型训练。交叉熵测量模型的输出概率分布与真实标签之间的差异,可以用来指导模型参数的优化,使得模型输出更加接近真实标签。
13.2怎么用
import torch
import torch.nn as nn
import torch.optim as optim
# 生成模拟数据
input_data = torch.randn(4, 10) # 模拟4个样本,每个样本有10个特征
target = torch.LongTensor([2, 4, 1, 8]) # 模拟4个样本的真实标签,标签值为整数
# 定义交叉熵损失函数
loss_func = nn.CrossEntropyLoss()
# 计算预测结果并计算损失
output = loss_func(input_data, target)
print(output)
13.3为什么这样用
在上面的代码中,input_data
表示模型的输出结果,形状为(4, 10)
,即4个样本,每个样本有10个特征。target
表示4个样本的真实标签,形状为(4,)
,标签值为整数。使用nn.CrossEntropyLoss()
定义了一个交叉熵损失函数,然后将input_data
和target
传入该损失函数,即可得到交叉熵损失的值。最后将输出打印出来,即可得到交叉熵损失的值。
第十四课 多分类问题
14.1是什么
多分类问题是指将输入数据映射到多个不同的类别中,例如将一张图片分类到10个不同的类别中。在深度学习中,多分类问题通常使用 softmax 函数作为最后一层的激活函数,并使用交叉熵损失函数来优化模型。
14.2怎么用
import torch
import torch.nn as nn
import torch.optim as optim
# 生成模拟数据
input_data = torch.randn(4, 10) # 模拟4个样本,每个样本有10个特征
target = torch.LongTensor([2, 4, 1, 8]) # 模拟4个样本的真实标签,标签值为整数
# 定义模型
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc = nn.Linear(10, 5) # 全连接层,将10个特征映射到5个类别上
self.softmax = nn.Softmax(dim=1) # 在第二个维度上进行 softmax 计算
def forward(self, x):
x = self.fc(x)
x = self.softmax(x)
return x
# 初始化模型
model = Net()
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.1)
# 模型训练
for epoch in range(100):
optimizer.zero_grad() # 清空梯度
output = model(input_data) # 模型输出
loss = criterion(output, target) # 计算损失
loss.backward() # 反向传播
optimizer.step() # 更新参数
if epoch % 10 == 0:
print('Epoch: {}, Loss: {:.4f}'.format(epoch, loss.item()))
# 预测
test_data = torch.randn(1, 10) # 模拟一个样本
pred = model(test_data)
pred_label = torch.argmax(pred, dim=1) # 求预测类别
print('Predicted Label:', pred_label.item())
14.3为什么这样用
在上面的代码中,我们首先生成了模拟数据input_data
和target
,其中input_data
表示模型的输入数据,形状为(4, 10)
,target
表示每个样本的真实标签,形状为(4,)
。然后我们定义了一个多分类模型Net
,该模型包含一个全连接层和一个 softmax 层,用于将输入数据映射到5个不同的类别上。在训练时,我们使用交叉熵损失函数和随机梯度下降(SGD)优化器对模型进行训练。最后,我们使用训练好的模型对一个新的样本进行预测,并输出预测结果。
第十五课 过拟合与欠拟合
15.1是什么
欠拟合和过拟合是机器学习中常见的问题,它们会影响模型的性能和泛化能力。
欠拟合:指模型无法学习到数据的基本特征,即模型过于简单而不能很好地拟合数据,导致训练误差和测试误差都很大。通常的解决方法包括增加模型复杂度、增加训练数据量等。
过拟合:指模型过于复杂,导致在训练数据上表现很好,但是在新数据上的表现却很差。过拟合的主要原因是模型过于复杂,参数过多,容易造成对训练数据的过度拟合。通常的解决方法包括增加数据量、增加正则化等。
15.2怎么用
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
# 构造数据集
x_train = torch.randn(100, 1) * 10
y_train = x_train + torch.randn(100, 1) # 加入随机噪声
x_test = torch.randn(50, 1) * 10
y_test = x_test + torch.randn(50, 1)
# 转换为 DataLoader
train_dataset = TensorDataset(x_train, y_train)
train_loader = DataLoader(train_dataset, batch_size=10, shuffle=True)
# 定义模型
class SimpleModel(nn.Module):
def __init__(self):
super(SimpleModel, self).__init__()
self.fc = nn.Linear(1, 1) # 一个线性层
def forward(self, x):
out = self.fc(x)
return out
model = SimpleModel()
# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 训练模型
for epoch in range(100):
for batch_idx, (inputs, targets) in enumerate(train_loader):
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, targets)
loss.backward()
optimizer.step()
if epoch % 10 == 0:
print('Epoch:', epoch, 'Loss:', loss.item())
# 在测试集上测试模型
with torch.no_grad():
y_pred = model(x_test)
test_loss = criterion(y_pred, y_test)
print('Test Loss:', test_loss.item())
# 过拟合解决方法:增加正则化项
class RegularizedModel(nn.Module):
def __init__(self):
super(RegularizedModel, self).__init__()
self.fc = nn.Linear(1, 1)
def forward(self, x):
out = self.fc(x)
return out
model = RegularizedModel()
# 定义损失函数和优化器(加入正则化项)
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, weight_decay=0.1) # 加入
第十六课 交叉验证
16.1是什么
交叉验证是一种模型评估方法,将数据集划分为k个互斥的子集(通常是5或10个),然后进行k次模型训练和验证,每次使用其中的一个子集作为验证集,其余子集作为训练集。交叉验证可以有效地评估模型的性能,尤其是在数据集较小的情况下。
16.2怎么用
以Fashion MNIST数据集为例:
import torch
import torchvision
import torchvision.transforms as transforms
from sklearn.model_selection import KFold
import numpy as np
# 加载数据集并进行数据增强和归一化
transform = transforms.Compose([transforms.RandomHorizontalFlip(), transforms.RandomCrop(28, padding=4),
transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
trainset = torchvision.datasets.FashionMNIST(root='./data', train=True, download=True, transform=transform)
testset = torchvision.datasets.FashionMNIST(root='./data', train=False, download=True, transform=transform)
# 定义模型
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = torch.nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.conv2 = torch.nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.pool = torch.nn.MaxPool2d(kernel_size=2, stride=2)
self.fc1 = torch.nn.Linear(64 * 7 * 7, 128)
self.fc2 = torch.nn.Linear(128, 10)
def forward(self, x):
x = torch.relu(self.conv1(x))
x = self.pool(torch.relu(self.conv2(x)))
x = x.view(-1, 64 * 7 * 7)
x = torch.relu(self.fc1(x))
x = self.fc2(x)
return x
# 定义交叉验证函数
def cross_validation(model, criterion, optimizer, trainset, n_splits=5, batch_size=64, num_epochs=5):
kf = KFold(n_splits=n_splits, shuffle=True)
train_losses = np.zeros((n_splits, num_epochs))
val_losses = np.zeros((n_splits, num_epochs))
for fold, (train_index, val_index) in enumerate(kf.split(trainset)):
print('Fold [%d/%d]' % (fold + 1, n_splits))
train_sampler = torch.utils.data.sampler.SubsetRandomSampler(train_index)
val_sampler = torch.utils.data.sampler.SubsetRandomSampler(val_index)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, sampler=train_sampler)
valloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, sampler=val_sampler)
for epoch in range(num_epochs):
train_loss = 0.0
val_loss = 0.0
model.train()
for inputs, labels in trainloader:
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
train_loss += loss.item() * inputs.size(0)
train_loss /= len
第十七课 正则化
17.1是什么
正则化是一种用于减少模型过拟合的技术,在损失函数中添加一个惩罚项来惩罚模型的复杂性。这个惩罚项的值与模型参数的大小相关,即参数越大,惩罚项就越大,从而使模型更加简单。
17.2怎么用
#以下是一个使用L2正则化的示例代码:
import torch
import torch.nn as nn
import torch.optim as optim
# 创建一个带有两个线性层和一个ReLU激活函数的模型
class MyModel(nn.Module):
def __init__(self):
super(MyModel, self).__init__()
self.fc1 = nn.Linear(10, 5)
self.fc2 = nn.Linear(5, 2)
self.relu = nn.ReLU()
def forward(self, x):
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
return x
# 创建一个带有L2正则化的优化器
model = MyModel()
optimizer = optim.SGD(model.parameters(), lr=0.01, weight_decay=0.001)
# 使用L2正则化计算损失
criterion = nn.CrossEntropyLoss()
l2_reg = torch.tensor(0.)
for param in model.parameters():
l2_reg += torch.norm(param)
loss = criterion(output, target) + 0.001 * l2_reg
# 反向传播和优化
optimizer.zero_grad()
loss.backward()
optimizer.step()
17.3为什么这样用
这个示例代码使用了PyTorch中的nn.Module类创建了一个带有两个线性层和一个ReLU激活函数的模型。然后使用optim.SGD
创建了一个带有L2正则化的优化器,其中weight_decay
参数表示L2正则化项的系数。
在计算损失时,需要将L2正则化项添加到损失函数中。在这个示例中,我们使用了PyTorch中的torch.norm
函数计算模型参数的L2范数,并将所有参数的L2范数相加得到L2正则化项的值。最终的损失是交叉熵损失和L2正则化项的和。
在反向传播和优化过程中,我们使用标准的PyTorch方法执行。
第十八课 卷积
18.1是什么
卷积(Convolution)是一种在深度学习中广泛使用的数学运算。卷积神经网络(Convolutional Neural Network,CNN)使用卷积操作来提取特征,用于图像、语音和自然语言等任务。
卷积运算可以看作是一种加权求和运算,它将输入数据(例如图像)与卷积核(也称为过滤器或滤波器)进行卷积操作,输出特征图(Feature Map)。
卷积操作的计算过程如下:
- 在输入数据上移动卷积核,将卷积核的每一个元素与输入数据对应的元素相乘,得到对应位置的加权值。
- 将所有加权值求和,得到输出特征图上对应位置的值。
- 重复以上过程,直到将卷积核移动到输出特征图的所有位置,得到完整的输出特征图。
18.2怎么用
#在PyTorch中,可以使用torch.nn.Conv2d()函数实现二维卷积操作。下面是一个简单的示例:
import torch
# 定义输入数据,大小为 [batch_size, channels, height, width]
input_data = torch.randn(1, 3, 32, 32)
# 定义卷积核,大小为 [out_channels, in_channels, kernel_size, kernel_size]
conv_filter = torch.randn(6, 3, 3, 3)
# 定义卷积层,输入通道数为 3,输出通道数为 6,卷积核大小为 3x3
conv_layer = torch.nn.Conv2d(in_channels=3, out_channels=6, kernel_size=3)
# 将卷积核参数赋值给卷积层
conv_layer.weight.data = conv_filter
# 进行卷积操作
output_feature_map = conv_layer(input_data)
# 输出特征图的大小为 [batch_size, out_channels, output_height, output_width]
print(output_feature_map.shape)
18.3为什么这样用
在上面的代码中,首先定义了输入数据input_data
和卷积核conv_filter
,它们的大小分别为[1, 3, 32, 32]
和[6, 3, 3, 3]
。然后,使用torch.nn.Conv2d()
函数定义了一个卷积层conv_layer
,其中in_channels
表示输入通道数,out_channels
表示输出通道数,kernel_size
表示卷积核大小。将卷积核赋值给卷积层后,调用conv_layer()
函数对输入数据进行卷积操作,得到输出特征图output_feature_map
。
需要注意的是,卷积操作中会出现边界问题,因此在实际应用中通常会使用填充(padding)和步幅(stride)等技术来调整输出特征图的大小。
第十九课 卷积神经网络
19.1是什么
卷积神经网络(Convolutional Neural Network, CNN)是一类特殊的神经网络,广泛应用于图像识别、计算机视觉和自然语言处理等领域。与全连接神经网络不同,卷积神经网络中每个神经元只与输入数据的一部分相连,从而大大减少了网络参数的数量,提高了网络的性能和泛化能力。
19.2怎么用
下面是一个使用PyTorch实现的卷积神经网络的例子,以MNIST数据集为例,训练一个可以识别手写数字的CNN模型:
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
# 定义卷积神经网络模型
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = nn.Conv2d(1, 16, kernel_size=3, padding=1)
self.conv2 = nn.Conv2d(16, 32, kernel_size=3, padding=1)
self.pool = nn.MaxPool2d(2)
self.fc1 = nn.Linear(32 * 7 * 7, 128)
self.fc2 = nn.Linear(128, 10)
self.dropout = nn.Dropout(0.5)
def forward(self, x):
x = self.conv1(x)
x = nn.functional.relu(x)
x = self.pool(x)
x = self.conv2(x)
x = nn.functional.relu(x)
x = self.pool(x)
x = torch.flatten(x, 1)
x = self.fc1(x)
x = nn.functional.relu(x)
x = self.dropout(x)
x = self.fc2(x)
return x
# 数据预处理
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
train_data = datasets.MNIST(root='./data', train=True, transform=transform, download=True)
test_data = datasets.MNIST(root='./data', train=False, transform=transform, download=True)
# 定义训练和测试的dataloader
train_loader = torch.utils.data.DataLoader(train_data, batch_size=64, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_data, batch_size=64)
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
# 训练模型
def train(model, train_loader, optimizer, criterion):
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
# 测试模型
def test(model, test_loader, criterion):
model.eval()
test_loss = 0
correct = 0
with torch.no_grad():
for data, target in test_loader:
output = model(data)
test_loss += criterion(output, target).item()
pred = output.argmax(dim=1, keepdim=True)
correct += pred.eq(target.view_as(pred)).sum().item()
test_loss /= len(test_loader.dataset)
accuracy = 100. *
第二十课 池化层与采样
20.1是什么
池化层和采样层是卷积神经网络中的常用层,用于减小特征图的大小,同时保留关键信息,减轻计算负担。BN层用于加速训练和提高泛化能力,FC层则是用于将卷积神经网络的特征图转化为分类结果
20.2怎么用
import torch
import torch.nn as nn
import torch.optim as optim
# 定义卷积神经网络模型
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) # 定义全连接层1
self.fc2 = nn.Linear(120, 84) # 定义全连接层2
self.fc3 = nn.Linear(84, 10) # 定义全连接层3
self.bn1 = nn.BatchNorm2d(6) # 定义BN层
def forward(self, x):
x = self.pool(nn.functional.relu(self.conv1(x))) # 第一层:卷积,激活,池化
x = self.pool(nn.functional.relu(self.bn1(self.conv2(x)))) # 第二层:卷积,BN,激活,池化
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
# 定义损失函数和优化器
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个batch输出一次损失函数值
print('[%d, %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss / 2000))
running_loss = 0.
第二十一课 批归一化
21.1是什么
批归一化(Batch Normalization)是一种用于神经网络的技术,旨在加速神经网络的训练,同时还可以降低对初始权重值的选择敏感度。该技术通过对神经网络的每一层进行规范化,即使得每一层的输入具有零均值和单位方差,从而加速了网络的训练和提高了网络的泛化性能。
21.2怎么用
在PyTorch中,可以使用torch.nn.BatchNorm1d()
、torch.nn.BatchNorm2d()
、torch.nn.BatchNorm3d()
等函数来实现批归一化。下面是一个简单的示例:
import torch
import torch.nn as nn
# 定义一个带有批归一化的神经网络
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, kernel_size=5)
self.bn1 = nn.BatchNorm2d(6)
self.conv2 = nn.Conv2d(6, 16, kernel_size=5)
self.bn2 = nn.BatchNorm2d(16)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.bn3 = nn.BatchNorm1d(120)
self.fc2 = nn.Linear(120, 84)
self.bn4 = nn.BatchNorm1d(84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.conv1(x)
x = self.bn1(x)
x = nn.functional.relu(x)
x = nn.functional.max_pool2d(x, 2)
x = self.conv2(x)
x = self.bn2(x)
x = nn.functional.relu(x)
x = nn.functional.max_pool2d(x, 2)
x = x.view(-1, 16 * 5 * 5)
x = self.fc1(x)
x = self.bn3(x)
x = nn.functional.relu(x)
x = self.fc2(x)
x = self.bn4(x)
x = nn.functional.relu(x)
x = self.fc3(x)
return x
21.3为什么这样用
在上面的代码中,我们首先定义了一个神经网络Net
,该网络包含两个卷积层、四个全连接层和四个批归一化层。在forward
方法中,我们先对输入进行卷积和批归一化,然后使用ReLU函数进行激活,再通过最大池化层进行降维,最后使用全连接层将特征映射到10个类别上。
第二十二课 经典卷积神经网络
22.1是什么
卷积神经网络(Convolutional Neural Network,CNN)是一类基于深度学习的神经网络,用于处理具有类似网格结构的数据。卷积神经网络已经被广泛应用于计算机视觉任务,如图像分类、目标检测、图像分割等。下面介绍一些经典的卷积神经网络。
- LeNet-5
LeNet-5是Yann LeCun等人在1998年提出的卷积神经网络模型,是第一个成功应用于手写数字识别的卷积神经网络。该模型由卷积层、池化层、全连接层组成,其中卷积层和池化层交替出现,全连接层用于分类。LeNet-5模型的输入是28×28的手写数字图像,输出为10个数字类别。
- AlexNet
AlexNet是Alex Krizhevsky等人在2012年提出的卷积神经网络模型,是第一个在ImageNet图像识别挑战赛中取得胜利的卷积神经网络。该模型由8个卷积层和3个全连接层组成,其中使用了ReLU激活函数、Dropout正则化和批归一化等技术。AlexNet模型的输入是224×224的图像,输出为1000个类别。
- VGG
VGG是Karen Simonyan和Andrew Zisserman在2014年提出的卷积神经网络模型,其特点是采用了非常深的网络结构,有16或19个卷积层。VGG模型的卷积层中使用了非常小的3×3的卷积核,以增加网络的深度和复杂性。VGG模型的输入和输出与AlexNet相同。
- GoogLeNet
GoogLeNet是Google在2014年提出的卷积神经网络模型,其特点是采用了Inception模块,即在同一层中使用了多种不同大小的卷积核和池化核,以增加网络的深度和宽度。GoogLeNet模型的输入和输出与AlexNet相同。
- ResNet
ResNet是Kaiming He等人在2015年提出的卷积神经网络模型,其特点是采用了残差学习的方法,即通过添加跨层连接,使得网络可以更深。ResNet模型的输入和输出与AlexNet相同,其网络层数可以达到152层,是目前深度最大的卷积神经网络之一。
以上是一些经典的卷积神经网络,它们在计算机视觉领域的任务中具有广泛的应用。
第二十三课 ResNet和DenseNet
23.1是什么
ResNet(Residual Network)是Kaiming He等人在2015年提出的一种深度卷积神经网络,其特点是采用了残差学习的方法,即通过添加跨层连接(skip connection),使得网络可以更深而不容易发生梯度消失问题。ResNet在ImageNet图像识别挑战赛中取得了很好的成绩,并被广泛应用于计算机视觉任务中。
DenseNet 是一种深度学习神经网络,它的主要特点是具有密集连接(Dense Connection),这意味着网络中的每个层都与前面的所有层直接相连,从而使得**信息的流动更加充分和高效,避免了深层网络中的梯度消失问题,**提高了模型的性能和训练速度。DenseNet可以用于图像分类、物体检测、语义分割等任务。
23.2怎么用
import torch
import torch.nn as nn
import torch.nn.functional as F
# 定义BasicBlock模块,包含两个3x3的卷积层和一个跨层连接
class BasicBlock(nn.Module):
expansion = 1 # 扩展系数,用于调整输出通道数
def __init__(self, in_channels, out_channels, stride=1, downsample=None):
super(BasicBlock, self).__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(out_channels)
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(out_channels)
self.downsample = downsample
self.stride = stride
def forward(self, x):
identity = x # 记录输入,用于跨层连接
out = self.conv1(x)
out = self.bn1(out)
out = F.relu(out)
out = self.conv2(out)
out = self.bn2(out)
if self.downsample is not None: # 如果需要调整输入输出通道数,则通过downsample进行下采样
identity = self.downsample(x)
out += identity # 跨层连接
out = F.relu(out)
return out
# 定义ResNet模型,包含多个BasicBlock模块和一个全连接层
class ResNet(nn.Module):
def __init__(self, block, layers, num_classes=1000):
super(ResNet, self).__init__()
self.in_channels = 64
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
self.bn1 = nn.BatchNorm2d(64)
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
self.layer1 = self._make_layer(block, 64, layers[0])
self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
self.fc = nn.Linear(512 * block.expansion, num_classes)
def _make_layer(self, block, out_channels, blocks, stride=1):
downsample = None
import torch
import torch.nn as nn
# 定义 Dense Block
class DenseBlock(nn.Module):
def __init__(self, in_channels, growth_rate, num_layers):
super(DenseBlock, self).__init__()
self.layers = nn.ModuleList()
for i in range(num_layers):
self.layers.append(nn.Sequential(
nn.BatchNorm2d(in_channels + i * growth_rate),
nn.ReLU(inplace=True),
nn.Conv2d(in_channels + i * growth_rate, growth_rate, kernel_size=3, padding=1, bias=False)
))
def forward(self, x):
features = [x]
for layer in self.layers:
out = layer(torch.cat(features, dim=1))
features.append(out)
return torch.cat(features, dim=1)
# 定义 Transition Layer
class TransitionLayer(nn.Module):
def __init__(self, in_channels, out_channels):
super(TransitionLayer, self).__init__()
self.layers = nn.Sequential(
nn.BatchNorm2d(in_channels),
nn.ReLU(inplace=True),
nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False),
nn.AvgPool2d(kernel_size=2, stride=2)
)
def forward(self, x):
return self.layers(x)
# 定义 DenseNet
class DenseNet(nn.Module):
def __init__(self, growth_rate=32, block_config=(6, 12, 24, 16), num_classes=1000):
super(DenseNet, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
)
num_features = 64
for i, num_layers in enumerate(block_config):
block = DenseBlock(num_features, growth_rate, num_layers)
self.features.add_module(f'denseblock{i+1}', block)
num_features = num_features + num_layers * growth_rate
if i != len(block_config) - 1:
trans = TransitionLayer(num_features, num_features // 2)
self.features.add_module(f'transition{i+1}', trans)
num_features = num_features // 2
self.features.add_module('norm5', nn.BatchNorm2d(num_features))
self.classifier = nn.Linear(num_features, num_classes)
def forward(self, x):
features = self.features(x)
out = nn.functional.adaptive_avg_pool2d(features, (1, 1))
out = torch.flatten(out, 1)
out = self.classifier(out)
return out
第二十四课 数据增强
24.1是什么
数据增强(Data Augmentation)是指在训练神经网络时,对原始数据进行随机变换,从而增加数据量,提高模型的泛化能力。常见的数据增强方式包括:随机翻转、随机裁剪、随机旋转、随机缩放等。
24.2怎么用
下面是使用pytorch实现常见数据增强方法的代码,包括随机翻转、随机裁剪和随机旋转,代码中包含了详细的注释:
import torch
import torchvision.transforms as transforms
# 定义随机翻转、随机裁剪和随机旋转的数据增强
train_transform = transforms.Compose([
transforms.RandomHorizontalFlip(), # 随机水平翻转
transforms.RandomCrop(size=32, padding=4), # 随机裁剪为32x32大小
transforms.RandomRotation(degrees=15) # 随机旋转15度以内
])
# 定义数据集,并应用数据增强
train_dataset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=train_transform)
# 加载数据集
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True)
24.3为什么这样用
可以看到,使用pytorch实现数据增强非常方便,只需要使用transforms
模块中的相关函数组合成transforms.Compose
对象即可。在定义数据集时,将数据增强函数传入transform
参数中即可对数据进行增强。在训练时,通过加载数据集的方式将增强后的数据输入到神经网络中进行训练。
第二十五课 卷积神经网络实站
第二十六课 ResNet实战
第二十七课 时间序列
27.1是什么
时间序列(Time Series)是指按照时间先后顺序排列的一组连续的数据点序列,通常用于描述时间变化的趋势、周期性、随机波动等。
27.2怎么用
在pytorch中,可以使用torch.utils.data.Dataset
和torch.utils.data.DataLoader
等模块来加载和处理时间序列数据,下面是一个简单的时间序列数据加载和处理的示例代码,包含了详细的注释:
import torch
import torch.utils.data as data
import numpy as np
# 定义一个时间序列数据集
class TimeSeriesDataset(data.Dataset):
def __init__(self, data_path):
self.data = np.loadtxt(data_path, delimiter=',') # 从csv文件中读取数据
self.len = self.data.shape[0] # 获取数据点个数
def __getitem__(self, index):
# 将一个数据点按照时间步长分成多个特征
feature = self.data[index, :-1]
# 获取数据点的标签
label = self.data[index, -1]
# 将numpy数组转换成tensor
feature = torch.from_numpy(feature).float()
label = torch.from_numpy(np.array([label])).float()
return feature, label
def __len__(self):
return self.len
# 加载时间序列数据集
dataset = TimeSeriesDataset('data.csv')
# 定义数据加载器
dataloader = torch.utils.data.DataLoader(dataset, batch_size=32, shuffle=True)
# 定义一个简单的时间序列模型
class TimeSeriesModel(torch.nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim):
super(TimeSeriesModel, self).__init__()
self.rnn = torch.nn.RNN(input_dim, hidden_dim, batch_first=True)
self.fc = torch.nn.Linear(hidden_dim, output_dim)
def forward(self, x):
# 经过RNN层,获取最后一个时间步长的隐状态
out, hidden = self.rnn(x)
# 将隐状态作为输入,经过全连接层得到输出
out = self.fc(hidden)
return out
# 初始化模型
model = TimeSeriesModel(input_dim=5, hidden_dim=10, output_dim=1)
# 定义优化器和损失函数
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
criterion = torch.nn.MSELoss()
# 训练模型
for epoch in range(10):
for i, (feature, label) in enumerate(dataloader):
optimizer.zero_grad()
output = model(feature)
loss = criterion(output, label)
loss.backward()
optimizer.step()
print('Epoch: {}, Batch: {}, Loss: {:.4f}'.format(epoch, i, loss.item()))
27.3为什么这样用
可以看到,使用pytorch加载和处理时间序列数据非常简单,只需要定义一个继承自torch.utils.data.Dataset
的类,并在__getitem__
方法中将数据点按照时间步长分成多个特征和一个标签,然后将数据点转换成tensor即可。在训练时,只需要将时间序列数据输入到定义好的模型中进行训练即可。
第二十八课 循环神经网络
28.1是什么
循环神经网络(Recurrent Neural Network,RNN)是一种能够处理序列数据的神经网络。相比于传统的前馈神经网络,**RNN在处理序列数据时引入了时间维度,能够对输入序列中前后顺序和时间间隔进行建模,**因此在自然语言处理、语音识别、时间序列预测等领域应用广泛。
RNN的核心思想是引入一个循环结构,将当前时间步的输入和上一个时间步的输出作为输入,同时引入一个状态向量,用于记忆之前的信息。具体而言,设输入序列为 x 1 , x 2 , . . . , x T {x_1, x_2, ..., x_T} x1,x2,...,xT,输出序列为 y 1 , y 2 , . . . , y T {y_1, y_2, ..., y_T} y1,y2,...,yT,隐藏状态为 h t h_t ht,则RNN的计算可以表示为:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YgFK8ktR-1682268742071)(pytorch/1682265917461.png)]
其中, f f f和 g g g为激活函数, W x h W_{xh} Wxh、 W h h W_{hh} Whh、 W h y W_{hy} Why为权重矩阵, b h b_h bh和 b y b_y by为偏置项。由于每个时间步都使用相同的参数,因此RNN的参数共享,能够处理不同长度的序列数据。
28.2怎么用
在pytorch中,可以使用torch.nn.RNN
模块实现RNN,下面是一个简单的RNN示例代码,包含了详细的注释:
import torch
# 定义一个简单的RNN模型
class RNNModel(torch.nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim):
super(RNNModel, self).__init__()
self.rnn = torch.nn.RNN(input_dim, hidden_dim, batch_first=True)
self.fc = torch.nn.Linear(hidden_dim, output_dim)
def forward(self, x):
# 经过RNN层,获取最后一个时间步的隐状态
out, hidden = self.rnn(x)
# 将隐状态作为输入,经过全连接层得到输出
out = self.fc(hidden)
return out
# 初始化模型
model = RNNModel(input_dim=5, hidden_dim=10, output_dim=1)
# 定义优化器和损失函数
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
criterion = torch.nn.MSELoss()
# 构造输入数据和标签
x = torch.randn(32, 10, 5) # 32个序列,每个序列10个时间步,每个时间步5个特征
y = torch.randn(32, 1) # 32个标签
# 训练模型
for epoch in range(10):
optimizer.zero_grad()
output = model(x)
loss = criterion(output.squeeze(), y)
loss.backward()
optimizer.step()
print('Epoch: {}, Loss: {:.4f}'.format(epoch, loss.item()))
第二十九课 时间序列预测实战
第三十课 梯度消失和梯度爆炸
30.1是什么
梯度消失和梯度爆炸是深度神经网络中常见的问题。**梯度消失指的是当反向传播算法将误差从输出层向输入层传递时,梯度逐渐变小,最终变得非常小,导致深层网络的参数更新变得非常缓慢,甚至无法更新;**而梯度爆炸则是梯度变得非常大,导致训练过程发散,无法收敛。
30.2怎么用
为了解决梯度消失和梯度爆炸问题,可以采用一些技巧,比如参数初始化、批归一化、梯度裁剪等。下面是一个使用梯度裁剪技巧来避免梯度爆炸问题的示例代码:
import torch
import torch.nn as nn
import torch.optim as optim
# 定义一个具有10层的全连接网络
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(100, 200)
self.fc2 = nn.Linear(200, 400)
self.fc3 = nn.Linear(400, 800)
self.fc4 = nn.Linear(800, 1600)
self.fc5 = nn.Linear(1600, 3200)
self.fc6 = nn.Linear(3200, 6400)
self.fc7 = nn.Linear(6400, 12800)
self.fc8 = nn.Linear(12800, 25600)
self.fc9 = nn.Linear(25600, 51200)
self.fc10 = nn.Linear(51200, 1)
self.relu = nn.ReLU()
def forward(self, x):
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
x = self.relu(x)
x = self.fc3(x)
x = self.relu(x)
x = self.fc4(x)
x = self.relu(x)
x = self.fc5(x)
x = self.relu(x)
x = self.fc6(x)
x = self.relu(x)
x = self.fc7(x)
x = self.relu(x)
x = self.fc8(x)
x = self.relu(x)
x = self.fc9(x)
x = self.relu(x)
x = self.fc10(x)
return x
# 初始化模型、优化器和损失函数
model = Net()
optimizer = optim.Adam(model.parameters(), lr=0.001)
criterion = nn.MSELoss()
# 构造输入数据和标签
x = torch.randn(100, 100)
y = torch.randn(100, 1)
# 训练模型,并进行梯度裁剪
for epoch in range(100):
optimizer.zero_grad()
output = model(x)
loss = criterion(output, y)
loss.backward()
nn.utils.clip_grad_norm_(model.parameters(), max_norm=1) # 对梯度进行裁剪
optimizer.step()
print('Epoch: {}, Loss: {:.4f}'.format(epoch, loss.item()))
第三十一课 LSTM
31.1是什么
LSTM(Long Short-Term Memory)是一种常用的循环神经网络(RNN)的变种,能够有效地解决长序列训练过程中的梯度消失问题。它引入了三个门控(input gate、forget gate、output gate),通过门控来控制信息的流动,实现长期记忆和避免梯度消失问题。
31.2怎么用
import torch
import torch.nn as nn
import torch.optim as optim
# 定义一个LSTM模型
class LSTM(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, output_size):
super(LSTM, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_size, output_size)
def forward(self, x):
h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device=x.device)
c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device=x.device)
out, _ = self.lstm(x, (h0, c0))
out = self.fc(out[:, -1, :])
return out
# 定义模型超参数
input_size = 10
hidden_size = 20
num_layers = 2
output_size = 1
lr = 0.001
num_epochs = 10
# 初始化模型、优化器和损失函数
model = LSTM(input_size, hidden_size, num_layers, output_size)
optimizer = optim.Adam(model.parameters(), lr=lr)
criterion = nn.MSELoss()
# 构造输入数据和标签
x = torch.randn(100, 5, input_size)
y = torch.randn(100, output_size)
# 训练模型
for epoch in range(num_epochs):
optimizer.zero_grad()
output = model(x)
loss = criterion(output, y)
loss.backward()
optimizer.step()
print('Epoch: {}, Loss: {:.4f}'.format(epoch, loss.item()))
31.3为什么这样用
在这个示例代码中,我们使用PyTorch内置的nn.LSTM
类定义了一个LSTM模型。input_size
表示输入数据的特征数,hidden_size
表示隐藏层的特征数,num_layers
表示LSTM的层数,output_size
表示输出数据的特征数。
在forward
函数中,我们首先定义了两个全0的张量h0
和c0
作为LSTM的初始隐状态和细胞状态,然后将输入数据x
和初始隐状态、细胞状态作为输入传入nn.LSTM
中,获取LSTM的输出out
和最终的隐状态和细胞状态。最后,我们通过一个全连接层nn.Linear
将LSTM的输出转换为指定维度的输出数据。
在训练过程中,我们使用随机生成的输入数据和标签进行训练,并使用均方误差损失函数和Adam优化
第三十二课 情感分类问题实战
32.1是什么
情感分类是指将一段文本分为积极、消极或中性等情感类别的任务。它在自然语言处理领域中有着广泛的应用,比如情感分析、舆情监测等。
32.2怎么用
import torch
import torch.nn as nn
import torch.optim as optim
import torchtext
from torchtext.datasets import IMDB
from torchtext.data import Field, LabelField, BucketIterator
# 定义Field
TEXT = Field(tokenize='spacy', lower=True)
LABEL = LabelField(dtype=torch.float)
# 加载IMDB数据集
train_data, test_data = IMDB.splits(TEXT, LABEL)
# 构建词汇表
TEXT.build_vocab(train_data, max_size=10000, vectors='glove.6B.100d')
LABEL.build_vocab(train_data)
# 定义超参数
batch_size = 64
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
input_size = len(TEXT.vocab)
hidden_size = 128
output_size = 1
num_epochs = 10
lr = 0.001
# 定义模型
class SentimentClassifier(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(SentimentClassifier, self).__init__()
self.embedding = nn.Embedding(input_size, hidden_size)
self.lstm = nn.LSTM(hidden_size, hidden_size, batch_first=True)
self.fc = nn.Linear(hidden_size, output_size)
def forward(self, x):
x = self.embedding(x)
out, _ = self.lstm(x)
out = self.fc(out[:, -1, :])
return out
# 初始化模型、优化器和损失函数
model = SentimentClassifier(input_size, hidden_size, output_size).to(device)
optimizer = optim.Adam(model.parameters(), lr=lr)
criterion = nn.BCEWithLogitsLoss()
# 构造数据迭代器
train_iterator, test_iterator = BucketIterator.splits(
(train_data, test_data), batch_size=batch_size, device=device)
# 训练模型
for epoch in range(num_epochs):
for i, batch in enumerate(train_iterator):
text = batch.text
label = batch.label
optimizer.zero_grad()
output = model(text).squeeze(1)
loss = criterion(output, label)
loss.backward()
optimizer.step()
if i % 100 == 0:
acc = ((output > 0.5).float() == label).float().mean()
print('Epoch: {}, Batch: {}, Loss: {:.4f}, Accuracy: {:.4f}'.format(
epoch, i, loss.item(), acc.item()))
32.3为什么这样用
在这个示例代码中,我们使用了PyTorch内置的IMDB数据集作为训练集和测试集。我们使用了torchtext
库中的Field
和LabelField
定义了文本和标签的处理方式,并使用BucketIterator
构建了数据迭代器。
在模型方面,我们使用了一个单层LSTM模型,其中嵌入层、LSTM层和全连接层分别使用了nn.Embedding
、nn.LSTM
和nn.Linear
。
第三十三课 数据处理+特征工程
33.1是什么
预先对数据进行处理(缺失值、正则化、归一化、正态分布…)
特征工程:更好地提取数据特征, 指对原始数据进行预处理和特征提取,以便更好地支持模型训练和预测。在深度学习中,特征工程通常是指对原始数据进行变换、归一化、降维等操作,以便更好地与神经网络结合使用
33.2怎么用
以下是几个常用的数据处理方法的介绍和使用PyTorch实现的代码示例:
- 数据标准化
数据标准化是将数据转换为均值为0,标准差为1的分布的过程。它的主要作用是消除数据间的量纲影响,使不同变量之间具有可比性。
PyTorch中可以使用torch.nn.functional.normalize
实现数据标准化,示例代码如下:
import torch
import torch.nn.functional as F
# 生成随机数据
x = torch.randn(10, 3)
# 对数据进行标准化
x_normalized = F.normalize(x, dim=1)
print(x_normalized)
- One-hot编码
One-hot编码是将离散型数据转换为向量表示的过程,其中每个维度代表一个类别,只有对应类别的维度值为1,其余维度值为0。
PyTorch中可以使用torch.nn.functional.one_hot
实现One-hot编码,示例代码如下:
import torch
import torch.nn.functional as F
# 定义数据和类别数
x = torch.tensor([0, 1, 2, 1, 0])
num_classes = 3
# 对数据进行One-hot编码
x_one_hot = F.one_hot(x, num_classes=num_classes)
print(x_one_hot)
- 数据切分
数据切分是将数据集按照一定比例划分为训练集、验证集和测试集的过程。它的主要作用是用于模型的训练、调参和评估。
PyTorch中可以使用torch.utils.data.random_split
实现数据切分,示例代码如下:
import torch
from torch.utils.data import random_split, DataLoader
# 生成数据集
dataset = torch.randn(100, 3)
# 划分数据集
train_set, val_set, test_set = random_split(dataset, [60, 20, 20])
# 构造数据迭代器
train_loader = DataLoader(train_set, batch_size=10, shuffle=True)
val_loader = DataLoader(val_set, batch_size=10, shuffle=False)
test_loader = DataLoader(test_set, batch_size=10, shuffle=False)
# 遍历训练集
for batch in train_loader:
print(batch)
break
在这个示例代码中,我们使用random_split
函数将数据集按照6:2:2的比例划分为训练集、验证集和测试集,并使用DataLoader
构造数据迭代器用于模型的训练和评估。
特征工程指的是将原始数据转化为能够被机器学习算法所接受的特征表示的过程。在实际应用中,特征工程往往会占据整个机器学习流程的大部分时间,其好坏直接关系到模型的最终性能。下面介绍几种常用的特征工程方法,并用pytorch实现。
- 特征缩放
特征缩放指的是将特征的数值范围缩放到一定范围内,通常是0到1之间。这样做的目的是使各个特征的权重更加均衡,避免某个特征的权重过大而影响整个模型的表现。
import torch
def feature_scaling(X):
"""
对特征进行缩放
"""
X_min = X.min(0, keepdim=True)[0]
X_max = X.max(0, keepdim=True)[0]
X_scaled = (X - X_min) / (X_max - X_min)
return X_scaled
- 特征选择
特征选择指的是从原始特征中选择出对模型预测最有用的特征。这样做的目的是减少模型复杂度,避免过拟合。
import torch
from sklearn.feature_selection import SelectKBest, f_regression
def feature_selection(X, y, k):
"""
对特征进行选择,选出最有用的k个特征
"""
selector = SelectKBest(score_func=f_regression, k=k)
selector.fit(X, y)
X_new = selector.transform(X)
return X_new
- 特征构造
特征构造指的是根据原始特征生成新的特征。这样做的目的是增加模型对数据的理解,提高模型的泛化能力。
import torch
def feature_construction(X):
"""
对特征进行构造
"""
X_new = torch.cat((X[:, :2], X[:, 2:] ** 2), dim=1)
return X_new
- 特征编码
特征编码指的是将特征从原始形式转化为模型所能接受的形式。例如将类别型特征转化为数值型特征。
import torch
from sklearn.preprocessing import OneHotEncoder
def feature_encoding(X, categorical_features):
"""
对特征进行编码
"""
enc = OneHotEncoder(categorical_features=categorical_features)
X_new = enc.fit_transform(X)
return X_new
以上是几种常用的特征工程方法,需要根据具体场景选择使用。在实际应用中,也会采用多种特征工程方法的组合来提高模型性能。
第三十四课 自定义数据集
34.1是什么
自己定义数据集
34.2怎么用
使用PyTorch实现自定义数据集主要涉及以下两个步骤:
- 定义数据集类
定义一个类,继承torch.utils.data.Dataset
,实现__len__
和__getitem__
方法,分别用于返回数据集大小和获取数据样本。以下是一个简单的自定义数据集示例:
import torch
from torch.utils.data import Dataset
class MyDataset(Dataset):
def __init__(self, data, labels):
self.data = data
self.labels = labels
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
return self.data[idx], self.labels[idx]
在这个示例代码中,我们定义了一个MyDataset
类,该类接受两个参数data
和labels
,并实现了__len__
和__getitem__
方法,其中__len__
返回数据集大小,__getitem__
用于获取数据样本。
- 加载数据集
加载数据集通常使用torch.utils.data.DataLoader
类。以下是一个简单的数据加载示例:
import torch
from torch.utils.data import DataLoader
# 定义数据集
data = torch.randn(100, 3, 32, 32)
labels = torch.randint(low=0, high=10, size=(100,))
# 定义数据集类
dataset = MyDataset(data, labels)
# 定义数据加载器
loader = DataLoader(dataset, batch_size=32, shuffle=True)
# 迭代数据
for batch_data, batch_labels in loader:
print(batch_data.shape, batch_labels.shape)
在这个示例代码中,我们先定义了一个数据集data
和labels
,然后使用MyDataset
类封装数据集,并使用DataLoader
类加载数据集,设置批次大小为32并打乱数据,最后迭代数据进行训练。
第三十五课 自定义网络
35.1是什么
自己根据需要定义网格结构
35.2怎么用
使用PyTorch实现自定义网络主要包括以下步骤:
- 定义网络结构
定义网络结构需要继承nn.Module
类,并实现__init__
和forward
方法。其中,__init__
方法用于定义网络中的各个层,forward
方法用于描述前向传播的计算过程。
以下是一个简单的自定义网络结构示例:
import torch.nn as nn
class MyNet(nn.Module):
def __init__(self):
super(MyNet, self).__init__()
self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, padding=1)
self.relu1 = nn.ReLU()
self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1)
self.relu2 = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
self.fc = nn.Linear(in_features=64*16*16, out_features=10)
def forward(self, x):
x = self.conv1(x)
x = self.relu1(x)
x = self.conv2(x)
x = self.relu2(x)
x = self.pool(x)
x = x.view(-1, 64*16*16)
x = self.fc(x)
return x
在这个示例代码中,我们定义了一个MyNet
类,该类继承nn.Module
类,并实现了__init__
和forward
方法。在__init__
方法中,我们定义了卷积层、ReLU激活函数、最大池化层和全连接层等各个层。在forward
方法中,我们定义了前向传播的计算过程。
- 定义损失函数和优化器
定义损失函数和优化器需要使用PyTorch中的相应类。以下是一个简单的定义损失函数和优化器的示例:
import torch.optim as optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), lr=0.001)
在这个示例代码中,我们使用nn.CrossEntropyLoss
类定义交叉熵损失函数,并使用optim.Adam
类定义Adam优化器。net.parameters()
用于获取网络中的可学习参数,lr=0.001
为学习率。
- 训练网络
训练网络需要迭代数据集,并进行前向传播、计算损失、反向传播、更新参数等操作。以下是一个简单的训练网络的示例:
for epoch in range(num_epochs):
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 % 100 == 99:
print('[%d, %5d] loss: %.3f' % (epoch+1, i+1, running_loss/100))
running_loss = 0.0
``
第三十六课 迁移学习
36.1是什么
迁移学习是一种机器学习技术,它将已经训练好的模型在新的任务上进行微调。迁移学习的核心思想是利用预训练模型的权重和结构,将其用于新的任务上,从而可以显著提高模型的泛化能力和训练效率。
36.2怎么用
迁移学习通常有以下两种方法:
- 从预训练的模型中提取特征,并将这些特征用于新任务的训练。
- 将预训练模型的权重用于新任务的初始化,然后在新任务上进行微调。
下面是一个使用迁移学习的示例,使用ResNet18对CIFAR-10数据集进行分类:
import torch
import torchvision
import torchvision.transforms as transforms
import torch.nn as nn
import torch.optim as optim
# 定义数据预处理的方法
transform_train = transforms.Compose([
transforms.RandomCrop(32, padding=4),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
transform_test = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
# 加载CIFAR-10数据集
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
download=True, transform=transform_train)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=128,
shuffle=True, num_workers=2)
testset = torchvision.datasets.CIFAR10(root='./data', train=False,
download=True, transform=transform_test)
testloader = torch.utils.data.DataLoader(testset, batch_size=100,
shuffle=False, num_workers=2)
# 加载预训练的ResNet18模型
net = torchvision.models.resnet18(pretrained=True)
# 修改最后一层全连接层的输出
num_ftrs = net.fc.in_features
net.fc = nn.Linear(num_ftrs, 10)
# 将模型移动到GPU上
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net.to(device)
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
# 训练模型
for epoch in range(10): # 10个epoch
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
# 前向传播
outputs = net(inputs)
loss = criterion(outputs, labels)
# 反向传播
loss.backward()
optimizer.step()
# 统计损失值
running_loss += loss.item()
if i % 100 == 99: # 每100个batch打印一次平均损失值
print('[%d,
第三十七课 无监督学习
37.1是什么
无监督学习是指在没有标签或目标输出的情况下,从数据本身的结构和特征中学习有用的信息的一种机器学习方法。无监督学习的目标是通过对数据进行自动编码、聚类、降维等操作来提取数据的有用信息,例如数据的分布、潜在表示、重要特征等。无监督学习在深度学习中被广泛应用,例如生成模型、自编码器、GAN等模型。
37.2怎么用
以下是一个使用自编码器实现无监督学习的示例代码:
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
from torchvision.transforms import transforms
from tqdm import tqdm
# 定义自编码器网络
class AutoEncoder(nn.Module):
def __init__(self):
super(AutoEncoder, self).__init__()
self.encoder = nn.Sequential(
nn.Linear(28*28, 256),
nn.ReLU(),
nn.Linear(256, 128),
nn.ReLU(),
nn.Linear(128, 64),
nn.ReLU(),
nn.Linear(64, 16)
)
self.decoder = nn.Sequential(
nn.Linear(16, 64),
nn.ReLU(),
nn.Linear(64, 128),
nn.ReLU(),
nn.Linear(128, 256),
nn.ReLU(),
nn.Linear(256, 28*28),
nn.Sigmoid()
)
def forward(self, x):
x = self.encoder(x)
x = self.decoder(x)
return x
# 加载数据集并进行预处理
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
train_set = MNIST(root='./data', train=True, transform=transform, download=True)
test_set = MNIST(root='./data', train=False, transform=transform, download=True)
train_loader = DataLoader(train_set, batch_size=256, shuffle=True)
test_loader = DataLoader(test_set, batch_size=256, shuffle=True)
# 定义模型和优化器
model = AutoEncoder()
criterion = nn.BCELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 训练自编码器
num_epochs = 20
for epoch in range(num_epochs):
running_loss = 0.0
for data in tqdm(train_loader):
inputs, _ = data
inputs = inputs.view(inputs.size(0), -1)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, inputs)
loss.backward()
optimizer.step()
running_loss += loss.item() * inputs.size(0)
epoch_loss = running_loss / len(train_set)
print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, epoch_loss))
# 测试自编码器
total_loss = 0.0
with torch.no_grad():
for data in tqdm(test_loader):
inputs, _ = data
inputs = inputs.view(inputs.size(0), -1)
outputs = model(inputs)
loss = criterion(outputs, inputs)
total_loss += loss.item() * inputs.size(0)
test_loss = total_loss / len(test_set)
print('Test Loss: {:.4f}'.format(test_loss
第三十八课 自编码器
38.1是什么
自编码器(Autoencoder)是一种无监督学习的神经网络,主要用于数据的降维、特征提取和数据重建等任务。其基本原理是将输入数据经过一个编码器(Encoder)映射到隐藏层表示,再通过一个解码器(Decoder)将隐藏层表示映射到输出层,最终重建输入数据。在训练过程中,自编码器的目标是最小化输入数据和重建数据之间的差距,即重建误差,从而得到具有良好特征表达的隐藏层表示。
38.2怎么用
下面是使用PyTorch实现一个简单的自编码器,包括编码器和解码器。
import torch
import torch.nn as nn
class Autoencoder(nn.Module):
def __init__(self, input_size, hidden_size):
super(Autoencoder, self).__init__()
self.encoder = nn.Linear(input_size, hidden_size)
self.decoder = nn.Linear(hidden_size, input_size)
def forward(self, x):
x = self.encoder(x)
x = torch.relu(x)
x = self.decoder(x)
x = torch.sigmoid(x)
return x
# 定义输入数据维度和隐藏层维度
input_size = 784 # 输入数据维度为28*28=784
hidden_size = 64 # 隐藏层维度为64
# 初始化自编码器模型
model = Autoencoder(input_size, hidden_size)
# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
# 训练自编码器模型
num_epochs = 10
for epoch in range(num_epochs):
for data in dataloader:
img, _ = data
img = img.view(img.size(0), -1)
output = model(img)
loss = criterion(output, img)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item()))
38.3为什么这样用
在上述代码中,我们定义了一个名为Autoencoder
的类,继承自nn.Module
。在该类的__init__
方法中,我们定义了一个encoder
层和一个decoder
层,其中encoder
层为全连接层,将输入数据映射到隐藏层表示,decoder
层也为全连接层,将隐藏层表示映射回输入数据维度。在forward
方法中,我们首先将输入数据输入到encoder
层中,然后使用ReLU激活函数得到隐藏层表示,再将隐藏层表示输入到decoder
层中,使用Sigmoid激活函数得到输出数据,最终返回输出数据。
接下来,我们定义了输入数据维度和隐藏层维度,并初始化自编码器模型。在训练过程中,我们使用MSELoss
作为损失函数,Adam
作为优化器,并使用一个简单的循环
第三十九课 GAN
39.1是什么
GAN,全称为生成式对抗网络(Generative Adversarial Networks),是一种基于深度学习的生成模型。GAN的主要思想是同时训练一个生成模型和一个判别模型,两者相互对抗,不断提高各自的性能。
GAN包含两个神经网络:生成器(Generator)和判别器(Discriminator)。生成器从潜在空间中随机取样作为输入,其输出结果需要尽量模仿训练集中的真实样本;而判别器则尝试将生成器的输出与真实样本区分开来。两个模型不断交互训练,直到生成器可以生成接近真实样本的数据。
39.2怎么用
下面是一个使用PyTorch实现简单的GAN模型的示例代码:
import torch
import torch.nn as nn
# 定义生成器模型
class Generator(nn.Module):
def __init__(self):
super(Generator, self).__init__()
self.fc = nn.Sequential(
nn.Linear(100, 128),
nn.BatchNorm1d(128),
nn.ReLU(inplace=True),
nn.Linear(128, 256),
nn.BatchNorm1d(256),
nn.ReLU(inplace=True),
nn.Linear(256, 784),
nn.Tanh()
)
def forward(self, x):
x = self.fc(x)
return x
# 定义判别器模型
class Discriminator(nn.Module):
def __init__(self):
super(Discriminator, self).__init__()
self.fc = nn.Sequential(
nn.Linear(784, 256),
nn.LeakyReLU(0.2, inplace=True),
nn.Linear(256, 128),
nn.LeakyReLU(0.2, inplace=True),
nn.Linear(128, 1),
nn.Sigmoid()
)
def forward(self, x):
x = self.fc(x)
return x
# 初始化生成器和判别器
G = Generator()
D = Discriminator()
# 定义损失函数和优化器
criterion = nn.BCELoss()
G_optimizer = torch.optim.Adam(G.parameters(), lr=0.0002, betas=(0.5, 0.999))
D_optimizer = torch.optim.Adam(D.parameters(), lr=0.0002, betas=(0.5, 0.999))
# 训练GAN模型
for epoch in range(num_epochs):
for i, (images, _) in enumerate(train_loader):
batch_size = images.size(0)
images = images.view(batch_size, -1)
# 真实样本label为1,生成的样本label为0
real_labels = torch.ones(batch_size, 1)
fake_labels = torch.zeros(batch_size, 1)
# 训练判别器
D_optimizer.zero_grad()
real_outputs = D(images)
real_loss = criterion(real_outputs, real_labels)
real_loss.backward()
z = torch.randn(batch_size, 100)
fake_images = G(z)
fake_outputs = D(fake_images)
fake_loss = criterion(fake_outputs, fake_labels)
fake_loss.backward()
D_loss = real_loss + fake_loss
D_optimizer.step()
# 训练生成
第四十课 BP神经网络
40.1是什么
BP神经网络(Back Propagation Neural Network)是一种多层前馈神经网络,是一种监督学习算法,用于解决分类和回归问题。
在BP神经网络中,通过多层神经元的组合将输入特征转换为输出结果,其中隐藏层的神经元可以把输入空间映射到新的特征空间。BP神经网络的训练过程就是通过误差反向传播算法来不断调整网络的参数,以最小化预测结果与实际结果之间的误差。
40.2怎么用
下面是一个简单的BP神经网络的实现代码,包含两个隐藏层和一个输出层,使用了Sigmoid激活函数和交叉熵损失函数,其中加入了批归一化和dropout来防止过拟合。代码中的注释将逐句解释实现过程。
import torch
import torch.nn as nn
class Net(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(Net, self).__init__()
self.fc1 = nn.Linear(input_size, hidden_size) # 第一个全连接层,输入大小为input_size,输出大小为hidden_size
self.bn1 = nn.BatchNorm1d(hidden_size) # 批归一化
self.dropout1 = nn.Dropout(p=0.5) # dropout层,p为保留神经元的概率
self.fc2 = nn.Linear(hidden_size, hidden_size) # 第二个全连接层
self.bn2 = nn.BatchNorm1d(hidden_size) # 批归一化
self.dropout2 = nn.Dropout(p=0.5) # dropout层
self.fc3 = nn.Linear(hidden_size, output_size) # 输出层
def forward(self, x):
x = self.fc1(x)
x = self.bn1(x)
x = torch.sigmoid(x) # Sigmoid激活函数
x = self.dropout1(x)
x = self.fc2(x)
x = self.bn2(x)
x = torch.sigmoid(x)
x = self.dropout2(x)
x = self.fc3(x)
return x
在使用该模型进行训练时,需要定义损失函数和优化器。例如:
net = Net(10, 20, 1) # 定义模型,输入大小为10,隐藏层大小为20,输出大小为1
criterion = nn.BCEWithLogitsLoss() # 二分类交叉熵损失函数
optimizer = torch.optim.Adam(net.parameters(), lr=0.001) # Adam优化器,学习率为0.001
for epoch in range(num_epochs):
for i, (inputs, labels) in enumerate(train_loader):
optimizer.zero_grad() # 梯度清零
outputs = net(inputs.float()) # 前向传播
loss = criterion(outputs.squeeze(), labels.float()) # 计算损失
loss.backward() # 反向传播
optimizer.step() # 更新参数
第四十一课 多层感知机
41.1是什么
多层感知机(Multilayer Perceptron,MLP)是一种经典的前馈神经网络,由输入层、若干个隐藏层和输出层组成。每一层的神经元与上一层的所有神经元相连,通过学习来建立输入与输出之间的映射关系。其中,隐藏层通常采用ReLU激活函数,输出层通常根据不同的任务选择不同的激活函数,如sigmoid函数、softmax函数等。
41.2怎么用
以下是用PyTorch实现一个简单的多层感知机模型,包含一个输入层、两个隐藏层和一个输出层,隐藏层的激活函数采用ReLU,输出层的激活函数采用softmax,用于进行10类手写数字图像分类任务。注释在代码中给出。
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision.datasets import MNIST
from torch.utils.data import DataLoader
from torchvision.transforms import ToTensor
# 定义多层感知机模型
class MLP(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(MLP, self).__init__()
self.fc1 = nn.Linear(input_size, hidden_size) # 输入层到第1个隐藏层
self.fc2 = nn.Linear(hidden_size, hidden_size) # 第1个隐藏层到第2个隐藏层
self.fc3 = nn.Linear(hidden_size, output_size) # 第2个隐藏层到输出层
self.relu = nn.ReLU() # ReLU激活函数
self.softmax = nn.Softmax(dim=1) # softmax激活函数
def forward(self, x):
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
x = self.relu(x)
x = self.fc3(x)
x = self.softmax(x)
return x
# 加载MNIST数据集
train_set = MNIST(root='./data', train=True, download=True, transform=ToTensor())
test_set = MNIST(root='./data', train=False, download=True, transform=ToTensor())
train_loader = DataLoader(train_set, batch_size=64, shuffle=True)
test_loader = DataLoader(test_set, batch_size=64, shuffle=False)
# 定义模型参数
input_size = 784 # 输入层大小
hidden_size = 128 # 隐藏层大小
output_size = 10 # 输出层大小
learning_rate = 0.001
# 初始化模型和优化器
model = MLP(input_size, hidden_size, output_size)
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
# 训练模型
num_epochs = 10
for epoch in range(num_epochs):
for i, (images, labels) in enumerate(train_loader):
# 将数据扁平化
images = images.view(-1, 28*28)
# 前向传播计算损失
outputs = model(images)
loss = nn.functional.cross_entropy(outputs, labels)
# 反向传播更新梯度
optimizer.zero_grad()
loss.backward()
optimizer.step
第四十二课 Attention结构
42.1是什么
Attention是一种在深度学习中广泛应用的机制,可以将输入序列中重要的部分加权表示,而不是一视同仁地对待所有输入。在自然语言处理、语音识别和计算机视觉等任务中都有广泛应用。
42.2怎么用
Attention通常由三个部分组成:**Query、Key和Value。**Query是需要进行加权表示的目标信息,Key和Value则是输入序列中的信息。Attention机制首先计算Query和每个Key之间的相似度,然后使用相似度对Value进行加权求和,得到最终的加权表示。
下面用PyTorch实现一个简单的Attention模型,该模型使用一个全连接层计算Query、Key和Value之间的相似度,然后对Value进行加权求和。
import torch
import torch.nn as nn
class Attention(nn.Module):
def __init__(self, input_size, hidden_size):
super(Attention, self).__init__()
self.query_layer = nn.Linear(input_size, hidden_size)
self.key_layer = nn.Linear(input_size, hidden_size)
self.value_layer = nn.Linear(input_size, hidden_size)
def forward(self, query, keys, values):
# 将query、keys和values分别通过全连接层变换到hidden_size维度
query = self.query_layer(query)
keys = self.key_layer(keys)
values = self.value_layer(values)
# 计算query和每个key之间的相似度
scores = torch.matmul(query, keys.transpose(1, 2))
# 对scores进行归一化处理,得到权重
weights = torch.softmax(scores, dim=-1)
# 使用权重对values进行加权求和
weighted_values = torch.matmul(weights, values)
return weighted_values
42.3为什么这样用
在该代码中,输入序列的维度是input_size
,全连接层的隐藏层维度是hidden_size
。在前向传播过程中,将Query、Key和Value分别通过全连接层变换到hidden_size
维度,然后计算Query和每个Key之间的相似度,使用softmax函数对相似度进行归一化处理,得到权重,最后使用权重对Value进行加权求和。
第四十三课 Trabsformer结构
43.1是什么
Transformer是一种用于序列到序列学习的深度学习模型,广泛应用于自然语言处理领域中的机器翻译、文本生成等任务。它是由谷歌的 Vaswani 等人在2017年提出的,是目前机器翻译领域的最佳模型之一。
43.2怎么用
Transformer的核心是self-attention机制,用于建立输入序列中不同元素之间的关系。其主要结构由多个Encoder层和Decoder层构成,每个层中包含一个self-attention子层和一个全连接前馈神经网络子层。
以下是一个简单的Transformer模型实现的示例,用于将一个序列翻译成另一个序列:
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.nn import TransformerEncoder, TransformerEncoderLayer, TransformerDecoder, TransformerDecoderLayer
class TransformerModel(nn.Module):
def __init__(self, input_vocab_size, output_vocab_size, d_model, nhead, num_layers, dropout=0.5):
super(TransformerModel, self).__init__()
self.model_type = 'Transformer'
self.d_model = d_model
self.nhead = nhead
self.num_layers = num_layers
self.encoder_embed = nn.Embedding(input_vocab_size, d_model)
self.decoder_embed = nn.Embedding(output_vocab_size, d_model)
encoder_layer = TransformerEncoderLayer(d_model, nhead, dim_feedforward=2048, dropout=dropout)
self.encoder = TransformerEncoder(encoder_layer, num_layers)
decoder_layer = TransformerDecoderLayer(d_model, nhead, dim_feedforward=2048, dropout=dropout)
self.decoder = TransformerDecoder(decoder_layer, num_layers)
self.output_layer = nn.Linear(d_model, output_vocab_size)
self.init_weights()
def init_weights(self):
init_range = 0.1
self.encoder_embed.weight.data.uniform_(-init_range, init_range)
self.decoder_embed.weight.data.uniform_(-init_range, init_range)
self.output_layer.bias.data.zero_()
self.output_layer.weight.data.uniform_(-init_range, init_range)
def forward(self, src, tgt):
src_emb = self.encoder_embed(src) * math.sqrt(self.d_model)
tgt_emb = self.decoder_embed(tgt) * math.sqrt(self.d_model)
src_pad_mask = (src == 0)
tgt_pad_mask = (tgt == 0)
tgt_mask = self.generate_square_subsequent_mask(tgt.size(0))
memory = self.encoder(src_emb.transpose(0, 1), src_key_padding_mask=src_pad_mask)
output = self.decoder(tgt_emb.transpose(0, 1), memory, tgt_mask=tgt_mask, tgt_key_padding_mask=tgt_pad_mask, memory_key_padding_mask=src_pad_mask)
output = self.output_layer(output.transpose(0, 1))
return output
def generate_square_subsequent_mask(self, sz):
mask = (torch.triu(torch.ones(sz, sz)) == 1).transpose(0, 1)
mask = mask.float().masked_fill(mask == 0, float('-inf')).masked_fill(mask == 1, float(0.0))
return mask
第四十四课 BERT结构
44.1是什么
BERT是一种预训练语言模型,全称为Bidirectional Encoder Representations from Transformers。它是由Google在2018年提出的一种新型的语言模型,通过使用大规模语料库进行无监督训练,可以实现在各种自然语言处理任务上取得最先进的性能。
BERT模型的核心是Transformer结构,通过编码器对输入的句子进行建模,使其能够捕捉到输入文本中的上下文信息。BERT还使用了一个双向的预训练策略,即通过同时预测输入序列中的前后文单词,来学习单词之间的语义关系和上下文信息。
44.2怎么用
下面是使用PyTorch实现BERT的示例代码:
import torch
import torch.nn as nn
from transformers import BertModel, BertTokenizer
class BertClassifier(nn.Module):
def __init__(self, bert_path, num_classes):
super(BertClassifier, self).__init__()
self.bert = BertModel.from_pretrained(bert_path)
self.classifier = nn.Linear(self.bert.config.hidden_size, num_classes)
def forward(self, input_ids, attention_mask):
outputs = self.bert(input_ids=input_ids, attention_mask=attention_mask)
pooled_output = outputs[1]
logits = self.classifier(pooled_output)
return logits
44.3为什么这样用
在这个例子中,我们首先导入了PyTorch、PyTorch的nn模块,以及transformers库中的BertModel和BertTokenizer。然后,我们定义了一个BertClassifier类,该类继承自nn.Module类,是我们自定义的BERT模型。其中,我们将预训练的BERT模型从bert_path中加载,并将输出连接到一个全连接层上,最后输出分类结果。
在BertClassifier的forward方法中,我们传入了input_ids和attention_mask两个参数,这是BERT模型的输入。input_ids是由句子中每个单词对应的ID组成的向量,attention_mask是由0和1组成的向量,用于标识哪些部分是句子中的单词,哪些是填充的部分。
在BertModel的输出中,我们取第二个输出,即pooler output,作为全连接层的输入。最后,我们将全连接层的输出作为分类结果返回。
第四十五课 NLP
45.1是什么
自然语言处理(Natural Language Processing,简称NLP)是人工智能领域中的一个重要分支,主要研究计算机如何理解、处理和生成自然语言。NLP技术可以被应用于各种领域,如语音识别、机器翻译、文本分类、命名实体识别、情感分析、问答系统等。
45.2怎么用
在NLP中,常用的处理方法包括以下几个方面:
-
分词(Tokenization):将一段文本切割成一个个的单词或词组,这是NLP中的第一步预处理。
-
词性标注(Part-of-speech tagging):给每个单词打上其在句子中的词性标签,如名词、动词、形容词等。
-
命名实体识别(Named entity recognition):从文本中识别出人名、地名、机构名等命名实体。
-
语法分析(Parsing):对句子进行分析,提取出其中的短语结构和语法关系。
-
语义分析(Semantic analysis):对句子进行语义分析,了解句子的含义和意图。
-
文本分类(Text classification):将文本划分到不同的类别中,如情感分类、主题分类等。
-
文本聚类(Text clustering):将文本聚类到不同的类别中,以便于对文本进行归类和处理。
在实现上,可以使用Python中的自然语言处理库,如NLTK、spaCy、TextBlob等。下面是一个示例代码,展示了如何使用NLTK进行文本分词和词性标注:
import nltk
text = "This is a sample text for natural language processing."
# 分词
tokens = nltk.word_tokenize(text)
# 词性标注
tags = nltk.pos_tag(tokens)
print(tags)
输出结果为:
[('This', 'DT'), ('is', 'VBZ'), ('a', 'DT'), ('sample', 'JJ'), ('text', 'NN'), ('for', 'IN'), ('natural', 'JJ'), ('language', 'NN'), ('processing', 'NN'), ('.', '.')]
其中,每个单词后面的缩写表示其词性标签。例如,'DT’表示限定词(determiner),'VBZ’表示三单现在时动词(third person singular present verb),'JJ’表示形容词(adjective),'NN’表示名词(noun)。
第四十六课 Attention编程实例
asked_fill(mask == 0, float(‘-inf’)).masked_fill(mask == 1, float(0.0))
return mask
##### 第四十四课 BERT结构
44.1是什么
BERT是一种**预训练语言模型**,全称为Bidirectional Encoder Representations from Transformers。它是由Google在2018年提出的一种新型的语言模型,通过使用大规模语料库进行无监督训练,可以实现在各种自然语言处理任务上取得最先进的性能。
BERT模型的核心是**Transformer结构**,**通过编码器对输入的句子进行建模,使其能够捕捉到输入文本中的上下文信息**。BERT还使用了一个双向的预训练策略,即通过同时预测输入序列中的前后文单词,来学习单词之间的语义关系和上下文信息。
44.2怎么用
下面是使用PyTorch实现BERT的示例代码:
```python
import torch
import torch.nn as nn
from transformers import BertModel, BertTokenizer
class BertClassifier(nn.Module):
def __init__(self, bert_path, num_classes):
super(BertClassifier, self).__init__()
self.bert = BertModel.from_pretrained(bert_path)
self.classifier = nn.Linear(self.bert.config.hidden_size, num_classes)
def forward(self, input_ids, attention_mask):
outputs = self.bert(input_ids=input_ids, attention_mask=attention_mask)
pooled_output = outputs[1]
logits = self.classifier(pooled_output)
return logits
44.3为什么这样用
在这个例子中,我们首先导入了PyTorch、PyTorch的nn模块,以及transformers库中的BertModel和BertTokenizer。然后,我们定义了一个BertClassifier类,该类继承自nn.Module类,是我们自定义的BERT模型。其中,我们将预训练的BERT模型从bert_path中加载,并将输出连接到一个全连接层上,最后输出分类结果。
在BertClassifier的forward方法中,我们传入了input_ids和attention_mask两个参数,这是BERT模型的输入。input_ids是由句子中每个单词对应的ID组成的向量,attention_mask是由0和1组成的向量,用于标识哪些部分是句子中的单词,哪些是填充的部分。
在BertModel的输出中,我们取第二个输出,即pooler output,作为全连接层的输入。最后,我们将全连接层的输出作为分类结果返回。
第四十五课 NLP
45.1是什么
自然语言处理(Natural Language Processing,简称NLP)是人工智能领域中的一个重要分支,主要研究计算机如何理解、处理和生成自然语言。NLP技术可以被应用于各种领域,如语音识别、机器翻译、文本分类、命名实体识别、情感分析、问答系统等。
45.2怎么用
在NLP中,常用的处理方法包括以下几个方面:
-
分词(Tokenization):将一段文本切割成一个个的单词或词组,这是NLP中的第一步预处理。
-
词性标注(Part-of-speech tagging):给每个单词打上其在句子中的词性标签,如名词、动词、形容词等。
-
命名实体识别(Named entity recognition):从文本中识别出人名、地名、机构名等命名实体。
-
语法分析(Parsing):对句子进行分析,提取出其中的短语结构和语法关系。
-
语义分析(Semantic analysis):对句子进行语义分析,了解句子的含义和意图。
-
文本分类(Text classification):将文本划分到不同的类别中,如情感分类、主题分类等。
-
文本聚类(Text clustering):将文本聚类到不同的类别中,以便于对文本进行归类和处理。
在实现上,可以使用Python中的自然语言处理库,如NLTK、spaCy、TextBlob等。下面是一个示例代码,展示了如何使用NLTK进行文本分词和词性标注:
import nltk
text = "This is a sample text for natural language processing."
# 分词
tokens = nltk.word_tokenize(text)
# 词性标注
tags = nltk.pos_tag(tokens)
print(tags)
输出结果为:
[('This', 'DT'), ('is', 'VBZ'), ('a', 'DT'), ('sample', 'JJ'), ('text', 'NN'), ('for', 'IN'), ('natural', 'JJ'), ('language', 'NN'), ('processing', 'NN'), ('.', '.')]
其中,每个单词后面的缩写表示其词性标签。例如,'DT’表示限定词(determiner),'VBZ’表示三单现在时动词(third person singular present verb),'JJ’表示形容词(adjective),'NN’表示名词(noun)。