实现一个简单的机器学习分类器:从零开始构建逻辑回归模型
在当今的科技世界中,机器学习(Machine Learning, ML)已经成为了处理复杂数据问题的关键技术之一。它广泛应用于推荐系统、图像识别、自然语言处理等领域。而逻辑回归(Logistic Regression)作为最基础且重要的机器学习算法之一,尽管名字中有“回归”二字,但实际上主要用于解决二分类问题。本文将带你深入了解逻辑回归的基本原理,并通过Python代码实现一个简单但完整的逻辑回归分类器。
逻辑回归原理简介
(一)线性回归与逻辑回归的区别
线性回归旨在找到一条直线(在一维情况下)或超平面(在多维情况下),使得预测值尽可能接近实际观测值。其输出是连续数值。然而,在面对二分类任务时,我们需要的是一个能给出类别概率的结果,例如对于垃圾邮件检测,我们想知道一封邮件属于垃圾邮件的概率是多少。这时逻辑回归就派上了用场。
逻辑回归通过引入Sigmoid函数(也称为Logistic函数)来将线性回归的结果映射到0 - 1之间,从而得到概率值。Sigmoid函数的形式为:[ \sigma(z) = \frac{1}{1 + e^{-z}} ]其中(z)可以看作是线性组合的结果,即(z = w^Tx + b),(w)是权重向量,(x)是输入特征向量,(b)是偏置项。
(二)损失函数
为了训练逻辑回归模型,我们需要定义一个损失函数来衡量模型预测值与真实标签之间的差异。常用的损失函数是交叉熵损失(Cross - Entropy Loss)。对于单个样本而言,如果真实标签为(y)(取值为0或1),预测概率为(\hat{y}),那么交叉熵损失为:[ L(y,\hat{y}) = -[y\log(\hat{y}) + (1 - y)\log(1 - \hat{y})] ]对于整个训练集,我们将所有样本的损失求和并取平均,得到最终的损失函数:[ J(w,b) = -\frac{1}{m}\sum_{i = 1}^{m}[y_i\log(\hat{y}_i) + (1 - y_i)\log(1 - \hat{y}_i)] ]其中(m)表示样本数量。
使用Python实现逻辑回归分类器
(一)导入必要的库
import numpy as npimport matplotlib.pyplot as pltfrom sklearn.datasets import make_classification
这里我们使用numpy
来进行矩阵运算等操作;matplotlib
用于可视化结果;sklearn.datasets.make_classification
可以方便地生成模拟的二分类数据集供我们实验。
(二)生成数据集
# 生成一个包含2个类别的数据集,每个样本有2个特征X, y = make_classification(n_samples=100, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, class_sep=1.5, random_state=42)plt.scatter(X[:, 0], X[:, 1], c=y, cmap='coolwarm')plt.show()
这段代码生成了一个具有明显可分性的二分类数据集,并绘制出散点图以便观察数据分布情况。
(三)初始化参数
def initialize_parameters(input_size): """ 初始化权重和偏置 :param input_size: 输入特征数量 :return: 权重向量w和偏置b """ w = np.zeros((input_size, 1)) b = 0.0 return w, b
(四)Sigmoid函数
def sigmoid(z): """ Sigmoid激活函数 :param z: 线性组合结果 :return: 概率值 """ return 1 / (1 + np.exp(-z))
(五)前向传播
def forward_propagation(X, w, b): """ 前向传播计算预测概率 :param X: 输入特征矩阵 :param w: 权重向量 :param b: 偏置 :return: 预测概率和线性组合结果 """ m = X.shape[0] z = np.dot(X, w) + b A = sigmoid(z) return A, z
(六)计算损失
def compute_cost(A, y): """ 计算交叉熵损失 :param A: 预测概率 :param y: 真实标签 :return: 平均损失 """ m = y.shape[0] cost = -1 / m * np.sum(y * np.log(A) + (1 - y) * np.log(1 - A)) return cost
(七)反向传播
def backward_propagation(X, A, y): """ 反向传播计算梯度 :param X: 输入特征矩阵 :param A: 预测概率 :param y: 真实标签 :return: 权重和偏置的梯度 """ m = y.shape[0] dw = 1 / m * np.dot(X.T, (A - y)) db = 1 / m * np.sum(A - y) return dw, db
(八)更新参数
def update_parameters(w, b, dw, db, learning_rate): """ 使用梯度下降法更新参数 :param w: 权重向量 :param b: 偏置 :param dw: 权重梯度 :param db: 偏置梯度 :param learning_rate: 学习率 :return: 更新后的权重和偏置 """ w = w - learning_rate * dw b = b - learning_rate * db return w, b
(九)训练模型
def train(X, y, num_iterations, learning_rate): """ 训练逻辑回归模型 :param X: 输入特征矩阵 :param y: 真实标签 :param num_iterations: 迭代次数 :param learning_rate: 学习率 :return: 训练好的权重和偏置 """ input_size = X.shape[1] w, b = initialize_parameters(input_size) costs = [] for i in range(num_iterations): A, z = forward_propagation(X, w, b) cost = compute_cost(A, y) dw, db = backward_propagation(X, A, y) w, b = update_parameters(w, b, dw, db, learning_rate) if i % 100 == 0: costs.append(cost) print(f"Iteration {i}, Cost: {cost}") plt.plot(costs) plt.xlabel('Iterations (per hundreds)') plt.ylabel('Cost') plt.title('Learning curve') plt.show() return w, b
(十)测试模型
def predict(X, w, b): """ 使用训练好的模型进行预测 :param X: 测试集输入特征矩阵 :param w: 权重向量 :param b: 偏置 :return: 预测标签 """ A, _ = forward_propagation(X, w, b) predictions = (A >= 0.5).astype(int) return predictionsif __name__ == "__main__": # 训练模型 w_trained, b_trained = train(X, y, num_iterations=2000, learning_rate=0.01) # 测试模型准确性 predictions = predict(X, w_trained, b_trained) accuracy = np.mean(predictions == y) * 100 print(f"Accuracy on training set: {accuracy:.2f}%")
以上代码实现了从数据预处理、模型构建到训练和测试的完整逻辑回归流程。通过这种方式,我们可以更深入地理解逻辑回归背后的原理,并掌握如何使用Python实现自己的机器学习算法。这不仅有助于加深对机器学习基础知识的理解,还为进一步探索更复杂的机器学习算法打下坚实的基础。