今天学习了求解一次线性回归的梯度下降方法,很明显自己那点可怜的数学知识都还给年龄了,重试高数等课本,算是把梯度搞了个一知半解,下面通过一道练习题讲解一次线性回归的梯度下降求解:
练习:运用已有的数据集去选择在哪开连锁店,数据集包括一个变量(每个城市的人口)和目标(利润)。我们实际上是要将数据集“喂”给我们的学习算法,进而学习得到一个假设ℎ,然后将我们要预测的城市作为输入变量输入给ℎ,预测出该城市的利润作为输出变量输出为结果。为了使我们的假设h更好的拟合我们的数据,我们构建了代价函数并运用梯度下降算法来寻找合适的参数theta。
数据集采用ex1data1.txt作为数据源,第一列表示城市的人口数,第二列表示利润。
1.数据集初始化
#导入相关的库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#通过pandas读取数据内容,并打印出前5行数据,以保证读取成功,
columnNames = ["PeopleCount", "lirun"]
shops = pd.read_csv('/home/myy/testData/fristTrain/ex1data1.txt', names = columnNames)
print(shops.head(5))
#打印数据如下,其中表头为peopleCount和lirun,如下所示:
绘制城市人口与开店利润之间的关系图,更直观的查看两者关系,代码如下:
plt.scatter(shops["PeopleCount"], shops["lirun"])
plt.xlabel('PeopleCount')
plt.ylabel('利润')
plt.show()
绘制图形如下所示:
2.梯度下降原理分析
我们可以看到预测两者是一元线性关系,本文也只讨论一元线性关系,建设函数为:
则预测值与实际值之间的方差为:
如何求得w和b使得方差loss最小呢,这就涉及到高等数学中的二元变量的求导法则,其中有方向导数和梯度的概念,梯度就是二元函数变化最快的方向导数,当方向导数与梯度相同时,函数增加最快;方向相反时函数减少最快;垂直时,变化最慢。有不熟悉的建议重温一下高等数学下册相关内容。
那么接下来求解梯度函数
分别求偏导数如下:
求出梯度函数的表达式,就可以求解(w0,b0)时的梯度值,然后将f(w,b)沿着梯度方向进行变化就能找到f(w,b)的最小值了。
3.一次梯度下降迭代
首先我们定义梯度下降的一次迭代函数如下:
def train(w, b, dataw):
learning_rate = 0.0001
dw = -2 * np.sum((dataw['lirun']-w * dataw['PeopleCount']-b)*dataw['PeopleCount'])
db = -2 * np.sum(dataw['lirun']-(dataw['PeopleCount']*w-b))
temp_w = w - learning_rate * dw
temp_b = b - learning_rate * db
w = temp_w
b = temp_b
return w, b
这里定义学习率为0.0001
4.进行100次梯度下降训练,并将曲线绘制在一个图形上,并保留最好的w、b的值:
dmin = 99999
for i in range(100):
w,b = train(w,b, data)
y_lirun = (data['PeopleCount'] * w + b)
loss = np.power((data['PeopleCount'] * w + b) - data['lirun'], 2).sum()
if loss < dmin:
dmin = loss
dwBest = w
dbBest = b
plt.cla()
plt.scatter(data['PeopleCount'], data['lirun'])
plt.plot(data['PeopleCount'], y_lirun)
plt.pause(0.1)
print(w)
print(b)
print(loss)
plt.pause(0.1)表示使得直线绘制在同一个图形中,大家可以查看一下其使用方法,最终得到的最有曲线如下: