Sklearn(全称 scikit-learn)是一个开源的机器学习库
在 Sklearn 中,机器学习的流程遵循一定的模式:数据加载、数据预处理、训练模型、评估模型 和 调优模型
数据加载:使用 Sklearn 或其他库加载数据集,例如通过 datasets.load_iris() 加载经典的鸢尾花数据集,或使用 train_test_split() 分割数据
数据预处理:根据数据的类型,可能需要进行标准化、去噪、缺失值填充等操作
选择算法和训练模型:选择适合的算法(如逻辑回归、支持向量机等),使用 .fit() 方法对模型进行训练
模型评估:使用交叉验证或单一训练/测试集来评估模型的准确性、召回率、F1分数等性能指标
模型优化:使用网格搜索(GridSearchCV)或随机搜索(RandomizedSearchCV)对模型进行超参数优化,提高模型性能
Sklearn 提供了大量经典的机器学习算法
分类算法:如逻辑回归、支持向量机(SVM)、K近邻(KNN)、随机森林等
回归算法:如线性回归、岭回归、Lasso回归等
聚类算法:如 K均值、层次聚类、DBSCAN 等
降维算法:如主成分分析(PCA)、t-SNE 等
模型选择与评估:交叉验证、网格搜索、模型评估指标等
Sklearn 可以很好地与 NumPy、SciPy、Pandas 等 Python 数据处理库兼容,支持多种数据格式(如 NumPy 数组、Pandas DataFrame)进行输入和输出
5大方面:数据表示、模型类型、预处理方法、评估指标、模型调优
数据表示:数据集和特征
import numpy as np
X = np.array([[1.0, 2.0], [2.0, 3.0], [3.0, 4.0]]) #3 个样本,每个样本有 2 个特征
特征和标签
数据集分割
在实际应用中,通常需要将数据集分割成训练集和测试集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
模型与算法
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X_normalized = scaler.fit_transform(X)
模型评估与验证
from sklearn.model_selection import cross_val_score
scores = cross_val_score(clf, X, y, cv=5) # 5-fold cross-validation 5折交叉验证
print("Cross-validation scores:", scores)
from sklearn.metrics import accuracy_score, classification_report
print("Accuracy:", accuracy_score(y_test, y_pred))
print("Classification Report:\n", classification_report(y_test, y_pred))
from sklearn.metrics import mean_squared_error, r2_score
print("MSE:", mean_squared_error(y_test, y_pred))
print("R²:", r2_score(y_test, y_pred))
模型选择与调优
from sklearn.model_selection import GridSearchCV
param_grid = {'max_depth': [3, 5, 7], 'min_samples_split': [2, 5, 10]}
grid_search = GridSearchCV(DecisionTreeClassifier(), param_grid, cv=5)
grid_search.fit(X_train, y_train)
print("Best parameters:", grid_search.best_params_)
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import randint
param_dist = {'max_depth': [3, 5, 7], 'min_samples_split': randint(2, 10)}
random_search = RandomizedSearchCV(DecisionTreeClassifier(), param_dist, n_iter=10, cv=5)
random_search.fit(X_train, y_train)
print("Best parameters:", random_search.best_params_)
import pandas as pd
from sklearn.impute import SimpleImputer
data={
'name':['Amy','Jhon'],
'age': [15,18]
}
df = pd.DataFrame(data)
print(df.isnull().sum()) # 查看每一列缺失值的数量
df_cleaned = df.dropna() # 删除包含缺失值的行
# 对于数值型数据,使用均值填充
imputer = SimpleImputer(strategy='mean') # 可选:'mean', 'median', 'most_frequent'
df_imputed = imputer.fit_transform(df) # 填充缺失值
# df_imputed = SimpleImputer(strategy='mean').fit_transfrom(df)
为什么需要标准化和归一化?
标准化:对于距离度量(如 K 最近邻、支持向量机等)非常重要,因为特征的尺度不一致可能导致某些特征对模型的影响过大。标准化能确保每个特征对模型有相同的贡献
归一化:有些算法(如神经网络、梯度下降优化算法等)对输入数据的范围非常敏感,归一化有助于加速收敛
机器学习模型通常无法直接处理字符串类型的类别变量,因此需要将类别变量转化为数值型数据
from sklearn.preprocessing import LabelEncoder
# 或者OrdinalEncoder
# 假设我们有一个类别变量 y
label_encoder = LabelEncoder()
y_encoded = label_encoder.fit_transform(y) # 将类别变量转换为整数
from sklearn.preprocessing import OneHotEncoder
# 假设我们有一个类别变量 X
encoder = OneHotEncoder(sparse=False) # sparse=False 返回一个密集矩阵
X_encoded = encoder.fit_transform(X) # 将类别变量转换为独热编码
# 在 pandas 中,也可以使用 get_dummies() 函数进行独热编码:
X_encoded = pd.get_dummies(X)
通过选择最重要的特征来提高模型的性能,并减少计算成本
from sklearn.ensemble import RandomForestClassifier
# 训练一个随机森林模型
clf = RandomForestClassifier()
clf.fit(X_train, y_train)
# 获取特征重要性
importances = clf.feature_importances_
print(importances)
from sklearn.feature_selection import RFE
# 使用线性模型进行递归特征消除
rfe = RFE(clf, n_features_to_select=3) # 保留 3 个最重要的特征
X_rfe = rfe.fit_transform(X_train, y_train)
通过对现有特征进行处理、组合或构造新的特征,以提高模型的表现
特征工程的常见方式包括:
旨在从原始特征中提取出新的、更具表达力的特征
常见的特征提取方法包括: 主成分分析(PCA) 和 线性判别分析(LDA)
from sklearn.decomposition import PCA
# 假设 X 是特征矩阵
pca = PCA(n_components=2) # 降维到 2 个主成分
X_pca = pca.fit_transform(X)
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
# 假设 X 是特征矩阵,y 是目标变量
lda = LinearDiscriminantAnalysis(n_components=2) # 降维到 2 个线性判别组件
X_lda = lda.fit_transform(X, y)
在分类问题中,如果数据集的各类别样本数量差异较大,可能会导致模型偏向预测多数类,从而影响模型的性能
常见的处理方法包括:
通过增加少数类样本的数量,使得数据集更加平衡
常见的方法是使用 SMOTE(Synthetic Minority Over-sampling Technique) 算法
from imblearn.over_sampling import SMOTE
smote = SMOTE()
X_resampled, y_resampled = smote.fit_resample(X_train, y_train)
通过减少多数类样本的数量,使得数据集更加平衡
from imblearn.under_sampling import RandomUnderSampler
undersampler = RandomUnderSampler()
X_resampled, y_resampled = undersampler.fit_resample(X_train, y_train)
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
iris=load_iris()
X=pd.DataFrame(iris.data,columns=iris.feature_names)
y=pd.Series(iris.target)
print(X.head()) # 查看前五行
# 假设 X 是特征矩阵,y 是标签
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
model = LogisticRegression()
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
K-近邻(KNN)是一种基于实例的学习方法,预测时通过计算待预测样本与训练集中所有样本的距离,选取距离最近的 K 个邻居,并根据邻居的标签进行预测
主要参数:
from sklearn.neighbors import KNeighborsClassifier
# 假设 X 是特征矩阵,y 是标签
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
model = KNeighborsClassifier(n_neighbors=3)
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
支持向量机是一种强大的分类模型,尤其适用于高维数据
SVM 的基本思想是找到一个超平面,使得不同类别的样本点之间的间隔最大化
对于非线性可分的数据,SVM 通过核技巧将数据映射到高维空间,找到一个分隔超平面
核函数:
from sklearn.svm import SVC
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.3,random_state=42)
model=SVC(kernel='linear')
model.fit(X_train,y_train)
y_pred=model.predict(X_test)
决策树是一种树形结构的分类模型,通过对数据进行分裂,最终将数据划分到不同的类别
随机森林则是通过构建多棵决策树,并通过投票或平均来决定最终的预测结果
决策树通过选择最优的特征进行数据划分,选择准则通常是 信息增益 或 基尼系数
随机森林通过多棵决策树的集成来减少过拟合,并提高模型的准确性。它通过引入随机性(如随机选择特征、随机选择数据子集)来增加模型的多样性
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
# 假设 X 是特征矩阵,y 是标签
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 决策树
dt_model = DecisionTreeClassifier()
dt_model.fit(X_train, y_train)
# 随机森林
rf_model = RandomForestClassifier(n_estimators=100)
rf_model.fit(X_train, y_train)
# 预测
dt_pred = dt_model.predict(X_test)
rf_pred = rf_model.predict(X_test)
from sklearn.linear_model import LinearRegression
# 假设 X 是特征矩阵,y 是目标变量
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
model = LinearRegression()
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
岭回归是线性回归的一个变种,使用 L2 正则化 来约束模型的复杂度,避免过拟合
通过惩罚回归系数的大小,岭回归能更好地处理多重共线性问题
from sklearn.linear_model import Ridge
model = Ridge(alpha=1.0) # alpha 是正则化参数
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
Lasso 回归也是线性回归的一种形式,它使用 L1 正则化 来对回归系数进行惩罚
与岭回归不同,Lasso 会将一些回归系数压缩到零,从而实现特征选择
from sklearn.linear_model import Lasso
model = Lasso(alpha=0.1) # alpha 是正则化参数
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
from sklearn.cluster import KMeans
model = KMeans(n_clusters=3)
model.fit(X)
# 获取聚类标签
labels = model.predict(X)
DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种基于密度的聚类算法,它通过寻找密度相对较高的区域来进行聚类,不需要事先指定簇的数量
from sklearn.cluster import DBSCAN
model=DBSCAN(eps=0.5,min_samples=5)
model.fit(X)
# 获取聚类标签
labels = model.labels_
层次聚类是一种通过递归地合并或分割簇的方式进行聚类的方法
常用的层次聚类方法有 凝聚型聚类(Agglomerative)和 分裂型聚类(Divisive)
from sklearn.cluster import AgglomerativeClustering
model=AgglomerativeClustering(n_clusters=3)
labels=model.fit_predict(X)
from sklearn.metrics import accuracy_score, recall_score, f1_score
accuracy = accuracy_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
print(f"Accuracy: {accuracy}")
print(f"Recall: {recall}")
print(f"F1 Score: {f1}")
classification_report 提供了精度、召回率、F1 分数和支持度(每个类别的样本数)等信息
confusion_matrix 混淆矩阵用于显示分类模型在各个类别上的表现,特别是如何将正类预测为负类,反之亦然
roc_auc_score ROC AUC(接收者操作特征曲线下面积)是评估分类模型性能的指标,尤其适用于不平衡数据集。AUC 值越高,模型性能越好
from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred))
# precision recall f1-score support(样本数)
# 0 1.00 1.00 1.00 19
# 1 1.00 1.00 1.00 13
# 2 1.00 1.00 1.00 13
# accuracy(准确率) 1.00 45
# macro avg(宏平均) 1.00 1.00 1.00 45
# weighted avg(加权平均) 1.00 1.00 1.00 45
from sklearn.metrics import confusion_matrix
print(confusion_matrix(y_test, y_pred))
# [[19 0 0]
# [ 0 13 0]
# [ 0 0 13]]
# n*n的混淆矩阵,n个类别
# 行表示 真实类别
# 列表示 预测类别
# 对角线上的数字表示 预测正确 的样本数
# 非对角线上的数字表示 预测错误 的样本数
from sklearn.metrics import roc_auc_score
# y_test 是真实标签,y_pred_proba 是模型预测的概率值!!
# print(f"ROC AUC Score: {roc_auc_score(y_test, y_pred_proba)}")
对于回归问题
mean_squared_error 均方误差是回归模型的常见评估标准,计算预测值与真实值之间的平方误差的均值
r2_score 决定系数 R² 用于衡量模型对数据的拟合程度,值越接近 1,表示模型拟合得越好
from sklearn.metrics import mean_squared_error,r2_score
print(f"Mean Squared Error: {mean_squared_error(y_test, y_pred)}")
print(f"R² Score: {r2_score(y_test, y_pred)}")
将数据集分成多个子集(折叠),并多次训练和测试模型来获得更稳定、可靠的评估结果
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
# 进行 5 折交叉验证
scores = cross_val_score(model, X, y, cv=5)
print(f"Cross-validation scores: {scores}") # 返回每一折的评分
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC
# 定义参数网格
parameters = {'kernel': ['linear', 'rbf'], 'C': [1, 10, 100]}
# 指定需要调优的超参数及其候选值:
# kernel: SVM的核函数类型,测试线性核('linear')和高斯核('rbf')。
# C: 正则化参数,测试值为 1、10 和 100(控制模型的复杂度与训练误差的权衡)
model = SVC()
# 网格搜索
grid_search = GridSearchCV(model, parameters, cv=5) # 5折交叉验证
grid_search.fit(X, y)
# 输出最佳参数
print(f"Best parameters: {grid_search.best_params_}") # 返回网格搜索中表现最好的超参数组合
print(f"Best score: {grid_search.best_score_}") # 返回最佳参数组合下的交叉验证得分
一种更高效的超参数调优方法,它通过从超参数空间中随机选择一定数量的组合进行评估,从而加速调优过程
适用于超参数空间较大时,可以节省计算时间
from sklearn.model_selection import RandomizedSearchCV
from sklearn.svm import SVC
from scipy.stats import uniform
# 加载数据
data = load_iris()
X, y = data.data, data.target
# 创建模型
model = SVC()
# 定义超参数分布
param_distributions = {'C': uniform(0, 10), 'kernel': ['linear', 'rbf']}
# 执行随机搜索
random_search = RandomizedSearchCV(model, param_distributions, n_iter=10, cv=5)
random_search.fit(X, y)
# 输出最佳参数和最佳得分
print(f"Best parameters: {random_search.best_params_}")
print(f"Best score: {random_search.best_score_}")
在机器学习项目中,数据处理、特征工程、模型训练、评估等步骤往往是互相依赖的,这些步骤的顺序和协调性对于最终模型的性能至关重要
Pipeline 是 scikit-learn 中用于组织和简化这些步骤的一个重要工具
通过 Pipeline,我们可以将数据预处理与模型训练整合在一起,从而简化工作流并提高代码的可复用性
Pipeline 是一个可按顺序执行多个数据处理步骤和模型训练步骤的工具
Pipeline由多个步骤(step)组成,每个步骤是一个元组,包含一个名称和一个对象
每个对象通常是一个 转换器(Transformer) 或 估计器(Estimator),其中:
转换器(Transformer) 是执行数据转换的对象,比如数据预处理(例如归一化、标准化、特征选择等)估计器(Estimator) 是用于训练模型的对象,例如分类器或回归器Pipeline 使得将多个步骤整合为一个可重用的工作流变得简单,并且可以确保数据处理过程的一致性,避免因代码重复或手动处理导致的错误
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
# 加载数据
data = load_iris()
X, y = data.data, data.target
# 将数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建 Pipeline
pipeline = Pipeline([
('scaler', StandardScaler()), # 数据标准化,注意加逗号
('svc', SVC()) # 支持向量机分类器
])
# 训练模型
pipeline.fit(X_train, y_train)
# 预测结果
y_pred = pipeline.predict(X_test)
# 打印模型精度
print(f"Model accuracy: {pipeline.score(X_test, y_test)}")
# 首先执行数据预处理步骤(如标准化),然后传递处理后的数据给模型进行训练。
# 这个过程可以通过 pipeline.fit() 一步完成,pipeline.predict() 进行预测时,数据也会按照相同的顺序通过管道中的每个步骤
## 是否使用Pipeline对比
# Without Pipeline (需要多次执行预处理)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # 防止数据泄露,训练集标准化不能用到测试集
X_test_scaled = scaler.transform(X_test) # 同理,所以要分开计算
model = SVC()
model.fit(X_train_scaled, y_train)
y_pred = model.predict(X_test_scaled)
# With Pipeline (一步完成)
pipeline = Pipeline([
('scaler', StandardScaler()),
('svc', SVC())
])
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
当我们使用 Pipeline 时,可以直接进行超参数调优
通过结合 GridSearchCV 或 RandomizedSearchCV,可以优化管道中的每一个步骤的超参数
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
from sklearn.model_selection import GridSearchCV
# 加载数据
data = load_iris()
X, y = data.data, data.target
# 将数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建 Pipeline
pipeline = Pipeline([
('scaler', StandardScaler()), # 数据标准化
('svc', SVC()) # 支持向量机分类器
])
# 训练模型
pipeline.fit(X_train, y_train)
# 定义超参数网格
param_grid = {
'svc__C': [0.1, 1, 10], # 调整 SVC 中的 C 参数
'svc__kernel': ['linear', 'rbf'] # 调整 kernel 参数
}
# 创建 GridSearchCV 对象
grid_search = GridSearchCV(pipeline, param_grid, cv=5)
# 执行超参数调优
grid_search.fit(X_train, y_train)
# 输出最佳参数和得分
print(f"Best parameters: {grid_search.best_params_}")
print(f"Best score: {grid_search.best_score_}")
结合 Pipeline 和交叉验证
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score
data=load_iris()
X,y=data.data,data.target
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.3,random_state=42)
pipeline=Pipeline([
('scaler',StandardScaler()),
('svc',SVC())
])
pipeline.fit(X_train,y_train)
cv_scores = cross_val_score(pipeline,X,y,cv=5)
print(f"Cross-validation scores: {cv_scores}")
print(f"Mean cross-validation score: {cv_scores.mean()}")
除了使用现成的模型和预处理功能外,用户还可以根据自己的需求创建自定义的模型、转换器和功能
通常涉及继承 scikit-learn 的基类,如 BaseEstimator 和 TransformerMixin,然后实现特定的 fit 和 predict 方法
转换器是用于对数据进行转换的组件,例如标准化、特征选择等。自定义转换器可以继承 TransformerMixin,并实现 fit 和 transform 方法
import numpy as np
from sklearn.base import BaseEstimator, TransformerMixin
# 实现一个自定义的标准化转换器
class CustomScaler(BaseEstimator, TransformerMixin):
def fit(self, X, y=None):
"""
计算每个特征的均值和标准差
"""
self.mean_ = np.mean(X, axis=0)
self.std_ = np.std(X, axis=0)
return self # 返回对象本身
def transform(self, X):
"""
标准化数据
"""
return (X - self.mean_) / self.std_
# 测试自定义转换器
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# 加载数据
data = load_iris()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建自定义转换器对象
scaler = CustomScaler()
# 使用自定义标准化
scaler.fit(X_train) # 只能fit(X_train)并应用到测试集,避免数据泄露
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)
print("Scaled training data:\n", X_train_scaled)
# fit 方法计算训练数据的均值和标准差,并保存这些值
# transform 方法根据 fit 中计算的均值和标准差来转换数据
估计器是指模型本身,如回归器、分类器等
自定义估计器需要继承 BaseEstimator 类,并实现 fit 和 predict 方法
from sklearn.base import BaseEstimator
import numpy as np
class SimpleClassifier(BaseEstimator):
def fit(self,X,y):
"""
训练模型:计算每个特征的均值
"""
self.mean_=np.mean(X,axis=0)
return self
def predict(self,X):
"""
基于均值进行分类:如果特征值大于均值,则预测为 1,否则为 0
"""
return (X>self.mean_).astype(int)
# 测试自定义分类器
X_train = np.array([[1.5, 2.5], [2.0, 3.0], [3.5, 4.5], [4.0, 5.0]])
y_train = np.array([0, 0, 1, 1])
# 创建自定义分类器对象
classifier = SimpleClassifier()
# 训练模型
classifier.fit(X_train, y_train)
# 进行预测
X_test = np.array([[2.5, 3.5], [1.0, 2.0]])
y_pred = classifier.predict(X_test)
print("Predictions:", y_pred)
# fit 方法计算训练数据的均值并将其存储在 self.mean_ 中
# predict 方法通过比较测试数据与均值的大小,做出分类预测
scikit-learn 允许将自定义转换器和估计器作为管道的步骤
这使得可以将数据预处理和模型训练过程整合成一个工作流
自定义模型和功能可以像内建的转换器和估计器一样,与管道一起工作
import numpy as np
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.pipeline import Pipeline
# 利用前面俩个例子的自定义转换器和估计器
# 测试自定义分类器
X_train = np.array([[1.5, 2.5], [2.0, 3.0], [3.5, 4.5], [4.0, 5.0]])
y_train = np.array([0, 0, 1, 1])
# 创建管道,包含自定义的标准化和分类器
pipeline = Pipeline([
('scaler', CustomScaler()), # 自定义标准化
('classifier', SimpleClassifier()) # 自定义分类器
])
# 训练管道
pipeline.fit(X_train, y_train)
X_test = np.array([[2.5, 3.5], [1.0, 2.0]])
# 预测
y_pred = pipeline.predict(X_test)
print("Predictions:", y_pred)
通过继承这两个基类,我们可以非常方便地创建自己的自定义模型和功能,并且可以利用 scikit-learn 的工具(如 GridSearchCV 和 Pipeline)进行调优和评估。
from sklearn.base import BaseEstimator, TransformerMixin
import numpy as np
from sklearn.pipeline import Pipeline
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
class CustomEstimator(BaseEstimator, TransformerMixin):
def fit(self, X, y=None):
# 模拟一个简单的"模型":计算每个特征的均值
self.mean_ = np.mean(X, axis=0)
return self
def transform(self, X):
# 基于均值将数据标准化
return X - self.mean_
def predict(self, X):
# 简单的预测方法:如果特征值大于均值,则预测为 1,否则为 0
return (X > self.mean_).astype(int)
# 使用自定义估计器和转换器
# 加载数据
data = load_iris()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建管道
pipeline = Pipeline([
('custom', CustomEstimator())
])
# 训练模型
pipeline.fit(X_train, y_train)
# 没有标准化
# 预测
y_pred = pipeline.predict(X_test)
print("Predictions:", y_pred)
在机器学习中,模型的训练过程通常是耗时的,为了避免每次重新训练模型,我们可以将训练好的模型保存下来,便于以后进行加载和预测
scikit-learn 提供了两种常用的方式来保存和加载模型:joblib 和 pickl
joblib 是一个高效的 Python 序列化工具,特别适合用于保存包含大量数值数组(如 numpy 数组、scikit-learn 模型等)的对象
相较于 pickle,joblib 在处理大规模数据时更高效
joblib 提供了一个简单的 API 来保存和加载对象
我们可以使用 joblib.dump() 方法将模型保存到文件中
joblib.dump()
joblib.load()
import joblib
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
data = load_iris()
X, y = data.data, data.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建并训练模型
model = SVC(kernel='linear')
model.fit(X_train, y_train)
## 保存
# 保存模型到文件
joblib.dump(model, 'svm_model.joblib')
##加载
# 加载保存的模型
model = joblib.load('svm_model.joblib')
# 使用加载的模型进行预测
y_pred = model.predict(X_test)
# 打印预测结果
print("Predictions:", y_pred)
pickle 是 Python 内置的模块,允许将 Python 对象序列化和反序列化
虽然 joblib 更适用于处理大量数据,但 pickle 也是常用的保存和加载模型的工具,适用于一般情况
import pickle
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
data = load_iris()
X, y = data.data, data.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建并训练模型
model = SVC(kernel='linear')
model.fit(X_train, y_train)
## 保存
# 使用 pickle 保存模型
with open('svm_model.pkl', 'wb') as f:
pickle.dump(model, f)
## 加载
with open('svm_model.pkl', 'rb') as f:
loaded_model = pickle.load(f)
# 使用加载的模型进行预测
y_pred = loaded_model.predict(X_test)
# 打印预测结果
print("Predictions:", y_pred)
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
import joblib
# 创建一个管道
pipeline = Pipeline([
('scaler', StandardScaler()),
('svc', SVC(kernel='linear'))
])
# 训练管道
pipeline.fit(X_train, y_train)
## 保存
# 保存管道到文件
joblib.dump(pipeline, 'pipeline_model.joblib')
## 加载
# 加载管道
loaded_pipeline = joblib.load('pipeline_model.joblib')
# 使用加载的管道进行预测
y_pred = loaded_pipeline.predict(X_test)
# 打印预测结果
print("Predictions:", y_pred)
每次训练模型并保存时,最好为模型文件命名加上时间戳或版本号,以便区分不同版本的模型
import time
# 创建时间戳
timestamp = time.strftime("%Y%m%d-%H%M%S")
# 保存带时间戳的模型
joblib.dump(model, f'svm_model_{timestamp}.joblib')
可以将保存的模型与 Web 服务、批处理作业或其他应用程序集成
假设我们正在使用 Flask 创建一个简单的 Web 服务,通过 API 接口提供模型预测服务
from flask import Flask, request, jsonify
import joblib
import numpy as np
app = Flask(__name__)
# 加载模型
model = joblib.load('svm_model.joblib')
@app.route('/predict', methods=['POST'])
def predict():
data = request.get_json() # 获取输入数据
features = np.array(data['features']).reshape(1, -1) # 转换成适合预测的格式
prediction = model.predict(features) # 使用加载的模型进行预测
return jsonify({'prediction': prediction.tolist()}) # 返回预测结果
if __name__ == '__main__':
app.run(debug=True)
from sklearn.datasets import load_iris
import pandas as pd
# 加载鸢尾花数据集
data = load_iris()
# 转换为 DataFrame 方便查看
df = pd.DataFrame(data.data, columns=data.feature_names)
df['target'] = data.target # 添加目标列 target(0, 1, 2 分别代表三种鸢尾花)
df['species'] = df['target'].apply(lambda x: data.target_names[x]) # 添加物种名称列 species,通过映射 target_names 将数字标签转换为字符串名称
# 查看前5行数据
print(df.head())
from sklearn.datasets import load_iris
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 加载鸢尾花数据集
data = load_iris()
# 转换为 DataFrame 方便查看
df = pd.DataFrame(data.data, columns=data.feature_names)
df['target'] = data.target
df['species'] = df['target'].apply(lambda x: data.target_names[x])
# 绘制特征之间的关系
sns.pairplot(df, hue="species") #绘制所有特征两两之间的散点图矩阵,hue="species" 表示用不同颜色区分不同物种
plt.show()
from sklearn.datasets import load_iris
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 加载鸢尾花数据集
data = load_iris()
# 转换为 DataFrame 方便查看
df = pd.DataFrame(data.data, columns=data.feature_names)
df['target'] = data.target
df['species'] = df['target'].apply(lambda x: data.target_names[x])
# 绘制特征之间的关系
correlation_matrix = df.drop(columns=['target', 'species']).corr()
sns.heatmap(correlation_matrix, annot=True, cmap="coolwarm", fmt=".2f") # 热力图查看特征之间的相关性
plt.title("Correlation Heatmap")
plt.show()
from sklearn.preprocessing import StandardScaler
# 提取特征和标签
X = df.drop(columns=['target', 'species'])
y = df['target']
# 对于鸢尾花数据集,特征值已经是数值型数据,不需要太多的预处理。但是,我们可以对数据进行标准化,以提高模型的训练效果
# 标准化特征
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
from sklearn.feature_selection import SelectKBest, f_classif
# 使用卡方检验选择 2 个最相关的特征
selector = SelectKBest(f_classif, k=2)
X_new = selector.fit_transform(X_scaled, y)
# 打印选择的特征
selected_features = selector.get_support(indices=True)
print("Selected features:", X.columns[selected_features])
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
# 初始化决策树分类器
model_dt = DecisionTreeClassifier(random_state=42)
# 训练模型
model_dt.fit(X_train, y_train)
# 预测
y_pred_dt = model_dt.predict(X_test)
# 评估模型
accuracy_dt = accuracy_score(y_test, y_pred_dt)
print(f"Decision Tree Accuracy: {accuracy_dt:.4f}")
from sklearn.svm import SVC
# 初始化 SVM 分类器
model_svm = SVC(kernel='linear', random_state=42)
# 训练模型
model_svm.fit(X_train, y_train)
# 预测
y_pred_svm = model_svm.predict(X_test)
# 评估模型
accuracy_svm = accuracy_score(y_test, y_pred_svm)
print(f"SVM Accuracy: {accuracy_svm:.4f}")
from sklearn.metrics import classification_report, confusion_matrix
# 混淆矩阵
cm = confusion_matrix(y_test, y_pred_dt)
print("Confusion Matrix (Decision Tree):")
print(cm)
# 精度、召回率、F1 分数
report = classification_report(y_test, y_pred_dt)
print("Classification Report (Decision Tree):")
print(report)
from sklearn.model_selection import GridSearchCV
# 定义决策树的参数网格
param_grid = {
'max_depth': [3, 5, 10, None],
'min_samples_split': [2, 5, 10],
'min_samples_leaf': [1, 2, 4]
}
# 初始化 GridSearchCV
grid_search = GridSearchCV(estimator=DecisionTreeClassifier(random_state=42), param_grid=param_grid, cv=5)
# 训练网格搜索
grid_search.fit(X_train, y_train)
# 获取最佳参数和最佳模型
print("Best Parameters:", grid_search.best_params_)
best_model = grid_search.best_estimator_
# 预测和评估
y_pred_optimized = best_model.predict(X_test)
accuracy_optimized = accuracy_score(y_test, y_pred_optimized)
print(f"Optimized Decision Tree Accuracy: {accuracy_optimized:.4f}")
from sklearn.model_selection import cross_val_score
# 进行 5 折交叉验证
cross_val_scores = cross_val_score(best_model, X_scaled, y, cv=5)
print(f"Cross-validation Scores: {cross_val_scores}")
print(f"Mean CV Accuracy: {cross_val_scores.mean():.4f}")
# 导入必要的库
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, GridSearchCV, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# 1. 数据加载
# 加载鸢尾花数据集
data = load_iris()
# 转换为 DataFrame 方便查看
df = pd.DataFrame(data.data, columns=data.feature_names)
df['target'] = data.target
df['species'] = df['target'].apply(lambda x: data.target_names[x])
# 查看前几行数据
print("数据预览:")
print(df.head())
# 2. 数据可视化
# 绘制特征之间的关系
sns.pairplot(df, hue="species")
plt.show()
# 绘制热力图查看特征之间的相关性
correlation_matrix = df.drop(columns=['target', 'species']).corr()
sns.heatmap(correlation_matrix, annot=True, cmap="coolwarm", fmt=".2f")
plt.title("Correlation Heatmap")
plt.show()
# 3. 特征选择与数据预处理
# 提取特征和标签
X = df.drop(columns=['target', 'species'])
y = df['target']
# 数据标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 4. 建立分类模型
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
# 使用决策树分类器
model_dt = DecisionTreeClassifier(random_state=42)
model_dt.fit(X_train, y_train)
# 预测
y_pred_dt = model_dt.predict(X_test)
# 输出决策树的准确率
accuracy_dt = accuracy_score(y_test, y_pred_dt)
print(f"Decision Tree Accuracy: {accuracy_dt:.4f}")
# 使用支持向量机(SVM)分类器
model_svm = SVC(kernel='linear', random_state=42)
model_svm.fit(X_train, y_train)
# 预测
y_pred_svm = model_svm.predict(X_test)
# 输出SVM的准确率
accuracy_svm = accuracy_score(y_test, y_pred_svm)
print(f"SVM Accuracy: {accuracy_svm:.4f}")
# 5. 模型评估
# 决策树模型评估
print("\nDecision Tree Classification Report:")
print(classification_report(y_test, y_pred_dt))
print("\nDecision Tree Confusion Matrix:")
print(confusion_matrix(y_test, y_pred_dt))
# SVM模型评估
print("\nSVM Classification Report:")
print(classification_report(y_test, y_pred_svm))
print("\nSVM Confusion Matrix:")
print(confusion_matrix(y_test, y_pred_svm))
# 6. 网格搜索调优
# 定义决策树的参数网格
param_grid = {
'max_depth': [3, 5, 10, None],
'min_samples_split': [2, 5, 10],
'min_samples_leaf': [1, 2, 4]
}
# 初始化 GridSearchCV
grid_search = GridSearchCV(estimator=DecisionTreeClassifier(random_state=42), param_grid=param_grid, cv=5)
grid_search.fit(X_train, y_train)
# 获取最佳参数和最佳模型
print("\nBest Parameters from GridSearchCV (Decision Tree):")
print(grid_search.best_params_)
# 使用最佳模型进行预测
best_model = grid_search.best_estimator_
y_pred_optimized = best_model.predict(X_test)
# 输出优化后的决策树准确率
accuracy_optimized = accuracy_score(y_test, y_pred_optimized)
print(f"Optimized Decision Tree Accuracy: {accuracy_optimized:.4f}")
# 7. 交叉验证
# 进行 5 折交叉验证
cross_val_scores = cross_val_score(best_model, X_scaled, y, cv=5)
print("\nCross-validation Scores (Optimized Decision Tree):")
print(cross_val_scores)
print(f"Mean CV Accuracy: {cross_val_scores.mean():.4f}")
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
# 模拟数据:包含房屋的面积、房间数、楼层、建造年份、位置(类别变量),以及房价(目标变量)
data = {
'area': [70, 85, 100, 120, 60, 150, 200, 80, 95, 110],
'rooms': [2, 3, 3, 4, 2, 5, 6, 3, 3, 4],
'floor': [5, 2, 8, 10, 3, 15, 18, 7, 9, 11],
'year_built': [2005, 2010, 2012, 2015, 2000, 2018, 2020, 2008, 2011, 2016],
'location': ['Chaoyang', 'Haidian', 'Chaoyang', 'Dongcheng', 'Fengtai', 'Haidian', 'Chaoyang', 'Fengtai', 'Dongcheng', 'Haidian'],
'price': [5000000, 6000000, 6500000, 7000000, 4500000, 10000000, 12000000, 5500000, 6200000, 7500000] # 房价(目标变量)
}
# 创建 DataFrame
df = pd.DataFrame(data)
# 查看数据
print("数据预览:")
print(df.head())
# 特征选择
X = df[['area', 'rooms', 'floor', 'year_built', 'location']] # 特征数据
y = df['price'] # 目标变量
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 数据预处理:数值特征标准化、类别特征 One-Hot 编码
numeric_features = ['area', 'rooms', 'floor', 'year_built']
categorical_features = ['location']
# 数值特征预处理:标准化
numeric_transformer = Pipeline(steps=[
('scaler', StandardScaler())
])
# 类别特征预处理:One-Hot 编码,设置 handle_unknown='ignore'
categorical_transformer = Pipeline(steps=[
('onehot', OneHotEncoder(handle_unknown='ignore'))
# handle_unknown='ignore':如果测试集出现训练集中未见的类别,不会报错,而是将该样本的所有独热编码列设为0(避免预处理失败)
])
# 合并数值和类别特征的处理步骤
preprocessor = ColumnTransformer(
transformers=[ #transformers:定义列名和对应的预处理管道。格式:(名称, 转换器, 列名列表)
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features)
]
)
# 3. 建立模型
# 使用线性回归模型,结合数据预处理步骤
model_pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('regressor', LinearRegression())
])
# 训练模型
model_pipeline.fit(X_train, y_train)
# 进行预测
y_pred = model_pipeline.predict(X_test)
# 输出预测结果
print("\n预测结果:")
print(y_pred)
# 4. 模型评估:计算均方误差(MSE)和 R² 决定系数
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print("\n模型评估:")
print(f"均方误差 (MSE): {mse:.2f}")
print(f"决定系数 (R²): {r2:.2f}")
# 5. 模型优化:使用网格搜索调整超参数
# 对线性回归的超参数进行调优(仅调整 'fit_intercept')
param_grid = {
'regressor__fit_intercept': [True, False], # 是否拟合截距
}
grid_search = GridSearchCV(model_pipeline, param_grid, cv=5, scoring='neg_mean_squared_error', verbose=1)
grid_search.fit(X_train, y_train)
# 输出最佳参数和结果
print("\n最佳参数:")
print(grid_search.best_params_)
# 使用最佳模型进行预测
best_model = grid_search.best_estimator_
y_pred_optimized = best_model.predict(X_test)
# 输出优化后的评估结果
mse_opt = mean_squared_error(y_test, y_pred_optimized)
r2_opt = r2_score(y_test, y_pred_optimized)
print("\n优化后的模型评估:")
print(f"均方误差 (MSE): {mse_opt:.2f}")
print(f"决定系数 (R²): {r2_opt:.2f}")