栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

【python】吴恩达机器学习作业1实现(Machine Learning Ng homework1)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【python】吴恩达机器学习作业1实现(Machine Learning Ng homework1)

参考:某大佬的github
建议打开上面的链接看看。
此篇主要补充一些公式转化成线性代数语言和实现。
如有纰漏,欢迎指正。

大致思路

主要部分有:加载数据,归一化数据,计算代价cost,梯度下降。
另外需要一个训练函数,一个预测函数,一些可视化函数和主函数。

参数对应含义

x-特征
y-真实结果
h-假设函数的结果(计算得到的结果)
m-训练样本的数量
n-特征的维数(比如 2 :房屋面积,使用年限)
theta-参数

加载数据

去上面的链接复制粘贴就行

def load_data(filename, delimiter, dtype):
    loaddata = np.loadtxt(filename, delimiter=delimiter, dtype=dtype)
    # print(loaddata)
    return loaddata
归一化数据

公式:
上面的链接使用的标准差(代码std),而我用的最大值-最小值(代码ptp)

def normalization(data_x):  # 注意:接收的是x 此函数把参数转化成-0.5到+0.5之间
    # 使用x = (x-平均值)/范围 替代x ---------- 也可以除以标准差
    data_x_norm = np.array(data_x)  # 将X转化为numpy数组对象,才可以进行矩阵的运算
    mean = np.mean(data_x_norm, 0)  # 求每一列的平均值(0指定为列,1代表行)(一列是同一种特征)
    # print(f'mean={mean}')
    ptp = np.ptp(data_x_norm, 0)  # 求每一列的范围
    # print(f'ptp={ptp}')
    for col in range(data_x_norm.shape[1]):  # python遍历np数组的列
        # shape[0]第一维度的长度相当于行数 shape[1]第二维度的长度相当于列数
        data_x_norm[:, col] = (data_x_norm[:, col]-mean[col])/ptp[col]
        # 其中data_x_norm[:, col]应该是一列,mean[col],ptp[col] 应该是个数字
        # print(f'data_x_norm[:, col] ={data_x_norm[:, col] }')  # 显示的应该是科学计数法表示的数据,-0.5到+0.5之间是正常的
    return data_x_norm, mean, ptp
计算代价cost


有几点要注意的:
1.特征x应该有一列1,实现如下:

x_fin = np.hstack((np.ones((m, 1)), x_norm))  # 在X前加一列1  原因见吴恩达课    # np.vstack():在竖直方向上堆叠 np.hstack():在水平方向上平铺

原因吴恩达老师讲过,这样做可以使得 输出h = x 乘 参数theta

计算输出(假设函数)h的方法见上图,代码如下:

h = np.dot(x, theta)  # 计算预测值(把数据代入假设)

计算代价cost的公式:
对应代码:

cost_j = np.transpose(np.dot(x_cost, theta_cost) - y_cost) * (np.dot(x_cost, theta_cost) - y_cost) / (2 * m)

其中h我们刚刚讲过计算方法,
平方和的计算需要应用线性代数知识:a转置乘a就是平方和
证明如下(2022李永乐线代33页)

计算代价cost的代码如下:

def cost(x_cost, y_cost, m, theta_cost):  # 注意x第一列应该全为1
    # print(f'x_cost={x_cost}')
    # print(f'y_cost={y_cost}')
    # print(f'theta_cost={theta_cost}')
    cost_j = np.transpose(np.dot(x_cost, theta_cost) - y_cost) * (np.dot(x_cost, theta_cost) - y_cost) / (2 * m)
    # 计算代价J # at*a等价于平方和 线代知识
    return cost_j  # 应该是个行向量?
梯度下降

求导可以自己试试,很简单的复合函数求导

公式中

这一部分的处理其实和刚刚很像,h还用刚刚的方法计算:

h = np.dot(x, theta)  # 计算预测值(把数据代入假设)

剩下的“乘积求和” 和 “平方和”是一样的,用(h-y)转置乘x就是“乘积求和”的结果了。

实现如下:

def gradient_descent(x, y, m, n, theta, alpha, num_iters):
    temp = np.matrix(np.zeros((n, num_iters)))  # 暂存每次迭代计算的theta,转化为矩阵形式
    j_history = np.zeros((num_iters, 1))  # 记录每次迭代计算的代价值
    for i in range(num_iters):  # 遍历迭代次数
        h = np.dot(x, theta)  # 计算预测值(把数据代入假设)
        temp[:, i] = theta - ((alpha / m) * (np.dot(np.transpose(x), h - y)))  # 梯度的计算
        # temp[:, i]遍历列  transpose(x) 取转置就可以一一对应相乘了
        theta = temp[:, i]
        j_history[i] = cost(x, y, m, theta)  # 调用计算代价函数
        print('.', end=' ')
    print()
    return theta, j_history
完整代码
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:windowsfontssimsun.ttc", size=14)    # 解决windows环境下画图汉字乱码问题


def load_data(filename, delimiter, dtype):
    loaddata = np.loadtxt(filename, delimiter=delimiter, dtype=dtype)
    # print(loaddata)
    return loaddata


def normalization(data_x):  # 注意:接收的是x 此函数把参数转化成-0.5到+0.5之间
    # 使用x = (x-平均值)/范围 替代x ---------- 也可以除以标准差
    data_x_norm = np.array(data_x)  # 将X转化为numpy数组对象,才可以进行矩阵的运算
    mean = np.mean(data_x_norm, 0)  # 求每一列的平均值(0指定为列,1代表行)(一列是同一种特征)
    # print(f'mean={mean}')
    ptp = np.ptp(data_x_norm, 0)  # 求每一列的范围
    # print(f'ptp={ptp}')
    for col in range(data_x_norm.shape[1]):  # python遍历np数组的列
        # shape[0]第一维度的长度相当于行数 shape[1]第二维度的长度相当于列数
        data_x_norm[:, col] = (data_x_norm[:, col]-mean[col])/ptp[col]
        # 其中data_x_norm[:, col]应该是一列,mean[col],ptp[col] 应该是个数字
        # print(f'data_x_norm[:, col] ={data_x_norm[:, col] }')  # 显示的应该是科学计数法表示的数据,-0.5到+0.5之间是正常的
    return data_x_norm, mean, ptp


def cost(x_cost, y_cost, m, theta_cost):  # 注意x第一列应该全为1
    # print(f'x_cost={x_cost}')
    # print(f'y_cost={y_cost}')
    # print(f'theta_cost={theta_cost}')
    cost_j = np.transpose(np.dot(x_cost, theta_cost) - y_cost) * (np.dot(x_cost, theta_cost) - y_cost) / (2 * m)
    # 计算代价J # at*a等价于平方和 线代知识
    return cost_j  # 应该是个行向量?


def gradient_descent(x, y, m, n, theta, alpha, num_iters):
    temp = np.matrix(np.zeros((n, num_iters)))  # 暂存每次迭代计算的theta,转化为矩阵形式
    j_history = np.zeros((num_iters, 1))  # 记录每次迭代计算的代价值
    for i in range(num_iters):  # 遍历迭代次数
        h = np.dot(x, theta)  # 计算预测值(把数据代入假设)
        temp[:, i] = theta - ((alpha / m) * (np.dot(np.transpose(x), h - y)))  # 梯度的计算
        # temp[:, i]遍历列  transpose(x) 取转置就可以一一对应相乘了
        theta = temp[:, i]
        j_history[i] = cost(x, y, m, theta)  # 调用计算代价函数
        print('.', end=' ')
    print()
    return theta, j_history


def linear_regression(alpha=0.01, num_iters=400):  # 训练
    data = load_data('data.csv', ',', np.float64)  # 加载数据
    # 拆解数据
    x = data[:, 0:-1]  # 3列,0,1是【x】,2是【y】
    y = data[:, -1]  # y对应最后一列
    x_norm, mean, ptp = normalization(x)  # 归一化x
    plot_x1_x2(x_norm)  # 画图
    y = y.reshape(-1, 1)  # 将行向量转化为列
    m = len(y)  # 训练样本的数量
    x_fin = np.hstack((np.ones((m, 1)), x_norm))  # 在X前加一列1  原因见吴恩达课    # np.vstack():在竖直方向上堆叠 np.hstack():在水平方向上平铺
    n = data.shape[1]      # data的列数 即特征的维数(2+1 有一列1)
    theta = np.zeros((n, 1))  # 初始化参数
    print(u"n执行梯度下降算法....n")
    theta, j_history = gradient_descent(x_fin, y, m, n, theta, alpha, num_iters)
    plotJ(j_history, num_iters)
    return theta, mean, ptp  # 返回学习的结果theta 平均值mean 范围ptp(用于预测时用normalization(x)同样的放缩处理输入数据)


def plotJ(j_history, num_iters):  # 画每次迭代代价的变化图
    x = np.arange(1, num_iters+1)
    plt.plot(x, j_history)
    plt.xlabel(u"迭代次数", fontproperties=font) # 注意指定字体,要不然出现乱码问题
    plt.ylabel(u"代价值", fontproperties=font)
    plt.title(u"代价随迭代次数的变化", fontproperties=font)
    plt.show()


def plot_x1_x2(x):
    plt.scatter(x[:, 0], x[:, 1])
    plt.show()


def predict(pre_x, theta, mean, ptp):
    norm_pre_x = (pre_x - mean) / ptp
    fin_pre_x = np.hstack((np.ones((1)), norm_pre_x))
    result = np.dot(fin_pre_x, theta)
    return result


if __name__ == "__main__":
    theta, mean, ptp = linear_regression()
    pre_x = np.array([1650, 4])

    print(predict(pre_x, theta, mean, ptp))

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/316785.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号