学习周报(二)

本文介绍了机器学习中的梯度下降法,用于实现一元线性回归、多元线性回归和多项式回归的模型建立与拟合。通过代码展示了最小二乘法和梯度下降法的实现过程,并对比了使用sklearn库进行线性回归的便捷性。同时,文章探讨了不同回归模型在数据拟合中的应用,包括一元线性、多元线性以及多项式回归的效果和优化方法。
摘要由CSDN通过智能技术生成

摘要

本周主要是学习机器学习的 梯度下降法,代码实现一元线性回归和多元线性回归以及多项式回归实现建模并拟合模型,以及调用sklearn库方法建模。

Abstract

This week is mainly about learning the gradient descent method of machine learning, code implementation of unary linear regression and multiple linear regression and polynomial regression implementation modeling and fitting models, as well as calling the sklearn library method modeling.

一.基础概念

1.一元线性回归

1.1基本术语

回归这一术语最早来源于生物遗传学,由高尔顿(Francis Galton)引入。

回归的解释:回归分析是研究某一变量(因变量)与另一个或多个变量(解释变量、自变量)之间的依存关系,用解释变量的已知值或固定值来估计或预测因变量的总体平均值。

因变量:Y
自变量:X 或X1,X2,X3……等等。

数值型自变量和数值型因变量之间关系的分析方法,就是相关与回归分析。

相关与回归是处理变量之间关系的一种统计方法。如果研究的是两个变量之间的关系,则称为简单相关与简单回归分析;如果研究的是两个以上变量之间的关系,则称为多元相关与多元回归分析。

从变量之间的关系形态来看,有线性相关与线性回归分析及非线性相关与非线性回归分析。

1.2相关系数

两个变量之间的相关程度通过相关系数r来表示。相关系数的值在-1和1之间,但可以是此范围内的任何值。

正相关时,r值在0和1之间,散点图是斜向上的,这时一个变量增加,另一个变量也增加;

负相关时,r值在-1和0之间,散点图是斜向下的,此时一个变量增加,另一个变量将减少。

r的绝对值越接近1,两变量的关联程度越强,

r的绝对值越接近0,两变量的关联程度越弱。

样本相关系数的计算公式为:

image-20230618211402961

按上述公式计算的相关系数也称为线性相关系数(Linear Correlation Coefficient),或称为 Pearson 相关系数(Pearson’s Correlation Coefficient)

2.代价函数

如果我们有一个包含输入特性(features)的训练集 X 和 输出目标(targets) Y ,

这个训练集的模型是一个线性函数,f w, b (x) = w*x + b, 这个是x 的函数,

在机器学习中,w和b被称为模型的参数 parameters,
模型的参数是我们可以在训练中 调整的变量,通过改变这些变量来改进模型,
有时,w 和b 也会被称为系数 coefficients 或权重 weights 。

我们赋予w 和b 的值,赋予不同的值,我们会得到不同的关于x 的函数 function 。

当w = 0, b = 1.5 时,y的预测值始终是一个常数1.5
当w = 0.5, b = 0 时,函数是一个过原点的,斜率为0.5 的直线
当w = 0.5, b = 1 时,函数是一个过(0,1)点的,斜率为0.5 的直线

我们要构造代价函数,代价函数取预测的y 值,通过取预测的y 值与真实y 值之差,与真实y 值相比较,
预测的y 值与真实y 值之差,这种差异称为误差,我们在测量下一个预测离目标有多远

一般情况,我们会计算这个误差的平方,对于不同的训练例子,我们都要计算这个项,所以当测量误差时,要计算所有的误差

如果我们想测量整个训练集的误差,我们需要计算这些平方误差的总和。

m 是训练例数,m 越大,我们计算出来的代价函数就越大。

一元线性回归常用最小二乘法,具体代码实现将在后面实现

image-20230618211630330

二.梯度下降

概述

梯度下降(gradient descent)在机器学习中应用十分的广泛,不论是在线性回归还是Logistic回归中,它的主要目的是通过迭代找到目标函数的最小值,或者收敛到最小值。梯度下降的基本过程就和下山的场景很类似。

首先,我们有一个可微分的函数。这个函数就代表着一座山。我们的目标就是找到这个函数的最小值,也就是山底。根据之前的场景假设,最快的下山的方式就是找到当前位置最陡峭的方向,然后沿着此方向向下走,对应到函数中,就是找到给定点的梯度 ,然后朝着梯度相反的方向,就能让函数值下降的最快!

前置软件

首先我们需要下载Anaconda并在其中下载jupyter,中间出现过许多错误,比如pip命令出错,python版本不对等等,不过都通过别人的博客解决了,最后让我成功安装使用的一篇博客是

https://blog.csdn.net/fan18317517352/article/details/123035625(Anaconda超详细安装教程(Windows环境下))

1.梯度下降法代码实现一元线性回归

相关参数

# 学习率learning rate
lr = 0.0001
# 截距
b = 0 
# 斜率
k = 0 
# 最大迭代次数
epochs = 50

首先我们需要导入库

import numpy as np
import matplotlib.pyplot as plt

然后需要导入数据,我们在data.csv中写入了以逗号为分隔符的数据

image-20230618213727274

接下来用plt绘制这些点

# 载入数据
data = np.genfromtxt("data.csv", delimiter=",")
x_data = data[:,0]
y_data = data[:,1]
plt.scatter(x_data,y_data)
plt.show()

image-20230618213915269

最小二乘法

image-20230618214213316

代码实现

def compute_error(b, k, x_data, y_data):
    totalError = 0  #代价函数的值
    for i in range(0, len(x_data)):
        totalError += ((k * x_data[i] + b)-y_data[i]) ** 2 #预测值减去真实值
    return totalError / float(len(x_data)) / 2.0  #除以2m

梯度下降

image-20230618214934518

image-20230618214822706

我们循环对代价函数求偏导并更新函数的b和k,代码实现如下

def gradient_descent_runner(x_data, y_data, b, k, lr, epochs):
    # 计算总数据量
    m = float(len(x_data))
    # 循环epochs次
    for i in range(epochs):
        b_grad = 0
        k_grad = 0
        # 计算梯度的总和再求平均
        for j in range(0, len(x_data)):
            b_grad += (1/m) * (((k * x_data[j]) + b) - y_data[j])#预测值减去真实值 对b求导
            k_grad += (1/m) * x_data[j] * (((k * x_data[j]) + b) - y_data[j]) #对k求导
        # 更新b和k
        b = b - (lr * b_grad)
        k = k - (lr * k_grad)
        # 每迭代5次,输出一次图像
        if i % 5==0:
            print("epochs:",i)
            plt.plot(x_data, y_data, 'b.')
            plt.plot(x_data, k*x_data + b, 'r')
            plt.show()
    return b, k

主函数

print("Starting b = {0}, k = {1}, error = {2}".format(b, k, compute_error(b, k, x_data, y_data)))#迭代前k,b和误差
print("Running...")
b, k = gradient_descent_runner(x_data, y_data, b, k, lr, epochs)
print("After {0} iterations b = {1}, k = {2}, error = {3}".format(epochs, b, k, compute_error(b, k, x_data, y_data)))#迭代后
# 画图
plt.plot(x_data, y_data, 'b.')#x,y用点画出
plt.plot(x_data, k*x_data + b, 'r')#回归线
plt.show()

运行结果

image-20230618232106646

image-20230618232129714

image-20230618232142088

image-20230618232153470

可以看出,迭代50次后,损失已经变小了很多

2.sklearn实现一元线性回归

sklearn 是 scikit — learn 的简称,是一个基于 Python 的第三方模块。 sklearn 库集成了一些常用的机器学习方法,在进行机器学习任务时,并不需要实现算法,只需要简单的调用 sklearn 库中提供的模块就能完成大多数的机器学习任务。

sklearn使用的是标准方程法

使用sklearn需要导入sklearn库

from sklearn.linear_model import LinearRegression

使用sklearn库后不需要写compute_error和gradient_descent_runner了,只需要调用接口,如下图

x_data = data[:,0,np.newaxis]#取到所有的行,取第一列,再加上一个维度
y_data = data[:,1,np.newaxis]
# 创建并拟合模型
model = LinearRegression()
model.fit(x_data, y_data)

为什么要再加上一个维度,因为使用sklearn需要二维的数据

画图的代码也差不多

# 画图
plt.plot(x_data, y_data, 'b.')
plt.plot(x_data, model.predict(x_data), 'r')# model.predict 预测值
plt.show()

3.代码实现多元线性回归

3.1 多元线性回归

当Y值的影响因素不是唯一时,采用多元线性回归模型

image-20230618233442883

和一元线性回归类似,分别对不同变量求偏导

image-20230618233525919

代码实现

数据

# 学习率learning rate
lr = 0.0001
# 参数
theta0 = 0
theta1 = 0
theta2 = 0
# 最大迭代次数
epochs = 1000

首先还是导入库和数据

import numpy as np
from numpy import genfromtxt
import matplotlib.pyplot as plt  
from mpl_toolkits.mplot3d import Axes3D  
# 读入数据 
data = genfromtxt(r"Delivery.csv",delimiter=',')

Delivery.csv多元数据,如下图

image-20230618233724292

切分数据

# 切分数据
x_data = data[:,:-1]#每一行,从第一列到最后一列,不包括最后一列
y_data = data[:,-1]#最后一列数据
print(x_data)
print(y_data)

输出x_data和y_data如下图

image-20230618234112808

最小二乘法和一元类似,多几个未知数加入几个数据,计算时还是预测值减去真实值

# 最小二乘法
def compute_error(theta0, theta1, theta2, x_data, y_data):
    totalError = 0
    for i in range(0, len(x_data)):
        totalError += (y_data[i] - (theta1 * x_data[i,0] + theta2*x_data[i,1] + theta0)) ** 2
    return totalError / float(len(x_data))

梯度下降算法也类似,分别求导

def gradient_descent_runner(x_data, y_data, theta0, theta1, theta2, lr, epochs):
    # 计算总数据量
    m = float(len(x_data))
    # 循环epochs次
    for i in range(epochs):
        theta0_grad = 0
        theta1_grad = 0
        theta2_grad = 0
        # 计算梯度的总和再求平均
        for j in range(0, len(x_data)):
            theta0_grad += (1/m) * ((theta1 * x_data[j,0] + theta2*x_data[j,1] + theta0) - y_data[j])
            theta1_grad += (1/m) * x_data[j,0] * ((theta1 * x_data[j,0] + theta2*x_data[j,1] + theta0) - y_data[j])
            theta2_grad += (1/m) * x_data[j,1] * ((theta1 * x_data[j,0] + theta2*x_data[j,1] + theta0) - y_data[j])
        # 更新b和k
        theta0 = theta0 - (lr*theta0_grad)
        theta1 = theta1 - (lr*theta1_grad)
        theta2 = theta2 - (lr*theta2_grad)
    return theta0, theta1, theta2

最后输出数据

print("Starting theta0 = {0}, theta1 = {1}, theta2 = {2}, error = {3}".
      format(theta0, theta1, theta2, compute_error(theta0, theta1, theta2, x_data, y_data)))
print("Running...")
theta0, theta1, theta2 = gradient_descent_runner(x_data, y_data, theta0, theta1, theta2, lr, epochs)
print("After {0} iterations theta0 = {1}, theta1 = {2}, theta2 = {3}, error = {4}".
      format(epochs, theta0, theta1, theta2, compute_error(theta0, theta1, theta2, x_data, y_data)))

输出数据如下图

Starting theta0 = 0, theta1 = 0, theta2 = 0, error = 47.279999999999994
Running...
After 1000 iterations theta0 = 0.006971416196678632, theta1 = 0.08021042690771771, theta2 = 0.07611036240566814, error = 0.7731271432218118

最后预测的图像展示代码

ax = plt.figure().add_subplot(111, projection = '3d') 
ax.scatter(x_data[:,0], x_data[:,1], y_data, c = 'r', marker = 'o', s = 100) #点为红色三角形  
x0 = x_data[:,0]
x1 = x_data[:,1]
# 生成网格矩阵
x0, x1 = np.meshgrid(x0, x1)
z = theta0 + x0*theta1 + x1*theta2
# 画3D图
ax.plot_surface(x0, x1, z)
#设置坐标轴  
ax.set_xlabel('Miles')  
ax.set_ylabel('Num of Deliveries')  
ax.set_zlabel('Time')  
#显示图像  
plt.show()  

image-20230618234932658

np.meshgrid函数解析

输入np.meshgrid([1,2,3],[4,5,6])

输出 x0

array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])

输出x1

array([[4, 4, 4],
       [5, 5, 5],
       [6, 6, 6]])

x0显示的是矩阵的横坐标,x1是纵坐标,最后矩阵如下

(1,4)(2,4)(3,4)
(1,5)(2,5)(3,5)
(1,6)(2,6)(3,6)

输出矩阵图

image-20230618235807348

3.2 sklearn多元线性回归

步骤和上述相似,下面我只展示不同的地方

导入sklearn库

import numpy as np
from numpy import genfromtxt
from sklearn import linear_model
import matplotlib.pyplot as plt  
from mpl_toolkits.mplot3d import Axes3D  

创建模型

# 创建模型
model = linear_model.LinearRegression()
model.fit(x_data, y_data)

查看系数和截距

# 系数
print("coefficients:",model.coef_)
# 截距
print("intercept:",model.intercept_)
# 测试
x_test = [[102,4]]
predict = model.predict(x_test)
print("predict:",predict)

生成网格矩阵

ax = plt.figure().add_subplot(111, projection = '3d') 
ax.scatter(x_data[:,0], x_data[:,1], y_data, c = 'r', marker = 'o', s = 100) #点为红色三角形  
x0 = x_data[:,0]
x1 = x_data[:,1]
# 生成网格矩阵
x0, x1 = np.meshgrid(x0, x1)

最后生成图像类似

image-20230619000537652

4.多项式回归

有些图如果用一条直线无论如果都达不到好的效果,用一条曲线可以很好的拟合,这时候就需要多项式回归表示的曲线或者超曲面。

image-20230619001239193

代码实现

4.1 线性拟合

导入包

import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression

载入数据

# 载入数据
data = np.genfromtxt("job.csv", delimiter=",")
x_data = data[1:,1]
y_data = data[1:,2]
plt.scatter(x_data,y_data)
plt.show()

图显示如下

image-20230619001551656

给数据多加一个维度,创建并拟合模型

x_data = x_data[:,np.newaxis]
y_data = y_data[:,np.newaxis]
# 创建并拟合模型
model = LinearRegression()
model.fit(x_data, y_data)

绘图

# 画图
plt.plot(x_data, y_data, 'b.')
plt.plot(x_data, model.predict(x_data), 'r')
plt.show()

image-20230619001958002

数据有明显偏差,下面使用多项式拟合

4.2 多项式拟合

# 定义多项式回归,degree的值可以调节多项式的特征
poly_reg  = PolynomialFeatures(degree=5) 
# 特征处理
x_poly = poly_reg.fit_transform(x_data)
# 定义回归模型
lin_reg = LinearRegression()
# 训练模型
lin_reg.fit(x_poly, y_data)

建模后绘图

# 画图
plt.plot(x_data, y_data, 'b.')
plt.plot(x_data, lin_reg.predict(poly_reg.fit_transform(x_data)), c='r')
plt.title('Truth or Bluff (Polynomial Regression)')
plt.xlabel('Position level')
plt.ylabel('Salary')
plt.show()

图像如下

image-20230619002340909

明显比线性拟合

优化

# 画图
plt.plot(x_data, y_data, 'b.')
x_test = np.linspace(1,10,100)
x_test = x_test[:,np.newaxis]
plt.plot(x_test, lin_reg.predict(poly_reg.fit_transform(x_test)), c='r')
plt.title('Truth or Bluff (Polynomial Regression)')
plt.xlabel('Position level')
plt.ylabel('Salary')
plt.show()

图像如下

image-20230619002704435

函数

poly_reg = PolynomialFeatures(degree=5) degree取值越大,项数越多,越拟合。

x_test = np.linspace(1,10,100) 从1开始,到10结束,生成100个点,点越多拟合程度越好
…(img-IQjFgOjl-1687105826448)]

明显比线性拟合

优化

# 画图
plt.plot(x_data, y_data, 'b.')
x_test = np.linspace(1,10,100)
x_test = x_test[:,np.newaxis]
plt.plot(x_test, lin_reg.predict(poly_reg.fit_transform(x_test)), c='r')
plt.title('Truth or Bluff (Polynomial Regression)')
plt.xlabel('Position level')
plt.ylabel('Salary')
plt.show()

图像如下

[外链图片转存中…(img-T8f7lX2o-1687105826448)]

函数

poly_reg = PolynomialFeatures(degree=5) degree取值越大,项数越多,越拟合。

x_test = np.linspace(1,10,100) 从1开始,到10结束,生成100个点,点越多拟合程度越好

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值