模型误差

偏差(Bias) - 预测结果的准确程度

bias^2(x)=[\bar{f}(x)-y]^2

高偏差原因:

  • 模型本身不适合
    • 例:线性模型拟合非线性数据
  • 欠拟合
    • 模型未收敛(射击手只在室内练习没在室外练习过)

方差(Variance) - 预测结果的集中程度

var(x)=E_D[(f(x:D)-\bar{f}(x))^2]

高方差原因:

  • 模型过于复杂
    • 例:特征太多(射击手心理活动过多:没吃饱)
  • 过拟合
    • 噪声数据影响(错误的肌肉记忆)

噪声(Noise) - 当前任务期望误差下界

\varepsilon ^2=E[(y_D-y)^2]

原因:

  • 观测误差
  • 计算机精度误差
  • 方法误差

模型误差的组成

\mathbb{E}[(y - \hat{f}(x))^2] = \text{Bias}^2 + \text{Variance} + \text{Noise}

  • 偏差:算法的拟合能力
  • 方差:数据扰动影响力
  • 噪声:任务期望误差的下界

偏差和方差的关系(相互冲突)

  • 偏差降低则方差会提高
  • 方差降低则偏差会提高

偏差、方差和模型复杂度的关系

  • 不同算法有不同偏差和方差
    • 非参数方程方差高,如KNN
    • 参数方程偏差高,如回归算法
  • 偏差方差通常可以调整

降低偏差:

  • 寻找更好的特征
  • 增加更多的特征
  • 提高模型复杂度

降低方差:

  • 尽量选择复杂度模型
  • 尽可能增加样本数
  • 尽可能减少数据维度
  • 使用验证集
  • 使用正则化

正则化

用约束换稳定,降低方差,防止过拟合

L1范数(LASSO回归)

\Omega(w)=\|w\|_1=\sum_{i=1}^n |w_i|

L2范数(岭回归)

\Omega(w)=\|w\|_2^2=\sum_{i=1}n w_i^2

LASSO和岭回归

LASSO回归

  • 会把部分参数压成 0(删除某些特征)

  • 自动特征选择

  • 稀疏模型

w^*=\underset{w}{argmin}\left \{ MSE(y,\hat{y},w) +\lambda \sum_{i=1}^n|w_i|\right \}

岭回归​​​​​​​

  • 参数变小但不为 0(所有特征都保留,只是权重变小)

  • 模型更平滑、稳定

  • 最常用

w^*=\underset{w}{argmin}\left \{ MSE(y,\hat{y},w) +\frac{\lambda }{2}\sum_{i=1}^n|w_i^2|\right \}

数据准备

import numpy as np 
from sklearn import datasets
import matplotlib.pyplot as plt
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
import warnings
warnings.filterwarnings("ignore")

import pandas as pd
boston = (pd.read_csv('./BostonHousing.csv')).to_numpy()
x = boston[:,12]
y = boston[:,-1]
x = x[y<50]
y = y[y<50]

from sklearn.model_selection import train_test_split

np.random.seed(666)
x_train,x_test,y_train,y_test = train_test_split(x.reshape(-1,1),y)


def show_plot(model):
    plt.scatter(x,y)
    X_plot = np.linspace(0,40,100).reshape(100,1)
    y_polt = model.predict(X_plot)
    plt.plot(X_plot[:,0],y_polt,color='red')
    plt.axis([0,40,0,50])
    plt.show()

LASSO回归代码实现

from sklearn.linear_model import Lasso

def LassoRegression(degree,alpha):
    return Pipeline([
        ("poly",PolynomialFeatures(degree=degree)),
        ("std_scale",StandardScaler()),
        ("lasso_reg",Lasso(alpha=alpha))
    ])

lasso_reg = LassoRegression(20,1)
lasso_reg.fit(x_train,y_train)
y_predict = lasso_reg.predict(x_test)
mean_squared_error(y_test,y_predict)

show_plot(lasso_reg)

岭回归代码实现

from sklearn.linear_model import Ridge

def RidgeRegression(degree,alpha):
    return Pipeline([
        ("poly",PolynomialFeatures(degree=degree)),
        ("std_scale",StandardScaler()),
        ("ridge_reg",Ridge(alpha=alpha))
    ])

ridge_reg = RidgeRegression(20,100)
ridge_reg.fit(x_train,y_train)
y_predict = ridge_reg.predict(x_test)
mean_squared_error(y_test,y_predict)

show_plot(ridge_reg)

模型泛化

机器学习算法对于新鲜样本的适应能力(比如使用美颜照片训练模型,当面对无美颜的照片时能否测试准确)

泛化理论:衡量模型复杂度

评价指标

混淆矩阵

实际 \ 预测预测为正预测为负
实际为正TPFN
实际为负FPTN

精确度(Precision):预测为正的里面,有多少是真的

\text{Precision}=\frac{TP}{TP+FP}

召回率(Reccall):真正的正样本,被找回了多少

\text{Recall}=\frac{TP}{TP+FN}

准确率(Accuracy):整体预测对了多少

\text{Accuracy}=\frac{TP+TN}{TP+TN+FP+FN}

F1Score

F1=\frac{2\cdot Precision\cdot Recall}{Precision+Recall}

PR曲线

在不同分类阈值(thresholds)下,观察“预测为正的质量”和“找全正样本能力”之间的权衡

输入:

  • y_test

  • decision_scores

​​​​​​​# 让逻辑回归模型给每个测试样本算一个“决策分数”
decision_scores = log_reg.decision_function(X_test)

输出:

  • 横轴:Recall(召回率)

  • 纵轴:Precision(精确率)

ROC曲线

输入:

  • y_test

  • decision_scores

输出:

  • 横轴:FPR

  • 纵轴:TPR

TPR(所有真正的正样本中,被模型抓住了多少,Recall)

\text{TPR}=\frac{TP}{TP+FN}

FPR(所有真实负样本中,被误判成正的比例)

\text{FPR}=\frac{FP}{FP+TN}

AUC(ROC 曲线下面积)

AUC 衡量的是:随机抽一个正样本和一个负样本,模型把正样本排在前面的概率

  • AUC = 1:完美排序

  • AUC = 0.5:随机猜

  • AUC < 0.5:反着猜

ROC VS PR

对比ROCPR
纵轴TPRPrecision
横轴FPRRecall
关注点排序能力正类质量
类别不平衡一般更敏感

数据准备

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets

# 加载鸢尾花数据集
iris = datasets.load_iris()
x = iris.data
y = iris.target.copy()
# 转为二分类问题
y[y!=0] = 1
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

X_train,X_test,y_train,y_test = train_test_split(x,y,random_state=666)

log_reg = LogisticRegression()
log_reg.fit(X_train,y_train)
y_predict = log_reg.predict(X_test)

混淆矩阵、Precision、Recall、F1 Score

# 手动实现
TN = np.sum((y_predict==0)&(y_test==0))
TP = np.sum((y_predict==1)&(y_test==1))
FP = np.sum((y_predict==1)&(y_test==0))
FN = np.sum((y_predict==0)&(y_test==1))

confusion_matrix = np.array([
    [TN,FP],
    [FN,TP]
])

precision = TP/(TP+FP)
recall = TP/(TP+FN)
f1_score = 2*precision*recall/(precision+recall)

# sklearn实现
from sklearn.metrics import precision_score,recall_score,f1_score,confusion_matrix
confusion_matrix(y_test,y_predict)
precision_score(y_test,y_predict)
recall_score(y_test,y_predict)
f1_score(y_test,y_predict)

PR曲线、ROC曲线、AUC

# 让逻辑回归模型给每个测试样本算一个“决策分数”
decision_scores = log_reg.decision_function(X_test)

from sklearn.metrics import precision_score,recall_score

precision_scores,recall_scores =[],[]
# 阈值列表
thresholds = np.sort(decision_scores)
for threshold in thresholds:
    y_predict = np.array(decision_scores>=threshold,dtype='int')
    precison = precision_score(y_test,y_predict)
    recall = recall_score(y_test,y_predict)
    precision_scores.append(precison)
    recall_scores.append(recall)

plt.plot(thresholds,precision_scores,color='r',label='Precision')
plt.plot(thresholds,recall_scores,color='b',label='Recall')
plt.legend()
plt.show()

plt.plot(recall_scores,precision_scores)
plt.xlabel("Recall")
plt.ylabel("Precision")
plt.show()

# sklearn实现PR曲线
from sklearn.metrics import precision_recall_curve
# 注意:precision_scores,recall_scores比thresholds多出来一个值
precision_scores,recall_scores,thresholds = precision_recall_curve(y_test,decision_scores)
plt.plot(thresholds,precision_scores[:-1],color='r',label='Precision')
plt.plot(thresholds,recall_scores[:-1],color='b',label='Recall')
plt.legend()
plt.show()
plt.plot(recall_scores,precision_scores)
plt.xlabel("Recall")
plt.ylabel("Precision")
plt.show()

# ROC曲线
from sklearn.metrics import roc_curve

fpr,tpr,thresholds = roc_curve(y_test,decision_scores)
plt.plot(fpr,tpr)
plt.xlabel("FPR")
plt.ylabel("TPR")
plt.show()

# AUC
from sklearn.metrics import roc_auc_score

auc = roc_auc_score(y_test,decision_scores)
auc

            

更多推荐