赞
踩
本文将会使用python语言将机器学习中常用的6种算法进行复现,代码会贴在每章后面
算法包括:线性回归、逻辑回归、梯度下降、神经网络、决策树和k均值聚类算法
接下来将探讨这些算法的背景、原理、优缺点及应用场景
线性回归属于最简单和最古老的回归算法之一,由 Carl Friedrich Gauss 提出。回归算法被提出最初的应用主要集中在天文学和物理学当中,用于预测物体运动诡异或者其他连续变量的预测。随着计算技术的进步,回归算法逐渐在其他领域广泛运用
原理:线性回归通过寻找数据点之间的最佳拟合直线,来预测目标变量
通过最小化均方误差(Mean Squared Error, MSE)来估计这些参数
如下:
实验步骤如下:
数据准备:收集和准备数据,包括数据清洗和特征选择。
模型训练:使用训练数据拟合线性回归模型,通过最小二乘法估计参数
模型评估:使用测试数据评估模型性能,常用评估指标均方误差。
预测:使用训练好的模型进行预测。
优点:
简单易懂:线性回归模型结构简单,容易理解和实现。
计算速度快:计算复杂度低,适用于大规模数据集。
解释性强:模型参数具有明确的统计意义,可以解释特征对目标变量的影响。
缺点:
线性假设:假设特征和目标变量之间是线性关系,无法捕捉非线性关系。
对异常值敏感:异常值(outliers)会显著影响模型参数的估计。
多重共线性:特征之间的多重共线性会导致参数估计不稳定。
下述就是对异常值敏感的例子,预测直线应该往下面偏,因为上方的数据点原因,导致预测的回归线整体向上浮动
实验代码:
- import numpy as np
- import matplotlib.pyplot as plt
- from sklearn.linear_model import LinearRegression
-
- # 设置matplotlib支持中文显示
- plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文显示
- plt.rcParams['axes.unicode_minus'] = False # 正确显示负号
-
- X = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).reshape(-1, 1) # 学习时长
- y = np.array([20, 30, 35, 50, 60, 75, 80, 90, 95, 100]) # 成绩
-
- # 使用线性回归模型
- model = LinearRegression()
- model.fit(X, y) # 训练模型
-
- X_predict = np.array([11, 12, 13]).reshape(-1, 1)
- y_predict = model.predict(X_predict) # 进行预测
-
- plt.scatter(X, y, color='red', label='实际时长、成绩') # 原始数据点
- plt.plot(X, model.predict(X), color='blue', label='线性模型') # 拟合的直线
- plt.scatter(X_predict, y_predict, color='green', label='预测') # 预测点
- plt.xlabel('学习时长')
- plt.ylabel('实际成绩')
- plt.title('学习时长和成绩的关系')
- plt.legend()
- plt.show()
我们首先创建了一组简单的数据,模拟学习时长与他们实际成绩之间的关系
然后,我们使用了线性回归模型来拟合这些数据,并对新学习时长进行了成绩的预测
逻辑回归(Logistic Regression)最早由 David Cox 提出
尽管其名称中包含“回归”二字,但它实际上是一种分类算法,主要用于解决二分类问题。随着计算能力的提升和数据量的增加,逻辑回归在医学、金融、社会科学等领域得到了广泛应用,成为统计学习和机器学习的重要工具之一
原理:通过一个逻辑函数(logistic function)将线性回归的输出映射到一个 (0, 1) 区间,从而进行二分类
通过最大似然估计法(Maximum Likelihood Estimation, MLE)来估计这些参数。
值得一提的是Sigmoid 函数
Sigmoid 函数:逻辑回归中使用的Sigmoid函数 能将任意实数值映射到 (0, 1) 区间,便于解释为概率
具体步骤包括:
初始化参数:随机初始化参数 ( \beta_0 ) 和 ( \beta_1 )。
计算预测值:根据当前参数计算每个样本的预测概率 ( \hat{P} )。
计算损失函数:损失函数通常采用对数似然函数(Log-Likelihood Function):
优化参数:通过梯度下降法或其他优化算法,最大化对数似然函数,更新参数。
优点:
简单易解释:模型输出的是事件发生的概率,具有直观的解释性。
计算效率高:计算复杂度低,适用于大规模数据集。
稳健性强:在处理缺失值和异常值方面表现良好。
缺点:
线性假设:假设特征和目标变量之间是线性关系,对于非线性关系效果较差。
只能处理二分类问题:虽然可以通过扩展(如一对多、多对多)处理多分类问题,但效果不如专门的多分类算法。
对特征独立性要求高:特征之间的高度相关性会影响模型的稳定性和准确性。
实验案例:
- from sklearn.linear_model import LogisticRegression
- from sklearn.datasets import make_classification
- import matplotlib.pyplot as plt
- import numpy as np
-
- # 设置matplotlib支持中文显示
- plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文显示
- plt.rcParams['axes.unicode_minus'] = False # 正确显示负号
-
- X, y = make_classification(n_samples=100, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, random_state=42)
-
- # 创建逻辑回归模型对象
- lr = LogisticRegression()
-
- # 训练模型
- lr.fit(X, y)
-
- # 定义决策边界绘制函数
- def plot_decision_boundary(X, y, model):
- # 设置最小和最大值,以及增量
- x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
- y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
- xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.1),
- np.arange(y_min, y_max, 0.1))
-
- # 预测整个网格的值
- Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
- Z = Z.reshape(xx.shape)
-
- # 绘制决策边界和散点图
- plt.contourf(xx, yy, Z, alpha=0.4)
- plt.scatter(X[:, 0], X[:, 1], c=y, s=20, edgecolor='k')
- plt.xlabel('学习时长')
- plt.ylabel('成绩等级')
- plt.title('分类图')
-
- # 绘制决策边界和数据点
- plot_decision_boundary(X, y, lr)
- plt.show()
我们首先使用make_classification函数生成了一组模拟的二维数据
然后,我们训练了一个逻辑回归模型并绘制了决策边界,以及不同类别的样本点,直观展示了模型的分类效果。
梯度下降法(Gradient Descent)由 Augustin-Louis Cauchy 提出,是一种用于寻找函数最小值(或最大值)的迭代优化算法
梯度下降在机器学习中尤为重要,因为它是许多算法(如线性回归、逻辑回归和神经网络)中用于参数优化的核心方法
原理:梯度下降的基本思想是从一个初始点开始,沿着函数的负梯度方向迭代更新参数,以最小化损失函数。梯度是函数在该点的偏导数向量,表示函数在该点的变化方向
具体步骤包括:
初始化参数:随机初始化参数 ( \theta )。
计算梯度:计算损失函数在当前参数下的梯度。
更新参数:根据梯度更新参数。
迭代:重复步骤 2 和 3,直到损失函数收敛或达到最大迭代次数。
梯度下降有几种常见的变种:
批量梯度下降(Batch Gradient Descent):使用整个数据集计算梯度,每次迭代更新参数。适用于小数据集。
随机梯度下降(Stochastic Gradient Descent, SGD):每次迭代仅使用一个样本计算梯度,更新参数。适用于大数据集,但收敛较慢且波动较大。
小批量梯度下降(Mini-batch Gradient Descent):每次迭代使用一个小批量样本计算梯度,更新参数。结合了批量梯度下降和随机梯度下降的优点。
优点:
简单易实现:梯度下降算法简单,容易实现。
适用广泛:可用于优化各种损失函数,广泛应用于不同的机器学习模型。
计算效率高:特别是小批量梯度下降,在处理大规模数据时效率高。
缺点:
学习率选择困难:学习率太大可能导致不收敛,学习率太小则收敛速度慢。
容易陷入局部最优:在非凸函数中,梯度下降可能陷入局部最优解。
收敛速度慢:在某些情况下,梯度下降的收敛速度较慢,特别是接近最优解时。
实验代码:
- import matplotlib.pyplot as plt
- import numpy as np
-
- # 设置matplotlib支持中文显示
- plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文显示
- plt.rcParams['axes.unicode_minus'] = False # 正确显示负号
-
- # 示例数据
- X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]])
- y = np.dot(X, np.array([1, 2])) + 3
-
- # 初始化参数,考虑偏置项
- theta = np.random.randn(3, 1)
- iterations = 1000
- alpha = 0.01
-
- # 损失函数
- def compute_cost(X, y, theta):
- m = len(y)
- predictions = X.dot(theta)
- cost = (1 / 2 * m) * np.sum(np.square(predictions - y))
- return cost
-
- # 梯度下降
- def gradient_descent(X, y, theta, alpha, iterations):
- m = len(y)
- cost_history = np.zeros(iterations)
-
- for i in range(iterations):
- gradients = X.T.dot(X.dot(theta) - y) / m
- theta = theta - alpha * gradients
- cost_history[i] = compute_cost(X, y, theta)
-
- return theta, cost_history
-
- # 添加偏置项
- X_b = np.c_[np.ones((len(X), 1)), X]
-
- # 运行梯度下降
- theta, cost_history = gradient_descent(X_b, y, theta, alpha, iterations)
-
- # 结果可视化
- plt.plot(range(1, iterations + 1), cost_history, 'b-')
- plt.xlabel('迭代次数')
- plt.ylabel('损失值')
- plt.title('梯度下降优化损失值')
- plt.show()
-
- print(f"优化后的参数: {theta.ravel()}")
结果如下:
决策树(Decision Tree)是一种基于树形结构的监督学习算法,用于分类和回归任务
决策树算法最早由 Ross Quinlan 提出,包括经典的 ID3、C4.5 和 CART 算法
原理:决策树通过递归地将数据集分割成更小的子集来构建树状模型。每个内部节点代表一个特征,每个分支代表该特征的一个取值,每个叶节点代表一个类别或预测值
决策树的构建过程包括以下步骤:
选择最优特征:根据某种指标(如信息增益、基尼系数)选择最优特征进行分割。
分割数据集:根据选择的特征将数据集分割成子集。
递归构建子树:对子集递归调用上述步骤,直到满足停止条件(如所有数据点属于同一类别或达到最大深度)。
信息增益:信息增益用于衡量某一特征对数据集进行分割时所带来的信息熵的减少。信息熵(Entropy)表示数据集的纯度,计算公式为:
基尼系数:基尼系数(Gini Index)用于衡量数据集的不纯度,计算公式为:
优点:
直观易懂:决策树的结构类似于人类的决策过程,容易理解和解释。
无需特征缩放:决策树对特征的缩放不敏感,不需要特征标准化。
处理多类型数据:能够处理数值型和分类型特征。
缺点:
容易过拟合:决策树容易对训练数据过拟合,需要剪枝(Pruning)等技术来防止过拟合。
不稳定性:对数据的微小变化敏感,可能导致结构大幅变化。
偏向于高频特征:在数据不平衡的情况下,决策树容易偏向于那些取值较多的特征。
实验代码:
- from sklearn.datasets import make_classification
- from sklearn.model_selection import train_test_split
- from sklearn.tree import DecisionTreeClassifier
- import matplotlib.pyplot as plt
- import numpy as np
-
- # 设置matplotlib支持中文显示
- plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文显示
- plt.rcParams['axes.unicode_minus'] = False # 正确显示负号
-
-
- # 生成武侠风格的数据,确保所有特征值为正数
- X, y = make_classification(n_samples=200, n_features=2, n_redundant=0, n_informative=2,
- n_clusters_per_class=1, random_state=42)
- X += np.abs(X.min()) # 平移数据确保为正
-
- # 将数据集分为训练集和测试集
- X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
-
- # 创建决策树模型,并设置最大深度为3
- dt = DecisionTreeClassifier(max_depth=3)
-
- # 训练模型
- dt.fit(X_train, y_train)
-
- # 绘制数据点和决策边界
- def plot_decision_boundary(model, X, y):
- # 设置最小和最大值,以及增量
- x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
- y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
- xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.01),
- np.arange(y_min, y_max, 0.01))
-
- # 预测整个网格的值
- Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
- Z = Z.reshape(xx.shape)
-
- # 绘制决策边界
- plt.contourf(xx, yy, Z, alpha=0.4)
- # 绘制不同类别的样本点
- plt.scatter(X[y == 0][:, 0], X[y == 0][:, 1], c='red', marker='x')
- plt.scatter(X[y == 1][:, 0], X[y == 1][:, 1], c='blue', marker='o')
-
-
- # 绘制决策边界和数据点
- plot_decision_boundary(dt, X, y)
- plt.show()
这段代码首先生成了一组包含200个样本数据,每个样本有两个特征,目标是分类
然后,我们使用DecisionTreeClassifier创建了一个决策树模型并对其进行训练。
通过定义plot_decision_boundary函数,我们绘制了模型的决策边界,并使用不同颜色和形状标记来区分不同数据,直观地展示了决策树在二分类任务中的分类效果。
K均值聚类(K-means Clustering)是一种常用的无监督学习算法,用于将数据集划分为 K 个互斥的簇
算法最早由 Stuart Lloyd 提出,K均值聚类在许多领域得到广泛应用,如图像处理、市场营销、模式识别等。
原理:K均值聚类通过迭代优化的方法,将数据点分配到 K 个簇中,使得每个簇内的数据点与簇中心(质心)之间的距离平方和最小化
具体步骤包括:
初始化中心点:随机选择 K 个初始中心点(质心)。
分配数据点:将每个数据点分配到最近的中心点所属的簇中。
更新中心点:重新计算每个簇的中心点,即簇内所有数据点的均值。
迭代:重复步骤 2 和 3,直到中心点不再发生变化或达到最大迭代次数。
算法的目标是最小化以下目标函数:
优点:
计算效率高:算法简单易实现,计算速度快,适用于大规模数据集。
结果直观:聚类结果容易理解和解释,便于后续分析和处理。
适用性广:广泛应用于不同类型的数据和多种领域。
缺点:
对初始值敏感:初始中心点的选择会影响最终结果,可能导致局部最优解。
簇的形状限制:假设簇是球形且各方向方差相同,不适用于非球形簇。
确定 K 值困难:需要事先指定 K 值,且不同 K 值会得到不同的聚类结果。
如下,K均值很难实现分类
实验代码:
- import pandas as pd
- import matplotlib.pyplot as plt
- from sklearn.cluster import KMeans
-
- # 示例数据
- data = {
- 'age': [25, 45, 35, 50, 23, 31, 22, 35, 42, 51],
- 'income': [50000, 100000, 75000, 120000, 40000, 60000, 45000, 80000, 110000, 130000]
- }
- df = pd.DataFrame(data)
-
- # 创建K均值模型
- kmeans = KMeans(n_clusters=3)
- kmeans.fit(df)
-
- # 预测聚类结果
- df['cluster'] = kmeans.labels_
-
- # 可视化聚类结果
- plt.scatter(df['age'], df['income'], c=df['cluster'], cmap='viridis')
- plt.xlabel('Age')
- plt.ylabel('Income')
- plt.title('Customer Segments')
- plt.show()
-
- print(df)
在这个例子中,使用 sklearn
库中的 KMeans
模型来对客户的年龄和收入进行聚类
通过训练模型,我们可以将客户分为三个群体,并可视化聚类结果。同时,可以输出每个客户的聚类标签。
神经网络(Neural Networks)起源于 20 世纪 40 年代,由 Warren McCulloch 和 Walter Pitts 提出。他们的工作灵感来源于人脑的结构和功能,希望通过数学模型模拟生物神经元的工作方式
神经网络的发展经历了多次起伏,直到 2006 年 Geoffrey Hinton 等人提出深度学习(Deep Learning)的概念,神经网络才重新获得关注,并迅速成为人工智能领域的热点
原理:神经网络由多个层级的节点(神经元)组成,每个节点通过加权连接传递信号。一个典型的神经网络结构包括输入层、隐藏层和输出层。输入层接收原始数据,隐藏层通过加权求和和激活函数处理数据,输出层生成最终的预测结果。每层节点的输出由前一层节点的加权和通过激活函数计算得到
其中,( a ) 是输出,( W ) 是权重矩阵,( x ) 是输入向量,( b ) 是偏置向量,( f ) 是激活函数。
典型的神经网络图如下:
激活函数:
Sigmoid:将输入映射到 (0, 1) 区间,适用于二分类问题。
ReLU(Rectified Linear Unit):将负值映射为 0,正值保持不变,适用于深层网络。
Tanh:将输入映射到 (-1, 1) 区间,适用于需要归一化的场景。
训练: 神经网络通过反向传播算法(Backpropagation)进行训练。反向传播通过计算损失函数的梯度,调整网络中的权重和偏置,以最小化预测误差。训练过程包括以下步骤:
正向传播:计算每层的输出,直到生成最终预测结果。
计算损失:使用损失函数(如均方误差、交叉熵)计算预测结果与真实值之间的误差。
反向传播:计算损失函数对每个权重和偏置的梯度。
参数更新:使用梯度下降或其他优化算法更新权重和偏置。
优点:
强大的非线性建模能力:能够捕捉复杂的非线性关系,适用于各种模式识别任务。
自动特征提取:隐藏层能够自动提取数据的高层次特征,减少了特征工程的工作量。
灵活性强:可以用于回归、分类、生成模型等多种任务。
缺点:
训练时间长:深层神经网络的训练需要大量的计算资源和时间。
需要大量数据:需要大量的标注数据才能有效训练,数据不足时容易过拟合。
难以解释:网络内部的权重和偏置难以解释,模型的可解释性较差。
实验代码
这里可以参考这篇博文:这篇文章中使用神经网络对sin函数进行拟合,并且其中的反向传播都是手动实现的,没有使用torch库
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。