如何端到端解决预测建模机器学习问题?我们将通过一个案例研究Python中的分类预测建模问题,包括应用机器学习过程的每一步。完成这个项目后,我们要知道:
-
如何端到端解决分类预测建模问题
-
如何使用数据转换来提高模型性能
-
如何使用算法调优来提高模型性能
-
如何使用集成方法和集成方法的调优来提高模型性能
代码示例
# coding: utf-8
"""
该脚本旨在对声纳数据集进行机器学习分类。
主要步骤包括:
1. 加载库和数据集
2. 数据可视化和描述性统计
3. 数据准备(清洗、特征选择和转换)
4. 评估多种算法并选择最佳模型
5. 调整算法参数以提高准确性
6. 使用集成方法提高模型性能
7. 最终确定模型并保存
注意:部分可视化代码在此示例中被注释。
"""
"""
步骤1:定义问题
- 加载库
- 加载数据集
"""
# 加载必要的库
from pathlib import Path # 用于处理文件路径
import joblib # 用于数据的存储和加载
import pandas as pd # 用于数据处理和分析
import numpy as np # 用于数学运算和数组操作
import matplotlib.pyplot as plt # 用于数据可视化
from sklearn.ensemble import AdaBoostClassifier, ExtraTreesClassifier, GradientBoostingClassifier, RandomForestClassifier # 用于集成学习的分类器
from sklearn.preprocessing import StandardScaler # 用于数据标准化
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis # 用于线性判别分析
from sklearn.linear_model import LogisticRegression # 用于逻辑回归
from sklearn.model_selection import GridSearchCV, KFold, cross_val_score, train_test_split # 用于模型选择和验证
from sklearn.naive_bayes import GaussianNB # 用于朴素贝叶斯分类
from sklearn.neighbors import KNeighborsClassifier # 用于K近邻分类
from sklearn.pipeline import Pipeline # 用于构建数据处理和模型训练的流水线
from sklearn.svm import SVC # 用于支持向量机
from sklearn.tree import DecisionTreeClassifier # 用于决策树分类
from sklearn.metrics import accuracy_score # 用于评估模型准确率
plt.rcParams['figure.figsize'] = (4, 4)
# plt.rcParams['font.size'] = 6
# plt.rcParams['figure.dpi'] = 150
# 加载数据集
filename = Path(__file__).parent / 'data/sonar.all-data.csv'
data = pd.read_csv(filename, header=None)
print(data.head())
"""
步骤2:总结数据(分析数据)
- 描述型统计
- 数据可视化
"""
# 描述性统计
print(data.shape) # 打印数据集的形状
print(data.dtypes) # 打印每列数据的类型
print(data.head(20)) # 打印前20行数据
print(data.describe()) # 打印数据的统计描述
print(data.groupby(60).size()) # 打印每类样本的数量
# 数据可视化
## 直方图
# data.hist(sharex=False, sharey=False, xlabelsize=1, ylabelsize=1)
# plt.show()
## 密度图
# data.plot(kind='density', subplots=True, layout=(8, 8), sharex=False)
# plt.show()
## 箱线图
# data.plot(kind='box', subplots=True, layout=(8, 8), sharex=False, sharey=False)
# plt.show()
## 相关矩阵图
# figure = plt.figure()
# axes = figure.add_subplot(1, 1, 1)
# data = data.drop(60, axis=1)
# caxes = axes.matshow(data.corr(method='pearson'), vmin=-1, vmax=1, interpolation='none')
# figure.colorbar(caxes)
# plt.show()
"""
步骤3:准备数据
- 数据清洗
- 特征选择
- 数据转换
"""
# 划分数据集为训练集和测试集
X = data.iloc[:, :60] # 特征数据
y = data.iloc[:, 60] # 目标变量
test_size, seed = 0.2, np.random.randint(10) # 测试集比例和随机种子
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size, random_state=seed, shuffle=True) # 划分数据集
print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)
"""
步骤4:评估算法
- 划分验证数据集
- 测试选项和评估指标
- 快速抽查算法
- 比较算法
"""
# 划分验证数据集
# 定义评估指标和划分验证集的参数
num_folds, seed, scoring = 10, 8, 'accuracy'
# 快速评估多种算法
models = [('LR', LogisticRegression()),
('LDA', LinearDiscriminantAnalysis()),
('KNN', KNeighborsClassifier()),
('CART', DecisionTreeClassifier()),
('NB', GaussianNB()),
('SVM', SVC())]
results, names = [], []
for name, model in models:
try:
kfold = KFold(n_splits=num_folds, random_state=seed, shuffle=True)
cv_results = cross_val_score(model, X_train, y_train, cv=kfold, scoring=scoring)
results.append(cv_results)
names.append(name)
print('%s: %f (%f)' % (name, cv_results.mean(), cv_results.std()))
except Exception as e:
print(f'Error occurred while evaluating {name}: {e}')
# 比较算法
# figure = plt.figure()
# figure.suptitle('Algorithm Comparison')
# axes = figure.add_subplot(111)
# plt.boxplot(results)
# axes.set_xticklabels(names)
# plt.show()
"""
我们怀疑原始数据的不同分布可能会对技能产生负面影响一些算法。让我们用一个标准化的拷贝来计算相同的算法数据集。
在这里对数据进行转换,使每个属性的平均值为零,标准差是1。我们还需要在转换时避免数据泄漏数据。
避免泄漏的一种好方法是使用标准化数据的管道,并构建在交叉验证测试工具中为每个折叠建立模型。
这样我们就能得到一个公平的估计每个具有标准化数据的模型如何处理未见过的数据。
"""
# 评估算法:标准化数据
pipelines = [('ScaledLR', Pipeline([('Scaler', StandardScaler()), ('LR', LogisticRegression())])),
('ScaledLDA', Pipeline([('Scaler', StandardScaler()), ('LDA', LinearDiscriminantAnalysis())])),
('ScaledKNN', Pipeline([('Scaler', StandardScaler()), ('KNN', KNeighborsClassifier())])),
('ScaledCART', Pipeline([('Scaler',StandardScaler()), ('CART', DecisionTreeClassifier())])),
('ScaledNB', Pipeline([('Scaler', StandardScaler()), ('NB', GaussianNB())])),
('ScaledSVM', Pipeline([('Scaler', StandardScaler()), ('SVM', SVC())]))]
results, names = [], []
for name, model in pipelines:
try:
kfold = KFold(n_splits=num_folds, random_state=seed, shuffle=True)
cv_results = cross_val_score(model, X_train, y_train, cv=kfold, scoring=scoring)
results.append(cv_results)
names.append(name)
print('%s: %f (%f)' % (name, cv_results.mean(), cv_results.std()))
except Exception as e:
print(f'Error occurred while evaluating {name}: {e}')
# 比较算法
# figure = plt.figure()
# figure.suptitle('Scaled Algorithm Comparison')
# axes = figure.add_subplot(111)
# plt.boxplot(results)
# axes.set_xticklabels(names)
# plt.show()
"""
步骤5:提高准确度
- 调整算法参数(算法调优)
- 集成方法
"""
# 调整算法参数(标准化数据后通过调优KNN算法参数)
print("\n\033[1;30m调优KNN算法参数:\033[0m")
scaler = StandardScaler().fit(X_train)
rescaled_X_train = scaler.transform(X_train)
neighbors = np.array([1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21])
param_grid = dict(n_neighbors=neighbors)
model = KNeighborsClassifier()
kfold = KFold(n_splits=num_folds, random_state=seed, shuffle=True)
grid_search_cv = GridSearchCV(model, param_grid=param_grid, scoring=scoring, cv=kfold)
grid_result = grid_search_cv.fit(rescaled_X_train, y_train)
print('Best: %f using %s' % (grid_result.best_score_, grid_result.best_params_))
means = grid_result.cv_results_['mean_test_score']
stds = grid_result.cv_results_['std_test_score']
params = grid_result.cv_results_['params']
for mean, stdev, param in zip(means, stds, params):
print('%f (%f) with: %r' % (mean, stdev, param))
# 调整算法参数(标准化数据后通过调优SVM算法参数)
print("\n\033[1;30m调优SVM算法参数:\033[0m")
scaler = StandardScaler().fit(X_train)
rescaled_X_train = scaler.transform(X_train)
c_values = np.array([0.1, 0.3, 0.5, 0.7, 0.9, 1.0, 1.3, 1.5, 1.7, 2.0])
kernel_values = ['linear', 'poly', 'rbf', 'sigmoid']
param_grid = dict(C=c_values, kernel=kernel_values)
model = SVC()
kfold = KFold(n_splits=num_folds, random_state=seed, shuffle=True)
grid_search_cv = GridSearchCV(model, param_grid=param_grid, scoring=scoring, cv=kfold)
grid_result = grid_search_cv.fit(rescaled_X_train, y_train)
print('Best: %f using %s' % (grid_result.best_score_, grid_result.best_params_))
means = grid_result.cv_results_['mean_test_score']
stds = grid_result.cv_results_['std_test_score']
params = grid_result.cv_results_['params']
for mean, stdev, param in zip(means, stds, params):
print('%f (%f) with: %r' % (mean, stdev, param))
# 集成方法算法
print("\n\033[1;30m集成方法算法:\033[0m")
ensembles = []
ensembles.append(('AB', AdaBoostClassifier()))
ensembles.append(('GB', GradientBoostingClassifier()))
ensembles.append(('RF', RandomForestClassifier()))
ensembles.append(('ET', ExtraTreesClassifier()))
results, names = [], []
for name, model in ensembles:
try:
kfold = KFold(n_splits=num_folds, random_state=seed, shuffle=True)
cv_results = cross_val_score(model, X_train, y_train, cv=kfold, scoring=scoring)
results.append(cv_results)
names.append(name)
print('%s: %f (%f)' % (name, cv_results.mean(), cv_results.std()))
except Exception as e:
print(f'Error occurred while evaluating {name}: {e}')
# 比较算法
# figure = plt.figure()
# figure.suptitle('Ensemble Algorithm Comparison')
# axes = figure.add_subplot(111)
# plt.boxplot(results)
# axes.set_xticklabels(names)
# plt.show()
"""
步骤6:最终确定模型且展示结果
- 在验证数据集上进行预测
- 在整个训练数据集上创建独立的模型
- 保存模型以供以后使用
"""
# 创建模型
scaler = StandardScaler().fit(X_train)
rescaled_X_train = scaler.transform(X_train)
model = SVC(C=2.0, kernel='rbf')
model.fit(rescaled_X_train, y_train)
# 转换验证数据集,并进行预测
scaler = StandardScaler().fit(X_test)
rescaled_X_test = scaler.transform(X_test)
y_pred = model.predict(rescaled_X_test)
print(accuracy_score(y_test, y_pred))
# 保存模型
filename = Path(__file__).parent / 'model/finalized_model.pkl'
joblib.dump(model, filename)
总结
通过本案例,我们使用Python解决了一个从端到端分类预测建模机器学习问题。具体而言,涵盖的步骤是:
-
问题定义(声纳回波数据)
-
加载数据集
-
分析数据(相同比例但数据分布不同)
-
评估算法(KNN 看起来不错)
-
使用标准化评估算法(KNN和SVM看起来不错)
-
算法调优(KNN的K=1良好,具有RBF内核的SVM 和 C=2.0是最好)
-
集成方法(装袋和提升,不如SVM)
-
最终确定模型(使用所有训练数据并使用验证数据集进行确认)
通过此案例研究,向我们展示了特定机器学习的任务可以组合成一个完整的项目。