逻辑斯谛函数下的线性模型
现需要用线性模型做分类问题,简单的阶跃函数在阈值处不可导,可导处导数均为0,性质不好
所以把0,1问题转化成P(y=0|x),P(y=1|x)的问题,这样就把离散的分类任务变成了求概率分布的回归任务,概率分布要求在(0,1)之间,且需要光滑连续的曲线才会有较好的梯度,所以定义逻辑斯谛函数
最大似然估计
对于有关概率分布的问题,我们常常使用最大似然估计(maximum likelihood estimation,MLE)的思想来优化模型,也即是寻找逻辑斯谛回归的参数使得模型在训练数据上预测出正确标签的概率最大。
对应梯度下降算法的矩阵形式为
再加入L2正则化
扩展到多分类上:
疑惑:sigmoid与softmax
sigmoid也是将x压缩到0~1之间,和softmax的区别在哪呢?(1)在实际应用中,一般将softmax用于多类分类的使用之中,而将sigmoid用于多标签分类之中。sigmoid函数,我们可以当作成它是对一个类别的“建模”,将该类别建模完成,另一个相对的类别就直接通过1减去得到。而softmax函数,是对两个类别建模,同样的,得到两个类别的概率之和是1
(2)softmax求出的概率不是相互独立,而是有关的。而sigmoid求出的概率之间互不影响,只和Xi大小有关。
(3)虽然都将输出激活到0-1,但softmax更离散,sigmoid更加均衡。在网络学习不到东西时,softmax通常会全部学习到一个类别上,全1。而sigmoid一般导致所有预测都是0.5。
分类问题的评价指标
正负类对目标的影响程度是不一样的,有的时候不容许犯错,有的时候宁可判对
需要混淆矩阵来充当评价指标
真阳性率(true positive rate,TPR),也称查全率或召回率(recall):
假阳性率(false positive rate,FPR):
查准率(precision):
F1 分数(F1 score),定义为精确率和召回率的调和平均值:
ROC曲线:
我们希望 ROC 曲线能尽可能偏向左上方,即所有的正样本都归为正类,所有的负样本都归为负类
AUC:ROC曲线与x轴和直线x=1围成面积,也就是图中的蓝色部分;AUC越大表示效果越好;AUC 的值事实上与阈值是的选取无关的,只与模型本身对正负类的预测结果有关。
动手实现逻辑斯谛回归
pos_index = np.where(y_total == 1)
neg_index = np.where(y_total == 0)
plt.scatter(x_total[pos_index, 0], x_total[pos_index, 1],
marker='o', color='coral', s=10)
plt.scatter(x_total[neg_index, 0], x_total[neg_index, 1],
marker='x', color='blue', s=10)
np.where提取符合要求的行的索引
x_total[pos_index, 0]是提取y为1的行的第一列数据,即点的x坐标;x_total[pos_index, 1]是点的y坐标
def acc(y_true, y_pred):
return np.mean(y_true == y_pred)
def auc(y_true, y_pred):
# 按预测值从大到小排序,越靠前的样本预测正类概率越大
idx = np.argsort(y_pred)[::-1]
y_true = y_true[idx]
y_pred = y_pred[idx]
# 把y_pred中不重复的值当作阈值,依次计算FP样本和TP样本数量
# 由于两个数组已经排序且位置对应,直接从前向后累加即可
tp = np.cumsum(y_true)
fp = np.cumsum(1 - y_true)
tpr = tp / tp[-1]
fpr = fp / fp[-1]
# 依次枚举FPR,计算曲线下的面积
# 方便起见,给FPR和TPR最开始添加(0,0)
s = 0.0
tpr = np.concatenate([[0], tpr])
fpr = np.concatenate([[0], fpr])
for i in range(1, len(fpr)):
s += (fpr[i] - fpr[i - 1]) * tpr[i]
return s
排序是因为预测概率越大,超过阈值就是正例
np.cumsum()
函数,它会计算数组元素的累积和
tpr = tp / tp[-1]
和 fpr = fp / fp[-1]
: 计算真正例率和假正例率,即ROC曲线上的纵坐标和横坐标。除以它们的最大值,以得到标准化后的值,也就是缩放到0~1
tpr = np.concatenate([[0], tpr]),fpr = np.concatenate([[0], fpr])增加(0,0)点
# 定义梯度下降迭代的次数,学习率,以及L2正则系数
num_steps = 250
learning_rate = 0.002
l2_coef = 1.0
np.random.seed(0)
# 在x矩阵上拼接1
X = np.concatenate([x_train, np.ones((x_train.shape[0], 1))], axis=1)
X_test = np.concatenate([x_test, np.ones((x_test.shape[0], 1))], axis=1)
theta, train_losses, test_losses, train_acc, test_acc, \
train_auc, test_auc = GD(num_steps, learning_rate, l2_coef)
# 计算测试集上的预测准确率
y_pred = np.where(logistic(X_test @ theta) >= 0.5, 1, 0)
final_acc = acc(y_test, y_pred)
print('预测准确率:', final_acc)
print('回归系数:', theta)
拼接1是弄个偏置出来
y_pred = np.where(logistic(X_test @ theta) >= 0.5, 1, 0)预测大于阈值0.5就是正例
画图部分中:
plt.gca().xaxis.set_major_locator(MaxNLocator(integer=True))用于设置当前图形的x轴主刻度定位器为整数定位器(MaxNLocator
),它会自动选择主要刻度以显示整数。在这种情况下,我们使用integer=True
参数告诉Matplotlib只显示整数刻度
交叉熵与最大似然估计
如果该分布中有某个事件发生的概率很大,预测的难度就较低;反过来,如果各个事件发生的概率都很接近,那么就很难预测到底哪一个事件会发生,也就是分布的不确定性更大。
在信息论中把这种东西叫作信息熵,越无规律信息熵越大,包含的信息越多
KL散度:比较两个分布之间的差异;始终是非负的;比值越接近0表示两个分布越相似
进一步拆分KL散度:
H(p,q)称为分布p与q的交叉熵,-H(p)只与样本的真实类别有关,因此我们只需要最小化交叉熵
对所有样本的交叉熵求和,就得到总的交叉熵为:
发现恰好等于负的对数似然函数,也就是逻辑回归问题中最大化对数似然函数与最小化交叉熵是等价的
习题
1.B。始终是对着取了对数的目标函数优化
2.CD。在设计损失函数时确实可以采用交叉熵损失,但是不是每一类的损失相乘,而是各分类的负对数似然之和;softmax不可以作为损失函数,逻辑回归函数≠sigmoid函数
3.B。准确率(Accuracy)是指分类正确的样本(包括正类和负类)占全体样本的比例
4.逻辑斯谛回归尽管在输出层使用了非线性的Sigmoid函数,但在决定模型预测结果的决策边界方面,它基于输入特征的线性组合。
5.交换正负标签
6.
先将数据按照预测概率从高到低排序
import numpy as np
import matplotlib.pyplot as plt
# 预测概率
probabilities = np.array([0.74, 0.71, 0.52, 0.48, 0.45, 0.34, 0.21, 0.15])
# 对应的标签
labels = np.array([1, 1, 1, 1, 0, 1, 0, 0])
# 按照预测概率从高到低排序
indices = np.argsort(probabilities)[::-1]
sorted_labels = labels[indices]
# 计算真阳性率(TPR)和假阳性率(FPR)
tpr = np.cumsum(sorted_labels) / np.sum(sorted_labels)
fpr = np.cumsum(1 - sorted_labels) / np.sum(1 - sorted_labels)
# 绘制ROC曲线
plt.figure()
plt.plot(fpr, tpr, color='blue', lw=2, label='ROC curve')
plt.plot([0, 1], [0, 1], color='gray', linestyle='--', lw=2, label='Random guess')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic (ROC) Curve')
plt.legend(loc='lower right')
plt.grid(True)
plt.show()
# 计算AUC值
auc = np.trapz(tpr, fpr)
print("AUC值为:", auc)
7.
8.z1=0时
求和仍为1;k=2时变成sigmoid
9.
(1)求导
(2)i,j 是指样本 i 的真实标签表示为一个长度为 K 的向量 yi,其中只有第 j 个元素为 1,其余元素均为 0
MLE:
交叉熵:
(3)略
10.KL散度非负性必须要证明log(q/p)是关于x的上凸函数,然后利用Jensen不等式