机器学习初学者——线性回归学习笔记

线型回归

是一种典型的参数学习,只能解决回归问题,

简单线性回归–最小二乘法

目的:使得用拟合的直线所求的的预测值与实际值的差距尽可能的小,差距可以用绝对值表示或者差距的平方表示,但由于需要通过求导求得系数,绝对值函数不连续可导,因此选择平方的形式,那么简单线型回归的目的为:
找到a和b使得∑(axi+b-yi)2(i=1,2,……m,m为样本个数)最小
这个函数也称为损失函数,用于度量模型没有拟合样本的程度,相应的,效用函数用于度量模型拟合样本的程度。
将目标函数分别对a和b求导,可得a和b的表达式分别为
在这里插入图片描述
简单线性回归的代码实现,即根据a和b的表达式用数学公式来逐步计算出a和b的值,从而可以用回归的直线对数据进行预测
模块一:模型的训练、预测

import numpy as np

class Simplereg:
    def __init__(self):
        self.a_=None
        self.b_=None
    def fit(self,x_train,y_train):
        assert x_train.ndim==1
        assert len(x_train)==len(y_train)
        x_mean=np.mean(x_train)
        y_mean=np.mean(y_train)
        //求a和b的方法一
        #numerator=0.0
        #distance=0.0
        #for i in range(len(x_train)):
         #   numerator+=(x_train[i]-x_mean)*(y_train[i]-y_mean)
         #   distance=(x_train[i]-x_mean)**2
         //方法二向量化,更简单快速
        numerator=(x_train-x_mean).dot(y_train-y_mean)
        distance=(x_train-x_mean).dot(x_train-x_mean)
        self.a_=numerator/distance
        self.b_=y_mean-self.a_*x_mean        
        return self
    def predict(self,x_predict):
        assert self.a_ is not None and self.b_ is not None
        assert x_predict.ndim==1
        y_predict=x_predict*self.a_+self.b_
        return y_predict
    def __repr__(self):
        return 'Simplereg()'

多元线型回归

???

y=θ01X12X23X3+……θnXn(n为特征数)

与简单线性回归相同之处在于。目的同样是求出使得∑(ytruei-ypredi)2(i=1,2,……m,m为样本个数)最小的参数,θ0、θ1、θ2、θ3……θn
y=θ01X12X23X3+……θnXn

创建一个列向量X0=np.ones((m,1))

yi0X0i1X1i2X2i3X3i+……θnXni(i=1,2,3……m,表示样本数)
令θ=(θ0、θ1、θ2、θ3……θnT
其中θ0表示截距,θ1—θn表示系数,在计算时分开
用X表示样本特征组成的矩阵
X=(X1,X2,……,Xn),其中Xn表示第m个样本第n个特征值所组成的列向量
X_b=(X0,X1,X2,……,Xn)则X_bi=(X0i,X1i,X2i,……,Xni)
Y=X_bmx(n+1)θ(n+1)x1
Yi=X1x(n+1)iθ(n+1)x1

目标函数:∑(ytruei-ypredi)2=∑(ytruei-X1x(n+1)iθ~(n+1)x1)2
用向量法可进一步简化为(y-X_b.θ)T.(y-X_b.θ)

因此,多元线性回归的目的为:使(y-X_b.θ)T.(y-X_b.θ)最小化,同样需要将该损失函数对每个参数θn求导,求导结果可得
θ=(X_bT.X_b)-1X_bT.y(正规方程解)
优点:由于θ是由原始数据通过数学计算所得的计算结果,且θ是一个没有量纲的系数,因此不需要对数据做归一化处理
缺点:时间复杂度高,计算量大
具体代码实现:

import numpy as np
class Linearreg:
    def __init__(self):
        self.intercept_=None
        self.coefficient_=None
        self._theta=None
    def fit_normal(self,x_train,y_train):
        assert len(x_train)==len(y_train)
        x_b=np.hstack((np.ones((len(x_train),1)),x_train))
        self._theta=np.linalg.inv(x_b.T.dot(x_b)).dot(x_b.T).dot(y_train)
        self.intercept_=self._theta[0]
        self.coefficient_=self._theta[1:]
        return self
    def predict(self,x_predict):
        assert x_predict.shape[1]==len(self.coefficient_)
        assert self.coefficient_ is not None
        x_b=np.hstack((np.ones((len(x_predict),1)),x_predict))
        //上一步很重要,易出错忘记
        y_predict=x_b.dot(self._theta)
        return y_predict
    def __repr__(self):
        return 'Linearreg()'

sklearn中代码实现
from sklearn.linear_model import LinearRegression\ object=LinearRegression()\ object.fit(x_train,y_train)

  • 梯度下降法(Gradient Desent)

不是一个机器学习的算法,只是一种基于搜索的最优化方法

梯度下降法的原理是用θ表达损失函数,那么函数曲线将会有一个最小点(区分局部的极值点),该点处的损失函数关于θ的导数为0,由于线性回归中,损失函数表达式为==∑(ytruei-ypredi)2=∑(ytruei-X1x(n+1)iθ(n+1)x1)2==是一个开口向上的二次函数,因此只有唯一的极小值也就是导数为0的处的值。
令J=∑(ytruei-Xiθ)2,J-θ图像是损失函数关于θ的曲线,任一点θ处的导数为dJ/dθ,其方向(正负号)为J增加的方向,那么-dJ/dθ即为梯度,表示J减小的方向。
因此线性回归中梯度下降法的目的是:设定θ的初始值。使θ沿着梯度方向以一定的步长改变,从而不断降低J的值,直到J将至最低点,此时的θ值即为所求

实现算法的过程:
一、求出损失函数J关于θ的表达式,
二、求出dJ/dθ的表达式
三、初始化θ、学习率η的值,
求出参数为θ时的J,和dJ/dθ,则下一个θ的值应为θ-η*dJ/dθ,直到两次的J值变化量小于一个接近于0的值epsilon,此时的θ即为所求。

批量梯度下降法(Batch Gradient Desent)

优点:稳定,一定是向损失函数的最小值方向进行,但是运算速度慢
批量梯度下降法即所有样本的所有特征都参与计算
目标函数的梯度为其在各个方向的偏导数组成的向量:
在这里插入图片描述
目标函数在各个方向上的偏导数计算结果如下:
在这里插入图片描述
由上式可知,最终求得的梯度值与样本数量有关,在样本数量过大的情况下,各个方向的偏导数都会过大,这将不利于损失函数的最小化。因此,目标函数改为1/m∑(ytruei-ypredi)2
那么相应地,梯度表达式为:
在这里插入图片描述在这里插入图片描述在这里插入图片描述这是一个行向量,为了便于表示θ,经过转置变为列向量在这里插入图片描述
其中在这里插入图片描述向量化为=(Xibθ-yi).dot(Xni),那么整个大括号的式子就可以向量化为以上形式,也就是下图所示的两个向量相乘
在这里插入图片描述
模型训练的代码如下:

def fit_gd(self,x_train,y_train,eta,n_iters=1e4):
        assert x_train.shape[0] == y_train.shape[0]
        def J(theta,x_b,y_train):
            try:
                return np.sum((y_train-x_b.dot(theta))**2)/len(x_b)
            except:
                return float('inf')
        def dJ(theta,x_b,y_train):
            return x_b.T.dot(x_b.dot(theta)-y_train)*2./len(y_train)//向量化方法
            [[[res=np.empty(len(theta))
            res[0]=np.sum(x_b.dot(theta)-y_train)
            for i in range(1,len(theta)):
                res[i]=(x_b.dot(theta)-y_train).dot(x_b[:,i])
            return res*2/len(y_train)
        def]]]//非向量化方法
         gradient_desent(x_b,y_train,initial_theta,eta,n_iters=1e4,epsilon=1e-8):
            theta=initial_theta
            i_iter=0         
            while i_iter<n_iters:
                gradient=dJ(theta,x_b,y_train)
                last_theta=theta
                theta=theta-eta*gradient
                if abs(J(last_theta,x_b,y_train)-J(theta,x_b,y_train))<epsilon:
                    break
                i_iter+=1
            return theta
        x_b=np.hstack((np.ones((len(x_train),1)),x_train))
        initial_theta=np.zeros(x_b.shape[1])
        self._theta=gradient_desent(x_b,y_train,initial_theta,eta)
        self.intercept_=self._theta[0]
        self.coefficient_=self._theta[1:]
        return self

随机梯度下降法(Stochastic Gradient Desent)

计算速度快,不稳定,每一次的方向不确定,有可能向损失函数增大的方向进行
可以跳出局部最优解,更容易找到整体最优解
随机梯度下降法的原理是每次只对一个样本进行计算,每次选取固定的一个i,那么每次计算方向变为:
在这里插入图片描述
为了避免随机的过程中,由于学习率η取之不当,在梯度随机下降的过程中,方向不固定,避免已经接近最小值时又跳出最小值,计算过程中保持η灵活改变,这里η的公式为在这里插入图片描述
随机梯度下降法中,不能以两次计算出来的目标函数的差值作为结束循环的判断条件,因为θ改变的方向是随机的,不是一直朝着目标函数最小的方向进行。

def fit_sgd(self, X_train, y_train, n_iters=50, t0=5, t1=50):
        """根据训练数据集X_train, y_train, 使用梯度下降法训练Linear Regression模型"""
        assert X_train.shape[0] == y_train.shape[0],           "the size of X_train must be equal to the size of y_train"
        assert n_iters >= 1
        def dJ_sgd(theta, X_b_i, y_i):
            return X_b_i * (X_b_i.dot(theta) - y_i) * 2.
        def sgd(X_b, y, initial_theta, n_iters=5, t0=5, t1=50):
            def learning_rate(t):
                return t0 / (t + t1)
            theta = initial_theta
            m = len(X_b)
            for i_iter in range(n_iters):  //双层循环,外层是将整个样本遍历几次,内层是不重复的一个一个的遍历样本
                indexes = np.random.permutation(m)
                X_b_new = X_b[indexes,:]
                y_new = y[indexes]
                for i in range(m):
                    gradient = dJ_sgd(theta, X_b_new[i], y_new[i])
                    theta = theta - learning_rate(i_iter * m + i) * gradient
            return theta
        X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
        initial_theta = np.random.randn(X_b.shape[1])
        self._theta = sgd(X_b, y_train, initial_theta, n_iters, t0, t1)
        self.intercept_ = self._theta[0]
        self.coef_ = self._theta[1:]
        return self

sklearn 中代码片

from sklearn.linear_model import SGDRegressor
sgd_reg = SGDRegressor()
sgd_reg.fit(x,y)
sgd_reg.score(x_test,y_test)
确定梯度计算的准确性,调试梯度下降法

其作用是用于判断求梯度的过程有没有错误,防止计算过程错误但是程序能够运行的情况,原理是用切线的斜率代替导数,用一小部分的样本用于测试,如果数学方法求导和该方法求导所得的结果相同,则程序没有错误

def J(theta, X_b, y):
    try:
        return np.sum((y - X_b.dot(theta))**2) / len(X_b)
    except:
        return float('inf')

def dJ_math(theta, X_b, y):
    return X_b.T.dot(X_b.dot(theta) - y) * 2. / len(y)

def dJ_debug(theta, X_b, y, epsilon=0.01):
    res = np.empty(len(theta))
    for i in range(len(theta)):
        theta_1 = theta.copy()
        theta_1[i] += epsilon
        theta_2 = theta.copy()
        theta_2[i] -= epsilon
        res[i] = (J(theta_1, X_b, y) - J(theta_2, X_b, y)) / (2 * epsilon)
    return res

def gradient_descent(dJ, X_b, y, initial_theta, eta, n_iters = 1e4, epsilon=1e-8):
    
    theta = initial_theta
    cur_iter = 0

    while cur_iter < n_iters:
        gradient = dJ(theta, X_b, y)
        last_theta = theta
        theta = theta - eta * gradient
        if(abs(J(theta, X_b, y) - J(last_theta, X_b, y)) < epsilon):
            break
            
        cur_iter += 1

    return theta
小批量梯度下降法

是前两种梯度下降法的结合
适用于所有函数类型

衡量线性回归的指标

均方误差、均方根误差、平均绝对误差用于衡量模型预测的j结果与真实值的差距:而==R2==用于衡量模型的准确度

  • 均方误差

MSE(Mean Squared Error)
在这里插入图片描述
相当于对损失函数求平均值,由此可保证测试标准与测试样本数无关
代码块:

def mean_squared_error(y_true,y_predict):
    return ((y_true-y_predict).dot(y_true-y_predict))/len(y_true)
    //或者是return np.sum(y_true == y_predict) / len(y_true)
  • 均方根误差

RMSE(Root Mean Squared Error),相当于对均方误差开方,可以消除量纲的影响
在这里插入图片描述
代码块:

def root_mean_squared_error(y_true,y_predict):
    return sqrt(mean_squared_error(y_true,y_predict))
     //或者是return sqrt(np.sum(y_true == y_predict) / len(y_true))
  • MAE

平均绝对误差(mean absolute error)
在这里插入图片描述
代码块:

def mean_absolute_error(y_true,y_predict):
    return np.sum(abs(y_true-y_predict))/len(y_true)
  • R2

在这里插入图片描述
代码块:

def r2_score(y_true,y_predict):
    return 1-mean_squared_error(y_true,y_predict)/np.var(y_true)
  • sklearn模块实现
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import mean_squared_error
from sklearn.metrics import r2_score

最小二乘法与梯度下降法计算过程中的区别,前者是解方程(组)求出使得损失函数导数为0的θ,而后者是求出损失函数关于θ的表达式,变换不同的θ值,让导数不断逼近0.
梯度下降法相比于最小二乘法的优势在于计算的速度,当样本量较大时,梯度下降法能远远增大速度

本项目是一个基于SSM(Spring+SpringMVC+MyBatis)后端框架与Vue.js前端框架开发的疫情居家办公系统。该系统旨在为居家办公的员工提供一个高效、便捷的工作环境,同时帮助企业更好地管理远程工作流程。项目包含了完整的数据库设计、前后端代码实现以及详细的文档说明,非常适合计算机相关专业的毕设学生和需要进行项目实战练习的Java学习者。 系统的核心功能包括用户管理、任务分配、进度跟踪、文件共享和在线沟通等。用户管理模块允许管理员创建和管理用户账户,分配不同的权限。任务分配模块使项目经理能够轻松地分配任务给团队成员,并设置截止日期。进度跟踪模块允许员工实时更新他们的工作状态,确保项目按计划进行。文件共享模块提供了一个安全的平台,让团队成员可以共享和协作处理文档。在线沟通模块则支持即时消息和视频会议,以增强团队之间的沟通效率。 技术栈方面,后端采用了Spring框架来管理业务逻辑,SpringMVC用于构建Web应用程序,MyBatis作为ORM框架简化数据库操作。前端则使用Vue.js来实现动态用户界面,搭配Vue Router进行页面导航,以及Vuex进行状态管理。数据库选用MySQL,确保数据的安全性和可靠性。 该项目不仅提供了一个完整的技术实现示例,还为开发者留下了扩展和改进的空间,可以根据实际需求添加新功能或优化现有功能。
本项目是一个基于SSM(Spring+SpringMVC+MyBatis)后端框架与Vue.js前端框架开发的网上球鞋竞拍系统。该项目旨在为球鞋爱好者提供一个便捷、高效的在线竞拍平台,用户可以在此平台上浏览、搜索、竞拍心仪的球鞋,并参与到各种有趣的竞拍活动中。 系统的主要功能包括用户注册登录、球鞋信息展示、竞拍活动创建与管理、实时竞拍以及交易安全保障等。用户可以通过注册账号后,浏览平台上发布的各类球鞋信息,包括品牌、型号、颜色、尺码以及当前竞拍状态等。系统支持用户创建和管理自己的竞拍活动,设定竞拍规则和时间,同时提供实时竞拍功能,确保公平、透明的交易过程。 在技术实现上,后端采用SSM框架进行开发,Spring负责业务逻辑层,SpringMVC处理Web请求,MyBatis进行数据库操作,保证了系统的稳定性和扩展性。前端则使用Vue.js框架,结合Axios进行数据请求,实现了前后端分离,提高了开发效率和用户体验。 数据库设计方面,系统采用了MySQL数据库,存储用户信息、球鞋信息、竞拍活动等数据,确保数据的安全性和完整性。此外,项目还包含了详细的文档资料,包括需求分析、系统设计、数据库设计以及测试报告等,为项目的实施和维护提供了有力的支持。 该项目不仅适合作为计算机相关专业学生的毕业设计题目,也适合Java学习者进行实战练习,通过在此基础上进行功能扩展和改进,可以进一步提升编程技能和项目管理能力。
【使用教程】 一、环境配置 1、建议下载anaconda和pycharm 在anaconda中配置好环境,然后直接导入到pycharm中,在pycharm中运行项目 anaconda和pycharm安装及环境配置参考网上博客,有很多博主介绍 2、在anacodna中安装requirements.txt中的软件包 命令为:pip install -r requirements.txt 或者改成清华源后再执行以上命令,这样安装要快一些 软件包都安装成功后才算成功 3、安装好软件包后,把anaconda中对应的python导入到pycharm中即可(不难,参考网上博客) 二、环境配置好后,开始训练(也可以训练自己数据集) 1、数据集准备 需要准备yolo格式的目标检测数据集,如果不清楚yolo数据集格式,或者有其他数据训练需求,请看博主yolo格式各种数据集集合链接:https://blog.csdn.net/DeepLearning_/article/details/127276492 里面涵盖了上百种yolo数据集,且在不断更新,基本都是实际项目使用。来自于网上收集、实际场景采集制作等,自己使用labelimg标注工具标注的。数据集质量绝对有保证! 本项目所使用的数据集,见csdn该资源下载页面中的介绍栏,里面有对应的下载链接,下载后可直接使用。 2、数据准备好,开始修改配置文件 参考代码中data文件夹下的banana_ripe.yaml,可以自己新建一个不同名称的yaml文件 train:训练集的图片路径 val:验证集的图片路径 names: 0: very-ripe 类别1 1: immature 类别2 2: mid-ripe 类别3 格式按照banana_ripe.yaml照葫芦画瓢就行,不需要过多参考网上的 3、修改train_dual.py中的配置参数,开始训练模型 方式一: 修改点: a.--weights参数,填入'yolov9-s.pt',博主训练的是yolov9-s,根据自己需求可自定义 b.--cfg参数,填入 models/detect/yolov9-c.yaml c.--data参数,填入data/banana_ripe.yaml,可自定义自己的yaml路径 d.--hyp参数,填入hyp.scratch-high.yaml e.--epochs参数,填入100或者200都行,根据自己的数据集可改 f.--batch-size参数,根据自己的电脑性能(显存大小)自定义修改 g.--device参数,一张显卡的话,就填0。没显卡,使用cpu训练,就填cpu h.--close-mosaic参数,填入15 以上修改好,直接pycharm中运行train_dual.py开始训练 方式二: 命令行方式,在pycharm中的终端窗口输入如下命令,可根据自己情况修改参数 官方示例:python train_dual.py --workers 8 --device 0 --batch 16 --data data/coco.yaml --img 640 --cfg models/detect/yolov9-c.yaml --weights '' --name yolov9-c --hyp hyp.scratch-high.yaml --min-items 0 --epochs 500 --close-mosaic 15 训练完会在runs/train文件下生成对应的训练文件及模型,后续测试可以拿来用。 三、测试 1、训练完,测试 修改detect_dual.py中的参数 --weights,改成上面训练得到的best.pt对应的路径 --source,需要测试的数据图片存放的位置,代码中的test_imgs --conf-thres,置信度阈值,自定义修改 --iou-thres,iou阈值,自定义修改 其他默认即可 pycharm中运行detect_dual.py 在runs/detect文件夹下存放检测结果图片或者视频 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值