题目一:用梯度下降法求得y=(x-2.5)²+3的最小值点
我们首先给出公式:X = X - α * grad,接下来,我将从两个方面对梯度下降进行讲解
(1)什么是梯度下降?
在二元一次方程中,如何让计算机求解出最小值呢,梯度下降法就可以解决
如图所示,梯度下降法就好像是一个人,从半坡走到波谷的过程。首先以他当前的所处的位置为基准,寻找这个位置最陡峭的地方,然后朝着下降方向走一步,然后又继续以当前位置为基准,再找最陡峭的地方,再走直到最后到达最低处;同理上山也是如此,只是这时候就变成梯度上升算法了
对于题目上的方程来讲,y=(x-2.5)²+3,导数即可写为:
grad = 2 * x - 5
我们可以看到,梯度就是变量进行微分,说明梯度其实一个向量。
梯度是微积分中一个很重要的概念,在单变量的函数中,梯度其实就是函数的微分,代表着函数在某个给定点的切线的斜率。在多变量函数中,梯度是一个向量,向量有方向,梯度的方向就指出了函数在给定点的上升最快的方向
(2) α是什么含义?
α在梯度下降算法中被称作为学习率或者步长,意味着我们可以通过α来控制每一步走的距离。不要走太快,错过了最低点。同时也要保证不要走的太慢,导致太阳下山了,还没有走到山下。所以α的选择在梯度下降法中往往是很重要的!α不能太大也不能太小,太小的话,可能导致迟迟走不到最低点,太大的话,会导致错过最低点!
所以在实际步骤上,我们对 x 进行一个随意的初始赋值,然后通过梯度下降算法,对最低点进行运算,代码如下:
x = 3.5 #初始赋值
grad = 2 * x - 5
lr = 0.1 #学习率α
i = 0
while abs(grad) > 0.0001: #循环截至条件为梯度值小于0。0001,即约等于0
i += 1 #统计次数
grad = 2 * x - 5
x = x - lr * grad #梯度代换
print("次数:{} X的值:{}".format(i,x)) #对结果进行输出
运行结果如图:
题目二:通过梯度下降求线性回归方程
对于梯度下降,我们通常用他来解决的实际问题是线性回归
通过分析披萨的直径与价格的线性关系,来预测任一直径的披萨的价格。而在这里,会用到损失函数的概念
(1)损失函数
在此公式中:
m是数据集中数据点的个数,也就是样本数
½是一个常量,这样是为了在求梯度的时候,二次方乘下来的2就和这里的½抵消了,自然就没有多余的常数系数,方便后续的计算,同时对结果不会有影响
y 是数据集中每个点的真实y坐标的值,也就是类标签
h 是我们的预测函数(假设函数),根据每一个输入x,根据Θ 计算得到预测的y值,即
代码如下:
首先,我们需要定义数据集和学习率
from numpy import *
# 数据集大小 即20个数据点
m = 20
# x的坐标以及对应的矩阵
X0 = ones((m, 1)) # 生成一个m行1列的向量,也就是x0,全是1
X1 = arange(1, m+1).reshape(m, 1) # 生成一个m行1列的向量,也就是x1,从1到m
X = hstack((X0, X1)) # 按照列堆叠形成数组,其实就是样本数据
# 对应的y坐标
y = np.array([
7, 9, 13, 17.5, 18
]).reshape(m, 1)
# 学习率
alpha = 0.01
接下来我们以矩阵向量的形式定义代价函数和代价函数的梯度
# 定义代价函数
def cost_function(theta, X, Y):
diff = dot(X, theta) - Y # dot() 数组需要像矩阵那样相乘,就需要用到dot()
return (1/(2*m)) * dot(diff.transpose(), diff)
# 定义代价函数对应的梯度函数
def gradient_function(theta, X, Y):
diff = dot(X, theta) - Y
return (1/m) * dot(X.transpose(), diff)
最后就是算法的核心部分,梯度下降迭代计算
# 梯度下降迭代
def gradient_descent(X, Y, alpha):
theta = array([1, 1]).reshape(2, 1)
gradient = gradient_function(theta, X, Y)
while not all(abs(gradient) <= 1e-5):
theta = theta - alpha * gradient
gradient = gradient_function(theta, X, Y)
return theta
optimal = gradient_descent(X, Y, alpha)
print('optimal:', optimal)
print('cost function:', cost_function(optimal, X, Y)[0][0])
当梯度小于1e-5时,说明已经进入了比较平滑的状态,类似于山谷的状态,这时候再继续迭代效果也不大了,所以这个时候可以退出循环!
运行代码,计算得到的结果如下:
print('optimal:', optimal) # 结果 [[0.51583286][0.96992163]]
print('cost function:', cost_function(optimal, X, Y)[0][0]) # 1.014962406233101
通过matplotlib画出图像,
# 根据数据画出对应的图像
def plot(X, Y, theta):
import matplotlib.pyplot as plt
ax = plt.subplot(111) # 这是我改的
ax.scatter(X, Y, s=30, c="red", marker="s")
plt.xlabel("X")
plt.ylabel("Y")
x = arange(0, 21, 0.2) # x的范围
y = theta[0] + theta[1]*x
ax.plot(x, y)
plt.show()
plot(X1, Y, optimal)
图下如下:
结语:
最后不得不说,通过短期的学习,最后能够看到自己画出的图像,还是很自豪的哈