线性回归之批量梯度下降代码实例

目录

一. 梯度下降

批量梯度下降

二. 学习率

散点图

 直线拟合


在学习了《机器学习》后,相信大家第一个接触的就是线性回归。可能有很多小伙伴跟我一样,一上来就一脸懵,关于线性回归为什么会使用哪些很复杂的公式。

我当时就想着,高中就学习了所谓的线性回归的公式,我们直接套用公式不就好了吗。确实,对于二维的直线,高中知识能解决,但是高维呢?高维显然就不太能按照高中知识做下去了。

也有些小伙伴想了上面的问题后,会想到下面的问题那就是,线性回归经过线性代数推导可以得出一个结论那就是

theta =(X^{T}X)^{T}X^{T}Y

那么我们用matlab或者python去直接算出来θ不就好了么?为什么还要使用梯度下降算法去求解呢?首先我们明确一点,什么叫做机器学习,如果直接得出答案的方法,怎么能叫做学习呢。所谓学习就是机器在运算过程中一点点学习逼近答案。所以这也是为什么我们要使用梯度下降,牛顿法等去求解答案。

我们简单介绍下梯度下降法。

一. 梯度下降

       我们的目标是预测值与真实值的差距越小越好,由此可以设置目标函数为:

J(theta )=frac{1}{2m}sum (y^i-h(x^i))^2

批量梯度下降

       frac{partial J(theta )}{partial theta _i}=-frac{1}{m}sum (y^i-h(x^i))x_j^i

theta _j:=theta _j+frac{1}{m}sum (y^i-h(x^i))x_j^i

特点:对所有的点都进行运算,最终取一个平均。
优缺点:容易得到最优解,但是由于每次计算需考虑所有样本,计算速度很慢。

二. 学习率

       即步长,每次前进的距离,一般设置的很小,如0.001。本次实验我设置为0.07。

接下来,我们进入实验吧。

给出两个数据集,它们包含了一些测量两到8岁之间不同男孩身高的例子。y值是以米为单位测量的高度,x值是与身高对应的男孩的年龄。x:ex1x.dat y:ex1y.dat

接下来展示我是怎么玩的。

首先玩出这群数据集的散点图。

散点图

#导入包
import pandas as pd
import matplotlib.pyplot as plt#导入matlab包画图
import numpy as np
from mpl_toolkits.mplot3d import Axes3D#打印三D图片
#导入数据使用read_table,读取出的格式是dataframe
x=pd.read_table(r'D:\vscode\机器学习\ex1x.dat',header=None)
x=pd.array(x.iloc[:,0])#读取所有行,第0列的数字
x=x[:,np.newaxis]#在列上新增一个维度
y=pd.read_table('D:\vscode\机器学习\ex1y.dat',header=None)
y=pd.array(y.iloc[:,0])
y=y[:,np.newaxis]
画出散点图
plt.figure()
plt.scatter(x,y,color="white",marker='o',edgecolors="blue",label='scatter')
plt.xlabel("height in meters")
plt.ylabel('age in years')
plt.legend()
plt.show()

结果如下

 直线拟合

#定义函数包括损失函数lostfunction,目标函数h以及梯度下降函数grad
m=y.shape[0]
print(m)
on=np.ones((m,1))
x=np.hstack((on,x))
theta=np.zeros((x.shape[1],1))
print(theta)
h=np.zeros((m,1))
def lostfuntion(theta):
    J=1/(2*m)*np.dot((np.dot(x,theta)-y).T,np.dot(x,theta)-y)
    return J
def h(x):    
    return np.dot(x,theta)
print(x)
print(theta)
def grad(alpha,nn):
    for k in range(nn):
        for j in range(theta.shape[0]):
            sum=0
            for i in range(m):
                sum+=(h(x[i,:])-y[i])*x[i][j]
            theta[j]=theta[j]-alpha/m*sum
        print(theta,k)
#设置学习次数s,和学习率a,利用两个参数进行迭代,建议值为s=1500,a=0.07,画出拟合直线
s=int(input("请设置学习次数"))
a=float(input("请设置学习率"))
grad(a,s)
#print(theta)
plt.plot(x[:,1],np.dot(x,theta))    
plt.scatter(x[:,1],y)
plt.show()  

损失函数与theta关系图

j_vals=np.zeros((100,100))
theta0_vals=np.linspace(-3,3,100)#生成-3到3之间的100个点
theta0_vals=np.array(theta0_vals)
theta0_vals=theta0_vals[:,np.newaxis]
theta1_vals=np.linspace(-1,1,100)
theta1_vals=np.array(theta1_vals)
theta1_vals=theta1_vals[:,np.newaxis]
#print(theta1_vals)
for i in range(theta0_vals.shape[0]):
    for j in range(theta1_vals.shape[0]):
        t=np.array([theta0_vals[i][0],theta1_vals[j][0]])
        j_vals[i][j]=lostfuntion(t[:,np.newaxis])
#print(j_vals)
j_vals=j_vals.T
fig=plt.figure()
ax=Axes3D(fig)#三维图片
X=theta0_vals
Y=theta1_vals
X,Y=np.meshgrid(X,Y)
Z=j_vals
ax.plot_surface(X,Y,Z,cmap=plt.get_cmap('rainbow'))#三维lostfunction图片
ax.contourf(X,Y,Z,zdir='z',offset=-2,cmap=plt.get_cmap('rainbow'))#这是等高线图
plt.show()

 

总结:我写错了很多次,总是写错行列关系。而且python和matlab实在是不太一样(之前写的是matlab代码),但是好在我坚持了下来。写代码一定要贵在坚持。

实验数据可在我的空间查看

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>