今天我想分享一个完整的机器学习项目实践,主要围绕UCI公开数据集展开多模型分类对比和特征选择。这个项目非常适合刚入门机器学习的朋友,通过实际代码演示如何从数据准备到模型评估的全流程。
在真实业务场景中,我们经常会遇到这样的问题:面对大量特征,哪些才是真正有用的?不同模型在同一数据集上表现如何?这正是本项目要解决的核心问题。我将使用随机森林进行特征选择,然后用KNN、SVM、ELM和RF四种经典算法进行分类对比。
UCI机器学习仓库是机器学习领域最著名的公开数据集来源之一。在选择数据集时,我通常会考虑以下几个因素:
以经典的Iris数据集为例(虽然简单但很适合教学),我们可以这样加载:
python复制from sklearn.datasets import load_iris
import pandas as pd
# 加载数据集
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = pd.Series(iris.target)
在实际项目中,数据清洗往往要花费80%的时间。以下是几个关键步骤:
python复制# 检查缺失值
print(X.isnull().sum())
# 简单填充(根据实际情况选择)
X.fillna(X.mean(), inplace=True)
python复制# 使用箱线图检测异常值
import seaborn as sns
sns.boxplot(data=X)
python复制from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
注意:特征选择应该在数据标准化之后进行,但随机森林本身对数据尺度不敏感,可以不用标准化。
随机森林通过以下方式计算特征重要性:
这种方法的优势在于:
python复制from sklearn.ensemble import RandomForestClassifier
import matplotlib.pyplot as plt
# 初始化随机森林
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X, y)
# 获取特征重要性
importances = rf.feature_importances_
features = X.columns
indices = np.argsort(importances)[::-1]
# 可视化
plt.figure(figsize=(10,6))
plt.title("Feature Importances")
plt.bar(range(X.shape[1]), importances[indices], align="center")
plt.xticks(range(X.shape[1]), [features[i] for i in indices], rotation=90)
plt.xlim([-1, X.shape[1]])
plt.tight_layout()
plt.show()
在实际项目中,我通常采用以下策略:
python复制from sklearn.feature_selection import SelectFromModel
# 自动选择重要性>平均值的特征
selector = SelectFromModel(rf, threshold='mean')
X_selected = selector.fit_transform(X, y)
selected_features = X.columns[selector.get_support()]
print(f"Selected features: {list(selected_features)}")
python复制from sklearn.model_selection import train_test_split
# 使用选择后的特征
X_train, X_test, y_train, y_test = train_test_split(
X_selected, y, test_size=0.3, random_state=42)
KNN的关键在于K值选择,我通常使用网格搜索:
python复制from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
# 参数网格
param_grid = {'n_neighbors': range(1, 15)}
# 网格搜索
knn = GridSearchCV(KNeighborsClassifier(), param_grid, cv=5)
knn.fit(X_train, y_train)
# 最佳参数
print(f"Best K: {knn.best_params_['n_neighbors']}")
实操心得:KNN对特征缩放敏感,如果未做标准化,效果可能很差。
SVM有两个关键参数:C和gamma。我的调优策略:
python复制from sklearn.svm import SVC
svm = SVC(probability=True, random_state=42)
param_grid = {
'C': [0.1, 1, 10, 100],
'gamma': ['scale', 'auto', 0.1, 1]
}
svm_grid = GridSearchCV(svm, param_grid, cv=3, n_jobs=-1)
svm_grid.fit(X_train, y_train)
print(f"Best SVM params: {svm_grid.best_params_}")
ELM在sklearn中没有直接实现,可以使用PyELM库:
python复制!pip install pyelm
from pyelm import ELMClassifier
elm = ELMClassifier(n_hidden=50, activation_func='sigmoid')
elm.fit(X_train, y_train)
注意事项:ELM的隐藏层节点数需要根据数据规模调整,太少会欠拟合,太多会过拟合。
python复制rf_params = {
'n_estimators': [50, 100, 200],
'max_depth': [None, 5, 10],
'min_samples_split': [2, 5]
}
rf_grid = GridSearchCV(RandomForestClassifier(), rf_params, cv=3)
rf_grid.fit(X_train, y_train)
python复制from sklearn.metrics import (accuracy_score, precision_score,
recall_score, f1_score, roc_auc_score)
def evaluate_model(model, X_test, y_test):
y_pred = model.predict(X_test)
print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")
print(f"Precision: {precision_score(y_test, y_pred, average='macro'):.3f}")
print(f"Recall: {recall_score(y_test, y_pred, average='macro'):.3f}")
print(f"F1 Score: {f1_score(y_test, y_pred, average='macro'):.3f}")
我通常会创建一个对比表格:
python复制results = []
models = {
'KNN': knn.best_estimator_,
'SVM': svm_grid.best_estimator_,
'ELM': elm,
'Random Forest': rf_grid.best_estimator_
}
for name, model in models.items():
y_pred = model.predict(X_test)
results.append({
'Model': name,
'Accuracy': accuracy_score(y_test, y_pred),
'Training Time': time.time() - start_time
})
results_df = pd.DataFrame(results)
print(results_df.sort_values('Accuracy', ascending=False))
了解模型是否欠拟合或过拟合:
python复制from sklearn.model_selection import learning_curve
def plot_learning_curve(model, title, X, y, cv=5):
train_sizes, train_scores, test_scores = learning_curve(
model, X, y, cv=cv, n_jobs=-1)
plt.figure()
plt.title(title)
plt.plot(train_sizes, np.mean(train_scores, axis=1), 'o-', label="Training score")
plt.plot(train_sizes, np.mean(test_scores, axis=1), 'o-', label="Cross-validation score")
plt.legend()
plt.show()
plot_learning_curve(rf_grid.best_estimator_, "Random Forest", X_selected, y)
准确率始终为0:
SVM训练极慢:
随机森林过拟合:
在实际应用中,这个项目可以进一步扩展:
python复制# TPOT自动机器学习示例
from tpot import TPOTClassifier
tpot = TPOTClassifier(generations=5, population_size=20, cv=5)
tpot.fit(X_train, y_train)
print(tpot.score(X_test, y_test))
tpot.export('tpot_pipeline.py')
经过这个完整项目实践,我深刻体会到特征工程和模型选择的重要性。在实际业务中,没有绝对最好的模型,只有最适合当前数据和业务需求的模型。建议初学者多尝试不同的组合,建立自己的模型评估直觉。