softmax python实现

softmax将k维度的向量压缩至另一个k维度向量,新向量每个元素都在0,1之间,加起来等于1。
σ ( z ) j = e z j ∑ k = 1 K e z k , j ∈ 1 , . . . , K \sigma{(\mathbf z)}_j=\frac{\boldsymbol e^{z_j}}{\sum_{k=1}^{\boldsymbol K}\boldsymbol e^{z_k}},j\in1,...,K σ(z)j=k=1Kezkezj,j1,...,K
数值稳定问题:
e c \boldsymbol e^c ec当c很大的时候, e c \boldsymbol e^c ec会overflow。
e c \boldsymbol e^c ec当c很小的时候, e c \boldsymbol e^c ec会underflow。
已知softmax(x)=softmax(x+c)。所以可以这样,x是一个向量,令x_max为x元素的最大值,x_i为x的任意元素,把所有x_i都减去x_max,得到一个新的向量z。由softmax(x)=softmax(x+c)知softmax(z)=softmax(x)。算softmax(z)可以防止overflow和underflow。
用pytorch的softmax时不支持整型,也不支持float16。
自己写的softmax不支持整型,支持所有浮点型。
应养成习惯,在初始化ndarray时指定数据类型,第一是有些功能只支持某些数据类型,第二是避免内存浪费,比如如果float32就可以满足要求没必要float64,因为如果不加以限制,在反向传播时可能会占用过多内存,在实际模型部署时也不利于模型加速。

'''

1. 使用numpy实现Softmax(假设2个样本,给定[[1, 2, 3], [2,1,3]]);
2. 使用torch.nn.functional.softmax() 验证结果是否一致。
'''
import numpy as np
import torch
import torch.nn.functional as F

# 支持1维度或2维度或一批的数据
def stable_softmax(x):
    z = x - np.max(x, axis=-1, keepdims=True)
    numerator = np.exp(z)
    denominator = np.sum(numerator, axis=-1, keepdims=True)
    softmax = numerator / denominator
    return softmax


def softmax_my(predict):
    '''
    使用numpy实现Softmax
    input:
        numpy.ndarray
        [[1, 2, 3],
        [2,1,3]]
    output:
        softmax value: numpy.ndarray
    '''

    row_size, col_size = predict.shape

    # 使用max(),其中参数 axis = 1 表示二维数组中沿着横轴取最大值
    max_i = np.max(predict, axis=-1)


    # 每一行减去本行最大的数字,reshape
    reshaped_max_i = max_i.reshape(-1, 1)
    z = predict - reshaped_max_i
    # max_i.shape:(2,)
    # predict.shape:(2, 3)
    # reshaped_max_i.shape:(2, 1)
    # z.shape:(2, 3)



    # 计算每个元素e的指数次幂
    numerator = np.exp(z)

    # 对每一行进行求和操作
    denominator = np.sum(numerator, axis=-1, keepdims=True)

    # 每一行 predict_exp / predict_exp_row_sum
    return numerator/denominator




if __name__ == '__main__':
    '''
    假设两个样本
    [[1, 2, 3],
    [2,1,3]]
    '''
    # 如果想尝试随机数
    # np.random.seed(0)
    # predict = np.random.randn(2, 3) # 返回标准正态分布的一组数据
    # print(predict)
    predict = np.array([[1, 2, 3], [2, 1, 3]], dtype=np.float16)
    softmax_value = softmax_my(predict)
    print('softmax结果:', softmax_value)

    # 验证softmax是否每行和为1
    print(softmax_value.sum(axis=1))

    # torch.nn.functional.softmax(input, dim)
    # 参数:dim:指明维度,dim=0表示按列计算;dim=1表示按行计算
    predict_tensor = torch.tensor([[1, 2, 3], [2, 1, 3]], dtype=torch.float32) # F.softmax不支持整型数,也不支持float16, 会报错RuntimeError: "softmax_lastdim_kernel_impl" not implemented for 'Half'
    softmax_torch = F.softmax(predict_tensor, dim=1)









你可能感兴趣的:(计算机视觉,计算机视觉,python)