一、梯度下降算法
:目标值和预测之间的平方差。
:每个目标值和预测之间平方差的和
:总的平均方差
1、定义
梯度下降(Gradient Descent)是一种用于最小化损失函数的优化算法。它通过不断更新模型参数,使得损失函数的值逐渐减小,最终达到最小值。这是机器学习和深度学习中最常用的优化方法之一,尤其是在训练神经网络时。
成本函数与损失函数
成本函数(Cost Function)和损失函数(Loss Function)在机器学习和深度学习中的概念密切相关,但有一些细微的区别:
1. 损失函数(Loss Function)
定义:损失函数用来衡量单个样本的预测值与真实值之间的误差,也就是说它计算单个数据点的预测误差。
目标:衡量一个样本的预测值与实际值之间的差异,通常用于优化模型的参数。
常见形式:
均方误差(MSE, Mean Squared Error):用于回归任务,计算预测值与真实值的平方差。
L ( y , y ^ ) = ( y − y ^ ) 2 L(y, \hat{y}) = (y - \hat{y})^2 L(y,y^)=(y−y^)2 L ( y i , y ^ i ) = ( y i − y ^ i ) 2 L(y_i,\hat{y}_i)=(yi−\hat{y}_i)^2 L(yi,y^i)=(yi−y^i)2
交叉熵损失(Cross-Entropy Loss):常用于分类任务,计算分类预测值与真实值的差异。
作用:每次计算一个样本的损失后,可以通过梯度下降等优化算法来调整模型参数。
2. 成本函数(Cost Function)
定义:==成本函数通常是指对整个数据集的损失进行平均或求和后得到的结果,它衡量了模型在整个训练数据集上的表现。==成本函数就是所有训练样本的预测值与实际值之间的误差平方和。
目标:它用于指导模型的优化,使得整个数据集上的平均误差最小化,从而提高模型的整体性能。
常见形式:
对于回归问题,成本函数通常是均方误差(MSE)的均值形式:
J ( w , b ) = 1 2 m ∑ i = 0 m − 1 ( y i − y ^ i ) 2 J(w, b) = \frac{1}{2m} \sum_{i=0}^{m-1} (y_i - \hat{y}_i)^2 J(w,b)=2m1∑i=0m−1(yi−y^i)2
:目标值和预测之间的平方差。
:每个目标值和预测之间平方差的和
其中,
m
是数据集的样本数, y i y_i yi 是真实值, y ^ i \hat{y}_i y^i是预测值。目标是通过调整参数 w 和 b,使得成本函数 $J(w,b) $最小化,从而优化模型的性能。
对于分类问题,成本函数可以是交叉熵损失的均值形式:
J ( w , b ) = − 1 m ∑ i = 1 m y i log ( y ^ i ) J(w, b) = - \frac{1}{m} \sum_{i=1}^{m} y_i \log(\hat{y}_i) J(w,b)=−m1∑i=1myilog(y^i)
作用:成本函数是对所有样本的损失进行的汇总,它是模型在整个训练集上的平均损失,用来衡量模型的整体好坏,优化目标是最小化成本函数。
3. 区别总结
区别 损失函数 成本函数 作用对象 单个样本的误差 整个训练集的平均误差 表达形式 衡量一个样本的预测与真实值的差异 衡量整个数据集的平均误差 常见公式 均方误差、交叉熵损失等 均方误差均值、交叉熵均值等 用途 计算单个样本的误差,用于更新模型参数 用于优化模型,使整个训练集的平均误差最小化 4. 具体联系
- 损失函数是成本函数的组成部分,成本函数是对所有样本损失的综合统计。优化算法(如梯度下降)使用成本函数来更新模型的参数,以达到最优解。
2、梯度的概念
在多维空间中,梯度表示一个函数在每个维度上变化的方向和速率。对于损失函数 J(w)
,其梯度 ∇J(w)
是一个向量,指向损失函数增大的方向。因此,梯度下降的核心思想是沿着梯度的反方向移动,从而减小损失函数的值。
具体而言:
- 如果我们沿着梯度的方向移动,损失函数的值会增加;
- 如果沿着梯度的反方向移动,损失函数的值会减小。
3. 梯度下降的更新公式
假设我们要最小化某个损失函数 J(w)
,并且 w
是模型的参数。梯度下降的更新公式为:
w : = w − α ⋅ ∂ J ( w ) ∂ w w := w - \alpha \cdot \frac{\partial J(w)}{\partial w} w:=w−α⋅∂w∂J(w)
b : = b − α ⋅ ∂ J ( b ) ∂ b b := b - \alpha \cdot \frac{\partial J(b)}{\partial b} b:=b−α⋅∂b∂J(b)
其中:
w
是参数;α
是学习率,它决定了每次参数更新的步长;-
∂
J
(
w
)
∂
w
\frac{\partial J(w)}{\partial w}
∂w∂J(w) 是损失函数
J(w)
对参数w
的梯度,即导数。
4、 梯度下降的工作流程
- 步骤 1:初始化模型参数
w
和b
(通常是随机的或为0)。 - 步骤 2:计算损失函数
J(w)
,用于衡量模型在当前参数下的预测误差。 - 步骤 3:计算损失函数对参数的偏导数,即梯度。这个梯度告诉我们损失函数在参数空间中增大的方向。
- 步骤 4:根据梯度的反方向更新参数,更新步长由学习率
α
决定。 - 步骤 5:重复步骤 2 到步骤 4,直到损失函数达到局部或全局最小值,或满足提前终止条件(如迭代次数、损失函数的变化幅度等)。
5、计算损失函数 j ( w , b ) j(w,b) j(w,b)代码实例
# 导入numpy、matplotlib模块
import numpy as np
from matplotlib import pyplot as plt
# 设定特征值
x_train = np.array([1, 2 , 3])
y_train = np.array([1, 2 , 3])
x = np.array([1, 2, 3])
# 设定权重
w=[]
for n in range(-1,6,1):
w.append(n/2)
# 设定偏移
b=0
# 获取x(特征值)数量
m = len(x)
# 定义变量
cost_sum = 0
J_wb=[]
# 计算成本函数
for j in range(len(w)):
for i in range(m):
f_wb = w[j] * x[i] + b
cost = (f_wb - y_train[i]) ** 2
cost_sum = cost_sum + cost
j_wb = (1 / (2 * (m+1))) * cost_sum
cost_sum = 0
J_wb.append(j_wb)
# 绘制成本函数点
plt.scatter(w, J_wb)
# 绘制成本函数线
plt.plot(w, J_wb, color='red')
# 添加标题和标签
plt.title('Cost function')
plt.xlabel('w')
plt.ylabel('J_wb')
# 显示图形
plt.show()
代码:https://blog.csdn.net/cornki/article/details/132003714?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522A168A2B3-B7CA-448F-8E12-3C84771054D5%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=A168A2B3-B7CA-448F-8E12-3C84771054D5&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_click~default-2-132003714-null-null.142v100pc_search_result_base3&utm_term=%E6%A2%AF%E5%BA%A6%E4%B8%8B%E9%99%8D&spm=1018.2226.3001.4187
由上图可以清晰看到随着w的变化,总的平均方差也在改变,因此可以通过梯度下降的方法最小化成本来改变w和b就可以得到一条与数据完美拟合的线
6、梯度下降算法代码示例
# 导入numpy、matplotlib模块
import numpy as np
from matplotlib import pyplot as plt
# 设定特征值
x_train = np.array([1,2,3,4,5,6] )
y_train = np.array([15,22,31,44,57,62] )
# 设定权重、偏移、学习率、x的数量、方差列表、w的列表(后面作图)
w = 1
b = 0
a = 0.01
m = len(x_train)
J_wb_list = []
w_list = []
# 定义#J_wb函数(方差)
def J_wb(w,x,b,m):
cost_sum = 0
for i in range(m):
f_wb = w * x[i] + b
cost = (f_wb - y_train[i]) ** 2
cost_sum = cost_sum + cost
J_wb = 1 / (2 * m) * cost_sum
return J_wb
# 定义w_new函数(优化w值)
def w_new(w,x,b,m,a):
cost_w_sum = 0
for i in range(m):
f_wb = w * x[i] + b
cost_w = (f_wb - y_train[i]) * x[i]
# print(cost_w)
cost_w_sum = cost_w_sum + cost_w
J_wb_w = w - (1 / m) * a * cost_w_sum
return J_wb_w
# 定义b_new函数(优化b值)
def b_new(w,x,b,m,a):
cost_b_sum = 0
for i in range(m):
f_wb = w * x[i] + b
cost_b = f_wb - y_train[i]
cost_b_sum = cost_b_sum + cost_b
J_wb_b = b - (1 / m) * a * cost_b_sum
return J_wb_b
# 设置循环判定条件和结束条件
J_wb_one = J_wb(w,x_train,b,m)
w_one = w_new(w,x_train,b,m,a)
b_one = b_new(w,x_train,b,m,a)
w=w_one
b=b_one
# 如果方差在图形(学习率的图片)左侧
if J_wb_one > J_wb(w,x_train,b,m):
while J_wb_one > J_wb(w,x_train,b,m):
J_wb_one = J_wb(w, x_train, b, m)
w_one = w_new(w,x_train,b,m,a)
b_one = b_new(w,x_train,b,m,a)
w=w_one
b=b_one
J_wb_list.append(J_wb(w, x_train, b, m))
w_list.append(w)
if J_wb(w,x_train,b,m) == J_wb_one:
break
# 如果方差在图形(学习率的图片)右侧
else:
while J_wb_one < J_wb(w,x_train,b,m):
J_wb_one = J_wb(w, x_train, b, m)
w_one = w_new(w,x_train,b,m,a)
b_one = b_new(w,x_train,b,m,a)
w=w_one
b=b_one
J_wb_list.append(J_wb(w, x_train, b, m))
w_list.append(w)
if J_wb(w,x_train,b,m) == J_wb_one:
break
print(w,b,J_wb(w,x_train,b,m))
plt.subplot(211)
# 绘制成本函数点
plt.scatter(w_list, J_wb_list)
# 绘制成本函数线
plt.plot(w_list, J_wb_list, color='red')
# 添加标题和标签
plt.title('Change map')
plt.xlabel('w')
plt.ylabel('J_wb')
# 显示图形
plt.subplot(212)
plt.plot(x_train, y_train, 'o', color='blue')
plt.show()
解读:
这个代码实现了一个简单的线性回归模型,通过梯度下降法来优化模型的权重参数
w
和 偏置b
,以最小化模型的损失函数(也就是方差)。代码的主要目的是通过不断优化w
和b
,使得模型的预测值与实际值的差距(即损失)最小,并最终绘制出损失函数J_wb
随w
的变化图。1. 导入必要模块
import numpy as np from matplotlib import pyplot as plt
numpy
用于处理数组和数值计算。matplotlib.pyplot
用于绘制图形。2. 设置训练数据
x_train = np.array([1,2,3,4,5,6]) y_train = np.array([15,22,31,44,57,62])
x_train
和y_train
是你手动设置的训练数据(特征和标签)。这里的x_train
是输入特征,y_train
是输出目标值。3. 初始化模型参数
w = 1 b = 0 a = 0.01 m = len(x_train) J_wb_list = [] w_list = []
w
:模型的权重,初始值为 1。b
:偏置,初始值为 0。a
:学习率(梯度下降的步长),设定为 0.01。m
:数据集的大小,x_train
的长度为6。J_wb_list
和w_list
:用于记录每次迭代中的损失和权重值,方便后面绘制曲线。4. 定义损失函数
J_wb
def J_wb(w,x,b,m): cost_sum = 0 for i in range(m): f_wb = w * x[i] + b cost = (f_wb - y_train[i]) ** 2 cost_sum = cost_sum + cost J_wb = 1 / (2 * m) * cost_sum return J_wb
- 损失函数:
J_wb
是线性回归中的平方差损失函数,用来计算模型的预测值与真实值之间的差异。f_wb = w * x[i] + b
是模型的预测值公式,其中w
是权重,b
是偏置。- 通过循环遍历所有数据点,计算总的平方误差,然后平均化并返回损失值。
5. 定义更新
w
的函数def w_new(w,x,b,m,a): cost_w_sum = 0 for i in range(m): f_wb = w * x[i] + b cost_w = (f_wb - y_train[i]) * x[i] cost_w_sum = cost_w_sum + cost_w J_wb_w = w - (1 / m) * a * cost_w_sum return J_wb_w
- 通过计算损失函数对
w
的偏导数,来更新权重w
,即通过梯度下降法调整w
。cost_w_sum
是对所有样本的误差与x[i]
的乘积进行累加。w_new
使用了梯度下降公式:w_new = w - learning_rate * gradient_w
。
6. 定义更新
b
的函数def b_new(w,x,b,m,a): cost_b_sum = 0 for i in range(m): f_wb = w * x[i] + b cost_b = f_wb - y_train[i] cost_b_sum = cost_b_sum + cost_b J_wb_b = b - (1 / m) * a * cost_b_sum return J_wb_b
- 同样是通过计算损失函数对
b
的偏导数来更新b
,即通过梯度下降法调整b
。7. 进行迭代优化
J_wb_one = J_wb(w,x_train,b,m) w_one = w_new(w,x_train,b,m,a) b_one = b_new(w,x_train,b,m,a) w=w_one b=b_one
- 初始计算当前的损失函数值
J_wb_one
,并用新的权重和偏置更新模型参数。8. 梯度下降循环
if J_wb_one > J_wb(w,x_train,b,m): while J_wb_one > J_wb(w,x_train,b,m): # 更新权重、偏置,并记录损失值 else: while J_wb_one < J_wb(w,x_train,b,m): # 更新权重、偏置,并记录损失值
- 代码中对损失函数进行了判断,分别根据损失函数是否在左侧或右侧进行梯度下降。
- 不断优化权重
w
和偏置b
,直到损失函数不再变化(达到最优解)。9. 打印结果
print(w,b,J_wb(w,x_train,b,m))
- 打印最终优化后的
w
和b
值,以及对应的损失函数值。10. 绘制损失函数变化曲线
plt.scatter(w_list, J_wb_list) plt.plot(w_list, J_wb_list, color='red') plt.title('Change map') plt.xlabel('w') plt.ylabel('J_wb') plt.show()
w_list
和J_wb_list
分别记录了每次迭代中的权重和损失函数值,通过matplotlib
将这些值绘制成曲线。- 通过该图,可以观察到模型的损失值如何随着权重的变化而变化。
11. 总结
- 该程序实现了一个简单的线性回归模型,使用了梯度下降法来优化权重
w
和偏置b
,并通过绘制图形观察损失函数的变化。- 损失函数用于衡量模型预测与实际值的差距,梯度下降通过最小化损失函数来找到最优的参数。
二、手写数字识别任务(十分类)
手写数字识别任务是一项经典的机器学习和计算机视觉任务,主要目标是让模型能够识别手写的数字,并将其分类为0到9中的某一个数字。它是多分类问题的一个具体应用,最常见的数据集是MNIST数据集。在手写数字识别中,模型会从一张图片中提取特征,然后根据这些特征来预测图片上显示的数字。
1. 手写数字识别任务的背景与应用
手写数字识别最初的应用场景是自动处理银行支票、邮件分拣、自动化表单处理等。现在,手写数字识别是机器学习、深度学习中的入门任务之一,用来测试和验证模型的分类性能。
常见应用包括:
- 光学字符识别(OCR):将手写或印刷文本转换为计算机可读的文本。
- 自动化表单处理:如银行支票的金额识别,文档扫描自动识别文字等。
2. MNIST数据集
MNIST(Modified National Institute of Standards and Technology)数据集是手写数字识别任务中最常用的数据集。它包含从0到9的手写数字图像。数据集由两部分组成:
- 训练集:包含60,000个手写数字图像及其对应的标签(0到9)。
- 测试集:包含10,000个手写数字图像及其对应的标签,用来评估模型性能。
每张图片都是28x28像素的灰度图像,像素值在0到255之间,其中:
- 值为0表示背景(黑色),
- 值为255表示前景(白色),
- 中间值表示不同的灰度级别。
每张图片的标签是一个数字,代表图片上所显示的手写数字。
归一化与像素值
像素值 是图像中每个像素(图片的最小单位)的数值表示。不同的像素值决定了该像素的颜色或亮度。对于灰度图像(如MNIST数据集中的手写数字图片),每个像素值代表该像素的亮度。通常灰度图像的像素值范围是 0到255,其中:
- 0 表示黑色,
- 255 表示白色,
- 0到255之间的数值表示不同的灰度级别。
RGB 则是针对彩色图像的一种颜色表示方式。RGB代表 红色(Red)、绿色(Green)、蓝色(Blue) 三个颜色通道,通过组合这三个颜色通道的强度值,来表示图像中每个像素的颜色。
1. 像素值
在灰度图像中,像素值是0到255之间的整数,代表该像素的亮度:
- 0:纯黑色,
- 255:纯白色,
- 中间的数值表示从黑色到白色的不同灰度。
在彩色图像中,像素的表示更加复杂。每个像素由三个值组成,分别是红色、绿色和蓝色(RGB),每个值的范围也在0到255之间。
- 0 表示该颜色通道的强度为最低(即没有该颜色),
- 255 表示该颜色通道的强度为最高。
2. RGB 与 像素值的关系
RGB图像的每个像素包含三个颜色通道,每个通道的像素值范围也是0到255。通过组合红、绿、蓝三个颜色通道的值,可以表示所有颜色。例如:
- (255, 0, 0) 代表红色:红色通道的值为255,绿色和蓝色通道的值为0。
- (0, 255, 0) 代表绿色:绿色通道的值为255,红色和蓝色通道的值为0。
- (0, 0, 255) 代表蓝色:蓝色通道的值为255,红色和绿色通道的值为0。
- (255, 255, 255) 代表白色:所有通道的值都为255。
- (0, 0, 0) 代表黑色:所有通道的值都为0。
3. 为什么要进行归一化
当处理图像时,尤其是在训练神经网络模型时,通常需要对输入的像素值进行归一化处理,即将像素值从0到255的范围缩放到0到1之间。这样做有以下好处:
减少数值范围差异:原始的像素值范围较大,输入到神经网络中时可能会导致梯度消失或爆炸问题。通过将像素值缩放到0到1之间,可以减少模型的计算负担,提升收敛速度。
更稳定的训练:归一化后的数据使得模型在训练时参数更新更加平稳,不容易因为大范围的输入数据导致优化器工作不正常。
4. 归一化的示例
归一化的基本公式是:
$ x_{\text{norm}} = \frac{x}{255} $对于灰度图像,假设一个像素值是 128,归一化后的值就是:
$x_{\text{norm}} = \frac{128}{255} \approx 0.502 $对于彩色图像,每个像素的三个通道的值都会分别进行归一化。例如,像素值 (255, 128, 64) 的归一化结果是:
[ (1.0, 0.502, 0.251) ]总结
- 像素值 是图像中每个像素的颜色或亮度的数值表示,灰度图像是0到255的灰度级,而彩色图像则使用RGB三个通道的值来表示颜色。
- RGB 图像通过红、绿、蓝三个颜色通道的组合来定义每个像素的颜色。
- 归一化 是将像素值从0到255缩放到0到1之间,以减少数值范围的差异,帮助神经网络模型更好地进行训练。
如果你正在处理图像数据,归一化是一个非常重要的步骤,尤其是在使用深度学习模型时,比如在手写数字识别任务中对MNIST数据集的处理。
3. 手写数字识别任务的工作流程
通常,手写数字识别任务可以通过以下几个步骤来完成:
3.1. 数据预处理
在任务开始时,我们需要对原始数据进行一些预处理:
- 归一化:将像素值从0到255的范围缩放到0到1,以减少输入特征的数值范围。
- 图像变换:有时候还会进行一些数据增强操作,比如随机旋转、缩放等,增加数据的多样性,提高模型的泛化能力。
3.2. 特征提取
特征提取的目的是将手写数字的图片转换为一种可以被模型理解的形式。在深度学习之前,常常会用手工设计的特征,如边缘、纹理等。如今,卷积神经网络(CNN)可以自动学习图片的特征,因此手写数字识别任务中广泛使用CNN来提取特征。
3.3. 模型训练
为了实现手写数字识别,通常使用以下几种常见的模型:
- 卷积神经网络(CNN):这是解决手写数字识别任务的主流模型。CNN能够有效捕捉图像的空间特征,通过卷积层、池化层提取特征,再通过全连接层进行分类。
- 支持向量机(SVM):在深度学习流行之前,SVM也是解决手写数字识别任务的常用模型,特别是线性SVM或多项式核SVM。
- K最近邻(KNN):KNN是一种简单的非参数模型,通过计算输入图像与训练集中所有图像的距离,选取K个最近的样本进行投票决策。
- 全连接神经网络(MLP):一种经典的神经网络结构,但由于其不能有效处理图像的空间信息,在手写数字识别上表现不如CNN。
3.4. 损失函数与优化
在训练过程中,模型会通过损失函数来计算预测值与真实值之间的误差。常用的损失函数是交叉熵损失(Cross-Entropy Loss),它适合多分类任务。然后通过反向传播(Backpropagation)来更新模型参数,优化方法通常使用梯度下降(如Adam、SGD等)。
3.5. 模型评估
模型训练完成后,会使用测试集对模型进行评估。常见的评估指标包括:
- 准确率:模型预测正确的样本数与总样本数的比值。
- 混淆矩阵:显示模型在不同类别上的预测表现,用来评估模型在每个数字上的分类效果。