吴恩达《机器学习》第一周作业Python实现——单变量及多变量线性回归 参考

一、单变量线性回归

1.假设函数:

2.代价函数:

  Python实现:

3.利用梯度下降的思想去迭代地改变theta的值,以求理想的theta的值使得代价函数取值最小,思路如下:

  Python代码实现:

    疑惑解答:parameter获取到的是θ的值的个数,循环遍历parameter可以实现对每个θ的值下降一次。

 最后的图绘结果如下图所示:

 完整实现过程如下:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

path = 'C:/Users/nydcomputer/Desktop/机器学习/数据集/ex1/ex1dta.txt'
# 读取csv文件
# header=0时是默认情况,表示以数据的第一行为列索引,若改names则第一行数据会丢失
# header=None时,添加names第一行数据不会丢失
# names为横向索引header的名字,可以是数字
data = pd.read_csv(path, header=None,names = ['Population', 'Profit'])
# 读取csv文件
# header = 0是默认情况(即不标明,默认就是header = 0),表示以数据的第一行为列索引,若改names,则第一行数据会丢失(直接修改第一行数据)。
# header=None时,显示每一行数据,添加names,第一行数据不会丢失
# names为横向索引header的名字,可以是数字,如names=range(2,6)

data.head()  # 检验数据,可检验5行
data = pd.DataFrame(data)  # 生成图表,pandas中方法,也可以直接用data
print(data.head())  # head函数默认输出五行

# 特征归一化(为了使梯度下降得更方
# 便)
data = (data - data.mean()) / data.std()  # (原始数据 - 平均值)/ 标准差
data.head()


# 定义代价函数
def computeCost(X, y, theta):
    inner = np.power(((X * theta.T) - y), 2)  # X为输入矩阵。*theta的转置为假设函数,-y后整体平方;power函数计算幂
    return np.sum(inner) / (2 * len(X))


# 在原始数据集表上增加第0列,总共数据集为三列
data.insert(0, 'Ones', 1)
cols = data.shape[1]  # shape函数读取data中的二维的长度,即为数据的列数,此时共有三列,clos=3;shape[0]为行数
X = data.iloc[:, :-1]  # X为数据中的所有行,以及除了最后一列,此时X中有ones列与population列,X是72*2的数据,列数等同于[0:2]
y = data.iloc[:, cols - 1:cols]  # y为最后一列数据,等同于[2:3]
X = np.matrix(X.values)  # 将X转换为矩阵,72*2
y = np.matrix(y.values)  # 将y转换为矩阵,72*1
theta = np.matrix(np.array([0, 0]))  # theta向量是两个值都初始化为0的一维向量,1*2,转置后为2*1
print("初始theta值的代价为:")
print(computeCost(X, y, theta))  # 此时theta为初始自定义的值(0,0),计算出了此时输入的代价


# 定义梯度下降函数
def gradientDecent(X, y, theta, alpha, iters):  # alpha为学习率,iters为设定迭代次数
    tempt = np.matrix(np.zeros(theta.shape))  # theta的维度的所有数据全部初始化为0
    parameters = int(theta.ravel().shape[1])  # ravel函数将theta的维度降为一维,shape[1]为列数
    cost = np.zeros(iters)  # 初始化代价,值为0的有iters个值的矩阵
    for i in range(iters):
        error = (X * theta.T) - y  # 预测值与实际值的误差,为72*1矩阵,放在大循环内小循环外,每次迭代后的theta进行了更新,error值随之变换。
        for j in range(parameters):  # 梯度下降重要步骤,根据公式将每个theta[j]的值下降一次
            term = np.multiply(error, X[:, j])  # error与第j列的向量对应位置相乘并最终求和,之前增加ones列用于与1相乘
            tempt[0, j] = theta[0, j] - ((alpha / len(X)) * (np.sum(term)))
        cost[i] = computeCost(X, y, tempt)  # 计算第i此迭代时此theta值的代价
        theta = tempt  # 将theta向量更新,进行下次迭代循环继续处理theta
    return theta, cost

# 赋值
alpha = 0.01
iters = 1500
g, cost = gradientDecent(X, y, theta, alpha, iters)
print("参数theta向量:")
print(g)
print(cost)

# 预测70000人口的时候,根据公式h= theta0 + theta1*X
predict1 = (1, 7) * g.T  # g.T为g的转置,g为1*2的参数向量 ,1*theta[0],7为population,7*参数theta[1]得到预测值profit
print("预测值1:")
print(predict1)

# 作图
x = np.linspace(data.Population.min(), data.Population.max(), 100)  # 生成等差数列,100个等差点
f = g[0, 0] + (g[0, 1] * x)  # f为假设函数,theta0+theta1*x
fig, ax = plt.subplots(figsize=(8, 6))  # 创建作图画布
ax.plot(x, f, 'r', label='Prediction')  # 画出线,红色,名为Prediction
ax.scatter(data.Population, data.Profit, label='training data')  # scatter为散点图
ax.legend(loc=2)  # 在图上标明一个图例,用于说明每条曲线的文字显示,loc为第二象限
ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()

二、多变量线性回归

  多变量的意思是指假设函数中的θ可能不止有两个,可能有多个,但仍然是线性函数。

1.假设函数

2.代价函数

3.计算梯度

Python实现的过程与单变量线性回归大差不差,只是theta变量在初始赋值的时候以及在对每一个theta变量下降时有所区别。

 最后的图绘结果如下图所示:

完整实现过程如下:

import numpy as np
import pandas as pd
# pyplot是常用的绘图模块,能很方便让用户绘制2D图表
import matplotlib.pyplot as plt
# 通过从mpl_toolkits.mplot3d引入axes3d来创建3d图现象
from mpl_toolkits.mplot3d import Axes3D

path = 'C:/Users/nydcomputer/Desktop/机器学习/数据集/ex1/ex1dta2.txt'
data = pd.read_csv(path, header=None, names=['Sizes', 'Bedrooms', 'Price'])
# 多个特征相差过大,容易震荡,故需要归一化操作
data = (data-data.mean())/data.std()
print(data.head())

data.insert(0, 'ones', 1)
cols = data.shape[1]
X = data.iloc[:, 0: cols-1]
y = data.iloc[:, cols-1:cols]
X = np.matrix(X.values)
y = np.matrix(y.values)
theta = np.matrix(np.array([0, 0, 0]))  # 多变量梯度需要三个theta,初始化为0

def computeCost(X, y, theta):
    inner = np.power(((X*theta.T)-y), 2)
    return np.sum(inner) / (2*len(X))

def gredientDecent(X, y, theta, alpha, iters):  # alpha为学习率,iters为迭代次数
    tempt = np.matrix(np.zeros(theta.shape))
    parameters = int(theta.ravel().shape[1])
    cost = np.zeros(iters)  # cost为iters个值的一维矩阵,仅有一行,iters列
    for i in range(iters):
        error = (X * theta.T) - y
        for j in range(parameters):
            term = np.multiply(error, X[:, j])
            tempt[0, j] = theta[0, j] - ((alpha/len(X))*(np.sum(term)))
        theta = tempt
        cost[i] = computeCost(X, y, theta)
    return theta, cost

alpha = 0.01
iters = 1500
g, cost = gredientDecent(X, y, theta, alpha, iters)
print("theta变量与最小代价")
print(g)
print(cost)

predict1 = (1, 1650, 3) * g.T
print("预测值:")
print(predict1)

#作图
x = np.linspace(data.Sizes.min(), data.Sizes.max(), 100)
y = np.linspace(data.Bedrooms.min(), data.Bedrooms.max(), 100)
f = g[0, 0] + (g[0, 1] * x) + (g[0, 2] * y)
fig = plt.figure()
ax = Axes3D(fig)
ax.scatter3D(x, y, f, cmap='Blues')
ax.plot3D(x, y, f, 'gray')
plt.show()

从实现的方式上看,单变量线性回归与多变量线性回归的差别并不大,主要的区别有如下几点:

  • 在特征较多时,如果特征之间的数量级相差过大,在计算时需要进行归一化处理,避免不必要的震荡。实际上,单变量和多变量都做了归一化处理。
  • 在单变量线性回归时,初始化θ用到的是:
    theta = np.matrix(np.array([0, 0]))
    

    而在多变量线性回归时,初始化θ用到的是:

    theta = np.matrix(np.array([0, 0, 0])) 

    意思就是,theta的值有两个转变成了多个。

  • 最后这一点不同也是由theta初始化的不同导致的,在定义梯度下降函数gredientDecent时,用

    parameters = int(theta.ravel().shape[1])
    ​​​​​来获取theta的值,单变量中获取到的是2,而多变量中获取到的是3,所以在函数中的双层循环中遍历的次数是不一样的,但是原理都是相同的。

本文是我个人的学习记录,由于本人才疏学浅,在学习的过程中是边参考着别人的知识总结边学习的,以下是我参考的链接:

https://blog.csdn.net/wangjia2575525474/article/details/119912142

https://blog.csdn.net/m0_37830950/article/details/84781473?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-1-84781473-blog-119912142.pc_relevant_multi_platform_whitelistv3&spm=1001.2101.3001.4242.2&utm_relevant_index=4

若大家发现本文有任何不当或不正确之处,请在评论区批评指正,我会及时查看并加以修正!

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小牛不怕码代码

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

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值