AI通识:数据归一化处理
配套视频课程:www.bilibili.com/video/BV1Rx…
领取全套教材、资料包与源码请+ AIxiaoyun0000
一、Softmax归一化
Softmax是一种数学函数,通常用于将一组任意实数转换为表示概率分布的实数。其本质上是一种归一化函数,可以将一组任意的实数值转化为在[0, 1]之间的概率值,因为softmax将它们转换为0到1之间的值,所以它们可以被解释为概率。如果其中一个输入很小或为负,softmax将其变为小概率,如果输入很大,则将其变为大概率,但它将始终保持在0到1之间。
Softmax是逻辑回归的一种推广,可以用于多分类任务,其公式与逻辑回归的sigmoid函数非常相似。只有当分类是互斥的,才可以在分类器中使用softmax函数,也就是说只能是多元分类(即数据只有一个标签),而不能是多标签分类(即一条数据可能有多个标签)。
许多多层神经网络输出层的最后一层是一个全连接层,输出是一个实数向量,这个向量通常代表了每个类别的得分或置信度。为了将这些得分转换为概率分布,通常会使用softmax函数。因为它将分数转换为规范化的概率分布,可以显示给用户或用作其他系统的输入。所以通常附加一个softmax函数在神经网络的最后一层之后。
softmax函数的输入是一个包含K个元素的向量,其中不带箭头的z表示向量的一个元素:
Softmax的分子将指数函数应用于向量的每个元素,对于最高的输入值返回最高的输出值。因为它的范围是(0,∞),所以任何负数也变成正数。就是说,e的任意次方,必然是0或者一个正数。这样就可以很好的解决归一化后取值为0-1之间。
自然对数e的值为2.71828,也可以引用python中的math.e,输出为更精确的值:2.718281828459045
Softmax分母中的求和是通过确保函数的和为1来标准化每个元素,创建一个概率分布。所有的指数元素加在一起,所以当每个指数元素除以这个和时,它将是它的一个百分比。[5,7,10]的指数元素之和如下:
比如要计算第2个向量7的归一化结果,则运算过程如下:
当然,公式也可以由以下方式来表达,本质是一样的:
给定一个n维向量,softmax函数将其映射为一个概率分布。标准的softmax函数由下面的公式定义[1]:
直观上看,标准softmax函数用一个自然底数 e 先拉大了输入值之间的差异,然后使用一个配分将其归一化为一个概率分布。在分类问题中,我们希望模型分配给正确的类别的概率接近1,其他的概率接近0,如果使用线性的归一化方法,很难达到这种效果,而softmax有一个先拉开差异再归一化的“两步走”战略,因此在分类问题中优势显著。
事实上,在势能函数和配分函数中,可以采用的底数不仅仅是自然底数 e ,也可以采用一些其他的底数。原则上,任意 >0 的数都可以作为这里的底数,越大的底数越能起到“拉开差异”的作用。
二、使用Python原生实现
任意假定一个向量(在Python中可以使用列表或元组来表示),比如 list = [5, 7, 10, 9, 8, 2, 12, 15, 6],现通过Softmax函数分别计算每一个向量的概率分布,代码如下:
import math
def softmax(list):
# 先求分母的总和,输出为:3466538.535767658
sum = 0
for m in list:
sum += math.pow(math.e, m)
# sum += math.exp(m) # 或直接调用math.exp完成运算
# 再遍历每一个元素,求出其概率,并添加到新的列表中
result = []
for n in list:
z = math.pow(math.e, n) / sum
# result.append("{:.8f}".format(z)) # 保留8位小数,该操作会将其转换为字符串
# result.append(format(z, ".8f"))
result.append(round(z, 8)) # 会出现科学计数法表示,不影响使用
return result
if __name__ == '__main__':
list = [5, 7, 10, 9, 8, 2, 12, 15, 6]
list = softmax(list)
print(list)
以上代码的输出结果为:
[4.281e-05, 0.00031635, 0.00635402, 0.00233751, 0.00085992, 2.13e-06, 0.04695023, 0.94302064, 0.00011638]
以上代码涉及两次针对list列表的遍历和运算,所以可以使用列表推导式进行代码简化。
三、使用numpy库来实现
1、最简化版本
def softmax_3(list):
numpy.set_printoptions(suppress=True)
matrix = numpy.array(list, dtype=float)
sum = 0
for n in matrix:
sum += math.exp(n)
print(sum)
for i in range(matrix.size):
# 直接修改matrix元素的值为概率值,覆盖了matrix原本的值,节省内存空间
matrix[i] = math.exp(matrix[i]) / sum
return matrix
2、只为利用一下numpy的特征
import numpy
def softmax_2(list):
# 禁止使用科学计数法来表示数字,看起来比较不方便
numpy.set_printoptions(suppress=True)
matrix = numpy.array([list]) # 构建为二维数组 [[5, 7, 10, 9, 8, 2, 12, 15, 6]]
m, n = numpy.shape(matrix) # m表示第一维的个数, n为9,表示第二维的个数
# numpy.zeros,生成一个均为0的二维矩阵,里面有第一维是m个,第二维是n个, [[0. 0. 0. 0. 0. 0. 0. 0. 0.]]
zeros = numpy.zeros((m,n), dtype=float)
print(zeros)
# numpy.mat 将期转换为matrix矩阵类型,便于后续运算
out_matrix = numpy.mat(zeros)
sum = 0
for i in range(0, n):
out_matrix[0, i] = math.exp(matrix[0, i])
sum += out_matrix[0, i]
for j in range(0, n):
out_matrix[0, j] = out_matrix[0, j] / sum
return out_matrix
输出结果为:
[[0.00004281 0.00031635 0.00635402 0.00233751 0.00085992 0.00000213
0.04695023 0.94302064 0.00011638]]
四、其他数据标准化
1、Min-Max标准化
这种方法将数据线性地映射到[0,1]的范围内。
2、平均值标准化
这种方法将数据线性地映射到[-1,1]的范围内。
3、Z-Score标准化
这种方法将数据转化为标准正态分布,均值为0,标准差为1。
其中x是原始数据,mean是原始数据的均值,std是原始数据的标准差。
4、均值方差标准化
这种方法将数据转化为均值为0,方差为1的分布
其中x是原始数据,mean是原始数据的均值,var是原始数据的方差。
5、Sigmoid标准化
这种方法将数据通过Sigmoid函数映射到[0,1]范围内
请使用Python或Numpy将以上公式用代码实现,并观察其规律。
五、在SKLearn中实现标准化
- MinMaxScaler:归一化去量纲处理,适用于数据有明显的上下限,不会存在严重的异常值,例如考试得分0-100之间的数据可首选归一化处理
- StandardScaler:标准化去量纲处理,适用于可能存在极大或极小的异常值,此时用MinMaxScaler时,可能因单个异常点而将其他数值变换的过于集中,而用标准正态分布去量纲则可有效避免这一问题
- Binarizer:二值化处理,适用于将连续变量离散化
- OneHotEncoder:独热编码,一种经典的编码方式,适用于离散标签间不存在明确的大小相对关系时。例如对于民族特征进行编码时,若将其编码为0-55的数值,则对于以距离作为度量的模型则意味着民族之间存在”大小”和”远近”关系,而用独热编码则将每个民族转换为一个由1个”1”和55个”0”组成的向量。弊端就是当分类标签过多时,容易带来维度灾难,而特征又过于稀疏
- Ordinary:数值编码,适用于某些标签编码为数值后不影响模型理解和训练时。例如,当民族为待分类标签时,则可将其简单编码为0-55之间的数字
from sklearn.preprocessing import MinMaxScaler
nd1 = numpy.array([1,2,3,4,5,6])
nd2 = nd1.reshape(-1, 1)
mm = MinMaxScaler()
list3 = mm.fit_transform(nd2)
print(list3)
配套视频课程:www.bilibili.com/video/BV1Rx…
领取全套教材、资料包与源码请+ AIxiaoyun0000