文章目录
- 基于机器学习的数值预测
- 机器学习简介
- 监督学习的任务
- 创建第一个机器学习模型
- 机器学习的目标——泛化
- 过拟合现象
- 评价函数与最优化
- 建模前的数据处理
- 进一步特征变换
- 多元线性回归模型
- LASSO回归
- kNN
- 算法原理
- 算法步骤
- k值的选择
基于机器学习的数值预测
机器学习是人工智能的核心领域,通过算法让计算机从数据中自动学习规律并完成预测或决策任务。其核心思想是“经验提升性能”,核心流程包括数据预处理、模型训练、评估与优化。
监督学习
需使用标注数据(输入+明确标签),目标是建立输入到输出的映射关系。
- 分类任务:如垃圾邮件识别(标签:是/否)
- 回归任务:如房价预测(标签:连续数值)
常用算法:决策树、支持向量机(SVM)、神经网络(如CNN用于图像分类)
无监督学习
处理无标签数据,目标是发现数据内在结构或模式。
- 聚类:如客户分群(K-means算法)
- 降维:如PCA提取数据主成分
- 关联规则:如购物篮分析(啤酒与尿布的经典案例)
强化学习
智能体通过与环境的动态交互学习策略,以最大化累积奖励。
- 核心要素:状态、动作、奖励、策略
- 典型应用:游戏AI(AlphaGo)、机器人控制
- 算法示例:Q-learning、深度强化学习(DQN、PPO)
三者对比
类型 | 数据类型 | 学习目标 | 典型应用场景 |
---|---|---|---|
监督学习 | 带标签数据 | 输入输出映射 | 图像分类、语音识别 |
无监督学习 | 无标签数据 | 发现数据结构 | 客户分群、异常检测 |
强化学习 | 环境交互反馈 | 优化序列决策 | 自动驾驶、游戏AI |
当前机器学习正朝着多模态学习(结合文本、图像等)、小样本学习(少数据下训练)、可解释性AI等方向发展,在医疗、金融、智能制造等领域持续产生变革性影响。
机器学习简介
监督学习的任务
监督学习的任务一般有两种类型:回归和分类。它们的区别很明显,依据是目标的类型:
- 回归:对应着目标是一个数值特征的情形。
- 分类:对应着目标是一个分类特征的情形。
- 二元分类:非黑即白的
- 多元分类:目标的类别多于两个
- 多标签分类:多个类别或标签指派向一个结果
创建第一个机器学习模型
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
# 生成一些示例数据
np.random.seed(0)
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建线性回归模型
model = LinearRegression()
# 训练模型
model.fit(X_train, y_train)
# 进行预测
y_pred = model.predict(X_test)
# 计算均方误差
mse = mean_squared_error(y_test, y_pred)
print(f"均方误差: {mse}")
# 打印模型参数
print(f"截距: {model.intercept_[0]}")
print(f"斜率: {model.coef_[0][0]}")
机器学习的目标——泛化
预测分析的目的就是预测未知事件。应用机器学习的过程就是找到特征与目标的关系。这也是机器学习的目的。换言之:
所以泛化是什么?泛化就是从数据中学到的算法推广到样本之外的点。
如何检验模型的泛化能力呢?使用交叉验证,一般是使用
hold-out
\textit{hold-out}
hold-out方法,把数据集合分为两部分:
- 数据集:进行学习的集合,用来训练模型的部分数据。
- 测试集:评价集合,验证结果怎么样?是否符合实际。
过拟合现象
这种情况的发生是因为模型对训练集适应得太好,甚至开始学习一些训练集的无效噪声。
相应的:还有欠拟合,良好的学习和过拟合。
- 欠拟合
- 定义:指模型未能学习到数据中的模式和规律,对训练数据的拟合程度较差,在训练集和测试集上的表现都不佳。
- 产生原因
- 模型复杂度不够:例如使用线性模型去拟合非线性的数据,模型无法捕捉数据中的复杂关系。
- 特征不足:没有提供足够的特征让模型学习,导致模型无法全面了解数据的特性。
- 训练时间过短:模型还没有充分学习到数据的特征就停止训练。
- 解决办法
- 增加模型复杂度:比如从简单的线性模型转换为多项式模型。
- 添加更多特征:挖掘更多与目标变量相关的特征。
- 延长训练时间:让模型有更多的时间去学习数据中的规律。
- 良好的学习
- 定义:模型能够很好地学习到数据中的一般模式,既不会过于简单而忽略重要信息,也不会过于复杂而学习到噪声。在训练集和测试集上都能有较好的表现,泛化能力强。
- 特点
- 误差平衡:训练误差和测试误差都比较小,且两者之间的差距不大。
- 泛化能力强:对于未见过的数据,模型也能做出准确的预测。
- 实现途径
- 选择合适的模型:根据数据的特点和问题的复杂度,选择恰当的模型结构。
- 合理调整超参数:通过交叉验证等方法,找到最优的超参数组合。
- 数据预处理:对数据进行清洗、归一化等操作,提高数据质量。
- 过拟合
- 定义:模型对训练数据拟合得过于精确,不仅学习到了数据中的真实模式,还学习到了训练数据中的噪声和随机波动。在训练集上表现很好,但在测试集上表现不佳,泛化能力差。
- 产生原因
- 模型复杂度太高:模型有过多的参数,能够完美地拟合训练数据,但对新数据缺乏适应性。
- 训练数据量太少:模型容易记住训练数据中的细节,而无法学习到普遍规律。
- 特征过多:包含了一些与目标变量无关或冗余的特征,导致模型学习到错误的信息。
- 解决办法
- 减少模型复杂度:简化模型结构,例如减少神经网络的层数或神经元数量。
- 增加训练数据:收集更多的数据,让模型学习到更广泛的模式。
- 正则化:在损失函数中添加正则化项,限制模型参数的大小,防止模型过拟合。
- 特征选择:选择最相关的特征,去除无关或冗余的特征。
直观理解
可以用一个比喻来理解这三种状态。假设你要画一幅猫的画像,欠拟合就像是只画出了一个模糊的轮廓,根本看不出是猫;良好的学习是画出了一只栩栩如生的猫,既抓住了猫的主要特征,又不过于追求细节;过拟合则是在画像上把猫身上的每一根毛发都画出来了,虽然在这只特定的猫上画得很精确,但换一只猫就完全不适用了。
评价函数与最优化
在机器学习中,评价函数(损失函数、代价函数)用于衡量模型预测结果与真实值之间的差异,而最优化则是通过不断调整模型的参数,使得评价函数的值达到最小(或最大)。
不同的任务类型(如分类、回归)适用不同的评价函数。
- 回归任务
- 均方误差(MSE, Mean Squared Error):计算预测值与真实值之间误差平方的平均值。公式为 M S E = 1 n ∑ i = 1 n ( y i − y ^ i ) 2 MSE=\frac{1}{n}\sum_{i = 1}^{n}(y_{i}-\hat{y}_{i})^{2} MSE=n1∑i=1n(yi−y^i)2,其中 y i y_{i} yi 是真实值, y ^ i \hat{y}_{i} y^i 是预测值, n n n 是样本数量。MSE 对异常值比较敏感,因为误差的平方会放大异常值的影响。
- 平均绝对误差(MAE, Mean Absolute Error):计算预测值与真实值之间误差绝对值的平均值。公式为 M A E = 1 n ∑ i = 1 n ∣ y i − y ^ i ∣ MAE=\frac{1}{n}\sum_{i = 1}^{n}|y_{i}-\hat{y}_{i}| MAE=n1∑i=1n∣yi−y^i∣。MAE 对异常值的鲁棒性比 MSE 强。
- 均方根误差(RMSE, Root Mean Squared Error):RMSE 是 MSE 的平方根,即 R M S E = 1 n ∑ i = 1 n ( y i − y ^ i ) 2 RMSE=\sqrt{\frac{1}{n}\sum_{i = 1}^{n}(y_{i}-\hat{y}_{i})^{2}} RMSE=n1∑i=1n(yi−y^i)2。它的单位与目标变量的单位相同,更直观地反映了预测误差的大小。
- 分类任务
- 准确率(Accuracy):分类正确的样本数占总样本数的比例。公式为 A c c u r a c y = T P + T N T P + T N + F P + F N Accuracy=\frac{TP + TN}{TP+TN+FP+FN} Accuracy=TP+TN+FP+FNTP+TN,其中 T P TP TP 是真正例, T N TN TN 是真反例, F P FP FP 是假正例, F N FN FN 是假反例。当样本类别不平衡时,准确率可能无法很好地反映模型的性能。
- 精确率(Precision):预测为正例的样本中,实际为正例的比例。公式为 P r e c i s i o n = T P T P + F P Precision=\frac{TP}{TP + FP} Precision=TP+FPTP。精确率主要关注预测为正例的准确性。
- 召回率(Recall):实际为正例的样本中,被预测为正例的比例。公式为 R e c a l l = T P T P + F N Recall=\frac{TP}{TP + FN} Recall=TP+FNTP。召回率主要关注模型对正例的识别能力。
- F1 值:精确率和召回率的调和平均数,公式为 F 1 = 2 × P r e c i s i o n × R e c a l l P r e c i s i o n + R e c a l l F1=\frac{2\times Precision\times Recall}{Precision + Recall} F1=Precision+Recall2×Precision×Recall。F1 值综合考虑了精确率和召回率,在两者之间取得平衡。
- 最优化方法
最优化的目标是找到使评价函数最小化(或最大化)的模型参数。常见的最优化方法有:
- 梯度下降法:通过迭代更新模型参数,沿着评价函数的负梯度方向更新参数,使得评价函数的值逐渐减小。
- 随机梯度下降法(SGD):每次只使用一个样本的梯度来更新参数,计算效率高,适用于大规模数据集。
- 批量梯度下降法:使用所有样本的梯度来更新参数,更新方向更准确,但计算成本高。
评价多个预测模型的好坏
可以按照以下步骤评价多个预测模型的好坏:
- 数据划分:将数据集划分为训练集、验证集和测试集。训练集用于模型训练,验证集用于调整模型的超参数,测试集用于最终评估模型的性能。
- 模型训练:使用训练集对每个模型进行训练,并通过验证集调整模型的超参数。
- 模型评估:使用测试集计算每个模型的评价指标(如上述的 MSE、Accuracy 等)。
- 结果比较:比较各个模型的评价指标,选择在评价指标上表现最优的模型。
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import mean_squared_error
# 生成一些示例数据
np.random.seed(0)
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 线性回归模型
linear_model = LinearRegression()
linear_model.fit(X_train, y_train)
linear_pred = linear_model.predict(X_test)
linear_mse = mean_squared_error(y_test, linear_pred)
# 决策树回归模型
tree_model = DecisionTreeRegressor()
tree_model.fit(X_train, y_train)
tree_pred = tree_model.predict(X_test)
tree_mse = mean_squared_error(y_test, tree_pred)
# 输出结果
print(f"线性回归模型的均方误差: {linear_mse}")
print(f"决策树回归模型的均方误差: {tree_mse}")
if linear_mse < tree_mse:
print("线性回归模型表现更好")
else:
print("决策树回归模型表现更好")
建模前的数据处理
对于数据处理,我们这里使用scikit-learn
。
进一步特征变换
数据的使用方式不同,模型收到的影响不同,因此不仅要将数据导入模型,提供数据的方式也要是最佳的。例如:对预测变量的偏度进行光滑处理,或变换离群点,这些处理都有益于学习模型。
准备数据有两种方法:
- 无监督预处理(包括那些在进行计算时不考虑目标的技术)
- 有监督预处理
现在我们创建一个包含特征值的矩阵,从而可以使用标准的机器学习符号,特征值称为
x
x
x,目标称为
y
y
y。创建这些变量之前应该要对分类变量使用one-hot
编码格式,理由之一就是scikit-learn
只接收数值。scikit-learn
不能直接提供分类数据。
- 训练-测试分割
在使用hold-out
交叉验证方法的时候,一般训练使用 60 % 60\% 60% ~ 85 85 85 % \% %的数据,其余部分留给测试。常用的数据集分割比是 80 % 80\% 80%。这里可以使用scikit-learn
提供随机分割的函数:
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.1,random_state=123)
- 使用PCA数据降维
降维是基于大量特征提取少量特征的过程,这些少量特征需要尽量保留原始特征的大部分信息。
最主流的降维分析技术是主成分分析。PCA的核心原理:
目标
找到一组正交的主成分(Principal Components),使得数据在这些主成分上的方差最大,从而用尽可能少的维度保留数据的主要信息。
from sklearn.decomposition imoprt PCA
pca = PCA(n_components = 3,random_state=123)
pca.fit(X_train[['x','y','z']])
princ_comp = pca.transform(X_train['x','y','z'])
我们还可以看出来各个成分捕捉了多少的方差信息:
pca.explained_variance_ratio_.round(3)
现在我们要保留第一主成分:
from sklearn.decomposition imoprt PCA
pca = PCA(n_components = 1,random_state=123)
pca.fit(X_train[['x','y','z']])
X_train['dim_index']=pca.transform(X_train[['x','y','z']]).flatten()
X_train.drop(['x','y','z'],axis=1,inplace=True)
- 对数据进行标准化
由于很多的数据是不一定满足正态分布的,但是我们在使用这样的数据投入到机器学习中的时候会造成执行效果很糟糕,所以我们要对数值特征进行标准化。
numerical_features=['carat','depth','table','dim_index']
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fix(X_train[numercial_features])
X_train.loc[:,numerical_features] = scaler.transform(X_train[numercial_features])
多元线性回归模型
多元线性回归模型是所有模型之母。
y
p
r
e
d
=
ω
0
+
∑
i
=
1
k
ω
i
x
i
y_{pred}=\omega_0+\sum_{i=1}^{k}\omega_ix_i
ypred=ω0+i=1∑kωixi
我们需要做的只是:
R S S m i n = ∑ i = 1 N ( y i − y p r e d ) 2 RSS_{min}=\sum_{i=1}^{N}\left(y_i -y_{pred}\right)^2 RSSmin=i=1∑N(yi−ypred)2
现在对模型进行评价:
M S E = 1 N ∑ i = 1 N ( y i − y p r e a d ) 2 MSE=\frac{1}{N}\sum_{i=1}^{N}\left(y_i-y_{pread}\right)^2 MSE=N1i=1∑N(yi−ypread)2
LASSO回归
找到下式的最小化权重组合:
1 2 N ∑ i = 1 N ( y i − y p r e d ) + α ∑ k = 1 P ∣ ω k ∣ , 0 ≤ α \frac{1}{2N}\sum_{i=1}^N \left( y_i-y_{pred}\right)+\alpha \sum_{k=1}^{P}\left|\omega_k\right| ,0 \le \alpha 2N1i=1∑N(yi−ypred)+αk=1∑P∣ωk∣,0≤α
总之最后的最后,我们可以得到一个权重,然后里面有几个是零,就把一些影响比较小的项给自动排除了。
kNN
k k k近邻 ( k − N e a r e s t N e i g h b o r s , k N N ) (k-Nearest Neighbors,kNN) (k−NearestNeighbors,kNN)算法是一种基本且常用的监督学习算法,可用于分类和回归任务。以下是关于kNN算法的详细介绍:
算法原理
kNN算法的核心思想基于“近朱者赤,近墨者黑”的理念。对于一个待预测的样本,它会在训练数据集中找到与该样本距离最近的k个样本,然后根据这k个样本的类别(分类任务)或者数值(回归任务)来进行预测。
- 分类任务:在分类问题中,通常采用“多数表决”的方式,即这k个最近邻样本中哪个类别出现的次数最多,就将待预测样本归为该类别。
- 回归任务:在回归问题中,会取这k个最近邻样本的目标值的平均值作为待预测样本的预测值。
算法步骤
- 数据准备:收集并整理训练数据集,包含特征和对应的标签(分类任务)或目标值(回归任务)。
- 计算距离:对于待预测样本,计算它与训练数据集中每个样本的距离。
- 选择k值:确定k的大小,即选择最近邻的样本数量。
- 找到最近邻:根据计算得到的距离,选择距离待预测样本最近的k个样本。
- 进行预测:
- 分类任务:统计这k个样本中各个类别的数量,将待预测样本归为数量最多的类别。
- 回归任务:计算这k个样本目标值的平均值,作为待预测样本的预测值。
k值的选择
k值的选择对kNN算法的性能有重要影响:
- 较小的k值:模型的复杂度较高,对局部数据的敏感度高,容易受到噪声的影响,可能会导致过拟合。例如,当 k = 1 k = 1 k=1时,模型只根据最近的一个样本进行预测,可能会因为这个样本是噪声点而做出错误的预测。
- 较大的k值:模型的复杂度较低,对数据的整体特征更关注,但可能会忽略局部的重要信息,导致欠拟合。例如,当k值接近训练数据集的大小时,模型会将所有样本都考虑进来,预测结果会趋近于训练数据集中的整体分布,无法对新样本做出准确的预测。
通常可以通过交叉验证的方法来选择合适的k值,即尝试不同的k值,在验证集上评估模型的性能,选择性能最优的k值。
下面是一个使用kNN进行分类任务的简单示例,使用的是鸢尾花数据集:
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
# 加载鸢尾花数据集
iris = load_iris()
X = iris.data
y = iris.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 创建kNN分类器,这里k值选择为5
knn = KNeighborsClassifier(n_neighbors=5)
# 训练模型
knn.fit(X_train, y_train)
# 进行预测
y_pred = knn.predict(X_test)
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"模型的准确率: {accuracy}")