吴恩达机器学习课后作业——线性回归

一、单变量线性回归

一、作业内容

假设你是一家特许经营餐厅的首席执行官,正在考虑在不同的城市开一家新店,该连锁店已经在各个城市开设了餐车,文件ex1data1.txt中包含你这些城市的利润和人口数据。第一列是一个城市的人口,第二列是该城市一辆餐车的利润。利润为负值表示亏损。您将使用一个变量实现线性回归,以预测餐车的利润。
数据集下载位置(包含吴恩达机器学课后作业全部数据集):data

二、作业分析

1、数据集中包含了正确的答案,目的是通过这些数据集可以算出更多正确的答案。所以使用的是机器学习算法中的监督学习

2、此类问题也被称为回归问题,即设法预测连续值的属性。

3、根据人口预测利润,输入变量只有一个特征:人口,输出变量为利润。所以使用单变量线性回归

4、对于监督学习来说,我们需要一个假设函数来拟合输入数据。
可以尝试使用一元线性表达式:
在这里插入图片描述

5、对于假设函数,我们要设法选取最优的θ值,所以我们使用代价函数
在这里插入图片描述

代价函数又称为平方误差代价函数,代价函数时解决回归问题最常用的手段。

通过求得代价函数的最小值,便能计算出最优的θ。

6、可以使用梯度下降法实现代价函数最小化
在这里插入图片描述
梯度下降函数
在这里插入图片描述

梯度下降法取得的是局部最优,当初始值不同时,得到的局部最优也不同。但线性回归的代价函数则总是凸函数,因此并没有多个局部最优解,唯一的局部最优解就是全局最优解。

梯度下降法在计算的过程中要注意同步更新

三、代码实战

引入所需函数库

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import linear_model

首先我们加载数据,并且绘制散点图查看数据分布

# 加载数据
path = 'ex1data1.txt'
data = pd.read_csv(path, header=None, names=['Population', 'Profit'])

# 绘制图像
data.plot(kind='scatter', x='Population', y='Profit', figsize=(12,8))
plt.show()

在这里插入图片描述然后,我们先对数据做一些预处理

# 为了使用向量化的解决方案来计算代价和梯度
# 在第0列插入一列,这列值全为1
data.insert(0, 'Ones', 1)
#0:行;1:列
cols = data.shape[1]
# X是所有行,去掉最后一列
X = data.iloc[:,0:cols-1]
#y是所有行,最后一列
y = data.iloc[:,cols-1:cols]
# 将X和y转化为numpy矩阵
X = np.matrix(X.values)
y = np.matrix(y.values)
# theta为初始值为0的(1,2)矩阵
theta = np.matrix(np.array([0,0]))

对数据做完预处理后,首先我们将创建一个以参数θ为特征函数的代价函数

#计算代价函数
def computeCost(X, y, theta):
    inner = np.power(((X * theta.T) - y), 2)
    return  np.sum(inner) / (2 * len(X))

再创建一个批量梯度下降函数

# 批量梯度下降
# alpha学习率,iters迭代次数
def gradientDescent(X, y, theta, alpha, iters):
    # 创建一个与theta相同维度的0矩阵
    temp = np.matrix(np.zeros(theta.shape))
    # parameters:训练的theta的个数
    # ravel()将多维降为一维
    parameters = int(theta.ravel().shape[1])
    # 保存迭代之后的cost
    cost = np.zeros(iters)

    for i in range(iters):
        error = (X * theta.T) - y
        for j in range(parameters):
            term = np.multiply(error, X[:,j])
            temp[0,j] = theta[0,j] - ((alpha / len(X)) * np.sum(term))
            theta = temp
            cost[i] = computeCost(X, y, theta)

    return theta, cost

此时我们可以初始化一些附加变量 :学习速率α和要执行的迭代次数。
并且运行梯度下降算法来将训练我们的参数θ使其适合于训练集。

alpha = 0.01
iters = 1000

theta, cost = gradientDescent(X, y, theta, alpha, iters)
print(theta)

查看得到的theta值

[[-3.24140214  1.1272942 ]]

最后,我们可以使用我们拟合的参数计算训练模型的代价函数(误差)

result = computeCost(X, y, theta)
print(result)

查看最优theta下的误差是多少

4.515955503078912

最后我们来绘制线性模型以及数据,直观地看出它的拟合

def plot():
    # 横坐标在最大和最小直接分100份
    x = np.linspace(data.Population.min(), data.Population.max(), 100)
    f = theta[0, 0] + (theta[0, 1] * x)

    # 设置窗口尺寸
    fig, ax = plt.subplots(figsize=(12, 8))

    ax.plot(x, f, 'r', label='Prediction')
    ax.scatter(data.Population, data.Profit, label='Traning Data')
    #控制图例位置,loc=2即4象项中的第二象项
    ax.legend(loc=2)
    ax.set_xlabel('Population')
    ax.set_ylabel('Profit')
    ax.set_title('Predicted Profit vs. Population Size')
    plt.show()

直接调用该函数

if __name__ == '__main__':
	plot()

在这里插入图片描述由于梯度方程式函数也在每个训练迭代中输出一个代价的向量,所以我们也可以绘制

def optplot():
    fig, ax = plt.subplots(figsize=(12, 8))
    ax.plot(np.arange(1000), cost, 'r')
    ax.set_xlabel('Iterations')
    ax.set_ylabel('Cost')
    ax.set_title('Error vs. Training Epoch')
    plt.show()

在这里插入图片描述代价总是降低 - 这是凸优化问题的一个例子

二、多变量线性回归

一、作业内容

假设你要卖掉你的房子,你想知道一个好的市场价格是多少。其中一种方法是,首先收集最近出售的房屋的信息,并制作房价模型。文件ex1data2.txt包含俄勒冈州波特兰市的房价训练集。第一栏是房子的面积(单位:平方英尺),第二栏是卧室的数量,第三栏是房子的价格。您将使用多元线性回归来预测房屋价格。

二、作业分析

1、预测房价,输入变量有两个特征,房子面积,房子卧室数量。输出变量,房子的价格

2、该数据集中有多个特征可用于房价分析,所以我们使用多元线性回归

3、根据该数据集,我们使用多元假设函数和多元梯度下降算法,原理上和一元一样。
假设函数
在这里插入图片描述
梯度下降算法

在这里插入图片描述
梯度下降函数
在这里插入图片描述
代价函数
在这里插入图片描述

4、在进行多元的梯度下降时,如果各个特征的取值范围比较相,那么梯度下降的收敛速度会比较。如果各个特征的取值范围差异较大,那么梯度下降的收敛过程就会比较缓慢

所以我们需要对特征进行缩放,通过对特征进行缩放就可以获得一个梯度下降更快的代价函数。

对于梯度下降,特征的取值范围最好是位于**[-1,1]**之间。

在进行特征缩放时可采用两种方法:
(1)数值除以最大值的
(2)均值归一化

均值归一化:
(1)通常会使用特征 x i x_i xi减去该特征的均值 u i u_i ui,这样可以使你的特征值具有为0的平均值
(2)对于 x 0 x_0 x0是不需要进行变换的,因为不可能使得具有为0的平均值
(3) S i S_i Si=当前特征最大值-当前特征最小值, x i x_i xi代表当前特征的原数值, u i u_i ui代表当前特征的原数值的平均值。当然Si也可以用当前特征的标准差来代替。
在这里插入图片描述
5、在选取学习速率时,通常通过绘制一幅图来判断是否正确运行梯度下降,当代价函数下降幅度不大时,就差不多是收敛了。

6、梯度下降异常的情况及解决方案
(1)异常:梯度没有下降,反而上升
解决方案:使用更小的α
(2)异常:梯度反复上升下降
解决方案:使用更小的α

7、求最优θ的另一种方法:正规方程
正规方程
正规方程是通过求解在这里插入图片描述来找出使得代价函数最小的参数的。
假设我们的训练集特征矩阵为 X(包含了 x 0 x_0 x0=1)并且我们的训练集结果为向量 y,则利用正规方程解出向量在这里插入图片描述

梯度下降与正规方程的比较:

梯度下降:需要选择学习率α,需要多次迭代,当特征数量n大时也能较好适用,适用于各种类型的模型
正规方程:不需要选择学习率α,一次计算得出,需要计算在这里插入图片描述。如果特征数量n较大则运算代价大,因为矩阵逆的计算时间复杂度为𝑂(𝑛3),通常来说当𝑛小于10000 时还是可以接受的,只适用于线性模型,不适合逻辑回归模型等其他模型。使用正规方程法求最优θ,也不需要进行特征缩放。

正规方程的方法无需进行迭代,可以直接求得最优的θ

正规方程操作步骤:
(1)在数据集中加上一列,对应额外的特征变量 x 0 x_0 x0,它的取值永远是1
(2)将数据填写到矩阵中
(3)通过计算在这里插入图片描述,直接求出最优的θ

当出现正规方程不可逆时:
(1)存在冗余的特征。因为冗余的特征会导致矩阵不是满秩,从而出现矩阵内部的向量线性相关。
解决办法:删除存在线性关系的其中一个特征。
(2)特征数大于样本的个数.方程中,变量的个数大于方程的个数,会出现无穷多解,也就是线性相关.
解决办法:删除一些特征或者进行正规化。

三、代码实战

首先我们加载数据集,并进行数据的预处理

path =  'ex1data2.txt'
data2 = pd.read_csv(path, header=None, names=['Size', 'Bedrooms', 'Price'])

# 特征归一化
data2 = (data2 - data2.mean()) / data2.std()

# 添加一列1,使得矩阵乘法运算更简单
data2.insert(0, 'Ones', 1)

# 设置X(训练数据),Y(目标变量)
cols = data2.shape[1]
X2 = data2.iloc[:,0:cols-1]
y2 = data2.iloc[:,cols-1:cols]

# 将变量转换为numpy数组并初始化theta数组
X2 = np.matrix(X2.values)
y2 = np.matrix(y2.values)
theta2 = np.matrix(np.array([0,0,0]))

# 对数据集进行线性回归
theta2, cost2 = gradientDescent(X2, y2, theta2, alpha, iters)

# 获得模型的代价(误差)
cost = computeCost(X2, y2, theta2)

查看训练进程

fig, ax = plt.subplots(figsize=(12,8))
ax.plot(np.arange(iters), cost2, 'r')
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title('Error vs. Training Epoch')
plt.show()

在这里插入图片描述

我们也可以使用scikit-learn的线性回归函数

from sklearn import linear_model
model = linear_model.LinearRegression()
model.fit(X, y)

scikit-learn model的预测表现

x = np.array(X[:, 1].A1)
f = model.predict(X).flatten()

fig, ax = plt.subplots(figsize=(12,8))
ax.plot(x, f, 'r', label='Prediction')
ax.scatter(data.Population, data.Profit, label='Traning Data')
ax.legend(loc=2)
ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()

在这里插入图片描述
使用正规方程得到最优θ

# 正规方程
def normalEqn(X, y):
    # X.T@X等价于X.T.dot(X),矩阵的乘法
    theta = np.linalg.inv(X.T@X)@X.T@y
    return theta
final_theta2=normalEqn(X, y)
print(final_theta2)

梯度下降得到的结果是

[[-3.89578088]
 [ 1.19303364]]

参考链接:https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes
https://blog.csdn.net/weixin_41799019/article/details/116464569?spm=1001.2014.3001.5502

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值