编程作业(python)| 吴恩达机器学习(1)线性回归

参考:吴恩达机器学习系列课后习题(视频)
作业及代码:https://pan.baidu.com/s/1L-Tbo3flzKplAof3fFdD1w 密码:oin0
编程环境:Jupyter Notebook
本课程8道编程作业及解析见:Coursera吴恩达机器学习编程作业


    :     +   \color{#f00}{***\ 点击查看\ :吴恩达机器学习 \ —— \ 整套笔记+编程作业详解\ ***}

Programming Exercise 1:Linear Regression

1. 单变量线性回归

题目

餐馆老板想在不同城市开分店,并收集了这些城市的 人口数当地餐馆的利润 作为训练样本保存在 ex1data1.txt:

(97行×2列,第一列为人口数(万),第二列为餐馆利润(万元))

请利用线性回归,根据城市的人口数据预测其利润。

1.1 导入数据

  • 导入库:

    import numpy as np  			# 科学计算库,处理多维数组,进行数据分析
    import pandas as pd				# 基于 NumPy 的一种解决数据分析任务工具
    import matplotlib.pyplot as plt # 提供一个类似 Matlab 的绘图框架
    
  • 导入数据集:

    data = pd.read_csv('ex1data1.txt',names=['population','profit']) # 读取文件,指定列名
    

    可以用data.head()data.tail()查看 数据集 的 前几组数据 和 倒数几组数据:

    在这里插入图片描述

  • 数据可视化

    扫描二维码关注公众号,回复: 10558104 查看本文章
    data.plot.scatter('population','profit',label='profit of population') # 绘制散点图
    plt.show()
    

    得到利润和人口的分布散点图:

在这里插入图片描述

1.2 构造数据集

已知单变量线性回归的假设函数为:
h θ ( x ) = θ 0 + θ 1 x = [ 1 x ] [ θ 0 θ 1 ] = X θ h_\theta(x)=\theta_0+\theta_1x =\begin{bmatrix} 1&x \end{bmatrix} \begin{bmatrix} \theta_0\\\theta_1 \end{bmatrix} =X\theta X = [ 1 x ] X=\begin{bmatrix} 1&x \end{bmatrix}

  • 获取数据集中的输入向量 X X ,需要在数据集加入 x 0 = 1 x_0=1 的一列:

    data.insert(0,'$x_0$',1) # 在 data 第 0 列插入列名为 x_0 值为 1 的列
    

    data.head() 验证下是否插入:
    在这里插入图片描述

  • 通过切片操作获取输入向量和输出向量:

    cols = data.shape[1] # 获取 data 的列数
    X = data.iloc[:,0:cols-1] # X 为 0~cols-1列,所有行
    y = data.iloc[:,cols-1:cols] # y 为倒数第 1 列,所有行
    

    X.head()y.head()验证:
    在这里插入图片描述

  • 此时 X X y y 的数据结构为DataFrame,需要转换为ndarray类型才能用于后续的矩阵操作:

    X = X.values 		
    y = y.values	
    

    可以用 X.shapey.shape 查看数组的维度 ,维度分别为(97,2)和(97,1)

  • 初始化参数向量 θ \theta :由于 X θ X\theta 的维度等于 y y 的维度,计算得到 θ \theta 的维度为(2,1),并初始化为0

    theta = np.zeros((2,1)) 
    

1.3 代价函数

J ( θ ) = 1 2 m i = 1 m ( h θ ( x ( i ) ) y ( i ) ) 2 = 1 2 m ( X θ y ) ( X θ y ) J(θ)=\frac{1}{2m} \sum_{i=1}^{m} ( h_θ( x^{(i)} ) - y^{(i)})^2 =\frac{1}{2m} (X θ - y)·(X θ - y) 其中第二项表示向量 ( X θ y ) (X θ - y) 自身的内积(公式推导见:线性回归模型向量化 1.3

define costFunction(X, y, theta):
	inner = np.power(X @ theta - y, 2)  # power(*,2)使向量(Xθ-y)每一项平方,返回仍为向量
	reture np.sum(inner) / (2 * len(X)) # 求向量每一项之和,结果相当于(Xθ-y)自身的内积

1.4 梯度下降函数

θ = θ α 1 m X T ( X θ y ) \theta=\theta-\alpha\frac{1}{m}X^T(X\theta-y) (公式推导见:线性回归模型向量化 1.4

  • 定义梯度下降函数:

    def gradientDescent(X,y,theta,alpha,iters): # iters为梯度下降中的迭代次数
    	costs = []								# 将每次迭代的代价函数值保存在列表
    
    	for i in range(iters):
            theta = theta - (X.T @ (X@theta - y) ) * alpha / len(X)
        	cost = costFunction(X,y,theta)
        	costs.append(cost)
        
        if i % 100 == 0:
            print(cost)							#每迭代 100 次打印一次cost
            
    return theta,costs       
    
  • 给学习率alpha 和迭代次数iters赋上初值:

    alpha = 0.02
    iters = 1000
    
    theta,costs = gradientDescent(X,y,theta,alpha,iters) #返回迭代1000次后
    
  • 绘制曲线图使代价函数可视化:

    fig,ax = plt.subplots()			#创建绘图实例
    ax.plot(np.arange(iters),costs)
    ax.set(xlabel='iters',
      	ylabel='cost',
      	title='cost vs iters')
    plt.show()
    

    在这里插入图片描述

1.5 拟合直线可视化

  • 绘制迭代后拟合的直线 ,并与原始数据在同一坐标轴

    # 创建绘图实例
    fig,ax = plt.subplots()
    
    #绘制拟合直线
    x = np.linspace(y.min(),y.max(),100)
    y_ = theta[0,0] + theta[1,0] * x
    ax.plot(x,y_,'r',label='predict')
    
    #绘制原始数据散点图
    ax.scatter(X[:,1],y,label='training data')
    
    #显示直线和散点图的标签
    ax.legend()
    
    #设置横纵轴名
    ax.set(xlabel='populaiton',
          ylabel='profit')
    plt.show()
    

在这里插入图片描述

  • 打印出theta即得到迭代后更新的参数值,然后给出新的population即可预测出其对应的profit

2. 多变量线性回归

题目

假设你现在打算卖房子,想知道房子能卖多少钱?
我们拥有房子面积、卧室数量 与 房子价格之间的对应数据: ex1data2.txt

(47行×3列,第一列为房子面积,第二列为卧室数量,第三列为房子价格)

2.1 导入数据

  • 导入库:

    import numpy as np  			# 科学计算库,处理多维数组,进行数据分析
    import pandas as pd				# 基于 NumPy 的一种解决数据分析任务工具
    import matplotlib.pyplot as plt # 提供一个类似 Matlab 的绘图框架
    
  • 导入数据集:

    data = pd.read_csv('ex1data2.txt',names=['size','bedrooms','price']) # 读取文件,指定列名
    data.head()
    

    在这里插入图片描述

  • 特征归一化
    由于房子面积和卧室数量的尺度相差很大,在提取特征向量之前需要先进行特征归一化(具体原因见 特征缩放
    x = x μ σ x=\frac{x-μ}{σ}

    def normalize_feature(data):
    	return (data - data.mean()) / data.std() # data.mean()为均值,data.std()为方差
    
    data = normalize_feature(data)
    data.head()
    

在这里插入图片描述
   可见归一化后的特征大部分都分布在[-1,1]之间。

  • 数据可视化
    # 获取坐标分布
    X1 = data.iloc[:,0:1]
    X2 = data.iloc[:,1:2]
    Y= data.iloc[:,-1]
    
    fig = plt.figure()
    ax = fig.gca(projection='3d')  			# 创建三维坐标
    ax.scatter(X1,X2,Y)						# 散点图 				
    ax.set(xlabel='size',ylabel='bedrooms',zlabel='price')# 坐标轴
    plt.show()
    

    得到房子价格与房子面积、房间数量的散点图:在这里插入图片描述

2.2 构造数据集

	# 添加 x_0=1这一列
	data.insert(0,'$x_0$',1)
	
	# 通过切片操作获取输入向量和输出向量
	cols = data.shape[1] 
	X = data.iloc[:,0:cols-1] 
	y = data.iloc[:,cols-1:cols] 

	# 将dataframe转成数组
	X = X.values
	y = y.values

 可以用 X.shapey.shape 查看数组的维度 ,维度分别为(47, 3)和(47, 1)

2.3 代价函数

# 同上
define costFunction(X, y, theta):
	inner = np.power(X @ theta - y, 2)
	reture np.sum(inner) / (2 * len(X)) 

theta = np.zeros((3,1)) #注意theta的维度变化 

2.4 梯度下降函数

def gradientDescent(X,y,theta,alpha,iters,isprint=False):
    costs = []
    
    for i in range(iters):
        theta = theta - (X.T @ (X@theta - y) ) * alpha / len(X)
        cost = costFunction(X,y,theta)
        costs.append(cost)
        
        if i % 100 == 0:
            if isprint:
                print(cost)
            
    return theta,costs
  • 不同alpha下的梯度下降效果
    candidate_alpha = [0.0003,0.003,0.03,0.0001,0.001,0.01]
    iters = 2000
    fig,ax = plt.subplots()
        
    for alpha in candidate_alpha:
    	_,costs = gradientDescent(X,y,theta,alpha,iters)
    	ax.plot(np.arange(iters),costs,label = alpha)
    	ax.legend()
    
    ax.set(xlabel='iters',
     	ylabel='cost',
      	title='cost vs iters')
    plt.show()
    

在这里插入图片描述

2.5 拟合平面可视化

由于有两个变量,最终的拟合结果是三维空间中的一个平面。

  • alpha=0.003iters=2000为例,就能得到迭代结束后的最终参数theta_final,并得到拟合平面: h θ ( x ) = θ 0 + θ 1 x 1 + θ 2 x 2 h_\theta(x)=\theta_0+\theta_1x_1+\theta_2x_2

  • 将拟合平面与原始散点数据放在同一个三维坐标系中:

    %matplotlib notebook # 有时候创建的三维图不能动态展示,加这个就可以
    fig = plt.figure()
    ax = fig.gca(projection='3d')#创建三维坐标
    
    #绘制原始数据的散点图
    ax.scatter(X1,X2,Y)
    
    # 绘制拟合平面
    x1, x2 = np.meshgrid(np.linspace(-2,3.5,2), np.linspace(-3,2.5,2))#生成网格采样点,这一步很重要
    h_x = theta[0,0] + theta[1,0] * x1 + theta[2,0] * x2 
    ax.plot_wireframe(x1,x2,h_x,color='g',alpha = 0.4)	#绘制线框 alpha表示透明度
    ax.plot_surface(x1,x2,h_x,color='g',alpha = 0.5)	#绘制平面
    	
    ax.set(xlabel='size',ylabel='bedrooms',zlabel='price')# 坐标轴
    
    plt.show()
    

    在这里插入图片描述

3. 正规方程

正规方程的推到见 线性回归模型向量化及正规方程
θ = ( X T X ) 1 X T y θ=(X^TX)^{-1}X^Ty

def normalEquation(X,y):
    theta = np.linalg.inv(X.T@X)@X.T@y
    return theta

theta = normalEquation(X,y)
发布了21 篇原创文章 · 获赞 21 · 访问量 1965

猜你喜欢

转载自blog.csdn.net/m0_37867091/article/details/104821004