Scikit-Learn机器学习实战:从入门到项目部署
1. Scikit-Learn机器学习实战入门
Scikit-Learn作为Python生态中最受欢迎的机器学习库之一,已经成为数据科学家和机器学习工程师的标准工具。我第一次接触这个库是在2015年一个电商推荐系统项目中,当时就被它简洁一致的API设计和丰富的算法实现所折服。经过多年实践,我发现无论是学术研究还是工业应用,Scikit-Learn都能提供可靠的支持。
这个库最吸引人的特点是它降低了机器学习的门槛。你不需要从头实现复杂的算法,也不用深入理解每个数学公式的推导过程,就能构建出性能不错的模型。但这并不意味着Scikit-Learn只是"玩具"——它的底层实现经过高度优化,完全可以处理生产环境中的实际问题。
1.1 为什么选择Scikit-Learn
在众多机器学习库中,Scikit-Learn脱颖而出有几个关键原因:
首先,它提供了极其一致的API设计。所有估计器(estimator)都遵循相同的接口规范,比如 fit() 方法用于训练, predict() 方法用于预测。这种一致性大大降低了学习成本,一旦你掌握了一个模型的使用方法,其他模型的使用方式也大同小异。
其次,Scikit-Learn与Python科学计算栈(NumPy、SciPy、Pandas、Matplotlib)无缝集成。这意味着你可以轻松地将数据预处理、特征工程、模型训练和结果可视化等环节串联起来,形成一个完整的工作流。
再者,这个库的文档非常完善。每个算法都有详细的说明文档,包含数学原理、参数解释和使用示例。对于初学者来说,这是极其宝贵的学习资源。
最后,Scikit-Learn背后有一个活跃的开源社区。这意味着它不断更新迭代,bug能及时修复,新功能也会持续加入。
1.2 安装与环境配置
开始使用Scikit-Learn前,我们需要设置合适的Python环境。我强烈建议使用虚拟环境来管理项目依赖,这样可以避免不同项目间的包冲突。
对于Python环境管理,我个人偏好conda,因为它能很好地处理科学计算包的依赖关系。以下是创建和激活conda环境的命令:
conda create -n sklearn-env python=3.9
conda activate sklearn-env
安装Scikit-Learn非常简单,可以通过pip或conda完成:
pip install scikit-learn
# 或者
conda install scikit-learn
为了获得完整的数据科学生态系统,我建议同时安装以下常用包:
pip install numpy scipy pandas matplotlib seaborn jupyter
验证安装是否成功:
import sklearn
print(sklearn.__version__)
注意:Scikit-Learn对NumPy和SciPy有版本要求。如果遇到兼容性问题,可以尝试更新这些依赖库。
2. 机器学习项目工作流
一个完整的机器学习项目通常遵循标准的工作流程。根据我的经验,这个流程可以划分为几个关键阶段,每个阶段都有其独特的挑战和解决方案。
2.1 数据收集与理解
任何机器学习项目的第一步都是获取和理解数据。没有高质量的数据,再先进的算法也无用武之地。我参与过的一个零售业客户分析项目中,我们花了近70%的时间在数据准备和探索上,这充分说明了这个阶段的重要性。
常见的数据来源包括:
- 公开数据集(如UCI机器学习仓库、Kaggle数据集)
- 公司内部数据库
- 网络爬虫获取的数据
- 第三方数据服务
加载数据后,我们需要进行探索性数据分析(EDA)。Pandas是这个阶段的利器:
import pandas as pd
# 加载数据
data = pd.read_csv('dataset.csv')
# 查看前几行
print(data.head())
# 统计摘要
print(data.describe())
# 检查缺失值
print(data.isnull().sum())
可视化工具如Matplotlib和Seaborn能帮助我们更直观地理解数据分布和关系:
import matplotlib.pyplot as plt
import seaborn as sns
# 绘制特征分布
sns.histplot(data['age'], kde=True)
plt.show()
# 特征间关系
sns.pairplot(data[['age', 'income', 'purchase_amount']])
plt.show()
2.2 数据预处理
原始数据很少能直接用于模型训练。预处理是确保模型性能的关键步骤,主要包括以下几个方面:
缺失值处理 :
- 删除缺失值:
data.dropna() - 填充缺失值:均值、中位数或众数填充
- 使用模型预测缺失值
Scikit-Learn提供了SimpleImputer来简化这个过程:
from sklearn.impute import SimpleImputer
# 数值型特征用中位数填充
num_imputer = SimpleImputer(strategy='median')
data[['age', 'income']] = num_imputer.fit_transform(data[['age', 'income']])
# 类别型特征用众数填充
cat_imputer = SimpleImputer(strategy='most_frequent')
data[['gender', 'education']] = cat_imputer.fit_transform(data[['gender', 'education']])
特征编码 : 机器学习算法通常需要数值输入,所以需要将类别型特征转换为数值表示。
from sklearn.preprocessing import OneHotEncoder, LabelEncoder
# 有序类别使用LabelEncoder
le = LabelEncoder()
data['education_level'] = le.fit_transform(data['education'])
# 无序类别使用OneHotEncoder
ohe = OneHotEncoder(sparse=False)
gender_encoded = ohe.fit_transform(data[['gender']])
特征缩放 : 不同尺度的特征会影响某些算法的性能(如KNN、SVM)。常用缩放方法包括:
from sklearn.preprocessing import StandardScaler, MinMaxScaler
# 标准化(均值0,方差1)
scaler = StandardScaler()
data[['age', 'income']] = scaler.fit_transform(data[['age', 'income']])
# 归一化(缩放到[0,1]区间)
minmax = MinMaxScaler()
data[['purchase_amount']] = minmax.fit_transform(data[['purchase_amount']])
2.3 特征工程
特征工程是机器学习中最具创造性的部分,好的特征可以显著提升模型性能。常见技巧包括:
- 创建交互特征(如年龄×收入)
- 分箱连续特征(将年龄分组)
- 提取日期特征(星期几、月份等)
- 文本特征提取(TF-IDF、词嵌入)
- 图像特征提取(HOG、SIFT等)
# 创建交互特征
data['age_income'] = data['age'] * data['income']
# 分箱处理
data['age_group'] = pd.cut(data['age'], bins=[0,18,35,50,100], labels=['child','young','middle','old'])
# 提取日期特征
data['purchase_date'] = pd.to_datetime(data['purchase_date'])
data['purchase_dayofweek'] = data['purchase_date'].dt.dayofweek
data['purchase_month'] = data['purchase_date'].dt.month
3. 模型构建与评估
有了准备好的数据,我们就可以开始构建和评估机器学习模型了。Scikit-Learn提供了丰富的算法实现,覆盖了监督学习和无监督学习的各种场景。
3.1 监督学习模型
监督学习是机器学习中最常见的类型,包括分类和回归问题。
分类问题 :预测离散的类别标签。常用算法包括:
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
# 逻辑回归
lr = LogisticRegression()
lr.fit(X_train, y_train)
# 决策树
dt = DecisionTreeClassifier(max_depth=5)
dt.fit(X_train, y_train)
# 随机森林
rf = RandomForestClassifier(n_estimators=100)
rf.fit(X_train, y_train)
# 支持向量机
svm = SVC(kernel='rbf', C=1.0)
svm.fit(X_train, y_train)
# K近邻
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)
回归问题 :预测连续数值。常用算法包括:
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.svm import SVR
# 线性回归
lin_reg = LinearRegression()
lin_reg.fit(X_train, y_train)
# 决策树回归
dt_reg = DecisionTreeRegressor(max_depth=5)
dt_reg.fit(X_train, y_train)
# 随机森林回归
rf_reg = RandomForestRegressor(n_estimators=100)
rf_reg.fit(X_train, y_train)
# 支持向量回归
svr = SVR(kernel='rbf', C=1.0)
svr.fit(X_train, y_train)
3.2 无监督学习模型
无监督学习用于发现数据中的潜在结构,主要包括聚类和降维。
聚类算法 :
from sklearn.cluster import KMeans, DBSCAN, AgglomerativeClustering
# K均值聚类
kmeans = KMeans(n_clusters=3)
kmeans.fit(X)
# DBSCAN(基于密度)
dbscan = DBSCAN(eps=0.5, min_samples=5)
dbscan.fit(X)
# 层次聚类
agg = AgglomerativeClustering(n_clusters=3)
agg.fit(X)
降维技术 :
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
# 主成分分析
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
# t-SNE(可视化常用)
tsne = TSNE(n_components=2)
X_tsne = tsne.fit_transform(X)
3.3 模型评估
评估模型性能是机器学习工作流中的关键环节。Scikit-Learn提供了丰富的评估指标和工具。
分类评估指标 :
from sklearn.metrics import (accuracy_score, precision_score,
recall_score, f1_score,
roc_auc_score, confusion_matrix)
# 准确率
accuracy = accuracy_score(y_true, y_pred)
# 精确率
precision = precision_score(y_true, y_pred)
# 召回率
recall = recall_score(y_true, y_pred)
# F1分数
f1 = f1_score(y_true, y_pred)
# ROC AUC
roc_auc = roc_auc_score(y_true, y_pred_proba)
# 混淆矩阵
cm = confusion_matrix(y_true, y_pred)
回归评估指标 :
from sklearn.metrics import (mean_absolute_error,
mean_squared_error,
r2_score)
# 平均绝对误差
mae = mean_absolute_error(y_true, y_pred)
# 均方误差
mse = mean_squared_error(y_true, y_pred)
# R平方
r2 = r2_score(y_true, y_pred)
交叉验证 : 为了避免过拟合,我们应该使用交叉验证来评估模型:
from sklearn.model_selection import cross_val_score
# 5折交叉验证
scores = cross_val_score(model, X, y, cv=5, scoring='accuracy')
print(f"平均准确率: {scores.mean():.2f} (±{scores.std():.2f})")
4. 模型优化与部署
构建初始模型后,我们需要优化其性能并考虑如何将其部署到生产环境。
4.1 超参数调优
模型参数分为两种:一种是模型从数据中学习的参数,另一种是我们需要手动设置的超参数。选择合适的超参数对模型性能至关重要。
网格搜索 : Scikit-Learn提供了GridSearchCV来自动搜索最佳超参数组合:
from sklearn.model_selection import GridSearchCV
# 定义参数网格
param_grid = {
'n_estimators': [50, 100, 200],
'max_depth': [None, 5, 10],
'min_samples_split': [2, 5, 10]
}
# 创建网格搜索对象
grid_search = GridSearchCV(
estimator=RandomForestClassifier(),
param_grid=param_grid,
cv=5,
scoring='accuracy',
n_jobs=-1
)
# 执行搜索
grid_search.fit(X_train, y_train)
# 最佳参数
print(f"最佳参数: {grid_search.best_params_}")
print(f"最佳分数: {grid_search.best_score_:.2f}")
随机搜索 : 当参数空间较大时,随机搜索可能更高效:
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import randint
# 定义参数分布
param_dist = {
'n_estimators': randint(50, 200),
'max_depth': randint(3, 15),
'min_samples_split': randint(2, 11)
}
random_search = RandomizedSearchCV(
estimator=RandomForestClassifier(),
param_distributions=param_dist,
n_iter=20,
cv=5,
scoring='accuracy',
n_jobs=-1
)
random_search.fit(X_train, y_train)
4.2 模型集成
结合多个模型的预测结果往往能获得更好的性能。常见的集成方法包括:
投票分类器 :
from sklearn.ensemble import VotingClassifier
# 定义多个分类器
clf1 = LogisticRegression()
clf2 = RandomForestClassifier()
clf3 = SVC(probability=True)
# 创建投票分类器
voting_clf = VotingClassifier(
estimators=[('lr', clf1), ('rf', clf2), ('svc', clf3)],
voting='soft'
)
voting_clf.fit(X_train, y_train)
堆叠 : 堆叠使用一个元模型来组合基模型的预测:
from sklearn.ensemble import StackingClassifier
from sklearn.linear_model import LogisticRegression
# 定义基模型和元模型
base_models = [
('lr', LogisticRegression()),
('rf', RandomForestClassifier()),
('svm', SVC(probability=True))
]
meta_model = LogisticRegression()
stacking_clf = StackingClassifier(
estimators=base_models,
final_estimator=meta_model,
cv=5
)
stacking_clf.fit(X_train, y_train)
4.3 模型持久化
训练好的模型需要保存以便后续使用。Scikit-Learn提供了模型持久化的方法:
import joblib
# 保存模型
joblib.dump(model, 'model.pkl')
# 加载模型
loaded_model = joblib.load('model.pkl')
4.4 模型部署
将模型部署为API服务是常见的生产化方式。以下是使用Flask创建简单API的示例:
from flask import Flask, request, jsonify
import joblib
import pandas as pd
app = Flask(__name__)
model = joblib.load('model.pkl')
@app.route('/predict', methods=['POST'])
def predict():
data = request.get_json()
df = pd.DataFrame(data, index=[0])
prediction = model.predict(df)
return jsonify({'prediction': prediction.tolist()})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
提示:在生产环境中,建议使用更健壮的框架如FastAPI,并添加输入验证、错误处理和日志记录等功能。
5. 实战案例:客户流失预测
让我们通过一个完整的案例来应用前面学到的知识。我们将构建一个预测电信客户流失的模型。
5.1 问题理解与数据探索
客户流失预测是电信行业的经典问题。我们的目标是基于客户的历史行为和数据,预测他们是否会流失(取消服务)。
首先加载并探索数据:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 加载数据
data = pd.read_csv('telecom_churn.csv')
# 查看数据概览
print(data.head())
print(data.info())
print(data.describe())
# 检查目标变量分布
sns.countplot(x='churn', data=data)
plt.title('Churn Distribution')
plt.show()
# 数值特征分布
numerical = ['tenure', 'monthly_charges', 'total_charges']
data[numerical].hist(bins=30, figsize=(10, 7))
plt.show()
5.2 数据预处理
处理缺失值、编码分类变量、特征缩放:
from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.impute import SimpleImputer
# 处理缺失值
data['total_charges'] = pd.to_numeric(data['total_charges'], errors='coerce')
imp = SimpleImputer(strategy='mean')
data['total_charges'] = imp.fit_transform(data[['total_charges']])
# 编码分类变量
cat_cols = ['gender', 'partner', 'dependents', 'phone_service',
'multiple_lines', 'internet_service', 'online_security',
'online_backup', 'device_protection', 'tech_support',
'streaming_tv', 'streaming_movies', 'contract',
'paperless_billing', 'payment_method']
le = LabelEncoder()
for col in cat_cols:
data[col] = le.fit_transform(data[col])
# 特征缩放
scaler = StandardScaler()
data[numerical] = scaler.fit_transform(data[numerical])
# 分离特征和目标
X = data.drop('churn', axis=1)
y = data['churn']
5.3 模型训练与评估
分割数据集,训练多个模型并比较性能:
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.metrics import classification_report, roc_auc_score
# 分割数据集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# 初始化模型
models = {
'Logistic Regression': LogisticRegression(max_iter=1000),
'Random Forest': RandomForestClassifier(n_estimators=100),
'SVM': SVC(probability=True)
}
# 训练和评估
results = {}
for name, model in models.items():
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
y_proba = model.predict_proba(X_test)[:, 1]
print(f"\n{name} 性能:")
print(classification_report(y_test, y_pred))
roc_auc = roc_auc_score(y_test, y_proba)
print(f"ROC AUC: {roc_auc:.2f}")
results[name] = {
'report': classification_report(y_test, y_pred, output_dict=True),
'roc_auc': roc_auc
}
5.4 特征重要性分析
理解哪些特征对预测最重要:
# 随机森林的特征重要性
rf = models['Random Forest']
importances = rf.feature_importances_
features = X.columns
# 创建DataFrame并排序
feature_importances = pd.DataFrame({
'feature': features,
'importance': importances
}).sort_values('importance', ascending=False)
# 可视化
plt.figure(figsize=(10, 6))
sns.barplot(x='importance', y='feature', data=feature_importances.head(10))
plt.title('Top 10 Important Features')
plt.show()
5.5 模型优化
对表现最好的模型进行超参数调优:
from sklearn.model_selection import GridSearchCV
# 定义参数网格
param_grid = {
'n_estimators': [100, 200, 300],
'max_depth': [None, 10, 20, 30],
'min_samples_split': [2, 5, 10],
'min_samples_leaf': [1, 2, 4]
}
# 网格搜索
grid_search = GridSearchCV(
estimator=RandomForestClassifier(),
param_grid=param_grid,
cv=5,
scoring='roc_auc',
n_jobs=-1,
verbose=1
)
grid_search.fit(X_train, y_train)
# 最佳模型
best_rf = grid_search.best_estimator_
print(f"最佳参数: {grid_search.best_params_}")
print(f"最佳ROC AUC: {grid_search.best_score_:.2f}")
# 在测试集上评估
y_pred = best_rf.predict(X_test)
y_proba = best_rf.predict_proba(X_test)[:, 1]
print(classification_report(y_test, y_pred))
print(f"ROC AUC: {roc_auc_score(y_test, y_proba):.2f}")
6. 高级技巧与最佳实践
在多年使用Scikit-Learn的实践中,我积累了一些高级技巧和最佳实践,可以显著提高工作效率和模型性能。
6.1 使用Pipeline简化工作流
Pipeline可以将多个处理步骤组合成一个对象,使代码更简洁并减少错误:
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
# 定义数值和类别特征
numeric_features = ['age', 'income']
categorical_features = ['gender', 'education']
# 创建预处理转换器
preprocessor = ColumnTransformer(
transformers=[
('num', StandardScaler(), numeric_features),
('cat', OneHotEncoder(), categorical_features)
]
)
# 创建完整管道
pipeline = Pipeline([
('preprocessor', preprocessor),
('classifier', RandomForestClassifier())
])
# 使用管道训练模型
pipeline.fit(X_train, y_train)
# 使用管道预测
y_pred = pipeline.predict(X_test)
6.2 处理类别不平衡
当类别分布不均衡时,模型可能会偏向多数类。解决方法包括:
重采样 :
from imblearn.over_sampling import SMOTE
from imblearn.under_sampling import RandomUnderSampler
from imblearn.pipeline import make_pipeline
# 过采样少数类
smote = SMOTE(sampling_strategy='minority')
X_res, y_res = smote.fit_resample(X_train, y_train)
# 或者使用组合采样
pipeline = make_pipeline(
SMOTE(sampling_strategy=0.5),
RandomUnderSampler(sampling_strategy=0.5),
RandomForestClassifier()
)
类别权重 : 许多算法支持通过class_weight参数调整类别权重:
# 计算类别权重
from sklearn.utils.class_weight import compute_class_weight
classes = np.unique(y_train)
weights = compute_class_weight('balanced', classes=classes, y=y_train)
class_weights = dict(zip(classes, weights))
# 在模型中使用
model = RandomForestClassifier(class_weight=class_weights)
6.3 自定义评估指标
Scikit-Learn允许定义自定义评估指标:
from sklearn.metrics import make_scorer
def custom_metric(y_true, y_pred):
# 自定义计算逻辑
tp = sum((y_true == 1) & (y_pred == 1))
fp = sum((y_true == 0) & (y_pred == 1))
return tp / (tp + fp + 1e-6) # 避免除以零
custom_scorer = make_scorer(custom_metric, greater_is_better=True)
# 在交叉验证中使用
scores = cross_val_score(model, X, y, cv=5, scoring=custom_scorer)
6.4 特征选择技巧
选择相关特征可以提高模型性能并减少过拟合:
过滤法 : 基于统计检验选择特征:
from sklearn.feature_selection import SelectKBest, f_classif
selector = SelectKBest(score_func=f_classif, k=10)
X_new = selector.fit_transform(X, y)
包装法 : 使用模型性能作为评价标准:
from sklearn.feature_selection import RFECV
selector = RFECV(
estimator=RandomForestClassifier(),
step=1,
cv=5,
scoring='accuracy'
)
selector.fit(X, y)
嵌入法 : 利用模型自身的特征重要性:
from sklearn.feature_selection import SelectFromModel
selector = SelectFromModel(
estimator=RandomForestClassifier(),
threshold='median'
)
selector.fit(X, y)
6.5 模型解释
理解模型如何做出预测对于业务应用至关重要:
SHAP值 :
import shap
# 创建解释器
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test)
# 可视化单个预测
shap.initjs()
shap.force_plot(explainer.expected_value[1], shap_values[1][0,:], X_test.iloc[0,:])
# 特征重要性
shap.summary_plot(shap_values, X_test)
部分依赖图 :
from sklearn.inspection import PartialDependenceDisplay
# 绘制部分依赖图
PartialDependenceDisplay.from_estimator(
model,
X_train,
features=['age', 'income'],
grid_resolution=20
)
plt.show()
7. 常见问题与解决方案
在实际项目中,我们经常会遇到各种挑战和问题。以下是我总结的一些常见问题及其解决方案。
7.1 数据质量问题
问题1:缺失值过多
- 解决方案:考虑删除缺失率过高的特征或样本,或者使用更复杂的插补方法如KNN插补或模型预测插补。
问题2:异常值影响
- 解决方案:使用统计方法(如IQR)检测异常值,并根据业务逻辑决定是修正、删除还是保留。
# 检测异常值
Q1 = data['income'].quantile(0.25)
Q3 = data['income'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = data[(data['income'] < lower_bound) | (data['income'] > upper_bound)]
7.2 模型性能问题
问题1:模型欠拟合
- 解决方案:增加模型复杂度,添加更多特征,减少正则化,或尝试更强大的模型。
问题2:模型过拟合
- 解决方案:增加训练数据,使用正则化,减少模型复杂度,或使用早停(对于迭代模型)。
# 使用早停的随机森林
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier(
n_estimators=1000, # 设置大量树
max_depth=5, # 限制树深度
min_samples_split=5,
n_jobs=-1,
verbose=1,
oob_score=True # 使用袋外样本评估
)
7.3 计算效率问题
问题1:训练速度慢
- 解决方案:使用更高效的算法(如SGD替代批量梯度下降),减少特征维度,或使用并行计算。
# 启用并行计算
model = RandomForestClassifier(n_estimators=100, n_jobs=-1)
问题2:内存不足
- 解决方案:使用小批量训练(partial_fit),选择内存效率高的算法,或使用Dask等分布式计算框架。
7.4 部署相关问题
问题1:模型服务延迟高
- 解决方案:优化特征处理流水线,使用更轻量级的模型,或考虑模型蒸馏。
问题2:模型漂移
- 解决方案:建立监控系统定期评估模型性能,设置自动重新训练流程。
# 简单的模型性能监控
from sklearn.metrics import accuracy_score
import numpy as np
class ModelMonitor:
def __init__(self, window_size=100):
self.window_size = window_size
self.predictions = []
self.actuals = []
def update(self, y_true, y_pred):
self.actuals.extend(y_true)
self.predictions.extend(y_pred)
if len(self.actuals) > self.window_size:
self.actuals = self.actuals[-self.window_size:]
self.predictions = self.predictions[-self.window_size:]
return accuracy_score(self.actuals, self.predictions)
7.5 业务理解问题
问题1:模型预测与业务直觉不符
- 解决方案:加强特征工程,引入领域知识,或使用可解释性更强的模型。
问题2:难以量化业务目标
- 解决方案:与业务方密切合作,将业务KPI转化为合适的机器学习指标。
# 自定义业务指标
def business_metric(y_true, y_pred, profit_matrix):
"""
profit_matrix: 2x2矩阵,表示不同预测结果的业务收益/损失
"""
cm = confusion_matrix(y_true, y_pred)
total_profit = np.sum(cm * profit_matrix)
return total_profit / len(y_true)
# 示例利润矩阵
# 预测负 预测正
# 实际负 [[ 0, -5], # 假阳性成本5
# 实际正 [-100, 50]] # 假阴性成本100,真阳性收益50
profit_matrix = np.array([[0, -5], [-100, 50]])
8. Scikit-Learn生态系统扩展
虽然Scikit-Learn本身功能强大,但有时我们需要借助其他库来扩展其功能。以下是一些常用的扩展库和技巧。
8.1 与深度学习集成
虽然Scikit-Learn主要关注传统机器学习算法,但可以与深度学习框架结合:
使用MLP : Scikit-Learn本身提供了简单的多层感知器实现:
from sklearn.neural_network import MLPClassifier
mlp = MLPClassifier(
hidden_layer_sizes=(100, 50),
activation='relu',
solver='adam',
max_iter=1000,
verbose=True
)
mlp.fit(X_train, y_train)
与TensorFlow/Keras集成 : 可以将Keras模型包装成Scikit-Learn兼容的估计器:
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from scikeras.wrappers import KerasClassifier
def create_model():
model = Sequential([
Dense(64, activation='relu', input_shape=(X_train.shape[1],)),
Dense(32, activation='relu'),
Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
return model
keras_model = KerasClassifier(model=create_model, epochs=10, batch_size=32)
keras_model.fit(X_train, y_train)
8.2 处理大规模数据
对于超出内存的数据集,可以使用以下方法:
增量学习 : 部分算法支持partial_fit方法,可以分批训练:
from sklearn.linear_model import SGDClassifier
model = SGDClassifier(loss='log_loss')
# 分批训练
for batch in pd.read_csv('large_data.csv', chunksize=1000):
X_batch = batch.drop('target', axis=1)
y_batch = batch['target']
model.partial_fit(X_batch, y_batch, classes=np.unique(y))
使用Dask-ML : Dask提供了与Scikit-Learn兼容的分布式计算接口:
from dask_ml.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X_dask, y_dask) # X_dask和y_dask是Dask数组
8.3 自动化机器学习
AutoML工具可以自动化模型选择和调优过程:
使用TPOT : TPOT是基于遗传算法的AutoML工具:
from tpot import TPOTClassifier
tpot = TPOTClassifier(
generations=5,
population_size=20,
cv=5,
random_state=42,
verbosity=2
)
tpot.fit(X_train, y_train)
使用Auto-Sklearn :
from autosklearn.classification import AutoSklearnClassifier
automl = AutoSklearnClassifier(
time_left_for_this_task=120, # 秒
per_run_time_limit=30,
n_jobs=-1
)
automl.fit(X_train, y_train)
8.4 时间序列处理
虽然Scikit-Learn不是为时间序列设计的,但可以用于一些时间序列任务:
特征工程 : 创建时间相关特征:
data['hour'] = data['timestamp'].dt.hour
data['dayofweek'] = data['timestamp'].dt.dayofweek
data['month'] = data['timestamp'].dt.month
滑动窗口 : 创建时间窗口特征:
def create_lags(df, column, lags):
for lag in lags:
df[f'{column}_lag_{lag}'] = df[column].shift(lag)
return df
data = create_lags(data, 'value', [1, 2, 3, 7, 14])
data.dropna(inplace=True)
8.5 图数据与网络分析
Scikit-Learn可以与图分析库结合:
使用NetworkX提取特征 :
import networkx as nx
# 创建图
G = nx.Graph()
G.add_edges_from([(1,2), (2,3), (3,4), (4,1)])
# 计算节点特征
degree_centrality = nx.degree_centrality(G)
betweenness_centrality = nx.betweenness_centrality(G)
# 添加到数据
data['degree'] = data['node_id'].map(degree_centrality)
data['betweenness'] = data['node_id'].map(betweenness_centrality)
图嵌入 : 使用节点嵌入作为特征:
from node2vec import Node2Vec
# 生成嵌入
node2vec = Node2Vec(G, dimensions=64, walk_length=30, num_walks=200, workers=4)
model = node2vec.fit(window=10, min_count=1)
# 获取嵌入向量
embeddings = {node: model.wv[node] for node in G.nodes()}
更多推荐
所有评论(0)