回归与分类算法全解析:从理论到实践
在机器学习领域,回归和分类算法是两大核心任务,它们构成了监督学习的基础。无论是预测房价、股票走势,还是识别图像中的物体、判断邮件是否为垃圾邮件,都离不开这两类算法。本文将深入探讨回归和分类算法的核心知识点,并通过详细的代码实例帮助读者全面理解这些算法。
一、机器学习基础概念
在深入讨论具体算法之前,我们先了解一些基础概念:
监督学习:通过已有标记数据训练模型,使模型能够预测新数据的输出。回归和分类都属于监督学习。
特征(Feature):描述数据的属性或变量,是模型的输入。
标签(Label):我们希望预测的结果,是模型的输出。
训练集:用于训练模型的数据集。
测试集:用于评估模型性能的数据集。
二、回归算法详解
回归算法用于预测连续值输出,如房价、温度、销售额等。下面我们详细介绍几种常见的回归算法。
2.1 线性回归
线性回归是最简单、最基础的回归算法,它假设特征和标签之间存在线性关系。
数学模型:
对于简单线性回归(单特征):
y=β0+β1x+ϵy=β0+β1x+ϵ
对于多元线性回归(多特征):
y=β0+β1x1+β2x2+...+βnxn+ϵy=β0+β1x1+β2x2+...+βnxn+ϵ
其中:
$y$:预测值
$\beta_0$:截距
$\beta_1, \beta_2, ..., \beta_n$:系数
$x_1, x_2, ..., x_n$:特征值
$\epsilon$:误差项
损失函数:均方误差(MSE)
MSE=1n∑i=1n(yi−yi^)2MSE=n1∑i=1n(yi−yi^)2
参数估计:通常使用最小二乘法或梯度下降法来估计参数。
python
import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score from sklearn.datasets import make_regression# 生成回归数据集 X, y = make_regression(n_samples=100, n_features=1, noise=10, random_state=42)# 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 创建并训练线性回归模型 lr = LinearRegression() lr.fit(X_train, y_train)# 预测 y_pred = lr.predict(X_test)# 评估模型 mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred)print(f"线性回归结果:") print(f"斜率: {lr.coef_[0]:.4f}") print(f"截距: {lr.intercept_:.4f}") print(f"均方误差: {mse:.4f}") print(f"R²分数: {r2:.4f}")# 可视化结果 plt.figure(figsize=(10, 6)) plt.scatter(X_test, y_test, color='blue', label='实际值') plt.plot(X_test, y_pred, color='red', linewidth=2, label='预测值') plt.xlabel('特征值') plt.ylabel('目标值') plt.title('线性回归示例') plt.legend() plt.show()
2.2 多项式回归
当数据关系不是简单的线性关系时,可以使用多项式回归,它是线性回归的扩展。
python
from sklearn.preprocessing import PolynomialFeatures from sklearn.pipeline import Pipeline# 生成非线性数据 np.random.seed(42) X = np.linspace(-3, 3, 100).reshape(-1, 1) y = 0.5 * X**3 + X**2 - 2*X + np.random.normal(0, 2, 100).reshape(-1, 1)# 创建多项式回归模型 degree = 3 poly_model = Pipeline([('poly', PolynomialFeatures(degree=degree)),('linear', LinearRegression()) ])# 训练模型 poly_model.fit(X, y)# 预测 X_test = np.linspace(-3, 3, 50).reshape(-1, 1) y_pred = poly_model.predict(X_test)# 可视化 plt.figure(figsize=(10, 6)) plt.scatter(X, y, color='blue', alpha=0.6, label='实际数据') plt.plot(X_test, y_pred, color='red', linewidth=2, label=f'{degree}次多项式拟合') plt.xlabel('X') plt.ylabel('y') plt.title('多项式回归示例') plt.legend() plt.show()
2.3 决策树回归
决策树不仅可以用于分类,也可以用于回归任务。它通过创建树状模型进行预测。
python
from sklearn.tree import DecisionTreeRegressor, plot_tree from sklearn.datasets import fetch_california_housing# 加载加州房价数据集 housing = fetch_california_housing() X, y = housing.data, housing.target# 只使用前两个特征以便可视化 X = X[:, :2]# 划分数据集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 创建决策树回归模型 dt_reg = DecisionTreeRegressor(max_depth=3, random_state=42) dt_reg.fit(X_train, y_train)# 预测 y_pred = dt_reg.predict(X_test)# 评估 mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred)print(f"决策树回归结果:") print(f"均方误差: {mse:.4f}") print(f"R²分数: {r2:.4f}")# 可视化决策树 plt.figure(figsize=(15, 10)) plot_tree(dt_reg, feature_names=housing.feature_names[:2], filled=True, rounded=True) plt.title('决策树回归树结构') plt.show()
2.4 随机森林回归
随机森林通过集成多个决策树来提高预测性能和稳定性。
python
from sklearn.ensemble import RandomForestRegressor# 创建随机森林回归模型 rf_reg = RandomForestRegressor(n_estimators=100, random_state=42) rf_reg.fit(X_train, y_train)# 预测 y_pred_rf = rf_reg.predict(X_test)# 评估 mse_rf = mean_squared_error(y_test, y_pred_rf) r2_rf = r2_score(y_test, y_pred_rf)print(f"随机森林回归结果:") print(f"均方误差: {mse_rf:.4f}") print(f"R²分数: {r2_rf:.4f}")# 特征重要性 feature_importance = rf_reg.feature_importances_ plt.figure(figsize=(8, 6)) plt.barh(housing.feature_names[:2], feature_importance) plt.xlabel('特征重要性') plt.title('随机森林特征重要性') plt.show()
2.5 支持向量回归(SVR)
SVR是支持向量机在回归问题上的应用,通过寻找一个超平面使得大部分数据点落在间隔内。
python
from sklearn.svm import SVR from sklearn.preprocessing import StandardScaler# 数据标准化 scaler = StandardScaler() X_scaled = scaler.fit_transform(X)# 重新划分数据集 X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)# 创建SVR模型 svr = SVR(kernel='rbf', C=1.0, epsilon=0.1) svr.fit(X_train, y_train)# 预测 y_pred_svr = svr.predict(X_test)# 评估 mse_svr = mean_squared_error(y_test, y_pred_svr) r2_svr = r2_score(y_test, y_pred_svr)print(f"支持向量回归结果:") print(f"均方误差: {mse_svr:.4f}") print(f"R²分数: {r2_svr:.4f}")
三、分类算法详解
分类算法用于预测离散类别输出,如图像分类、垃圾邮件检测等。下面我们详细介绍几种常见的分类算法。
3.1 逻辑回归
尽管名字中有"回归",但逻辑回归是一种分类算法,特别适用于二分类问题。
数学模型:
p=11+e−(β0+β1x1+...+βnxn)p=1+e−(β0+β1x1+...+βnxn)1
其中p是样本属于正类的概率。
损失函数:交叉熵损失
J(θ)=−1m∑i=1m[yilog(pi)+(1−yi)log(1−pi)]J(θ)=−m1∑i=1m[yilog(pi)+(1−yi)log(1−pi)]
python
import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, confusion_matrix, classification_report from sklearn.datasets import make_classification import seaborn as sns# 生成二分类数据集 X, y = make_classification(n_samples=1000, n_features=2, n_redundant=0, n_informative=2, n_clusters_per_class=1, random_state=42)# 划分数据集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)# 创建并训练逻辑回归模型 log_reg = LogisticRegression() log_reg.fit(X_train, y_train)# 预测 y_pred = log_reg.predict(X_test) y_pred_proba = log_reg.predict_proba(X_test)# 评估模型 accuracy = accuracy_score(y_test, y_pred) cm = confusion_matrix(y_test, y_pred)print(f"逻辑回归结果:") print(f"准确率: {accuracy:.4f}") print("分类报告:") print(classification_report(y_test, y_pred))# 可视化决策边界 plt.figure(figsize=(12, 5))# 左图:实际类别 plt.subplot(1, 2, 1) plt.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap='bwr', alpha=0.7) plt.xlabel('特征1') plt.ylabel('特征2') plt.title('实际类别') plt.colorbar()# 右图:预测类别 plt.subplot(1, 2, 2) plt.scatter(X_test[:, 0], X_test[:, 1], c=y_pred, cmap='bwr', alpha=0.7) plt.xlabel('特征1') plt.ylabel('特征2') plt.title('预测类别') plt.colorbar()plt.tight_layout() plt.show()# 混淆矩阵热力图 plt.figure(figsize=(6, 5)) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues') plt.title('混淆矩阵') plt.ylabel('实际类别') plt.xlabel('预测类别') plt.show()
3.2 K近邻分类(K-NN)
K-NN是一种基于实例的学习算法,它根据最近邻居的类别来预测新样本的类别。
python
from sklearn.neighbors import KNeighborsClassifier from sklearn.preprocessing import StandardScaler# 数据标准化 scaler = StandardScaler() X_scaled = scaler.fit_transform(X)# 重新划分数据集 X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.3, random_state=42)# 寻找最优K值 k_range = range(1, 20) accuracies = []for k in k_range:knn = KNeighborsClassifier(n_neighbors=k)knn.fit(X_train, y_train)y_pred = knn.predict(X_test)accuracies.append(accuracy_score(y_test, y_pred))# 绘制K值与准确率关系 plt.figure(figsize=(10, 6)) plt.plot(k_range, accuracies, marker='o') plt.xlabel('K值') plt.ylabel('准确率') plt.title('K值与模型准确率关系') plt.grid(True) plt.show()# 使用最优K值 best_k = k_range[np.argmax(accuracies)] print(f"最优K值: {best_k}")knn_best = KNeighborsClassifier(n_neighbors=best_k) knn_best.fit(X_train, y_train) y_pred_best = knn_best.predict(X_test)accuracy_best = accuracy_score(y_test, y_pred_best) print(f"最优K近邻准确率: {accuracy_best:.4f}")
3.3 决策树分类
决策树通过一系列规则对数据进行分割,形成树状结构。
python
from sklearn.tree import DecisionTreeClassifier, plot_tree from sklearn.datasets import load_iris# 加载鸢尾花数据集 iris = load_iris() X, y = iris.data, iris.target# 划分数据集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)# 创建决策树分类模型 dt_clf = DecisionTreeClassifier(max_depth=3, random_state=42) dt_clf.fit(X_train, y_train)# 预测 y_pred = dt_clf.predict(X_test)# 评估 accuracy = accuracy_score(y_test, y_pred) print(f"决策树分类准确率: {accuracy:.4f}")# 可视化决策树 plt.figure(figsize=(15, 10)) plot_tree(dt_clf, feature_names=iris.feature_names, class_names=iris.target_names, filled=True, rounded=True) plt.title('决策树分类器') plt.show()# 特征重要性 feature_importance = dt_clf.feature_importances_ plt.figure(figsize=(8, 6)) plt.barh(iris.feature_names, feature_importance) plt.xlabel('特征重要性') plt.title('决策树特征重要性') plt.show()
3.4 随机森林分类
随机森林通过集成多个决策树来提高分类性能。
python
from sklearn.ensemble import RandomForestClassifier# 创建随机森林分类模型 rf_clf = RandomForestClassifier(n_estimators=100, random_state=42) rf_clf.fit(X_train, y_train)# 预测 y_pred_rf = rf_clf.predict(X_test)# 评估 accuracy_rf = accuracy_score(y_test, y_pred_rf) print(f"随机森林分类准确率: {accuracy_rf:.4f}")# 特征重要性 feature_importance_rf = rf_clf.feature_importances_ plt.figure(figsize=(8, 6)) plt.barh(iris.feature_names, feature_importance_rf) plt.xlabel('特征重要性') plt.title('随机森林特征重要性') plt.show()
3.5 支持向量机(SVM)
SVM通过寻找最大间隔超平面来区分不同类别。
python
from sklearn.svm import SVC from sklearn.preprocessing import StandardScaler# 数据标准化 scaler = StandardScaler() X_scaled = scaler.fit_transform(X)# 重新划分数据集 X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.3, random_state=42)# 创建SVM模型 svm = SVC(kernel='rbf', probability=True) svm.fit(X_train, y_train)# 预测 y_pred_svm = svm.predict(X_test)# 评估 accuracy_svm = accuracy_score(y_test, y_pred_svm) print(f"SVM分类准确率: {accuracy_svm:.4f}")# 比较不同核函数性能 kernels = ['linear', 'poly', 'rbf', 'sigmoid'] kernel_accuracies = []for kernel in kernels:svm_temp = SVC(kernel=kernel, random_state=42)svm_temp.fit(X_train, y_train)y_pred_temp = svm_temp.predict(X_test)kernel_accuracies.append(accuracy_score(y_test, y_pred_temp))# 绘制不同核函数性能比较 plt.figure(figsize=(8, 6)) plt.bar(kernels, kernel_accuracies) plt.xlabel('核函数') plt.ylabel('准确率') plt.title('不同核函数SVM性能比较') plt.show()
3.6 朴素贝叶斯
朴素贝叶斯基于贝叶斯定理,假设特征之间相互独立。
python
from sklearn.naive_bayes import GaussianNB from sklearn.datasets import load_breast_cancer# 加载乳腺癌数据集 cancer = load_breast_cancer() X, y = cancer.data, cancer.target# 划分数据集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)# 创建朴素贝叶斯模型 nb = GaussianNB() nb.fit(X_train, y_train)# 预测 y_pred_nb = nb.predict(X_test)# 评估 accuracy_nb = accuracy_score(y_test, y_pred_nb) print(f"朴素贝叶斯分类准确率: {accuracy_nb:.4f}")# 绘制概率分布 y_proba = nb.predict_proba(X_test)plt.figure(figsize=(12, 5))plt.subplot(1, 2, 1) plt.hist(y_proba[y_test==0, 1], bins=20, alpha=0.7, label='实际为0', color='red') plt.hist(y_proba[y_test==1, 1], bins=20, alpha=0.7, label='实际为1', color='blue') plt.xlabel('预测概率') plt.ylabel('频数') plt.title('类别概率分布') plt.legend()plt.subplot(1, 2, 2) plt.scatter(range(len(y_proba)), y_proba[:, 1], c=y_test, cmap='bwr', alpha=0.7) plt.xlabel('样本索引') plt.ylabel('预测为1的概率') plt.title('样本预测概率') plt.colorbar()plt.tight_layout() plt.show()
四、模型评估与比较
4.1 回归模型评估指标
均方误差(MSE):预测值与真实值之差的平方的平均值
均方根误差(RMSE):MSE的平方根
平均绝对误差(MAE):预测值与真实值之差的绝对值的平均值
R²分数:模型可解释的方差比例
4.2 分类模型评估指标
准确率:正确预测的样本比例
精确率:正类预测中实际为正类的比例
召回率:实际正类中被正确预测的比例
F1分数:精确率和召回率的调和平均
AUC-ROC:ROC曲线下的面积
python
from sklearn.metrics import roc_curve, auc, precision_recall_curve from sklearn.model_selection import cross_val_score# 比较不同分类算法的性能 classifiers = {'逻辑回归': LogisticRegression(),'K近邻': KNeighborsClassifier(n_neighbors=5),'决策树': DecisionTreeClassifier(max_depth=3),'随机森林': RandomForestClassifier(n_estimators=100),'SVM': SVC(probability=True),'朴素贝叶斯': GaussianNB() }# 使用乳腺癌数据集进行性能比较 cancer = load_breast_cancer() X, y = cancer.data, cancer.target X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)results = {} for name, clf in classifiers.items():# 训练模型clf.fit(X_train, y_train)# 预测y_pred = clf.predict(X_test)y_proba = clf.predict_proba(X_test)[:, 1] if hasattr(clf, "predict_proba") else clf.decision_function(X_test)# 计算指标accuracy = accuracy_score(y_test, y_pred)# 交叉验证cv_scores = cross_val_score(clf, X, y, cv=5, scoring='accuracy')# ROC曲线fpr, tpr, _ = roc_curve(y_test, y_proba)roc_auc = auc(fpr, tpr)results[name] = {'accuracy': accuracy,'cv_mean': cv_scores.mean(),'cv_std': cv_scores.std(),'fpr': fpr,'tpr': tpr,'roc_auc': roc_auc}print(f"{name}: 准确率={accuracy:.4f}, 交叉验证={cv_scores.mean():.4f}±{cv_scores.std():.4f}")# 绘制ROC曲线比较 plt.figure(figsize=(10, 8)) for name, result in results.items():plt.plot(result['fpr'], result['tpr'], label=f'{name} (AUC = {result["roc_auc"]:.3f})')plt.plot([0, 1], [0, 1], 'k--', label='随机分类器') plt.xlim([0.0, 1.0]) plt.ylim([0.0, 1.05]) plt.xlabel('假正率') plt.ylabel('真正率') plt.title('不同分类算法的ROC曲线比较') plt.legend() plt.grid(True) plt.show()
五、实际应用案例
5.1 房价预测(回归案例)
python
import pandas as pd from sklearn.datasets import fetch_california_housing from sklearn.ensemble import GradientBoostingRegressor from sklearn.model_selection import GridSearchCV# 加载加州房价数据集 housing = fetch_california_housing() X, y = housing.data, housing.target# 创建DataFrame便于分析 df = pd.DataFrame(X, columns=housing.feature_names) df['Price'] = yprint("数据集基本信息:") print(df.info()) print("\n描述性统计:") print(df.describe())# 划分数据集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 使用梯度提升回归树 gbr = GradientBoostingRegressor(random_state=42)# 超参数调优 param_grid = {'n_estimators': [100, 200],'max_depth': [3, 4],'learning_rate': [0.1, 0.05] }grid_search = GridSearchCV(gbr, param_grid, cv=5, scoring='neg_mean_squared_error', n_jobs=-1) grid_search.fit(X_train, y_train)# 最佳模型 best_gbr = grid_search.best_estimator_ y_pred = best_gbr.predict(X_test)# 评估 mse = mean_squared_error(y_test, y_pred) rmse = np.sqrt(mse) r2 = r2_score(y_test, y_pred)print(f"\n梯度提升回归树结果:") print(f"最佳参数: {grid_search.best_params_}") print(f"均方误差: {mse:.4f}") print(f"均方根误差: {rmse:.4f}") print(f"R²分数: {r2:.4f}")# 特征重要性 feature_importance = best_gbr.feature_importances_ feature_importance_df = pd.DataFrame({'feature': housing.feature_names,'importance': feature_importance }).sort_values('importance', ascending=False)plt.figure(figsize=(10, 6)) plt.barh(feature_importance_df['feature'], feature_importance_df['importance']) plt.xlabel('特征重要性') plt.title('梯度提升回归树特征重要性') plt.show()
5.2 信用卡欺诈检测(分类案例)
python
from sklearn.ensemble import IsolationForest from sklearn.metrics import classification_report, confusion_matrix import pandas as pd# 生成模拟的信用卡交易数据(在实际应用中应使用真实数据) np.random.seed(42) n_samples = 10000 n_features = 5# 生成正常交易数据 normal_transactions = np.random.normal(0, 1, (int(n_samples * 0.99), n_features))# 生成欺诈交易数据(与正常交易有明显差异) fraud_transactions = np.random.normal(3, 1.5, (int(n_samples * 0.01), n_features))# 合并数据 X = np.vstack([normal_transactions, fraud_transactions]) y = np.hstack([np.zeros(len(normal_transactions)), np.ones(len(fraud_transactions))])# 打乱数据 shuffle_idx = np.random.permutation(len(X)) X, y = X[shuffle_idx], y[shuffle_idx]print(f"数据集形状: {X.shape}") print(f"欺诈交易比例: {y.mean():.4f}")# 划分数据集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y)# 使用多种算法进行欺诈检测 fraud_models = {'逻辑回归': LogisticRegression(class_weight='balanced'),'随机森林': RandomForestClassifier(n_estimators=100, class_weight='balanced', random_state=42),'孤立森林': IsolationForest(contamination=0.01, random_state=42) }fraud_results = {}for name, model in fraud_models.items():if name == '孤立森林':# 孤立森林是无监督算法,需要特殊处理model.fit(X_train)y_pred = model.predict(X_test)# 将孤立森林的输出转换为0/1(-1表示异常,1表示正常)y_pred = (y_pred == -1).astype(int)else:model.fit(X_train, y_train)y_pred = model.predict(X_test)accuracy = accuracy_score(y_test, y_pred)cm = confusion_matrix(y_test, y_pred)fraud_results[name] = {'accuracy': accuracy,'confusion_matrix': cm}print(f"\n{name}结果:")print(f"准确率: {accuracy:.4f}")print("混淆矩阵:")print(cm)print("分类报告:")print(classification_report(y_test, y_pred))# 可视化比较 model_names = list(fraud_results.keys()) accuracies = [result['accuracy'] for result in fraud_results.values()]plt.figure(figsize=(10, 6)) plt.bar(model_names, accuracies) plt.xlabel('算法') plt.ylabel('准确率') plt.title('不同算法在欺诈检测中的性能比较') plt.ylim(0.9, 1.0) plt.show()
六、总结与展望
本文详细介绍了回归和分类算法的核心知识点,包括:
回归算法:线性回归、多项式回归、决策树回归、随机森林回归、支持向量回归等
分类算法:逻辑回归、K近邻、决策树、随机森林、支持向量机、朴素贝叶斯等
模型评估:各种评估指标和可视化方法
实际应用:房价预测和欺诈检测案例
算法选择建议:
对于线性关系明显的数据,线性回归和逻辑回归是良好的起点
对于复杂非线性关系,树模型(决策树、随机森林)和SVM通常表现更好
当数据量较大且特征间关系复杂时,集成学习方法(随机森林、梯度提升)往往最优
对于高维稀疏数据,朴素贝叶斯和线性模型可能更合适
未来发展趋势:
自动化机器学习:自动选择算法和调参
可解释AI:提高模型透明度和可解释性
联邦学习:在保护隐私的前提下进行分布式模型训练
元学习:让模型学会如何学习,快速适应新任务
回归和分类算法是机器学习的基石,掌握这些算法对于任何数据科学家或机器学习工程师都至关重要。通过理论学习和实践结合,我们能够更好地理解这些算法的原理和应用场景,从而在实际问题中选择合适的算法并取得良好的预测效果。