深度学习(二)

  • 什么是激活函数?激活函数有什么作用呢?

激活函数是神经网络中的一种非线性转换函数,它将神经元的输入信号转换为输出信号。在神经网络的每一层中,激活函数都会对输入信号进行处理,以便引入非线性特性,从而使神经网络能够学习和表示更加复杂的函数关系。

可以看见下图是一个神经元,神经元的输入是n个不同的特征,每个特征占有一定的权重值,然后计算W1*X1+W2*X2+......+Wn*Xn,但是所得的结果是线性结果。如果遇到复杂的非线性关系,是不是就需要激活函数了。

所以激活函数主要的作用有以下两点:

  1. 引入非线性:激活函数能够解决神经网络的线性叠加问题,通过引入非线性,使得神经网络能够学习非线性关系,从而提高其表示能力。
  2. 激活神经元:激活函数能够控制神经元的激活状态,将输入信号转化为输出信号,从而传递到网络的下一层。(类似于脑神经元,当我们大脑受到比较小的刺激信号,可能没什么反应,也就是输出0,但是当我们大脑受到比较大的刺激信号,达到某种阈值以后,就会激活,刺激信号往下传递,输出1)

具体过程如下图:

附上一个小demo,给一些散乱的点,进行非线性拟合:

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt

# 生成训练数据
x_train = np.linspace(-2 * np.pi, 2 * np.pi, 100).reshape(-1, 1)
y_train = np.sin(x_train)

# 转换为 PyTorch 的 Tensor
x_train_tensor = torch.from_numpy(x_train).float()
y_train_tensor = torch.from_numpy(y_train).float()


# 定义更复杂的神经网络模型
class ComplexNet(nn.Module):
    def __init__(self):
        super(ComplexNet, self).__init__()
        self.fc1 = nn.Linear(1, 20)
        self.fc2 = nn.Linear(20, 20)
        self.fc3 = nn.Linear(20, 1)

    def forward(self, x):
        # 激活函数relu
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        x = self.fc3(x)
        return x


model = ComplexNet()

# 定义优化器和损失函数,并调整学习率
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 增加训练迭代次数
losses = []
for epoch in range(5000):
    optimizer.zero_grad()
    output = model(x_train_tensor)
    loss = criterion(output, y_train_tensor)
    loss.backward()
    optimizer.step()
    losses.append(loss.item())

# 可视化曲线拟合效果
x_test = np.linspace(-3 * np.pi, 3 * np.pi, 200).reshape(-1, 1)
x_test_tensor = torch.from_numpy(x_test).float()
y_pred = model(x_test_tensor).detach().numpy()

plt.figure()
plt.scatter(x_train, y_train, c='b', label='Actual')
plt.plot(x_test, y_pred, c='r', label='Predicted')
plt.legend()
plt.show()

print("finish!")

运行结果如下,可以看到这是一个非线性拟合,多亏了激活函数:

  • 什么是损失函数?

其实损失函数上一节课已经介绍过了,在这里再进行一个复习。损失函数(Loss Function)是用来衡量模型预测结果与真实数值之间的差异的函数。在神经网络的训练过程中,我们通过不断调整模型的参数,使得损失函数的数值逐渐减小,以达到使模型的预测结果更加接近真实数值的目的。

损失函数常用的有两种:均方误差(MSE)和交叉熵损失(Cross Entropy Loss)

  • 均方误差(MSE):常用于回归问题,计算预测值与真实值之间的平方差的均值。在pytorch中调用MSELoss()函数即可。
  • 交叉熵损失(Cross Entropy Loss):常用于分类问题,特别是多分类问题,衡量两个概率分布之间的差异。

  • 梯度下降算法

梯度下降算法是一种常用的优化算法,用于最小化函数的数值。在机器学习和深度学习中,梯度下降算法通常被用来更新模型参数,以使损失函数的数值逐渐减小,从而使模型的预测结果更加接近真实数值。

举一个最常见的例子:一个人站在山顶,想要快速下山,那什么决策是最好的呢,当然是每次选的都是最陡的路,一直执行这个决策,循环多次,总能到达山脚。而梯度就是衡量这个坡是否陡峭。

梯度是一个数学上的概念,指的是多元函数在某一点的变化率或斜率。对于一个具有多个自变量的函数,其梯度由各个自变量的偏导数组成,用向量表示。

上面已经解决了下山的方向,那我们是否还得考虑每次下山所迈步伐的大小。如果步子太大了,就存在来回波动的可能性,久久不能到达最低点;如果步子太小了,下山速度太慢,也是久久不能到达最低点,所以我们要确定一个合适的步长。

大步长的优点:

  1. 快速收敛: 使用较大的步长可以使算法更快地收敛到最优解,特别是在初始阶段能够快速朝着最优解的方向前进。
  2. 提高泛化能力: 有时候,通过使用较大的步长,模型更容易跳出局部最优解,从而提高泛化能力,尤其是在损失函数具有多个局部最优解的情况下。

大步长的缺点:

  1. 不稳定性: 较大的步长可能导致在参数空间中来回摆动,甚至可能导致算法无法收敛或发散。
  2. 风险: 过大的步长可能导致算法“跳过”最优解,甚至在参数空间内反复震荡而无法收敛。

小步长的优点:

  1. 稳定性: 使用较小的步长可以使得算法更加稳定,避免发散或者来回震荡。
  2. 精确度: 较小的步长可以使得算法更加精确地逼近最优解,特别是接近最优解时能够更细致地搜索最优参数。

小步长的缺点:

  1. 收敛慢: 使用较小的步长可能导致算法收敛速度较慢,特别是在初始阶段需要更多的迭代次数才能接近最优解。
  2. 陷入局部最优解: 过小的步长可能会使得算法难以跳出局部最优解,从而影响模型的泛化能力。

在下山的方向和步伐大小已经确定的情况下,我们现在考虑怎么实现梯度下降算法。

θ=θ'−α∗∇J(θ)

J是关于θ的函数,当前点处于θ',我们要想走到山底,我们就得沿着梯度的反方向-∇J(θ),按照一定的步长下降α,最终达到最低点θ

当谈到梯度下降算法时,通常会提到三种主要的变种:批量梯度下降(Batch Gradient Descent)、随机梯度下降(Stochastic Gradient Descent)和小批量梯度下降(Mini-Batch Gradient Descent)。

  1. 批量梯度下降 (Batch Gradient Descent):

    • 批量梯度下降是最基本的梯度下降算法。在每一次迭代中,它使用整个训练数据集来计算目标函数的梯度,然后更新模型的参数。
    • 优点是收敛稳定,能够保证在合理步长下收敛到局部最优解或全局最优解。然而,由于需要在整个数据集上进行计算,对于大规模数据集来说计算成本较高。
  2. 随机梯度下降 (Stochastic Gradient Descent):

    • 随机梯度下降与批量梯度下降的区别在于,它在每次迭代中仅使用单个样本来计算梯度并更新参数。因此,它的更新是更加频繁的,且计算开销较小。
    • 虽然随机梯度下降有助于跳出局部最优解,并且在大规模数据集上更为高效,但由于梯度估计的高方差性,使得其不太稳定,需要精心调整学习率。
  3. 小批量梯度下降 (Mini-Batch Gradient Descent):

    • 小批量梯度下降结合了批量梯度下降和随机梯度下降的优点。它在每次迭代中使用一个小批量的样本来计算梯度并更新参数。
    • 这种方法在实践中得到了广泛应用,因为它兼顾了收敛速度和计算效率,尤其对于中等规模的数据集表现良好。

总的来说,这三种梯度下降算法各有优劣,选择哪种取决于数据集的规模、计算资源和对收敛速度的要求。

梯度下降的实现代码:

# 执行梯度下降算法
losses = []  # 创建一个空列表用于存储每次迭代的损失值
for i in range(num_iterations):  # 进行指定次数的迭代训练
    y_pred = linear_function(w, b, x_train)  # 使用当前的参数 w 和 b 对输入数据 x_train 进行预测
    loss = mean_squared_error(y_train, y_pred)  # 计算预测值与实际值之间的均方误差损失
    losses.append(loss)  # 将本次迭代的损失值添加到列表中,用于后续可视化或分析

    dw, db = compute_gradients(x_train, y_train, y_pred)  # 计算损失函数关于参数 w 和 b 的梯度
    w -= learning_rate * dw  # 根据梯度下降算法更新参数 w
    b -= learning_rate * db  # 根据梯度下降算法更新参数 b

但是后续pytorch中封装好了一些优化器供我们使用,例如下图:

我们正在使用PyTorch中的Adam优化器,Adam是一种有效的梯度下降优化算法,结合了动量方法和自适应学习率。它能够在训练过程中自适应地调整学习率,并且通常能够更快地收敛到较好的解。

  • net.parameters(): 这部分将神经网络模型net的所有参数传递给优化器,以便优化器可以更新这些参数。这确保了优化器将对神经网络模型中的所有可训练参数进行优化。

  • lr=0.0002: 这部分指定了学习率(learning rate)为0.0002,学习率决定了在每次参数更新时的步长大小,它是梯度下降算法中非常重要的超参数之一。在Adam优化器中,学习率是动态调整的,但初始的学习率仍然起着关键作用。

下面是一个使用均分误差求损失函数的线性模型,可以运行一下代码。

import numpy as np
import matplotlib.pyplot as plt

# 目标函数
def linear_function(w, b, x):
    return w * x + b

# 均方误差损失函数
def mean_squared_error(y_true, y_pred):
    return np.mean((y_true - y_pred) ** 2)

# 计算梯度
def compute_gradients(x, y_true, y_pred):
    dw = np.mean((y_pred - y_true) * x)
    db = np.mean(y_pred - y_true)
    return dw, db

# 初始化参数
w = 0.5
b = 2.0
learning_rate = 0.05
num_iterations = 100

# 生成训练数据
x_train = np.random.rand(100)
y_train = 2.5 * x_train + 1.5 + np.random.randn(100) * 0.2

# 执行梯度下降算法
losses = []
for i in range(num_iterations):
    y_pred = linear_function(w, b, x_train)
    loss = mean_squared_error(y_train, y_pred)
    losses.append(loss)

    dw, db = compute_gradients(x_train, y_train, y_pred)
    w -= learning_rate * dw
    b -= learning_rate * db

# 绘制损失函数随迭代次数的变化
plt.plot(range(num_iterations), losses)
plt.xlabel('Iterations')
plt.ylabel('Loss')
plt.title('Training Loss over Iterations')
plt.show()

# 绘制训练数据和拟合结果的散点图
plt.scatter(x_train, y_train, label='Training Data')
plt.plot(x_train, linear_function(w, b, x_train), color='red', label='Fitted Line')
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Fitted Linear Model')
plt.legend()
plt.show()


print("finish!")

运行结果如下:(左图是线性模型拟合,右图是损失函数收敛过程)

  • 过拟合?欠拟合?如果造成这两种现象的?解决方案是什么?

1、什么是过拟合?

一家运动鞋公司,设计了一款新的运动鞋,设计师是按照他自己的脚来设计的,所以对他的脚来说无比贴合,然后他心里就会想这个鞋子的模型也太过于完美了,肯定可以大卖一把。但是对于其他一些高脚被、宽脚掌、扁平足的人很不友好!换个人可能这双鞋就不行了,也可以说这双鞋的适应力很差,在设计的时候感觉无比完美,但是拿出来实用的时候,好像显得不那么好了。这种就叫过度拟合,拟合的太完美了,反而不适应于正常的数据。

用官方一点的解释就是:过拟合是指机器学习模型过度适应训练数据,以致于在面对新数据时表现不佳的现象。具体而言,过拟合表现为模型在训练数据上表现良好,但在未曾见过的数据上表现糟糕。这种现象通常发生在模型过于复杂或者训练数据太少的情况下。

2、什么是欠拟合?

就是设计师在设计鞋的时候,可能谁的脚型他都不参考了,他大概设计出一双鞋,这个鞋可能都是圆形的......就会导致这个模型看起来很差。

用官方一点的解释就是:欠拟合是指机器学习模型无法很好地适应训练数据的特征和规律,导致在训练数据和新数据上都表现不佳的现象。具体而言,欠拟合表示模型不能很好地捕捉数据背后的复杂关系和模式,通常表现为在训练集和测试集上都呈现较高的误差。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值