吴恩达机器学习作业一,线性回归的梯度下降实现(python实现)

问题描述:

您将使用一个变量实现线性回归,以预测食品卡车的利润。假设你是一家连锁餐厅的首席执行官,正在考虑在不同的城市开一家新餐厅。该连锁店已经在多个城市拥有卡车,你可以从这些城市获得利润和人口数据。你想使用这些数据来帮助你选择下一个城市。文件ex1data1.txt包含我们的线性回归问题的数据集。第一列是一个城市的人口第二列是该城市一辆快餐车的利润。利润为负数表示亏损。

问题分析:

上述目的就是根据人口来预测利润,对于ex1data1.txt中的数据集,第一列的数据是人口,第二列的数据是利润,我们要做的就是找到一个回归方程来拟合这些数据,对于每一个给定的人口数据,能够较好的预测出与之对应的利润,本问题中采用两个参数  \theta _0  和 \theta _1,一次方程的方法进行拟合

分析过程:

1、假设函数:

在本问题中,我们的最终目的就是找到一个假设函数   h(x) = \theta_0 + \theta_1*x  ,使之能够较好的满足给定的数据集

2、代价函数:

对于假设函数,一个重要的要求就是尽可能地使得他的代价值最小,代价函数为       J(\theta_0, \theta_1) = \frac{1}{2m} \sum_{i=1}^{m}(h_\theta(x^{(i)})-y^{(i)})^{2}

而我们要求地是这个方程地最小值,直接求计算量太大而且复杂,所以使用梯度下降算法,就是从一个点出发,计算该点地梯度(梯度地定义为该点下降最快地方向,就是朝着不同维度正方向地偏导,这个问题就是分别对 \theta_0 \theta_1 求偏导,然后减去学习率乘以这两个偏导值,不断更新重复这个过程,直到偏导值为分别为0,方程如下

\theta_j:=\theta_j-\alpha\frac{\partial}{\partial \theta_j}J(\theta)(for j =1 ,j = 2)

函数J我们已知,为了编程方便,引入变量x_0,使其一直为1

J(\theta_0, \theta_1) = \frac{1}{2m} \sum_{i=1}^{m}((\theta_0*x_0^{(i)}) + \theta_1*x_1^{(i)})-y^{(i)})^{2}

对 \theta_0 求导得

\frac{1}{m} \sum_{i=1}^{m}((\theta_0*x_0^{(i)}) + \theta_1*x_1^{(i)})-y^{(i)})*x_0

对 \theta_1 求导得

\frac{1}{m} \sum_{i=1}^{m}((\theta_0*x_0^{(i)}) + \theta_1*x_1^{(i)})-y^{(i)})*x_1

综合来看,可以看成,对 \theta_j (j=0,j=1)求导得

\frac{1}{m} \sum_{i=1}^{m}((\theta_0*x_0^{(i)}) + \theta_1*x_1^{(i)})-y^{(i)})*x_j

所以迭代方程如下

\theta_j:=\theta_j-\alpha\frac{1}{m} \sum_{i=1}^{m}((\theta_0*x_0^{(i)}) + \theta_1*x_1^{(i)})-y^{(i)})*x_1

代码实现:

import pandas as pd
import numpy as np
from part_of_work.property import properties

# 读取数据,且索引值为population和profit
p1 = properties()
ex1data1 = p1.ex1data1
df1 = pd.read_csv(ex1data1, names=['population', 'profit'])


# 读取特征,自变量叫做特征,也就是x
def get_x(df):
    ones = pd.DataFrame({'ones': np.ones(len(df))})
    data = pd.concat([ones, df], axis=1)  # 按照列合并数据
    return np.matrix(data.iloc[:, :-1])  # 以数组的形式返回除了最后一行的数据,也就是第一列全1和第二列population的数据


# 读取标签,因变量叫做标签,也就是y
def get_y(df):
    return np.matrix(df.iloc[:, df.shape[1] - 1:])  # 返回最后一列的数据,也就是y的数据,profit的数据


# 特征缩放,由于特征在范围较大的尺度的时候,梯度下降的速度会很慢,所以将所有数据转化到-1,1之间
def normalize_feature(df):
    return df.apply(lambda column: (column - column.mean()) / column.std())  # 值减去均值除以标准差


# 计算代价函数
"""
本来的方程是
h = th_0 + th_1 * x1
但是为了描述方便,将方程变为 h = th_0 * x0 + th_1 * x1
其中,x0 永远为1
"""


def compute_cost(x1, y1, theta1):
    inner = np.power((x1 * theta1.T - y1), 2)  # 求代价的平方和函数,每一个对应得到的值与实际的相减
    return np.sum(inner) / (2 * x1.shape[0])  # 为了方便求导,除以2乘以数据的长度


"""
DataFrame函数
shape[0]中存储的是这个数据的高度
shape[1]中存储的是这个数据的宽度,不包含索引,单纯的数据
shape是查看尺寸
.T表示对一个矩阵进行转秩
"""
x1 = get_x(df1)
y1 = get_y(df1)
# 生成theta,theta是一行二列 1*2的矩阵
theta1 = np.matrix(np.array([0, 0]))


def gradient_decent(x, y, theta, alpha, iters):
    temp = np.matrix(np.zeros(theta1.shape))  # 建立1*2的,全为0的矩阵
    parameters = int(theta1.ravel().shape[1])  # 赋值为参数的个数多少,本问题中为2
    cost = np.zeros(iters)  # 建立一个迭代次数大小的全0矩阵
    for i in range(iters):  # 进行迭代,理论上只要迭代次数足够多一定会有结果
        error = (x * theta.T) - y  # 计算当前取值的theta对应的y和实际的差距,得到的是一个样本容量大小的一维矩阵
        for j in range(parameters):  # 分别对两个参数theta_0和theta_1进行处理
            term = np.multiply(error, x[:, j])  # x_0 * (x_0 * theta_0 + x_1 * theta_1 - y),就是求导公式中要求和的那一串
            temp[0, j] = temp[0, j] - (alpha/len(x)) * np.sum(term)  # 这个就是函数的更新过程theta值的更新
            pass
        theta = temp  # 赋值给theta
        cost[i] = compute_cost(x, y, theta)
        pass
    return theta, cost


theta2, cost2 = gradient_decent(x1, y1, theta1, alpha=0.01, iters=1000)
print(theta2)
print(np.min(cost2))

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值