一、Scikit-Learn简介
Scikit-Learn(sklearn)是 Python 语言中最流行的机器学习库之一,提供了丰富的工具用于数据预处理、特征工程、模型训练、模型评估以及超参数调优。
二、 主要特点
- 简单易用的 API 设计
- 支持各种监督学习和无监督学习算法
- 具备数据预处理、特征选择、模型选择等功能
- 兼容 NumPy、Pandas 以及 Matplotlib
三、 安装与导入
1. 安装
pip install scikit-learn
2. 导入基本模块
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
- sklearn.datasets: 提供了一些标准数据集,用于测试和练习机器学习算法。
- sklearn.model_selection.train_test_split: 用于将数据集随机划分为训练集和测试集。
- sklearn.preprocessing.StandardScaler: 用于对数据进行标准化处理(均值为0,方差为1)。
- sklearn.ensemble.RandomForestClassifier: 实现了随机森林分类算法,用于分类任务。
- sklearn.metrics.accuracy_score: 用于计算分类模型的准确率(预测正确的比例)。
注意:安装时是全称,导入时是缩写。
四、数据集加载与预处理
1. 定义加载数据集函数
Scikit-Learn 提供了多个内置数据集,例如 iris、digits、wine。此处以iris为例。
# iris 数据存储在 data/iris/iris.csv
def load_data():
iris_path = os.path.join(constant.DATA_DIR, "iris/iris.csv")
df = pd.read_csv(iris_path)
# print(df.head())
X = df.iloc[:, :4]
y = df.iloc[:, 4]
return X, y
逐行解释代码:
iris_data_path = os.path.join(constant.DATA_DIR, "iris/iris.csv")
作用: 构建文件路径。
解释:
- os.path.join() 是 Python 的 os 模块中的一个函数,用于将多个路径组件拼接成一个完整的路径。
- constant.DATA_DIR 是一个变量,表示数据存储的根目录(例如 "data")。详见文件管理01-设置项目的目录路径
- "iris/iris.csv" 是数据文件的相对路径。
最终,iris_data_path 是一个完整的文件路径,例如 "data/iris/iris.csv"。
df = pd.read_csv(iris_path)
iris.csv文件格式如下:
X = df.iloc[:, :4]
y = df.iloc[:, 4]
- X = df.iloc[:, :4]
作用: 提取 DataFrame 的前 4 列作为特征(X)。
解释:
- df.iloc[] 是 Pandas 中用于按位置(行和列的索引)选择数据的函数。
- : 表示选择所有行。
- :4 表示选择前 4 列(列的索引从 0 开始,到 3 结束)。
最终,X 是一个包含前 4 列数据的 DataFrame 或 NumPy 数组。
- y = df.iloc[:, 4]
作用: 提取 DataFrame 的第 5 列作为标签(y)。
解释:
- df.iloc[] 同样是按位置选择数据的函数。
- :表示选择所有行。
- 4 表示选择第 5 列(列的索引从 0 开始,第 5 列的索引是 4)。
最终,y 是一个包含第 5 列数据的 Series 或 NumPy 数组。
2. 数据集拆分
# 2. 数据预处理 数据分割
def prepare(X, y):
X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.2, random_state=42)
return X_train, X_test, y_train, y_test
解释代码:
参数X为特征(数据),y为标注(结果),test_size=0.2,表示20%为测试集,80%是训练集。random_state=42 是一个随机数种子。
参数解释:
- X:是刚才提取 DataFrame 的前 4 列的特征(X)
- y:是提取 DataFrame 的第 5 列的标签(y)。
- test_size=0.2:表示测试集占整个数据集的 20%,剩下的 80% 用于训练。你也可以指定一个 train_size 来控制训练集的比例。
train_test_split 函数:
将 X 和 labels 对应的内容按照给定的比例划分成两个部分:训练集和测试集。
假设 X 共有 4 个文本数据,labels 中有 4 个标签,执行这行代码后,X_train 和 y_train 将包含 80%(3个文本)的训练数据和标签,X_test 和 y_test 则包含 20%(1个文本)的测试数据和标签。
random_state :
是用来确保在数据划分时的随机性可以复现的参数。当我们设置了一个固定的 random_state 值,比如 42,每次运行代码时,train_test_split() 会根据这个值来做相同的划分。也就是说,每次你用相同的数据和相同的代码,分割出的训练集和测试集都是一样的。
3. 数据标准化(在鸢尾花这个例子中放到了训练模型中)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
提问:为什么只有特征需要标准化而标签不需要?
-
特征与标签的不同作用:特征(
X
)是输入数据,它影响模型的学习过程,而标签(y
)是模型预测的输出。特征标准化可以帮助模型更加有效地学习数据模式,尤其是在使用像支持向量机(SVM)、K-近邻(KNN)等依赖于距离计算的模型时。标准化后的特征使得模型在各个特征维度上的学习过程更加均衡。
五、 模型训练与评估
1. 训练模型
def train():
X, y = load_data()
X_train, X_test, y_train, y_test = prepare(X, y)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
逐行解释代码:
scaler = StandardScaler()
功能:创建一个 StandardScaler 对象,用于数据标准化。
标准化:
- 标准化是数据预处理中的常见操作,目的是将不同特征的数值范围缩放到相同的尺度。具体来说,StandardScaler 会将每个特征的值调整为 均值为 0,标准差为 1 的分布。
- 标准化的目的是避免某些数值较大的特征(例如,收入或年龄)对模型产生过大的影响,特别是在像 KNN 或 SVM 这样的距离敏感型算法中。
X_train = scaler.fit_transform(X_train)
功能:
- fit():计算训练集的均值和标准差,用于之后的标准化。
- transform():根据训练集计算得到的均值和标准差,转换训练集数据,使得每个特征的均值为 0,标准差为 1。
最终,返回标准化后的训练集。
X_test = scaler.transform(X_test)
功能:transform() 方法将相同的标准化方法应用于测试集 X_test,即使用训练集的均值和标准差来标准化测试集。
原因:在机器学习中,测试集的数据标准化(或其他预处理)必须使用训练集的参数,而不是在测试集上重新计算参数。所以我们不能在测试集上调用 fit_transform(),只用调用transform() 方法即可。
model = RandomForestClassifier(n_estimators=100, random_state=42)
功能:创建一个 随机森林分类器(RandomForestClassifier)对象,并指定一些参数。
- n_estimators=100:表示森林中将包含 100 个决策树。每棵树会对数据进行训练并输出预测结果,最终的预测结果是这些树的投票结果。
- random_state=42:设置随机种子,确保每次运行代码时训练过程和结果的一致性。
model.fit(X_train, y_train)
功能:通过调用 fit() 方法,将训练数据(X_train 和 y_train)提供给模型来进行训练。
- X_train:训练集特征,模型通过这些特征来进行学习。
- y_train:训练集标签,模型通过这些标签来进行监督学习,调整内部参数。
2. 预测与评估
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"模型准确率: {accuracy:.2f}")
逐行解释代码:
y_pred = model.predict(X_test)
功能:使用训练好的模型来对 测试集(X_test)进行预测,得到预测结果 y_pred。
- model:已经通过训练过的机器学习模型。
- X_test:测试集的特征数据。这个数据集包含了模型在训练过程中未见过的样本,因此它用于验证模型的性能。
- predict():这是模型的一个方法,用于根据训练后的模型对新的数据进行预测。它接受一个包含特征的输入数据(在此处是 X_test),然后输出每个样本的预测标签。
- y_pred:是模型预测的结果。
accuracy = accuracy_score(y_test, y_pred)
功能:计算模型在 测试集上的准确率(accuracy)。
- y_test:实际的测试集标签,即测试数据集中的正确类别。
- y_pred:模型的预测结果,代表模型对于每个测试样本的预测类别。
完整代码:
import os
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from common import constant
# sklearn示例
# 1. 加载数据集
def load_data():
iris_path = os.path.join(constant.DATA_DIR, "iris/iris.csv")
df = pd.read_csv(iris_path)
# print(df.head())
X = df.iloc[:, :4]
y = df.iloc[:, 4]
return X, y
# 2. 数据预处理 数据分割
def prepare(X, y):
X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.2, random_state=42)
return X_train, X_test, y_train, y_test
# 3. 模型训练
def train():
X, y = load_data()
X_train, X_test, y_train, y_test = prepare(X, y)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
# 4. 模型评估
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"模型准确率: {accuracy:.2f}")
def main():
train()
if __name__ == "__main__":
main()
学习效果检验
基于我在实践中不懂的问题,形成了一个问答测试,可用来检验学习效果。
问题 1: 为什么需要对特征数据(X_train 和 X_test)进行标准化处理?
-
解释为什么在使用模型之前需要对训练数据和测试数据的特征进行标准化。
答案 1:
标准化的目的是将特征的值转换到相同的尺度(通常是均值为0,标准差为1),这样可以避免某些特征值过大或过小,导致模型偏向于某些特征。特别是对于使用距离计算的算法(如 KNN、SVM 等),如果特征的尺度差异很大,可能会影响模型性能。在这段代码中,标准化的作用是确保所有特征在相同的尺度上进行处理,提升模型的训练效果和稳定性。
问题 2: 为什么在代码中使用了 train_test_split,并且为什么要有 random_state?
-
解释 train_test_split 的作用以及 random_state 的功能。
答案 2:
train_test_split 是一个用于将数据随机划分为训练集和测试集的函数。它的作用是保证模型能够在未见过的数据上进行测试,防止模型过拟合。random_state 是随机种子,用来保证数据划分的结果在每次运行时都保持一致。也就是说,如果你设置了固定的 random_state,每次分割的训练集和测试集数据都是相同的,这有助于保证实验的可重复性。
问题 3: 为什么 X_test 在标准化时用了 scaler.fit_transform(X_test) 而不是 scaler.transform(X_test)?
-
在这段代码中,X_train 和 X_test 标准化时为什么使用了不同的函数?
答案 3:
这段代码中使用了 scaler.fit_transform(X_train) 和 scaler.fit_transform(X_test),但实际应该是 X_test 只用 transform 方法,因为在标准化过程中,我们应该只使用 X_train 数据来计算均值和标准差(即 fit),然后再应用到测试集(即 transform)。fit_transform 是在训练集上同时进行 拟合 和 转换,而对于测试集,我们只需要 转换(使用 transform)。错误地使用 fit_transform 在 X_test 上会导致测试集也基于测试集的均值和标准差进行标准化,这会影响模型评估的准确性。
问题 4: RandomForestClassifier 的 n_estimators=100 参数是什么意思?
-
解释 RandomForestClassifier 中 n_estimators=100 的含义。
答案 4:
n_estimators=100 表示随机森林模型中树的数量,也就是说,模型会建立 100 棵决策树。随机森林是一种集成学习方法,通过多个决策树的组合来进行预测。增加树的数量通常能够提高模型的稳定性和准确性,但计算开销也会增加。
问题 5: 为什么我们需要使用 accuracy_score 来评估模型的性能?
-
解释为什么选择 accuracy_score 作为模型评估指标,适用于什么情况。
答案 5:
accuracy_score 是一种常见的模型评估指标,用于衡量模型在测试集上的准确度。它的计算方式是正确预测的样本数占总样本数的比例。对于类别不平衡问题较小的分类任务,accuracy 是一个直观且有效的评估指标。但对于类别分布不均匀的情况(如正负样本比例严重不平衡时),准确率可能会存在偏差,其他指标(如精确度、召回率、F1 分数)可能更加合适。
问题 6: train() 函数中的 model.fit(X_train, y_train) 是做什么的?
-
解释 model.fit() 方法的作用。
答案 6:
model.fit(X_train, y_train) 是模型训练的核心步骤,它会基于训练数据(X_train 和对应的标签 y_train)训练一个模型。在训练过程中,模型会从数据中学习到特征和标签之间的关系。通过这种学习,模型会调整内部的参数,使其能够在测试集或未来的数据上做出预测。
问题 7: model.predict(X_test) 的作用是什么?
-
解释 model.predict(X_test) 的功能。
答案 7:
model.predict(X_test) 是用来进行预测的函数。它使用已经训练好的模型来对测试集 X_test 进行预测,并返回预测的标签(y_pred)。在这段代码中,X_test 是模型从未见过的数据,predict 会根据模型在训练过程中学到的规律,预测出 X_test 中每个样本的标签。
问题 8: 为什么 print(f"模型准确率: {accuracy:.2f}") 使用了格式化字符串?
-
解释 print(f"模型准确率: {accuracy:.2f}") 的作用。
答案 8:
print(f"模型准确率: {accuracy:.2f}") 使用了 Python 的 f-string 格式化字符串,目的是将 accuracy 的值格式化为小数点后两位,并将其输出到屏幕上。{accuracy:.2f} 表示将 accuracy 值保留两位小数。例如,如果准确率是 0.9876,输出将是:模型准确率: 0.99。