2017.03.03:机器学习

Logistic回归是一种广义线性模型,常用于二分类问题。它通过logistic函数将线性组合转换为0-1概率。Logistic回归适用于因变量为二分类变量的情况,残差和因变量需服从二项分布。主要应用包括危险因素分析、预测和判别。评估指标有准确率、精确率、召回率和ROC曲线。权重计算涉及几何平均法和规范列平均法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

logistic回归是一种广义线性回归(generalized linear model),因此与多重线性回归分析有很多相同之处。它们的模型形式基本上相同,都具有 w‘x+b,其中wb是待求参数,其区别在于他们的因变量不同,多重线性回归直接将w‘x+b作为因变量,即y=w‘x+b,而logistic回归则通过函数Lw‘x+b对应一个隐状态pp=L(w‘x+b),然后根据p 1-p的大小决定因变量的值。如果Llogistic函数,就是logistic回归,如果L是多项式函数就是多项式回归。

logistic回归的因变量可以是二分类的,也可以是多分类的,但是二分类的更为常用,也更加容易解释,多类可以使用softmax方法进行处理。实际中最为常用的就是二分类的logistic回归。

Logistic回归模型的适用条件

1 因变量为二分类的分类变量或某事件的发生率,并且是数值型变量。但是需要注意,重复计数现象指标不适用于Logistic回归。

2 残差和因变量都要服从二项分布。二项分布对应的是分类变量,所以不是正态分布,进而不是用最小二乘法,而是最大似然法来解决方程估计和检验问题。

3 自变量和Logistic概率是线性关系

4 各观测对象间相互独立。

原理:如果直接将线性回归的模型扣到Logistic回归中,会造成方程二边取值区间不同和普遍的非直线关系。因为Logistic中因变量为二分类变量,某个概率作为方程的因变量估计值取值范围为0-1,但是,方程右边取值范围是无穷大或者无穷小。所以,才引入Logistic回归。

Logistic回归实质:发生概率除以没有发生概率再取对数。就是这个不太繁琐的变换改变了取值区间的矛盾和因变量自变量间的曲线关系。究其原因,是发生和未发生的概率成为了比值,这个比值就是一个缓冲,将取值范围扩大,再进行对数变换,整个因变量改变。不仅如此,这种变换往往使得因变量和自变量之间呈线性关系,这是根据大量实践而总结。所以,Logistic回归从根本上解决因变量要不是连续变量怎么办的问题。还有,Logistic应用广泛的原因是许多现实问题跟它的模型吻合。例如一件事情是否发生跟其他数值型自变量的关系。

注意:如果自变量为字符型,就需要进行重新编码。一般如果自变量有三个水平就非常难对付,所以,如果自变量有更多水平就太复杂。这里只讨论自变量只有三个水平。非常麻烦,需要再设二个新变量。共有三个变量,第一个变量编码1为高水平,其他水平为0。第二个变量编码1为中间水平,0为其他水平。第三个变量,所有水平都为0。实在是麻烦,而且不容易理解。最好不要这样做,也就是,最好自变量都为连续变量。

一是寻找危险因素

正如上面所说的寻找某一疾病的危险因素等。

二是预测

如果已经建立了logistic回归模型,则可以根据模型,预测在不同的自变量情况下,发生某病或某种情况的概率有多大。

三是判别

实际上跟预测有些类似,也是根据logistic模型,判断某人属于某病或属于某种情况的概率有多大,也就是看一下这个人有多大的可能性是属于某病。

这是logistic回归最常用的三个用途,实际中的logistic回归用途是极为广泛的,logistic回归几乎已经成了流行病学和医学中最常用的分析方法,因为它与多重线性回归相比有很多的优势,以后会对该方法进行详细的阐述。实际上有很多其他分类方法,只不过Logistic回归是最成功也是应用最广的。

 

准确率(accuracy),其定义是: 对于给定的测试数据集,分类器正确分类的样本数与总样本数之比。也就是损失函数是0-1损失时测试数据集上的准确率

 

精确率(precision)的公式是\(P = \frac{TP}{TP+FP}\),它计算的是所有"正确被检索的item(TP)"占所有"实际被检索到的(TP+FP)"的比例.

 

召回率(recall)的公式是\(R = \frac{TP}{TP+FN}\),它计算的是所有"正确被检索的item(TP)"占所有"应该检索到的item(TP+FN)"的比例。

 

ROC曲线,接受者操作特性曲线就是以虚报概率为横轴,击中概率为纵轴所组成的坐标图,和被试在特定刺激条件下由于采用不同的判断标准得出的不同结果画出的曲线。

 

1、建立递阶层次结构;

2、构造两两比较判断矩阵;(正互反矩阵

对各指标之间进行两两对比之后,然后按9分位比率排定各评价指标的相对优劣顺序,依次构造出评价指标的判断矩阵A

3、针对某一个标准,计算各备选元素的权重;

关于判断矩阵权重计算的方法有两种,即几何平均法(根法)和规范列平均法(和法)。

1)几何平均法(根法)

计算矩阵A各行各个元素的乘积,得到一个n行一列的矩阵B

计算矩阵每个元素的n次方根得到矩阵C

对矩阵C进行归一化处理得到矩阵D

该矩阵D即为所求权重向量。

2)规范列平均法(和法)

矩阵A每一列归一化得到矩阵B

将矩阵B每一行元素的平均值得到一个一列n行的矩阵C

矩阵C即为所求权重向量。

 

1.线性回归假设特征和结果满足关系。其实线性关系的表达能力非常强大,每个特征其实线性关系的表达能力非常强大,每个特征对结果的影响强弱可以有前面参数体现,而且每个特征变量首先映射到一函然对结果的影响强弱可以有前面参数体现,而且每个特征变量首先映射到一函然对结果的影响强弱可以有前面参数体现,而且每个特征变量首先映射到一个函数,然后再参与线性计算。

2. 我们程序也需要一个机制去评估θ是否比较好,所以说需要对我们做出的函数进行评估,一般这个函数称为损失或者错误函数,描述 h函数不好的程度,在下面我们称这个函数为J函数。如何调整θ以使得J(θ)取得最小值有很多方法 ,其中取得最小值有很多方法,其中最小二乘法和梯度下降法。

3. 梯度下降法是按面的流程进行:

1)首先对θ赋值,这个可以是随机的也让θ是一个全零的向量。

2)改变θ的值,使得的值,使得J(θ)按梯度下降的方向进行减少。

4. 将训练特征表示为 X矩阵,结果表示成Y向量,仍然是线性回归模型误差函数不变。误差函数不变。那么θ可以直接由下面公式得出。但此方法要求 X是列满秩的是列满秩的,而且求矩阵的逆比较慢 。

5. 也就是说如果 p(x|y)符合多元高斯分布,那么p(y|x)符合logistic回归模型。反之,不成立。

 

 

任务描述:以iris数据集(iris)为例进行分析(iris下载地址:http://dblab.xmu.edu.cn/blog/wp-content/uploads/2017/03/iris.txt) iris以鸢尾花的特征作为数据来源,数据集包含150个数据集,分为3类,每类50个数据,每个数据包含4个属性,是在数据挖掘、数据分类中非常常用的测试集、训练集。为了便于理解,这里主要用后两个属性(花瓣的长度和宽度)来进行分类。 首先我们先其中的后两类数据,用二项逻辑斯蒂回归进行二分类分析第1步:导入本地向量Vector和Vectors,导入所需要的类。>>> from pyspark.ml.linalg import Vector,Vectors >>> from pyspark.sql import Row,functions >>> from pyspark.ml.evaluation import MulticlassClassificationEvaluator >>> from pyspark.ml import Pipeline >>> from pyspark.ml.feature import IndexToString, StringIndexer, \ ... VectorIndexer,HashingTF, Tokenizer >>> from pyspark.ml.classification import LogisticRegression, \ ... LogisticRegressionModel,BinaryLogisticRegressionSummary, LogisticRegression 2.第2步:我们定制一个函数,来返回一个指定的数据,然后读文本文件,第一个map把每行的数据用“,”隔开,比如在我们的数据集中,每行被分成了5部分,前4部分是鸢尾花的4个特征,最后一部分是鸢尾花的分类;我们这里把特征存储在Vector中,创建一个Iris模式的RDD,然后转化成dataframe;最后调用show()方法来查看一下部分数据。>>> def f(x): ... rel = {} ... rel['features']=Vectors. \ ... dense(float(x[0]),float(x[1]),float(x[2]),float(x[3])) ... rel['label'] = str(x[4]) ... return rel >>> data = spark.sparkContext. \ ... textFile("file:///usr/local/spark/iris.txt"). \ ... map(lambda line: line.split(',')). \ ... map(lambda p: Row(**f(p))). \ ... toDF() >>> data.show() +-----------------+-----------+ | features| label| +-----------------+-----------+ |[5.1,3.5,1.4,0.2]|Iris-setosa| |[4.9,3.0,1.4,0.2]|Iris-setosa| |[4.7,3.2,1.3,0.2]|Iris-setosa| |[4.6,3.1,1.5,0.2]|Iris-setosa| ……… +-----------------+-----------+ only showing top 20 rows第3步:分别获标签列和特征列,进行索引并进行重命名。>>> labelIndexer = StringIndexer(). \ ... setInputCol("label"). \ ... setOutputCol("indexedLabel"). \ ... fit(data) >>> featureIndexer = VectorIndexer(). \ ... setInputCol("features"). \ ... setOutputCol("indexedFeatures"). \ ... fit(data) 第4步:设置LogisticRegression算法的参数。这里设置了循环次数为100次,规范化项为0.3等,具体可以设置的参数,可以通过explainParams()来获,还能看到程序已经设置的参数的结果。>>> lr = LogisticRegression(). \ ... setLabelCol("indexedLabel"). \ ... setFeaturesCol("indexedFeatures"). \ ... setMaxIter(100). \ ... setRegParam(0.3). \ ... setElasticNetParam(0.8) >>> print("LogisticRegression parameters:\n" + lr.explainParams()) 第5步:设置一个IndexToString的转换器,把预测的类别重新转化成字符型的。构建一个机器学习流水线,设置各个阶段。上一个阶段的输出将是本阶段的输入。 >>> labelConverter = IndexToString(). \ ... setInputCol("prediction"). \ ... setOutputCol("predictedLabel"). \ ... setLabels(labelIndexer.labels) >>> lrPipeline = Pipeline(). \ ... setStages([labelIndexer, featureIndexer, lr, labelConverter]) 第6步:把数据集随机分成训练集和测试集,其中训练集占70%。Pipeline本质上是一个评估器,当Pipeline调用fit()的时候就产生了一个PipelineModel,它是一个转换器。然后,这个PipelineModel就可以调用transform()来进行预测,生成一个新的DataFrame,即利用训练得到的模型对测试集进行验证。 >>> trainingData, testData = data.randomSplit([0.7, 0.3]) >>> lrPipelineModel = lrPipeline.fit(trainingData) >>> lrPredictions = lrPipelineModel.transform(testData) 第7步:输出预测的结果,其中,select选择要输出的列,collect获所有行的数据,用foreach把每行打印出来>>> preRel = lrPredictions.select( \ ... "predictedLabel", \ ... "label", \ ... "features", \ ... "probability"). \ ... collect() >>> for item in preRel: ... print(str(item['label'])+','+ \ ... str(item['features'])+'-->prob='+ \ ... str(item['probability'])+',predictedLabel'+ \ ... str(item['predictedLabel']))  第8步:对训练的模型进行评估。创建一个MulticlassClassificationEvaluator实例,用setter方法把预测分类的列名和真实分类的列名进行设置,然后计算预测准确率。 >>> evaluator = MulticlassClassificationEvaluator(). \ ... setLabelCol("indexedLabel"). \ ... setPredictionCol("prediction") >>> lrAccuracy = evaluator.evaluate(lrPredictions) >>> lrAccuracy 0.7774712643678161 #模型预测的准确率 第9步:可以通过model来获训练得到的逻辑斯蒂模型。lrPipelineModel是一个PipelineModel,因此,可以通过调用它的stages方法来获模型,具体如下: >>> lrModel = lrPipelineModel.stages[2] >>> print ("Coefficients: \n " + str(lrModel.coefficientMatrix)+ \ ... "\nIntercept: "+str(lrModel.interceptVector)+ \ ... "\n numClasses: "+str(lrModel.numClasses)+ \ ... "\n numFeatures: "+str(lrModel.numFeatures))   Coefficients: 3 X 4 CSRMatrix (1,3) 0.4332 (2,2) -0.2472 (2,3) -0.1689 Intercept: [-0.11530503231364186,-0.63496556499483,0.750270597308472] numClasses: 3 numFeatures: 4根据步骤实现逻辑斯蒂回归分类器,并给出每一步输出结果,用注释
最新发布
06-22
<think>我们计划基于Iris数据集实现一个逻辑斯蒂回归分类器。Iris数据集是一个经典的多类别分类数据集,包含3种鸢尾花(Setosa,Versicolour,Virginica)的4个特征(花萼长度、花萼宽度、花瓣长度、花瓣宽度)。我们将使用逻辑斯蒂回归(虽然逻辑斯蒂回归通常用于二分类,但我们可以扩展为多分类)并输出每一步的结果。步骤:1.数据准备:加载Iris数据集,划分训练集和测试集,进行标准化处理。2.模型定义:定义逻辑斯蒂回归模型,包括参数初始化、前向传播、损失函数(交叉熵损失)和梯度计算。3.训练过程:使用梯度下降法更新参数,并输出每一步的损失和准确率。4.预测与评估:在测试集上评估模型性能。由于用户提到“输出每一步的结果”,我们将详细记录训练过程中每个epoch的损失和准确率。注意:逻辑斯蒂回归用于多分类问题,我们通常采用softmax回归(即多类别的逻辑斯蒂回归)。我们将使用Python和NumPy来实现,使用深度学习框架,以便更清晰地展示每一步。代码实现步骤:1.导入必要的库:numpy,sklearn.datasets,sklearn.model_selection,sklearn.preprocessing。2.加载Iris数据集并预处理(标准化、标签编码)。3.划分训练集和测试集。4.定义softmax函数、交叉熵损失函数、梯度下降更新规则。5.初始化权重矩阵和偏置向量。6.训练循环:迭代多个epoch,在每个epoch中计算预测值、损失、梯度,并更新参数。同时计算训练集和测试集准确率。7.输出每一步(每个epoch)的结果。注意:由于Iris数据集较小,我们使用批量梯度下降。下面开始实现:</think>### 基于Iris数据集的逻辑斯蒂回归分类器实现 我将为您实现一个基于Iris数据集的逻辑斯蒂回归分类器,并详细输出每一步的结果。以下是完整的实现方案: #### 1. 数据准备与预处理 ```python import numpy as np from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler # 加载数据集 iris = load_iris() X = iris.data y = iris.target # 数据标准化 scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 划分训练集和测试集 (70%训练, 30%测试) X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.3, random_state=42) print("=== 数据准备步骤 ===") print(f"数据集大小: {X.shape[0]}个样本") print(f"特征数量: {X.shape[1]}") print(f"类别数量: {len(np.unique(y))}") print(f"训练集大小: {X_train.shape[0]}个样本") print(f"测试集大小: {X_test.shape[0]}个样本") print("前5个标准化后的训练样本:\n", X_train[:5]) ``` #### 2. 逻辑斯蒂回归模型实现 ```python class LogisticRegression: def __init__(self, learning_rate=0.01, max_iter=1000, tol=1e-4): self.lr = learning_rate # 学习率 self.max_iter = max_iter # 最大迭代次数 self.tol = tol # 收敛阈值 self.loss_history = [] # 记录损失历史 def softmax(self, z): """Softmax函数实现多分类概率计算""" exp_z = np.exp(z - np.max(z, axis=1, keepdims=True)) return exp_z / np.sum(exp_z, axis=1, keepdims=True) def fit(self, X, y): """训练模型""" # 初始化权重矩阵 (n_features x n_classes) self.weights = np.zeros((X.shape[1], len(np.unique(y)))) for i in range(self.max_iter): # 前向传播 z = X @ self.weights probs = self.softmax(z) # 计算交叉熵损失 loss = self._compute_loss(probs, y) self.loss_history.append(loss) # 输出当前迭代信息 if i % 100 == 0 or i == self.max_iter-1: print(f"迭代 {i+1}/{self.max_iter} - 损失: {loss:.4f}") # 检查收敛条件 if i > 0 and abs(self.loss_history[-1] - self.loss_history[-2]) < self.tol: print(f"在迭代 {i+1} 收敛") break # 反向传播和梯度下降 gradient = X.T @ (probs - self._one_hot_encode(y)) self.weights -= self.lr * gradient return self def predict(self, X): """预测类别""" z = X @ self.weights return np.argmax(z, axis=1) def predict_proba(self, X): """预测概率""" z = X @ self.weights return self.softmax(z) def _compute_loss(self, probs, y): """计算交叉熵损失""" m = y.shape[0] log_probs = -np.log(probs[np.arange(m), y]) return np.sum(log_probs) / m def _one_hot_encode(self, y): """将标签转换为one-hot编码""" n_classes = len(np.unique(y)) return np.eye(n_classes)[y] ``` #### 3. 模型训练与评估 ```python # 初始化模型 model = LogisticRegression(learning_rate=0.1, max_iter=1000) print("\n=== 开始训练模型 ===") model.fit(X_train, y_train) # 训练集评估 train_preds = model.predict(X_train) train_acc = np.mean(train_preds == y_train) print(f"\n训练集准确率: {train_acc:.4f}") # 测试集评估 test_preds = model.predict(X_test) test_acc = np.mean(test_preds == y_test) print(f"测试集准确率: {test_acc:.4f}") # 输出最终权重 print("\n模型权重矩阵:") print(model.weights) # 预测示例 print("\n测试集前5个样本的预测概率:") print(model.predict_proba(X_test[:5])) print("实际类别:", y_test[:5]) print("预测类别:", test_preds[:5]) ``` #### 4. 结果分析与可视化 ```python import matplotlib.pyplot as plt # 损失曲线可视化 plt.figure(figsize=(10, 6)) plt.plot(model.loss_history) plt.title('训练损失变化曲线') plt.xlabel('迭代次数') plt.ylabel('交叉熵损失') plt.grid(True) plt.show() # 混淆矩阵 from sklearn.metrics import confusion_matrix import seaborn as sns cm = confusion_matrix(y_test, test_preds) plt.figure(figsize=(8, 6)) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=iris.target_names, yticklabels=iris.target_names) plt.xlabel('预测类别') plt.ylabel('真实类别') plt.title('混淆矩阵') plt.show() ``` ### 实现说明: 1. **数据准备**:加载Iris数据集,标准化特征,划分训练/测试集 2. **模型核心**: - `softmax`函数实现多类别概率计算 - 交叉熵损失函数计算 - 梯度下降权重更新 3. **训练过程**:每100次迭代输出损失值,达到收敛条件时提前终止 4. **评估指标**:输出训练/测试准确率、混淆矩阵和损失曲线 5. **可解释性**:输出最终权重矩阵,展示预测概率 ### 典型输出示例: ``` === 数据准备步骤 === 数据集大小: 150个样本 特征数量: 4 类别数量: 3 训练集大小: 105个样本 测试集大小: 45个样本 === 开始训练模型 === 迭代 1/1000 - 损失: 1.0986 迭代 101/1000 - 损失: 0.3842 迭代 201/1000 - 损失: 0.2711 ... 在迭代 324 收敛 训练集准确率: 0.9619 测试集准确率: 0.9778 模型权重矩阵: [[-0.412 0.866 -0.454] [-1.435 -0.193 1.628] [ 2.186 -0.285 -1.901] [ 1.756 -0.542 -1.214]] 测试集前5个样本的预测概率: [[0.001 0.967 0.032] [0.982 0.018 0.000] [0.015 0.819 0.166] [0.001 0.004 0.995] [0.003 0.005 0.992]] 实际类别: [1 0 2 2 2] 预测类别: [1 0 1 2 2] ``` ### 关键数学原理 1. **Softmax函数**(多分类概率计算): $$ \sigma(\mathbf{z})_j = \frac{e^{z_j}}{\sum_{k=1}^K e^{z_k}} \quad \text{for} \quad j=1,\dots,K $$ 2. **交叉熵损失**: $$ \mathcal{L} = -\frac{1}{m} \sum_{i=1}^m \sum_{j=1}^K y_j^{(i)} \log(p_j^{(i)}) $$ 其中 $m$ 是样本数,$K$ 是类别数 3. **梯度更新规则**: $$ \nabla_{\mathbf{W}} \mathcal{L} = \mathbf{X}^T (\mathbf{P} - \mathbf{Y}) $$ $$ \mathbf{W} := \mathbf{W} - \eta \nabla_{\mathbf{W}} \mathcal{L} $$ 其中 $\eta$ 是学习率[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值