Scikit-learn 是一个开源的 Python 机器学习库,它为分类、回归、聚类等经典任务提供了一整套简洁、高效且易于使用的工具。
1. 主要算法分类
目前主流的算法可分为以下几类:
1.1 监督学习 (Supervised Learning)
向计算机提供已标记的数据(即数据与对应的正确答案/标签),让其学习数据与标签之间的映射关系。
常见的神经网络就属于监督学习的一种方式。
1.2 非监督学习 (Unsupervised Learning)
仅向计算机提供数据,不提供任何标签或答案,由计算机自行探索数据内部的结构、关联和规律。
计算机通过观察数据间的特性,自动进行聚类或降维,总结出隐藏的模式。
1.3 半监督学习 (Semi-Supervised Learning)
结合了监督学习与非监督学习的特点,利用少量有标签的样本和大量无标签的样本共同进行训练和分类。
1.4 强化学习 (Reinforcement Learning)
通过“试错”来学习。将计算机(Agent)置于一个陌生的环境中,通过与环境交互获得奖励或惩罚,从而学习到能最大化奖励的行为策略。
Agent自行尝试各种行为,根据行为结果(奖励或惩罚)不断调整和优化策略,最终学会在特定环境下完成任务的方法。
AlphaGo便是应用强化学习的著名案例。
1.5 遗传算法 (Genetic Algorithm)
模拟生物进化论中“适者生存,优胜劣汰”原则的一种优化算法。
过程:
- 初始化:创建一组初始解决方案(“种群”)。
- 评估:根据预设标准评估每个方案的优劣。
- 选择:淘汰表现差的方案,选择表现好的方案(“强者”)进行“繁殖”和“变异”。
- 迭代:重复评估和选择过程,不断进化出更优的解决方案或模型。
2. 选择合适的机器学习模型
在开始选择模型前,需要对数据进行初步评估:
数据量检查:样本数量 (Sample Size) 是首要的判断依据。
- 样本数量 < 50:当前数据量过小,训练出的模型可能泛化能力差、准确度低。应优先考虑收集更多的数据。
- 样本数量 > 50:可以进入下一步,根据任务类型选择合适的算法分支。
可以将机器学习问题大致归为以下四类:
2.1 分类 (Classification)
预测一个数据样本属于哪个预定义的类别。
学习类型:监督学习
2.2 回归 (Regression)
预测一个连续的数值,而非类别。
学习类型:监督学习
2.3 聚类 (Clustering)
在没有预先定义类别的情况下,将数据根据其内在的相似性自动分组(分簇)。
学习类型:非监督学习
2.4 降维 (Dimensionality Reduction)
减少数据中的特征(属性)数量,同时尽可能保留最重要的信息。
学习类型:通常为非监督学习
降维并非简单地从原有特征中挑选一部分,而是通过数学变换,将高维特征(例如,描述房价的20个因素)映射为低维的新特征(例如2个综合因素)。新的特征是原有所有特征的综合体现,旨在抓住数据的主要矛盾。
算法的通用性
许多机器学习算法非常灵活,稍作调整即可用于解决不同类型的问题。例如,随机梯度下降 (SGD) 是一种基础的优化算法,它既可以用于分类任务 (SGDClassifier
),也可以用于回归任务 (SGDRegressor
),只是在处理和优化目标上有所不同。
特征 (Features) vs. 标签 (Labels):
特征:描述数据点的属性或输入变量。在房价预测案例中,“房屋面积”、“地段”、“建造年份”等都是特征。
标签:我们希望预测的目标变量,即正确答案。在房价预测案例中,“房屋价格”就是标签。监督学习需要同时包含特征和标签的数据,而非监督学习通常只使用特征。
3. 使用 KNN 算法对鸢尾花 (Iris) 进行分类
Scikit-learn 将绝大多数机器学习模型的应用流程进行了统一,掌握此模式即可触类旁通,高效使用库中的各种算法。其核心步骤可概括为:
导入:从 sklearn
库中导入所需的模型
实例化:创建模型对象,可在此步骤设置模型的超参数
训练 (Fit) :使用 .fit(X_train, y_train)
方法,将训练集数据喂给模型进行学习
预测:使用 .predict(X_test)
方法,让训练好的模型对新的测试数据进行预测
3.1 导入库与数据
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split # 用于划分数据集
from sklearn.neighbors import KNeighborsClassifier # KNN模型
numpy
: 用于高效的数值计算。
sklearn.datasets
: 包含多种可供练习的经典数据集,如此处用到的 load_iris
。
sklearn.model_selection.train_test_split
: 将数据集划分为训练集和测试集的标准工具。
sklearn.neighbors.KNeighborsClassifier
: 本次案例中使用的分类算法。
3.2 数据加载
首先,加载 sklearn
内置的鸢尾花数据集,并分离特征和标签。
# 1.载入数据集
iris = datasets.load_iris()
# 2.分离数据集
iris_X = iris.data # 特征
iris_y = iris.target # 标签
特征 (iris_X) :描述样本属性的数据。每个样本包含 4 个特征。
说明:鸢尾花数据集的 4 个特征分别是:花萼长度 (Sepal Length)、花萼宽度 (Sepal Width)、花瓣长度 (Petal Length)、花瓣宽度 (Petal Width)。
示例数据:
[[5.1 3.5 1.4 0.2]
[4.9 3. 1.4 0.2]]
标签 (iris_y) :每个样本所属的类别。
说明:该数据集包含 3 个类别,分别用 0, 1, 2 表示。
数据概览:[0, 0, ..., 1, 1, ..., 2, 2, ...]
3.3 数据集划分
为了客观评估模型的性能,需将数据集划分为训练集(用于学习)和测试集(用于评估)。
# 3.划分数据集
X_train, X_test, y_train, y_test = train_test_split(iris_X, iris_y, test_size=0.3)
train_test_split(...)
:是 scikit-learn
库中的一个函数,用来把数据集分成两部分:训练集和测试集
test_size=0.3
:这个参数表示测试集占总数据的 30%,训练集占 70%
返回值:
X_train, X_test, y_train, y_test
函数会返回 4 个结果:
名称 | 含义 |
---|---|
X_train |
训练集的特征数据 |
X_test |
测试集的特征数据 |
y_train |
训练集的标签数据 |
y_test |
测试集的标签数据 |
train_test_split
的作用:
防止数据泄露:模型在训练时不应接触到测试数据,否则评估结果会过于乐观,无法反映其在未知数据上的真实表现。
自动打乱数据:该函数默认会随机打乱数据顺序再进行划分。这对于机器学习至关重要,可以防止模型因数据原始排列顺序(如按类别排序)而产生偏见。
3.4 模型训练与预测
遵循 Scikit-learn 的标准流程进行模型训练和预测。
# 4.实例化模型
knn = KNeighborsClassifier()
# 5.训练模型
knn.fit(X_train, y_train) # 训练完成后,所有学习到的参数都保存在模型对象自身的属性中,
# 6.对测试集进行预测
predictions = knn.predict(X_test)
3.5 结果评估
将模型的预测结果与真实的测试集标签进行对比,以评估模型效果。
print("预测结果:\n",predictions,"\n")
print("真实结果:\n",y_test,)
输出示例:
预测结果:
[1 2 0 1 2 1 0 0 2 0 1 1 2 1 1 0 2 1 1 0 2 2 2 0 0 2 0 0 1 0 2 1 0 1 0 0 1
2 2 0 2 2 2 2 2]
真实结果:
[1 2 0 1 2 1 0 0 2 0 1 1 2 1 1 0 2 1 1 0 2 2 2 0 0 2 0 0 1 0 2 1 0 1 0 0 1
1 2 0 2 2 2 2 2]
结论:可以看到预测结果与真实结果高度相似,但可能存在个别误差。这是机器学习的本质——模型致力于逼近真实规律,而非实现 100% 的精确复刻。如同人类会犯错一样,模型也存在误差范围。
4. 数据集的加载与生成
sklearn.datasets
为机器学习实践提供了丰富的数据来源,主要包含两大类数据:
真实世界数据集:
经过清洗和格式化的、源于真实世界问题的经典数据集。通常以 load_*
的形式调用,例如 load_iris()
、load_boston()
。
合成数据集:
可根据用户指定的参数(如样本数、特征数、噪声水平等)动态生成具有特定统计特性的数据。通常以 make_*
的形式调用,例如 make_regression()
、make_classification()
。
4.1 加载真实数据集并进行线性回归
使用加州房价数据集(fetch_california_housing()
) 来加载数据并应用线性回归模型。
from sklearn import datasets
from sklearn.linear_model import LinearRegression # 线性回归模型
from sklearn.model_selection import train_test_split
# 1.加载数据集
loaded_data = datasets.fetch_california_housing()
# 2.分离数据集
data_X = loaded_data.data # 特征
data_y = loaded_data.target # 标签
# 3.划分数据集
X_train, X_test, y_train, y_test = train_test_split(data_X, data_y,)
# 4.实例化模型
model = LinearRegression()
# 5.训练模型
model.fit(X_train, y_train)
# 6.对测试集进行预测
predictions = model.predict(X_test[:4, :])
print("预测房价:", predictions)
print("真实房价:", data_y[:4])
Scikit-learn 的标准化数据接口:
通过 load_*
加载的数据集对象,其特征和标签分别存储在 .data
和 .target
属性中,这种高度统一的模式简化了数据调用流程。
运行结果:
预测房价: [2.22492568 4.02422823 1.34033317 0.88996126]
真实房价: [4.526 3.585 3.521 3.413]
预测值与真实值存在差距
模型的预测结果与真实值不完全一致是正常的,这是机器学习的固有特性。原因包括:
模型简化:线性回归模型本身是一个简化的数学抽象,可能无法捕捉所有复杂现实因素。
数据质量:原始数据可能包含噪声或未包含所有关键特征。
缺少优化步骤:为了获得更高精度,通常需要:
- 数据预处理:例如对特征进行归一化。
- 模型调优:尝试不同的模型或调整当前模型的超参数。
4.2 生成合成回归数据并可视化
使用 make_regression
生成一组用于回归分析的数据,并用 matplotlib
将其可视化。
import matplotlib.pyplot as plt
# 1. 使用 make_regression 生成随机数据
# n_samples: 样本数量
# n_features: 特征数量
# n_targets: 目标值数量
# noise: 数据的噪声水平,值越大,数据点越离散
X, y = datasets.make_regression(n_samples=100, n_features=1, n_targets=1, noise=10)
# 2. 使用散点图进行可视化
plt.scatter(X, y)
# 3. 显示图像
plt.show()
make_regression
关键参数:
n_samples
: 生成的样本点数量。n_features
: 每个样本点的特征维度。noise
: 施加到数据上的高斯噪声的标准差,用于模拟真实世界数据的不完美性。
执行上述代码会生成一张散点图。图中的数据点大致沿一条直线分布,但由于设置了 noise
,点会在这条直线周围散布,为训练和测试回归模型提供了一个理想的、可控的数据环境。
5. 模型属性与方法
5.1 区分超参数和学习到的属性
超参数:在创建模型时由用户手动设置的参数,用于控制模型的学习过程,如LinearRegression(fit_intercept=True)
中的 fit_intercept
,使用 model.get_params()
方法查看
学习到的属性:模型在调用 .fit()
方法、从数据中学习后所得到的内部参数,Scikit-learn 的所有学习属性都以一个下划线 _
结尾,例如 coef_
,在模型训练 (.fit()
) 完成后,通过 model.attribute_
查看
5.2 LinearRegression
模型的核心属性与功能
from sklearn import datasets
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
# 1.加载数据集
loaded_data = datasets.fetch_california_housing()
# 2.分离数据集
data_X = loaded_data.data # 特征
data_y = loaded_data.target # 标签
# 3.划分数据集
X_train, X_test, y_train, y_test = train_test_split(data_X, data_y,)
# 4.实例化模型
model = LinearRegression()
# 5.训练模型
model.fit(X_train, y_train)
print("模型系数 (coef_):", model.coef_)
print("模型截距 (intercept_):", model.intercept_)
print("模型参数 (get_params):", model.get_params())
score = model.score(X_test, y_test)
print(f"模型在测试集上的 R^2 得分: {score}")
5.2.1 查看学习到的属性
在线性回归的数学公式 y = w_1*x_1 + ... + w_n*x_n + b
中:
model.coef_
:系数 (Coefficients), 对应于公式中的权重 w
,是一个数组,每个值代表对应特征的重要性或影响力。
model.intercept_
:截距 (Intercept), 对应于公式中的偏置项 b
,是一个标量值,代表当所有特征值都为0时,预测值的基准。
5.2.2 查看模型的超参数
model.get_params()
:以字典形式返回创建模型时设置的所有超参数。如果你没有手动设置,则返回的是默认值。
输出示例:{'copy_X': True, 'fit_intercept': True, 'n_jobs': None, 'positive': False}
5.2.3 评估模型性能
model.score(X, y)
:对模型进行性能评估并返回一个分数。
score
方法的打分机制:
- 对于回归模型:返回的是 R² (R-squared, 决定系数), 表示模型对数据变化的解释程度。值域通常在 0 到 1 之间。
- 对于分类模型:返回的是平均准确率, 即“预测正确的样本数 / 总样本数”。
好的,这是根据您提供的视频字幕和截图资料,为您生成的一份关于特征缩放(Feature Scaling)的学习笔记。
6. 特征缩放
特征缩放是将不同特征的数值范围调整到相似的尺度上。
当一个模型中的多个特征数值范围(量纲)差异巨大时(例如,房屋面积为 0-2000平方英尺,而房间数量为 1-5个),优化算法(如梯度下降)的收敛过程会变得低效。未缩放的特征会导致成本函数 J(θ)
的等高线图呈椭圆形,算法需要多次振荡才能找到最优解(最小值点)。
在进行特征缩放后,成本函数的等高线图会更接近圆形,使得梯度下降可以沿着更直接、更高效的路径收敛到最优点,从而加快模型训练速度并提升性能。
Scikit-Learn 的 preprocessing
模块提供了多种特征缩放工具,preprocessing.scale()
的作用是将数据进行标准化,即分别处理每一列特征,使其平均值为 0,标准差为 1。
代码示例:
from sklearn import preprocessing
import numpy as np
# 创建一个特征尺度差异很大的数组
# 第1列范围: -100 ~ 120
# 第2列范围: 2.7 ~ 20
# 第3列范围: -2 ~ 40
a = np.array([
[10, 2.7, 3.6],
[-100, 5, -2],
[120, 20, 40]
], dtype=np.float64)
# 使用 scale 函数进行标准化
scaled_a = preprocessing.scale(a)
print("原始数据:\n", a)
print("\n标准化后的数据:\n", scaled_a)
输出结果:
原始数据:
[[ 10. 2.7 3.6]
[-100. 5. -2. ]
[ 120. 20. 40. ]]
标准化后的数据:
[[ 0. -0.85170713 -0.55138018]
[-1.22474487 -0.55187146 -0.852133 ]
[ 1.22474487 1.40357859 1.40351318]]
可以看到,标准化后,每一列的数值都被缩放到一个相似的范围内。
说明:****
StandardScaler
类与scale
函数
在实际项目中,更推荐使用sklearn.preprocessing.StandardScaler
类。scale
函数会一步到位地计算并转换整个数据集,但在划分训练集和测试集时,我们必须保证用训练集的参数(均值、标准差)来转换测试集,以防止数据泄露。StandardScaler
对象可以先在训练数据上fit()
,然后用同一个对象去transform()
训练集和测试集,操作更规范、安全。
特征缩放对支持向量机(SVC)分类准确率的影响:
- 生成并可视化数据
使用make_classification
生成一组具有较大尺度(scale=100
)的样本数据。从散点图可以看出,数据本身是线性可分的,但其特征值分布在 -400 到 400 的广大区间内。 - 对比实验
使用相同的 SVC 模型,在“未缩放”和“已缩放”两种数据上分别进行训练和评估。
直接在原始数据上训练模型,其在测试集上的准确率仅为 48.8% 。这表明模型完全无法有效学习。
先使用preprocessing.scale()
对数据进行标准化,再进行训练和测试,准确率大幅提升至 94.4% 。
from sklearn import preprocessing
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_classification
from sklearn.svm import SVC
import matplotlib.pyplot as plt
# 1. 生成数据
X, y = make_classification(
n_samples=300,
n_features=2,
n_redundant=0,
n_informative=2,
random_state=22,
n_clusters_per_class=1,
scale=100
)
# 2. 对比实验
X_scaled = preprocessing.scale(X) # 对整个特征集进行标准化
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.3)
# 3. 训练并评估模型
clf = SVC()
clf.fit(X_train, y_train)
print("进行特征缩放后的准确率: ", clf.score(X_test, y_test))
其他缩放方法:归一化 (Min-Max Scaling)
除了标准化,另一种常见的缩放方法是归一化,它通过 sklearn.preprocessing.MinMaxScaler
实现。归一化将每个特征的数值线性地缩放到一个给定的区间,默认为 [0, 1]
。其计算公式为:
X_scaled = (X - X_min) / (X_max - X_min)
当数据分布有明显的边界且不符合高斯分布时,归一化是一个不错的选择。
哪些算法需要特征缩放?
高度敏感的算法一般需要特征缩放, 任何基于距离计算的算法(如 K-NN、K-Means)、依赖梯度下降优化的算法(如线性回归、逻辑回归、神经网络)以及依赖特征方差的算法(如主成分分析 PCA)。支持向量机(SVM)对尺度也非常敏感。
基本不敏感则一般不需要: 树模型(如决策树、随机森林、梯度提升树)。因为树模型在选择分裂点时是基于单个特征的,不涉及特征间的距离或幅度比较,因此对尺度不敏感。