|
💥项目专栏:【Python实现经典机器学习算法】附代码+原理介绍文章目录前言一、基于原生Python实现逻辑回归算法二、逻辑回归模型的算法原理三、算法实现3.1导包3.2定义随机数种子3.3定义逻辑回归模型3.3.1模型训练3.3.1.1初始化参数3.3.1.2正向传播3.3.1.3损失函数3.3.1.4反向传播3.3.2模型预测3.3.3模型分数3.3.4LogisticRegression模型3.4导入数据3.5划分训练集、测试集3.6模型训练3.7打印结果3.8可视化决策边界完整源码前言👑最近粉丝群中很多朋友私信咨询一些决策树、逻辑回归等机器学习相关的编程问题,为了能更清晰的说明,所以建立了本专栏专门记录基于原生Python实现一些入门必学的机器学习算法,帮助广大零基础用户达到轻松入门,为了更深刻算法的基本原理,本专栏没有采用第三方库来实现(sklearn),而是采用原生Python自己复现相关算法,从而帮助新手理解算法的内部细节。👑本专栏适用人群:🚨🚨🚨机器学习初学者,刚刚接触sklearn的用户群体,专栏将具体讲解如何基于原生Python来实现一些经典机器学习算法,快速让新手小白能够对机器学习算法有更深刻的理解。👑本专栏内包含基于原生Python从零实现经典机器学习算法,通过自复现帮助新手小白对算法有更深刻的认识,理论与实践相结合,每一篇文章都附带有完整的代码+原理讲解。🚨我的项目环境:平台:Windows11语言环境:Python3.7编译器:JupyterLabPandas:1.3.5Numpy:1.19.3Scipy:1.7.3Matplotlib:3.1.3💥项目专栏:【Python实现经典机器学习算法】附代码+原理介绍一、基于原生Python实现逻辑回归算法逻辑回归是一种经典机器学习分类算法,它被广泛应用于二元分类问题中,该算法的目的是预测二元输出变量(比如0和1),逻辑回归算法有很多应用,比如预测股票市场、客户购买行为、疾病诊断等等。它被广泛应用于医学、金融、社交网络、搜索引擎等各个领域。本篇文章我们采用Python语言实现经典的机器学习算法LogisticRegression,作为该专栏的第一篇文章,本篇将💎详细介绍项目的每个实现部分以及细节处理,帮助新手小白快速建立起机器学习算法训练的框架。二、逻辑回归模型的算法原理逻辑回归(LogisticRegression)是一种广泛使用的分类算法,它的主要思想是将输入变量的线性组合映射到0到1之间的概率,用于预测二元输出变量的概率。以下是逻辑回归模型的算法原理:假设我们有一个二元分类问题,需要预测一个样本属于两个类别中的哪一个。逻辑回归模型使用一个参数化函数来计算给定输入变量的输出概率。该函数称为sigmoid函数,它将输入变量的线性组合映射到0到1之间的值,表示预测样本属于正例的概率。sigmoid函数的数学形式为:g(z)=11+e−zg(z)=\frac{1}{1+e^{-z}}g(z)=1+e−z1其中,z是输入变量的线性组合,可以表示为:z=b+w1x1+w2x2+...+wnxnz=b+w_1x_1+w_2x_2+...+w_nx_nz=b+w1x1+w2x2+...+wnxn其中,wiw_iwi是模型的权重(即系数),xix_ixi是输入变量的值。训练模型的过程就是通过最大化似然函数来估计模型的权重。似然函数是一个关于模型参数的函数,表示给定模型下,样本的概率。在逻辑回归中,似然函数可以表示为:L(w)=∏i=1ng(zi)yi(1−g(zi))1−yiL(w)=\prod_{i=1}^ng(z_i)^{y_i}(1-g(z_i))^{1-y_i}L(w)=∏i=1ng(zi)yi(1−g(zi))1−yi其中,ziz_izi是第i个样本的线性组合,yiy_iyi是对应的类别标签(0或1)。为了最大化似然函数,我们可以使用梯度下降算法来更新模型的权重。梯度下降算法通过反复迭代来最小化损失函数,直到找到最优解。损失函数通常使用对数损失函数(logloss)来衡量模型的性能。对数损失函数可以表示为:J(w)=−1n∑i=1nyilogg(zi)+(1−yi)log(1−g(zi))J(w)=-\frac{1}{n}\sum_{i=1}^ny_i\logg(z_i)+(1-y_i)\log(1-g(z_i))J(w)=−n1∑i=1nyilogg(zi)+(1−yi)log(1−g(zi))其中,ziz_izi是第i个样本的线性组合,yiy_iyi是对应的类别标签(0或1)。训练模型后,我们可以使用模型来预测新的样本的类别标签。预测类别标签的方法是,将新样本的特征向量代入sigmoid函数,计算输出概率,如果概率大于0.5,则预测为正例,否则预测为负例。逻辑回归模型简单而直观,易于理解和实现,常用于二元分类问题的建模三、算法实现本部分将讲解如何使用原生Python来实现逻辑回归算法,本文并没有使用sklearn直接调用定义模型,而是采用自己复现,因为这样才能够帮新手小白理解算法内部的具体流程。注:本文复现的算法为逻辑回归算法的阉割版(为了刚入门的同学更容易理解),相对于sklearn框架实现的算法相对简略,但保留了算法的核心部分,这是因为在初学期间应更注重算法的主干到底做了什么事,对于一些小细节以及各种变体以及算法优化策略这些应在熟悉该算法之后再考虑。3.1导包对于本项目主要使用到的第三方库有以下几种,都是比较常见的numpy:常见的科学计算库matplotlib:进行绘图使用sklearn.datasets:导入训练需要的数据集train_test_split:划分训练集和测试集importnumpyasnpimportmatplotlib.pyplotaspltfromsklearn.datasetsimportload_irisfromsklearn.model_selectionimporttrain_test_split12343.2定义随机数种子在机器学习任务中,随机数种子的作用是确保实验结果的可重复性。具体来说,机器学习算法中通常会涉及到一些随机性,比如随机初始化参数、随机选择训练样本等,这些随机性会导致同一份代码运行多次得到的结果不一定完全相同。通过设定随机数种子,可以使得同一份代码在不同的时间运行得到的随机结果是相同的,从而确保实验结果的可重复性。这对于算法的评估和比较非常重要,因为它能够消除随机性带来的误差和不确定性,使得实验结果更加准确和可信。需要注意的是,在使用随机数种子的同时,应该确保数据集、算法和参数设置等都是相同的,才能保证结果的可重复性。#设置随机种子seed_value=2023np.random.seed(seed_value)1233.3定义逻辑回归模型为了更容易理解,本文定义逻辑回归模型的方式和sklearn封装的算法一致,都是定义fit、predict、score接口。逻辑回归模型的训练过程可以分为以下几个步骤:数据预处理:首先需要对数据进行预处理,包括数据清洗、特征选择、特征缩放等。确保数据的质量和可用性。模型初始化:根据数据集的特征数量初始化模型参数,即权重和偏置。前向传播:将训练数据集中的每个样本的特征向量乘以模型的权重,再加上偏置,得到线性组合。将线性组合输入到sigmoid函数中,得到该样本属于正例的概率。计算损失函数:使用对数损失函数来衡量模型的性能,该损失函数的定义在前面已经介绍过了。需要对所有训练样本的损失函数进行求和,并除以样本数量,得到平均损失函数。反向传播:使用梯度下降算法来最小化损失函数。首先需要计算损失函数对模型参数的偏导数,即梯度。然后,使用梯度下降算法来更新模型的权重和偏置。重复步骤3-5,直到达到预定的迭代次数或损失函数达到某个阈值。模型评估:使用测试数据集来评估训练得到的模型的性能。可以使用多个指标来评估模型的性能,如准确率、精确率、召回率、F1得分等。模型调优:根据评估结果来调整模型的参数,如学习率、迭代次数等,以提高模型的性能。在实际训练过程中,可以使用各种优化算法来加速收敛速度,如随机梯度下降(SGD)、Adam等。此外,还可以使用正则化方法来防止模型过拟合,如L1正则化、L2正则化等。上面是逻辑回归比较详细的训练过程,但是对于刚入门的小伙伴可以选择性的理解,可以先理解算法的基本骨架,在此基础上再去添枝加叶,所以本文在实现方面也是保留了核心部分,一些不必要的部分没有实现。3.3.1模型训练该部分主要定义模型的执行逻辑,也就是给定数据模型到底是如何训练的,对于逻辑回归模型主要包括三个部分:初始化参数、正向传播、计算损失、反向传播。模型初始化:根据数据集的特征数量初始化模型参数,即权重和偏置。前向传播:将训练数据集中的每个样本的特征向量乘以模型的权重,再加上偏置,得到线性组合。将线性组合输入到sigmoid函数中,得到该样本属于正例的概率。计算损失函数:使用对数损失函数来衡量模型的性能,该损失函数的定义在前面已经介绍过了。需要对所有训练样本的损失函数进行求和,并除以样本数量,得到平均损失函数。反向传播:使用梯度下降算法来最小化损失函数。首先需要计算损失函数对模型参数的偏导数,即梯度。然后,使用梯度下降算法来更新模型的权重和偏置。重复步骤2-4,直到达到预定的迭代次数或损失函数达到某个阈值。3.3.1.1初始化参数对于逻辑回归使用到的公式为y=b+w1x1+w2x2+...+wnxny=b+w_1x_1+w_2x_2+...+w_nx_ny=b+w1x1+w2x2+...+wnxn,对于该算法的核心就是学习到权重系数www,为此我们需要定义两个参数,分别为权重w和偏置b可以使用如下代码来初始化模型的可训练参数:#初始化参数self.weights=np.random.randn(X.shape[1])self.bias=01233.3.1.2正向传播由于逻辑回归是进行二分类,所以我们希望得到对应的概率,那么我们需要将计算的结果送入到Sigmoid中得到对应的概率值,对应公式为y^=sigmoid(y)=sigmoid(w∗x+b)=1(1+expw∗x+b)\haty=sigmoid(y)=sigmoid(w*x+b)=\frac{1}{(1+exp^{w*x+b})}y^=sigmoid(y)=sigmoid(w∗x+b)=(1+expw∗x+b)1。#计算sigmoid函数的预测值,y_hat=sigmoid(w*x+b)y_hat=sigmoid(np.dot(X,self.weights)+self.bias)123.3.1.3损失函数训练模型的目的就是希望通过模型预测的值更加接近真实的值,所以这里为了衡量预测值和真实值之间的差异,需要定义一个损失函数有些文章里也叫做代价函数,这里使用的是交叉熵函数(CrossEntropy)loss=−1n∑yln(y^)+(1−y)ln(1−y^)loss=-\frac{1}{n}\sumyln(\haty)+(1-y)ln(1-\haty)loss=−n1∑yln(y^)+(1−y)ln(1−y^)对于该损失通过如下代码实现:#计算损失函数loss=(-1/len(X))*np.sum(y*np.log(y_hat)+(1-y)*np.log(1-y_hat))123.3.1.4反向传播逻辑回归中使用的参数更新方法是梯度下降法,不断将当前参数减去损失对应的梯度,让模型向着损失减小的方向发展。在逻辑回归中,我们使用sigmoid函数将线性输出映射到[0,1]之间的概率值。如果我们定义代价函数为交叉熵,那么我们可以使用梯度下降算法更新权重参数。具体地,我们首先通过前向传播计算模型的预测值和代价函数的值。然后,我们使用反向传播算法计算代价函数相对于每个权重参数的导数,以便我们可以知道哪些权重需要更新。最后,我们使用梯度下降算法更新权重参数,使代价函数最小化。具体来说,在反向传播中,我们需要计算代价函数相对于每个权重参数的偏导数。对于逻辑回归模型,这可以通过链式法则来计算。#计算梯度dw=(1/len(X))*np.dot(X.T,(y_hat-y))db=(1/len(X))*np.sum(y_hat-y)#更新参数self.weights-=self.learning_rate*dwself.bias-=self.learning_rate*db12345673.3.2模型预测对于逻辑回归的正向传播是计算出对应的概率,为了得到该样本对应的类别,我们需要将其二值化,即大于0.5将其转化为类别1,小于0.5将其转化为类别0。使用如下代码实现预测过程:#预测defpredict(self,X):y_hat=sigmoid(np.dot(X,self.weights)+self.bias)y_hat[y_hat>=0.5]=1y_hat[y_hat=0.5]=1y_hat[y_hat>>训练集Accuracy:1.0>>>测试集Accuracy:0.95652173913043481234567891011123.8可视化决策边界为了可视化模型的分类效果,该部分实现了如下代码来绘制决策边界查看模型的分类效果如何,决策边界图如下:#可视化决策边界x1_min,x1_max=X[:,0].min()-0.5,X[:,0].max()+0.5x2_min,x2_max=X[:,1].min()-0.5,X[:,1].max()+0.5xx1,xx2=np.meshgrid(np.linspace(x1_min,x1_max,100),np.linspace(x2_min,x2_max,100))Z=model.predict(np.c_[xx1.ravel(),xx2.ravel()])Z=Z.reshape(xx1.shape)plt.contourf(xx1,xx2,Z,cmap=plt.cm.Spectral)plt.scatter(X[:,0],X[:,1],c=y,cmap=plt.cm.Spectral)plt.xlabel("Sepallength")plt.ylabel("Sepalwidth")plt.savefig('a.png',dpi=720)plt.show()123456789101112完整源码注意🚨🚨🚨:由于是针对于新手小白入门的系列专栏,所以代码并没有采用开发大型项目的方式,而是python单文件实现,这样能够帮助新人一键复制调试运行,不需要理解复杂的项目构造,另外一点就是由于是帮助新人理解机器学习算法基本训练预测过程,所以源码仅包含了算法的基本框架结构,有些地方实现略有简陋,有能力的小伙伴可以根据自己的能力在此基础上进行修改,尝试更多的参数,以及进行分文件编写(模型训练、模型测试、定义模型、绘制图像)达到项目开发流程。importnumpyasnpimportmatplotlib.pyplotaspltfromsklearn.datasetsimportload_irisfromsklearn.model_selectionimporttrain_test_split#设置随机种子seed_value=2023np.random.seed(seed_value)#Sigmoid激活函数defsigmoid(z):return1/(1+np.exp(-z))#定义逻辑回归算法classLogisticRegression:def__init__(self,learning_rate=0.003,iterations=100):self.learning_rate=learning_rate#学习率self.iterations=iterations#迭代次数deffit(self,X,y):#初始化参数self.weights=np.random.randn(X.shape[1])self.bias=0#梯度下降foriinrange(self.iterations):#计算sigmoid函数的预测值,y_hat=w*x+by_hat=sigmoid(np.dot(X,self.weights)+self.bias)#计算损失函数loss=(-1/len(X))*np.sum(y*np.log(y_hat)+(1-y)*np.log(1-y_hat))#计算梯度dw=(1/len(X))*np.dot(X.T,(y_hat-y))db=(1/len(X))*np.sum(y_hat-y)#更新参数self.weights-=self.learning_rate*dwself.bias-=self.learning_rate*db#打印损失函数值ifi%10==0:print(f"Lossafteriteration{i}:{loss}")#预测defpredict(self,X):y_hat=sigmoid(np.dot(X,self.weights)+self.bias)y_hat[y_hat>=0.5]=1y_hat[y_hat
|
|