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

单变量线性回归

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
path = "ex1data1.txt"
data = pd.read_csv(path, header=None, names=['Population', 'Profit'])
# pandas.read_csv默认情况下会把数据内容的第一行默认为字段名标题,header=None指明读取的原始文件数据没有列索引
data.head() # 方法用于返回数据帧或序列的前n行(默认值为5)。返回类型:DataFrame,可理解为一个表格,或者说矩阵
# DataFrame本质上是二维矩阵,跟常规二维矩阵的差别在于前者额外指定了每一行和每一列的名称。
PopulationProfit
06.110117.5920
15.52779.1302
28.518613.6620
37.003211.8540
45.85986.8233
data.describe()
# describe() 函数可以查看数据的基本情况,
# 包括:count 非空值数、mean 平均值、std 标准差、max 最大值、min 最小值、(25%、50%、75%)分位数等。
PopulationProfit
count97.00000097.000000
mean8.1598005.839135
std3.8698845.510262
min5.026900-2.680700
25%5.7077001.986900
50%6.5894004.562300
75%8.5781007.046700
max22.20300024.147000
# 画出图形
data.plot(kind='scatter',x='Population',y='Profit',figsize=(12,8))
# scatter表示散点图,figsize表示图片大小,单位:英寸
plt.show()


在这里插入图片描述

使用梯度下降来最小化代价函数,
创建一个以参数θ为特征函数的代价函数
J ( θ ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 J\left( \theta \right)=\frac{1}{2m}\sum\limits_{i=1}^{m}{{{\left( {{h}_{\theta }}\left( {{x}^{(i)}} \right)-{{y}^{(i)}} \right)}^{2}}} J(θ)=2m1i=1m(hθ(x(i))y(i))2
其中:
h θ ( x ) = θ T X = θ 0 x 0 + θ 1 x 1 + θ 2 x 2 + . . . + θ n x n {{h}_{\theta }}\left( x \right)={{\theta }^{T}}X={{\theta }_{0}}{{x}_{0}}+{{\theta }_{1}}{{x}_{1}}+{{\theta }_{2}}{{x}_{2}}+...+{{\theta }_{n}}{{x}_{n}}\\ hθ(x)=θTX=θ0x0+θ1x1+θ2x2+...+θnxn


def computeCost(X,y,theta): # 输入X是列向量,y也是列向量,theta是行向量
    inner = np.power(((X*theta.T)-y),2) # x*θ的转置就是假设函数 power函数计算numpy数组中每个数值的指定幂次
    return np.sum(inner/(2*len(X))) # 将数组/矩阵中的元素全部加起来 len(X)矩阵行数
data.insert(0,'Ones',1)  
# 插入一列为1是为了更好的向量化,需要在训练集中添加一列x_0,以便我们可以使用向量化的解决方案来计算代价和梯度,见视频p18
# 变量的初始化
cols = data.shape[1] # shape[0]是行数  shape[1]是列数
X = data.iloc[:,0:cols-1] # 数据集 行全要  列从0到cols-1(不包括) 左闭右开
y = data.iloc[:,cols-1:cols] # 目标值
X.head()
OnesPopulation
016.1101
115.5277
218.5186
317.0032
415.8598

获取的数据类型是DataFrame类型,所以需要进行类型转换。同时还需要初始化theta,即theta所有元素都设置为0

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

维度

X.shape, theta.shape, y.shape
((97, 2), (1, 2), (97, 1))
computeCost(X,y,theta) #计算代价函数
32.072733877455676

batch gradient decent(批量梯度下降)

θ j : = θ j − α ∂ ∂ θ j J ( θ ) {{\theta }_{j}}:={{\theta }_{j}}-\alpha \frac{\partial }{\partial {{\theta }_{j}}}J\left( \theta \right) θj:=θjαθjJ(θ)
梯度下降

def gradientDescent(X,y,theta,alpha,iters): # iters是迭代次数 alpha是学习率 即步长
    temp_theta = np.matrix(np.zeros(theta.shape)) # 零值矩阵 暂存theta
    parameters = int(theta.ravel().shape[1]) # ravel计算需要求解的参数个数   功能将多维数组降至一维 这里值为2
    cost = np.zeros(iters) #构建iters个0的数组
    #迭代:
    for i in range(iters):
        difference = (X*theta.T) - y # 差值
        for j in range(parameters):
            term = np.multiply(difference,X[:,j])    #乘以x_i  X[:,j]表示所有行 j列,简言之就是抽出第j列  
             # 注意这里就不是矩阵乘法了 这里是求导后要求乘的 multiply是两个相同大小矩阵对应位置的数直接相乘
            temp_theta[0,j] = theta[0,j] - (alpha/len(X))*np.sum(term) # 更新theta_j
        
        theta = temp_theta # 更新全部theta值
        cost[i] = computeCost(X,y,theta) # 更新代价值
    
    return theta,cost

初始化一些附加变量 - 学习速率α和要执行的迭代次数。

alpha = 0.01
iters = 1000

获取theta值,代价最小值

g,cost = gradientDescent(X,y,theta,alpha,iters)
g
matrix([[-3.24140214,  1.1272942 ]])
cost[-1] # 获取数组的最后一个值
4.515955503078913

最后,用我们拟合过的theta值计算训练模型的代价函数

computeCost(X, y, g)
4.515955503078913

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

x = np.linspace(data.Population.min(), data.Population.max(), 100) # 生成指定范围内指定个数的一维数组
f = g[0, 0] + (g[0, 1] * x) # x1=1  g[0, 0]表示theta_0 g[0, 1]表示theta_1

fig, ax = plt.subplots(figsize=(12,8)) # plt.subplot()函数用于直接指定划分方式和位置进行绘图。
# fig代表绘图窗口(Figure);ax代表这个绘图窗口上的坐标系(axis),一般会继续对ax进行操作。

# 设置横纵坐标的函数,并设置颜色为红色,在图标上标上'Prediction'标签  横坐标x 纵坐标f
ax.plot(x, f, 'r', label='Prediction') 
# 定义散点图的横纵坐标,并给出散点图点的'Traning Data'标签名
ax.scatter(data.Population, data.Profit, label='Traning Data') 
ax.legend(loc=2)  # 2表示在左上角


ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()


在这里插入图片描述

由于梯度方程式函数也在每个训练迭代中输出一个代价的向量,所以我们也可以绘制。 注意,代价总是降低

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


在这里插入图片描述

多变量的线性回归

该练习包括一个房屋价格数据集,其中包含两个变量(房屋大小、卧室数量)和目标(房子价格)。

path =  'ex1data2.txt'
data2 = pd.read_csv(path, header=None, names=['Size', 'Bedrooms', 'Price'])
data2.head()
SizeBedroomsPrice
021043399900
116003329900
224003369000
314162232000
430004539900
data2.describe()
SizeBedroomsPrice
count47.00000047.00000047.000000
mean2000.6808513.170213340412.659574
std794.7023540.760982125039.899586
min852.0000001.000000169900.000000
25%1432.0000003.000000249900.000000
50%1888.0000003.000000299900.000000
75%2269.0000004.000000384450.000000
max4478.0000005.000000699900.000000

房屋大小约为卧室数量的1000倍。当特征相差几个数量级时,首先执行特征缩放(均值归一化)可以使梯度下降更快地收敛。

data2 = (data2 - data2.mean()) / data2.std() # 解决的方法是尝试将所有特征尺度都尽量缩放到 -1 ~ 1
data2.head()
SizeBedroomsPrice
00.130010-0.2236750.475747
1-0.504190-0.223675-0.084074
20.502476-0.2236750.228626
3-0.735723-1.537767-0.867025
41.2574761.0904171.595389
data2.insert(0, 'Ones', 1) 
cols = data2.shape[1]
X2 = data2.iloc[:,0:cols-1]
y2 = data2.iloc[:,cols-1:cols]

X2 = np.matrix(X2.values)
y2 = np.matrix(y2.values)
theta2 = np.matrix(np.array([0,0,0]))

g2, cost2 = gradientDescent(X2, y2, theta2, alpha, iters)
computeCost(X2, y2, g2) # 计算代价
0.1307033696077189

代价函数收敛图

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()


在这里插入图片描述

使用sklearn线性回归函数简化过程

from sklearn import linear_model
model = linear_model.LinearRegression()  #基于最小二乘法的线性回归。
model.fit(X, y)
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()

在这里插入图片描述

normal equation(正规方程)

思路

正规方程是通过求解下面的方程来找出使得代价函数最小的参数的: ∂ ∂ θ j J ( θ j ) = 0 \frac{\partial }{\partial {{\theta }_{j}}}J\left( {{\theta }_{j}} \right)=0 θjJ(θj)=0
假设我们的训练集特征矩阵为 X(包含了 x 0 = 1 {{x}_{0}}=1 x0=1)并且我们的训练集结果为向量 y,则利用正规方程解出向量 θ = ( X T X ) − 1 X T y \theta ={{\left( {{X}^{T}}X \right)}^{-1}}{{X}^{T}}y θ=(XTX)1XTy
上标T代表矩阵转置,上标-1 代表矩阵的逆。设矩阵 A = X T X A={{X}^{T}}X A=XTX,则: ( X T X ) − 1 = A − 1 {{\left( {{X}^{T}}X \right)}^{-1}}={{A}^{-1}} (XTX)1=A1

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

梯度下降:需要选择学习率α,需要多次迭代,当特征数量n大时也能较好适用,适用于各种类型的模型
正规方程:不需要选择学习率α,一次计算得出,需要计算 ( X T X ) − 1 {{\left( {{X}^{T}}X \right)}^{-1}} (XTX)1,如果特征数量n较大则运算代价大,因为矩阵逆的计算时间复杂度为 O ( n 3 ) O(n3) O(n3),通常来说当 n n n小于10000 时还是可以接受的,只适用于线性模型,不适合逻辑回归模型等其他模型

# 正规方程函数
def normalEqn(X, y):
    theta = np.linalg.inv(X.T@X)@X.T@y#X.T@X等价于X.T.dot(X)  np.linalg.inv():矩阵求逆
    return theta
final_theta2=normalEqn(X, y)
final_theta2  # 梯度matrix([[-3.24140214,  1.1272942 ]])
matrix([[-3.89578088],
        [ 1.19303364]])
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值