【机器学习】SoftMax多分类

简介: 【机器学习】SoftMax多分类

softMax分类函数


首先给一个图,这个图比较清晰地告诉大家softmax是怎么计算的。

040e203015d37b8b260f03846a1b356b_99176d8d73c14086b6ba55ac080618b6.png

定义:


image.png

且可知


image.png

类别数k要小于特征维度n

如果类别数大于特征维度,那么就会出现过多的未知参数需要学习,导致模型过于复杂,难以训练和泛化。因此,通常是将类别数设定为特征维度的一个较小的值,以保证模型的简洁性和可行性。


softmax分类损失函数


交叉熵的理论部分在上一篇文章:Logistic回归

前面提到,在多分类问题中,我们经常使用交叉熵作为损失函数


image.png

其中image.png 表示真实值,image.png表示求出的softmax值。当预测第i个时,可以认为image.png此时损失函数变成了

image.png


代入

image.png

求梯度

image.png

上面的结果表示,我们只需要正向求出image.png ,将结果减1就是反向更新的梯度,导数的计算是不是非常简单!


总结一下:

ae305fa0e9f40fb17143953a6bb99aca_e2ccb669039e46a1bc3ee77f6685738f.png

0e976aab27f38bf589e5b94f38fbcd93_a0f7cca2f2544f66ac869290506e93e6.png

93973189e4e9b97599ae899624a5d27d_0e24a3dd1f6a4e2595e9e83fff8e1cdd.png


练习题:红酒产地预测


d6c53047b3cd0051f8af3a62e605e9a3_efe326c3b9244eb1b00b87d123485353.png

本实验使用softmax回归模型进行红酒品质分类。首先,导入红酒数据,并将类标签转换为one-hot向量表示, 特征组向量前面置1(为了将线性回归b吸收到w中)。

rwine = load_wine()  # 导入红酒数据
X = rwine.data
y = rwine.target
m, n = X.shape
y = convert_to_vectors(y)
X = np.concatenate((np.ones((m, 1)), X), axis=1)


然后,进行数据预处理,包括特征归一化和随机划分训练集和测试集。

# 正则化,原因是e = np.exp(scores)会溢出,将x正则化[]
X = normalize(X)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)


接着,使用softmax回归模型对训练集进行训练,并在测试集上进行预测和模型评估。得到的Accuracy值是:0.9444444444444444

# 使用自定义的SoftMax回归模型
model = SoftmaxRegression()
model.fit(X_train, y_train)
model.predict(X_test)
y_score = model.proba
y_true = max_indices = np.argmax(y_test, axis=1)
# 精确率计算
def t_pre(y_pre, y_true):
    count = 0
    for i in range(len(y_pre)):
        if y_pre[i] - y_true[i] == 0:
            count += 1
    return count
acc = (t_pre(np.argmax(model.proba, axis=1), y_true)) / len(y_true)
print(acc)


最后,绘制ROC曲线和计算AUC值,以进一步评估模型性能。

# 绘制ROC曲线:调用skelearn库中方法
# 将每个标签作为正例,其他两个标签合并作为负例,计算ROC曲线和AUC值
fpr, tpr, roc_auc = {}, {}, {}
for i in range(3):
    fpr[i], tpr[i], _ = roc_curve(y_true == i, y_score[:, i])
    roc_auc[i] = auc(fpr[i], tpr[i])
plt.figure()
colors = ['red', 'green', 'blue']
labels = ['Class A', 'Class B', 'Class C']
for i in range(3):
    plt.plot(fpr[i], tpr[i], color=colors[i], lw=2,
             label='{0} (AUC = {1:0.2f})'
                   ''.format(labels[i], roc_auc[i]))
plt.plot([0, 1], [0, 1], color='gray', lw=1, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.legend(loc="lower right")
plt.show()


b538a23543567d654f5f57d26d092054_d679e109de504804b3f4ee8b37176f08.png

完整代码:

from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_curve, auc, accuracy_score
import matplotlib.pyplot as plt
import numpy as np
def normalize(X):
    X_min = np.min(X, axis=0)
    X_max = np.max(X, axis=0)
    print(X_max)
    denom = X_max - X_min
    # 将所有分母为零的元素置为一个小值
    denom[denom == 0] = 1e-8
    return (X - X_min) / denom
def softmax(scores):
    e = np.exp(scores)
    s = e.sum(axis=1)
    for i in range(len(s)):
        e[i] /= s[i]
    return e
def threshold(t, proba):
    return (proba >= t).astype(np.int)
def plot_roc_curve(proba, y):
    fpr, tpr = [], []
    for i in range(100):
        z = threshold(0.01 * i, proba)
        tp = (y * z).sum()
        fp = ((1 - y) * z).sum()
        tn = ((1 - y) * (1 - z)).sum()
        fn = (y * (1 - z)).sum()
        fpr.append(1.0 * fp / (fp + tn))
        tpr.append(1.0 * tp / (tp + fn))
    plt.plot(fpr, tpr)
    plt.show()
class SoftmaxRegression:
    def __init__(self):
        self.w = None
        self.proba = None
    def fit(self, X, y, eta_0=50, eta_1=100, N=1000):
        m, n = X.shape
        m, k = y.shape
        w = np.zeros(n * k).reshape(n, k)
        if self.w is None:
            self.w = np.zeros(n * k).reshape(n, k)
        for t in range(N):
            i = np.random.randint(m)
            x = X[i].reshape(1, -1)
            print(x.dot(w))
            proba = softmax(x.dot(w))
            g = x.T.dot(proba - y[i])
            w = w - eta_0 / (t + eta_1) * g
            self.w += w
        self.w /= N
    def predict_proba(self, X):
        return softmax(X.dot(self.w))
    def predict(self, X):
        self.proba = self.predict_proba(X)
        return np.argmax(self.proba, axis=1)
def convert_to_vectors(c):  # 转换成 m*k 矩阵(one-hot向量), m样本数,k类别数
    # c为类标签列向量 m*1,c[i]{0,1,..,k-1}
    m = len(c)
    k = np.max(c) + 1
    y = np.zeros(m * k).reshape(m, k)
    for i in range(m):
        y[i][c[i]] = 1  # y[i]的第c[i]位置1,其余位为0
    return y
rwine = load_wine()  # 导入红酒数据
X = rwine.data
y = rwine.target
m, n = X.shape
y = convert_to_vectors(y)
X = np.concatenate((np.ones((m, 1)), X), axis=1)
# 正则化,原因是e = np.exp(scores)会溢出,将x正则化[]
X = normalize(X)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# 使用自定义的SoftMax回归模型
model = SoftmaxRegression()
model.fit(X_train, y_train)
model.predict(X_test)
y_score = model.proba
y_true = max_indices = np.argmax(y_test, axis=1)
# 精确率计算
def t_pre(y_pre, y_true):
    count = 0
    for i in range(len(y_pre)):
        if y_pre[i] - y_true[i] == 0:
            count += 1
    return count
acc = (t_pre(np.argmax(model.proba, axis=1), y_true)) / len(y_true)
print(acc)
# 绘制ROC曲线:调用skelearn库中方法
# 将每个标签作为正例,其他两个标签合并作为负例,计算ROC曲线和AUC值
fpr, tpr, roc_auc = {}, {}, {}
for i in range(3):
    fpr[i], tpr[i], _ = roc_curve(y_true == i, y_score[:, i])
    roc_auc[i] = auc(fpr[i], tpr[i])
plt.figure()
colors = ['red', 'green', 'blue']
labels = ['Class A', 'Class B', 'Class C']
for i in range(3):
    plt.plot(fpr[i], tpr[i], color=colors[i], lw=2,
             label='{0} (AUC = {1:0.2f})'
                   ''.format(labels[i], roc_auc[i]))
plt.plot([0, 1], [0, 1], color='gray', lw=1, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.legend(loc="lower right")
plt.show()


在用自定义的Softmax回归,对于没有正则化的X,它在进入softmax(scores)函数,会出现溢出情况,需要控制X.dot(w)的值的大小。这里的正则化是指的数据预处理的归一化(将每个特征值都缩放到0和1之间) 公式:x’ = (x - min(x)) / (max(x) - min(x)),不会影响分类结果(会影响W值,但是并不需要关注W值)


ROC曲线:对于多分类的ROC曲线的绘制,可以分别将各个类别作为正例,其他类别作为反例,最后可以取平均AUC值作为该模型的AUC值


相关文章
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
机器学习之线性回归与逻辑回归【完整房价预测和鸢尾花分类代码解释】
机器学习之线性回归与逻辑回归【完整房价预测和鸢尾花分类代码解释】
|
2月前
|
机器学习/深度学习 自然语言处理 算法
|
12天前
|
机器学习/深度学习 PyTorch 算法框架/工具
【机器学习】Softmax回归探索
【机器学习】Softmax回归探索
47 8
|
17天前
|
机器学习/深度学习 算法
机器学习方法分类
【6月更文挑战第14天】机器学习方法分类。
24 2
|
4天前
|
机器学习/深度学习 分布式计算 算法
在机器学习项目中,选择算法涉及问题类型识别(如回归、分类、聚类、强化学习)
【6月更文挑战第28天】在机器学习项目中,选择算法涉及问题类型识别(如回归、分类、聚类、强化学习)、数据规模与特性(大数据可能适合分布式算法或深度学习)、性能需求(准确性、速度、可解释性)、资源限制(计算与内存)、领域知识应用以及实验验证(交叉验证、模型比较)。迭代过程包括数据探索、模型构建、评估和优化,结合业务需求进行决策。
9 0
|
12天前
|
机器学习/深度学习 数据采集 自然语言处理
【机器学习】逻辑回归:智能垃圾邮件分类实例
【机器学习】逻辑回归:智能垃圾邮件分类实例
39 0
|
12天前
|
机器学习/深度学习 算法 数据挖掘
【机器学习】Voting集成学习算法:分类任务中的新利器
【机器学习】Voting集成学习算法:分类任务中的新利器
19 0
|
12天前
|
机器学习/深度学习 人工智能 算法
【机器学习】概率模型在机器学习中的应用:以朴素贝叶斯分类去为例
【机器学习】概率模型在机器学习中的应用:以朴素贝叶斯分类去为例
20 0
|
12天前
|
机器学习/深度学习 算法 数据可视化
【机器学习】分类与预测算法的评价与优化
【机器学习】分类与预测算法的评价与优化
26 0
|
2月前
|
机器学习/深度学习 数据采集 人工智能
使用Python和Scikit-learn实现机器学习分类任务
使用Python和Scikit-learn实现机器学习分类任务
44 1