python实现吴恩达机器学习线性回归ex.1

python实现吴恩达机器学习线性回归ex.1.1

前述: 本节我们简单介绍下线性回归知识点,然后用常规方式完成作业,进一步引入矩阵将代码简单化。
首先,让咱们下载数据集:
数据集下载
提取码:0r1r

单线性回归

数据集介绍:

 对于单线性回归我们用到的是ex1data1.txt数据集,该数据提供了两组数据,第一组是人口,第二组是收入,采取一对一的数据方式,一组人口对应一组收入。

线性回归简要介绍:

对于这个人口收入的模型,我们采取了很常规的直线模型(数据集输入绘图很类似直线):h(x) = θ1 * x  + θ0
所以我们要做的就是找到最合适的θ1和θ2来拟合整个数据。
因此我们引入了代价函数:(实在打不出来了,建议自己去看自己看视频笔记)
巧妙之处就在于,为了使代价函数值最小,需要使得模型结果与训练结果十分接近,为了使得两者接近,就需要使两个参数θ1,θ0调整成更加合适的值,于是引入了反向传播函数进行梯度下降。
梯度下降的目的就是调整θ1,θ0,调整后的θ1,θ0带入代价函数得到反向传播中的到新的梯度下降,然后连续套娃,得到合适的θ1,θ0值。

实战:

引入库:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
库自己去了解下,推荐B站up主,莫烦。https://space.bilibili.com/243821484/ 
数据输入:
data = pd.read_csv(r'C:\Users\Administrator\Desktop\ex1\ex1data1.txt',sep=',',names=['population','profit'])
简单介绍下代码参数功能,第一个参数是路径,建议写绝对路径,第二个参数是分隔符,就是参数分列的依据,默认是‘,’,第三个是自定义列名,该数据集有两列,分别为人口和收入。
我们提取前五列看看数据:
data.head()

输出:在这里插入图片描述
将数据集绘制成图片:

data.plot.scatter('population','profit')
我们重点讲思想,代码就简单一点,散点图绘制还是建议自己学习。那么输出的图片为:

在这里插入图片描述
看,很类似直线吧!

初始化数据:

我这里将X,Y赋值处理也算进初始化中,但一般初始化是指的权值、阈值初始化。
x,y赋值处理:

x = data.iloc[:,0]
y = data.iloc[:,1]
print(type(x))
x = np.array([x]).T
y = np.array([y]).T
我们将已经输入的数据data进行切片,将第一列数据作为输入x,第二列数据当成输出y。
但是我们输出了x,y的数据类型发现<class 'pandas.core.series.Series'>数据比较难处理,所以我们将数据转化成 ndarray类型处理。
转化后的维度是(1,97),我将它转置一下变成(97,1)维度处理(也可以不转置 ,w我转置只是为了符合我的习惯)。

θ1,θ2初始化
我们就直接把θ1,θ2赋值为0,由于传播性质(很重要),θ0,θ1在加减乘除过程中会被传播成与需要维度相同的矩阵。

theta1 = 0
theta0 = 0
正反向传播:
对于简单的模型,我正常将正反向传播合在一起:
def forbackward_propagation(theta1,theta0,x,y):
	#正向传播
    m = x.shape[0]
    a = theta1 * x + theta0
    J =np.sum(np.power(a-y,2))/(2*m)
    #反向传播
    d_theta1 = np.sum(x*(a-y))/m
    d_theta0 = np.sum(a-y)/m
    return J,d_theta1,d_theta0
很明显,正向传播的目的是为了得到模型结果,进而得到代价函数。
反向传播是为了的到θ1,θ0的偏导数(视频有偏导数计算)。
迭代函数:
def iter_propagation(theta1,theta0,x,y,rate,n):
    cost =[]
    for i in range(n):
        J,d_theta1,d_theta0 = forbackward_propagation(theta1,theta0,x,y)
        theta1 = theta1-rate*d_theta1
        theta0 = theta0-rate*d_theta0
        cost.append(J)
        if i %100 ==0:
            print(i,J)
    return cost,theta1,theta0

套娃开始,根据前边反向传播得到的dθ1,dθ0偏导,不断优化θ1,θ0,rate为学习速率,n为迭代次数。
我们设定一个cost列表来储存J的值,便于画图。
每迭代100次,我们将迭代次数与对应的代价函数打印出来。

测试

cost,theta1,theta2,= iter_propagation(theta1,theta0,x,y,rate=0.02,n=2000)
plt.plot(cost)
这里设置了学习率rate为0.02,迭代次数2000次。打印出cost (储存J的字典)的图片。运行:

在这里插入图片描述
在这里插入图片描述
我们可以看出代价函数结果很快的下降到5.17左右开始缓慢下降,最终趋于平缓。这就证明J已经下降到一个相对优的位置了,也就是说在这个位置得到的θ1,θ2可以算是最合适模型的解。

绘制拟合函数曲线。
plt.figure()
data.plot.scatter('population','profit',label='point')
x = np.linspace(np.min(x),np.max(x),100)
print(theta1,theta0)
y = theta1 * x + theta0
plt.plot(x,y,c='r',label='line')
plt.legend()
plt.show()
我们选取输入x(人口)最小和最大为定义域,将数据分为100等分,用得到的θ1,θ2求出拟合函数对应的输出y(收入),绘制成线,放入同一个图中。输出如下:

在这里插入图片描述


接下来引入矩阵:

引入库:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
数据输入:
data = pd.read_csv(r'C:\Users\Administrator\Desktop\ex1\ex1data1.txt',sep=',',names=['population','profit'])
数据处理(不同点开始)
我们之前知道h(x) = θ1 * x + θ0
换成矩阵形式,大概是这样的:

在这里插入图片描述

从x数据集中的单个元素的矩阵转换,引入了x数据集的矩阵转换。我们可以看出原本输入的x数据集变成了多出一列1的数据集,所以我们接下来要做的就是将数据集前加上一列1,创造[1,x]的数据集。

我们用以下的函数插入列1:

data.insert(0,'ones',1)
data.head()
第一个参数是插入的位置,第二个参数是插入标题,第三个参数是插入的数字。
老规矩,我们输出前五个数据:

在这里插入图片描述
(看,是不是多了一列1)

数据初始化
x = data.iloc[:,0:2]
y = data.iloc[:,2]
x = np.array(x).T
y = np.array([y]).T
theta = np.zeros((2,1))
对于输入x,我们需要切片出一组一列全部为1,一列为人口的数据。也就是处理后数据的第0,1列。
输出y收入则是处理后数据的第2列。
θ0,θ1需要合并成一个二行一列的矩阵,也就是初始化θ为一个维度为(2,1)的零矩阵。
正反向传播
其实与前边没用矩阵步骤一样,带入相同的公式往下计算,不同的是我们这次是矩阵乘法。
def forback_propagation(x,y,theta):
    m = x.shape[0]
    a = x @ theta
    J = np.sum(np.power(a-y,2))/(2*m)
    d_theta = x.T@(x@theta-y)/m
    return J,d_theta

注:
1.* = np.multiply(A,B) 指的是A,B两个矩阵对于元素相乘,需要A,B维度一致。
2.@ = np.dot(A,B) ,矩阵乘法。

d_theta的得到涉及到矩阵求导 ,我简单的手动推导下。
在这里插入图片描述

迭代

还是一样,不同的是迭代的不是单个的θ1,θ0,而是两个组合成的θ。

def iter_propagation(x,y,theta,rate=0.02,n=2000):
    costs = []
    for i in range (n):
        J,d_theta = forback_propagation(x,y,theta)
        theta = theta - rate*d_theta
        costs.append(J)
        if i %100 ==0:
            print(i,J)
    return costs,theta

我们输出一下发现与上边相同:

costs,theta_iterd = iter_propagation(x,y,theta,rate=0.02,n=2000)

输出为:
在这里插入图片描述

绘制拟合函数曲线:

步骤完全一样,只不过θ1,θ0,需要从矩阵θ取出来。

plt.figure()
data.plot.scatter('population','profit',label='point')
x = np.linspace(np.min(x),np.max(x),100)
print(theta_iterd )
y = x * theta_iterd[1,0] + theta_iterd[0,0] 
plt.plot(x,y,c='r',label='line')
plt.legend()
plt.show()

依旧没什么区别:
在这里插入图片描述

hahah,是不是突然发现有点变化,又感觉没错。自己找下为啥这样,话都我说了,怎么学习啊。
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

scum_JAKE

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值