欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

吴恩达 机器学习 ex1 单变量线性回归代码详解(非向量化写法)

程序员文章站 2022-06-18 19:12:08
前几天刚学完吴恩达老师的机器学习课程,然后尝试着去完成课后的编程作业,在这里分享一下ex1其中的单变量线性回归的心得。这一版是使用的非向量化的方式去编程。我会把每行代码的作用给大家解释清楚。让大家可以更好地理解整个线性回归的过程。大家在运行下面的代码时候要注意:①首先pip install 好需要用到的库和包。②txt的路径要写好,如果不会写相对路径的直接复制粘贴绝对路径也可以,不过要注意//和\的区别。③请手动在ex1data1.txt的第一行加入features这一个单词。(这主...

前几天刚学完吴恩达老师的机器学习课程,然后尝试着去完成课后的编程作业,在这里分享一下ex1其中的单变量线性回归的心得。

这一版是使用的非向量化的方式去编程。

我会把每行代码的作用给大家解释清楚。让大家可以更好地理解整个线性回归的过程。

大家在运行下面的代码时候要注意:

①首先pip install 好需要用到的库和包。

②txt的路径要写好,如果不会写相对路径的直接复制粘贴绝对路径也可以,不过要注意//和\的区别。

③请手动在ex1data1.txt的第一行加入features这一个单词。(这主要是因为我对pandas用的不熟,不会加列名,下一篇向量化的代码详解中,就没有这么蠢啦)

好啦 请阅读代码+注释吧 会让你对线性回归有一个新的理解的~

from matplotlib import pyplot as plt
import pandas as pd
import random
import numpy as np
#导入包 pyplot是用来画图的 pandas用来读取数据处理数据的
#      random用来生成随机数 numpy是用来做矩阵运算的
#      这一版代码中 用的是非向量化的方式 所以导入了numpy但是没有用到
#首先我们了解一下步骤:
#step1:假设函数:hx=theta0 + theta1 * x 并初始化theta0与theta1
#step2:cost函数:(hx-y)^2/ 求m项的和 再除以2m m是指数据的条数
#step3:如果cost函数求出来的值 也就是model error模型误差太大 就进行梯度下降
#step4:梯度下降:theta0=theta0-学习率*导数项
#               theta1=theta1-学习率*导数项
#               导数项为 (hx-y)*xi 求m项的和 并除以m  m是指数据的条数
#               对于theta0来说 相当于theta0*x0 x0=1 所以导数项就等于
#               (hx-y)*x0 ---> (hx-y)*1
#               对于theta1来说 导数项就等于
#               (hx-y)*x
#所以梯度下降的公式可以写成:theta0=theta0-学习率*(hx-y)*1
#                      theta1=theta1-学习率*(hx-y)*x
#然后重复进行step1 2 3 4 直至收敛
#上面的就是进行线性回归的基本流程 下面非向量化代码的详细解释
#由于是我第一次写读取文件的代码 过程很繁琐 显得很蠢 在向量化代码中改的很简单了
df = pd.read_table("ex1data1.txt")#使用pandas的readtable的方法读取txt文件
features = []#创建一个features列表用来存储数据
#!!!!这里需要注意 因为原始数据中 没有列名 而且数据之间使用“,”隔开,当时我不知道读取数据时可以加上列名,所以手动在txt文件开头加了一行 features
#在向量化代码中 读取数据会变得更简单
for row in df.itertuples(index=True, name='Pandas'):
    features.append(getattr(row, "features"))  #遍历数据的每一行,将列名为features的数据加入features列表中

# print(features)
x1 = []
x2 = []#创建两个列表用来存储使用“,”分开的数据  其中x1对应着上面线性回归流程中的x x2对应着y
for elements in features:
    elements = elements.split(",")
    # print(elements[0],elements[1])
    x1.append(float(elements[0]))
    x2.append(float(elements[1]))
#遍历features中的每个元素 其实每个元素的形式为“x1,x2”如“5.11,65.25”这样
#使用split按照“,”将每个元素分成两部分 第一部分存入x1列表 第二部分存入x2列表
plt.scatter(x1, x2)#使用散点图画出数据的分布
plt.show()
#到此我们就取出了x1 x2 并把他们存入了不同的列表以备后用 下面就开始线性回归的步骤啦
#——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
theta0, theta1,= random.randrange(-1, 1), random.randrange(-1, 1)#初始化theta0,theta1,机器学习课程中讲的也可以设置为0
x0 = [1 for i in range(97)]#其实上面提取数据只提取了x 对于theta1而言也就是x1 还有真实值y 但 对于theta0来说 虽然式子中只有theta0 其实相当于都乘了一个x0
#只不过x0都是1 所以这里也用了一个列表来表示x0
modelError = 0#设置模型误差 以备后用 其实就是(hx-y)^2 后面会循环m次 累加
learningRate = 0.001#设置学习率
sumModelError = 1000#设置总的模型误差 也就是代价 是上面累加完的modelError 然后再除以2m
lastSumModelError=10000#设置上一次的模型误差 可能你不懂这是用来干什么的 后面会详细解释的 先跳过这个变量也可以
derivative0=0 #设置theta0的导数项为0 用于后面进行累加
derivative1=0 #设置theta1的导数项为0 用于后面进行累加
#上面我设置了很多变量为0 用于累加 如果没有编程经验的可能不懂 就像求和需要设置一个sum=0 然后sum+=i一样 这是一种很小白的做法 可是对于第一次写线性回归我只会这么做了 哈哈

sumModelError_arr=[]#设置总的模型误差 也就是总的代价 总的损失(如果只听了机器学习这一门课可能不知道什么是损失,再继续听吴恩达的深度学习就懂啦)用于存入迭代过程中的代价,用于以后画图
derivative0_arr=[]#设置theta0的导数项的数组用于存入迭代过程中的导数项,用于以后画图
derivative1_arr=[]#设置theta1的导数项的数组用于存入迭代过程中的导数项,用于以后画图
minus=1#这是设置的一个变量用来判断迭代到底该什么时候停止 minus=上一次的总的代价-这一次的总的代价
for j in range(0,10000000):#先设置一个很大很大的迭代次数 这里设置了10000000
    if minus>0.0001:#这个判断的意思是 如果上一次的总的代价-这一次的总的代价 >0.0001 就继续迭代 如果小于等于 就说明已经收敛了 就不停止迭代了
        for i in range(0, len(x0)):#循环m次 m是数据条数 相当于每次都按顺序取不同的数据 第一条 第二条
            derivative0 += ((theta0 * x0[i] + theta1 * x1[i]) - x2[i]) * x0[i]#theta0的导数项 还记得我们上面流程中的公式么?
            #               对于theta0来说 相当于theta0*x0 x0=1 所以导数项就等于
            #               (hx-y)*x0 ---> (hx-y)*1
            derivative1 += ((theta0 * x0[i] + theta1 * x1[i]) - x2[i]) * x1[i]#theta1的导数项
            #               对于theta1来说 导数项就等于
            #               (hx-y)*x
            modelError += ((theta0 * x0[i] + theta1 * x1[i]) - x2[i]) *((theta0 * x0[i] + theta1 * x1[i]) - x2[i])
            #每一项的误差 代价 损失 这三种叫法都可以 然后累加
            #(hx-y)^2/ 求m项的和

        derivative0 = derivative0 / len(x0)#导数项还需除以m
        # print(j, i, derivative0)
        derivative1 = derivative1 / len(x0)#导数项还需除以m
        # print(j, i, derivative1)
        #导数项为 (hx-y)*xi 求m项的和 并除以m  m是指数据的条数
        temp0 = theta0 - learningRate * derivative0#计算新的theta0
        # print("derivative1", derivative1)
        temp1 = theta1 - learningRate * derivative1#计算新的theta1
        #梯度下降:theta0 = theta0 - 学习率 * 导数项
        #               theta1=theta1-学习率*导数项
        #之所以使用temp0 temp1是因为需要同步更新 我记得当时写的时候是按照吴恩达课程上给的伪代码写的 现在回过头写注释 感觉直接赋值给theta0 theta1好像也可以
        theta0 = temp0
        theta1 = temp1
        # print(theta0,theta1)
        sumModelError = modelError / (2 * len(x0))#计算总的代价 就多了一个除以2m
        sumModelError1=lastSumModelError
        minus = sumModelError1 - sumModelError
        lastSumModelError=sumModelError
        modelError=0# 上面四行代码都是为了计算上一次的代价-下一次的代价所做的准备 主要是逻辑关系有点难想明白 你按照上面四行去赋值 自己思考一下顺序就懂啦
        # print("derivative0",derivative0,"derivative1",derivative1)
        # print("sumModelError",sumModelError)
        sumModelError_arr.append(sumModelError)#把这一次的总代价加入到列表中
        derivative0_arr.append(derivative0)#把这一次theta0的导数项加入到列表中
        derivative1_arr.append(derivative1)#把这一次theta1的导数项加入到列表中
        #print(minus)
        #看到这里 你已经完成了一次循环过程啦 如果到这里minus(我们上面用四行代码设置的)还满足>0.0001这个要求的话 就会一直循环迭代下去
        #如果不满足 就会跳到下面的else中 break 停止循环啦
    else:
        break
plt.plot(sumModelError_arr,color="blue")
plt.show()#画图 画的图就是总的损失 或者说 总的代价随迭代次数的变化 最后会看到会收敛到一个值 然后线性回归就大功告成啦

#这是我的第一次写关于机器学习的文章 有什么不足请评论区留言啦 代码很繁琐 在下一篇 单变量线性回归(向量化)的代码中会很变得很简洁的啦

 下一篇文章应该是吴恩达 机器学习 ex1 单变量线性回归代码详解(向量化写法)超级适合小白看

如果以你觉得我写的文章帮助了你 请多多关注和评论区留言哟

你的支持是我写文章的动力!

以后还会陆续更新其他有关机器学习和深度学习的文章,超级详细的哟!

 

本文地址:https://blog.csdn.net/qq_17463345/article/details/111062719