快手 机器学习算法
一、AUC(Area Under the ROC Curve)怎么计算?AUC接近1可能的原因是什么?
见【搜广推校招面经四】
AUC 是评估分类模型性能的重要指标,用于衡量模型在不同阈值下区分正负样本的能力。它是 ROC 曲线(Receiver Operating Characteristic Curve)下的面积。
1.1. ROC 曲线的坐标
ROC 曲线以 真正例率(True Positive Rate, TPR) 为纵轴,假正例率(False Positive Rate, FPR) 为横轴。
1.1.1. 真正例率(TPR) = 召回率(Recall) = 灵敏度(Sensitivity)
=
T
P
T
P
+
F
N
=
T
P
P
= \frac{TP}{TP + FN} = \frac{TP}{P}
=TP+FNTP=PTP
其中:
- T P TP TP:真正例(True Positives),即模型正确预测的正样本数。
- F N FN FN:假反例(False Negatives),即模型错误预测的负样本数。
2.2 假正例率(FPR)
F
P
R
=
F
P
F
P
+
T
N
=
F
P
N
FPR = \frac{FP}{FP + TN} = \frac{FP}{N}
FPR=FP+TNFP=NFP
其中:
- F P FP FP:假正例(False Positives),即模型错误预测的正样本数。
- T N TN TN:真反例(True Negatives),即模型正确预测的负样本数。
1.2. AUC 的计算公式
AUC 是 ROC 曲线下的面积,可以通过以下方法计算:
1.2.1. 积分法
A
U
C
=
∫
0
1
T
P
R
(
F
P
R
)
d
F
P
R
AUC = \int_{0}^{1} TPR(FPR) \, dFPR
AUC=∫01TPR(FPR)dFPR
即对 ROC 曲线下的面积进行积分。
1.2.2. 排序法(更常用)
AUC 可以通过对样本的预测概率进行排序计算:
A
U
C
=
∑
i
=
1
N
+
∑
j
=
1
N
−
I
(
p
i
>
p
j
)
N
+
×
N
−
AUC = \frac{\sum_{i=1}^{N_+} \sum_{j=1}^{N_-} \mathbb{I}(p_i > p_j)}{N_+ \times N_-}
AUC=N+×N−∑i=1N+∑j=1N−I(pi>pj)
其中:
- ( N_+ ):正样本的数量。
- ( N_- ):负样本的数量。
- ( p_i ):第 ( i ) 个正样本的预测概率。
- ( p_j ):第 ( j ) 个负样本的预测概率。
- I ( p i > p j ) \mathbb{I}(p_i > p_j) I(pi>pj):指示函数,当 p i > p j p_i > p_j pi>pj 时为 1,否则为 0。
1.3. 手撕AUC
def cal_auc_1(label, pred):
numerator = 0 # 分子
denominator = 0 # 分母
for i in range(len(label) - 1):
for j in range(i, len(label)):
if label[i] != label[j]:
denominator += 1
# 统计所有正负样本对中,模型把相对位置排序正确的数量
r = (label[i] - label[j]) * (pred[i] - pred[j])
if r > 0:
numerator += 1
elif r == 0:
numerator += 0.5
return numerator / denominator
二、LR逻辑回归的损失函数,使用熟悉的语言,写出交叉熵的伪代码
首先明确,逻辑回归的损失函数是交叉熵损失函数,也被称为对数损失函数(log loss)。
手撕:见【搜广推校招面经二十三】
import numpy as np
class LogisticRegression:
def __init__(self, learning_rate=0.01, num_iterations=1000):
self.learning_rate = learning_rate # 学习率
self.num_iterations = num_iterations # 迭代次数
self.theta = None # 模型参数
def sigmoid(self, z):
"""计算 Sigmoid 函数"""
return 1 / (1 + np.exp(-z))
def compute_cost(self, X, y):
"""计算交叉熵损失函数"""
m = len(y)
h = self.sigmoid(np.dot(X, self.theta))
cost = - (1/m) * np.sum(y * np.log(h) + (1 - y) * np.log(1 - h))
return cost
def gradient_descent(self, X, y):
"""梯度下降优化"""
m = len(y)
for i in range(self.num_iterations):
h = self.sigmoid(np.dot(X, self.theta)) # 计算预测值
gradient = (1/m) * np.dot(X.T, (h - y)) # 计算梯度
self.theta -= self.learning_rate * gradient # 更新参数
if i % 100 == 0: # 每100次输出一次损失值
cost = self.compute_cost(X, y)
print(f"Iteration {i}, Cost: {cost}")
def fit(self, X, y):
"""训练模型"""
m, n = X.shape
self.theta = np.zeros(n) # 初始化参数
self.gradient_descent(X, y)
def predict(self, X):
"""预测新样本的类别"""
probabilities = self.sigmoid(np.dot(X, self.theta))
return probabilities >= 0.5 # 预测类别:如果大于等于 0.5,分类为 1,否则为 0
三、平均绝对误差(MAE)与均方误差(MSE)的理解及区别
见【搜广推实习面经四】
3.1. 平均绝对误差(MAE)
定义
MAE表示预测值和真实值之间绝对误差的平均值,是一个非负值,MAE越小表示模型越好。其公式如下:
M
A
E
=
1
n
∑
i
=
1
n
∣
y
i
−
y
^
i
∣
MAE = \frac{1}{n} \sum_{i=1}^{n} |y_i - \hat{y}_i|
MAE=n1i=1∑n∣yi−y^i∣
其中
y
i
y_i
yi 是真实值,
y
^
i
\hat{y}_i
y^i 是预测值,
n
n
n 是样本数量。
特点
- 直观性: MAE以原始数据单位表示,因此更直观易懂。例如,在房价预测问题中,MAE可以直接解释为预测价格与实际价格之间的平均偏差。
- 鲁棒性: MAE对异常值不敏感,因为它使用的是绝对值而不是平方值来计算误差。这意味着即使存在极端值,其影响也不会被放大。
3.2. 均方误差(MSE)
定义
MSE是预测值和真实值之间误差平方的平均值。其公式如下:
M
S
E
=
1
n
∑
i
=
1
n
(
y
i
−
y
^
i
)
2
MSE = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2
MSE=n1i=1∑n(yi−y^i)2
特点
- 敏感性: MSE对较大的误差更为敏感,因为误差被平方后,较大的误差会被进一步放大。这使得MSE非常适合用于检测异常值或重要的偏离情况。
- 可微性: MSE是一个平滑可微的函数,便于进行数学运算和优化算法的应用。
3.3. 区别
3.3.1. 误差处理方式
- MAE采用绝对值处理误差,所有个体差异在平均值上的权重都相等。
- MSE则通过对误差进行平方处理,给予大误差更多的权重,从而更加突出大误差的影响。
3.3.2. 对异常值的反应
- MAE由于其线性性质,对异常值具有较好的鲁棒性。
- 相比之下,MSE由于其平方特性,对异常值更加敏感。
3.3.3. 优化过程中的表现
- 在训练过程中,MAE可能导致更新梯度始终相同的问题,即使对于很小的损失值,梯度也可能较大,不利于模型的学习。
- 而MSE在这种情况下的表现较好,即便使用固定的学习率也可以有效收敛,因为其梯度随损失增大而增大,损失趋于0时则会减小。
3.3.4. 应用场景
- 如果异常点代表了商业上重要的异常情况,并且需要被检测出来,则应选用MSE作为损失函数。
- 若仅把异常值当作受损数据,则应选用MAE作为损失函数。