基于Softmax激活函数的数据分类
摘要
本文对的Softmax算法的原理进行了简单介绍,同时使用MATLAB语言对基于梯度下降算法的Softmax函数进行了编程。利用matlab自带的鸢尾花数据集进行了测试分类,并分析了结果的准确度。
1. Softmax激活函数
1.1 基本原理
单个输出节点的二分类问题一般在输出节点上使用Sigmoid函数,拥有两个及其以上的输出节点的二分类或者多分类问题一般在输出节点上使用Softmax函数。Softmax是一个将多分类的输出值范围映射到[0, 1],并且约束各个输出节点的输出值的和为1的函数。
softmax函数适用于处理多分类问题,应用广泛的逻辑函数就是softmax函数在二分类情形下的特例。softmax函数将一个n维的输入向量映射为n维的向量,使得输出向量的各元素取值在0到1之间,且所有元素之和为1,即所得到的向量可以作为事件发生的概率。
记函数的输入向量为:
Z
=
(
z
1
,
z
2
,
⋯
,
z
n
)
⊤
Z=\left(z_1,z_2,\cdots,z_n\right)^\top
Z=(z1,z2,⋯,zn)⊤,则函数值为:
s
o
f
t
m
a
x
(
X
)
=
(
e
x
1
∑
i
=
1
n
e
x
i
,
e
x
2
∑
i
=
1
n
e
x
i
,
⋯
,
e
x
n
∑
i
=
1
n
e
x
i
)
⊤
softmax\left(X\right)=\left(\frac{e^{x_1}}{\sum_{i=1}^{n}e^{x_i}},\frac{e^{x_2}}{\sum_{i=1}^{n}e^{x_i}},\cdots,\frac{e^{x_n}}{\sum_{i=1}^{n}e^{x_i}}\right)^\top
softmax(X)=(∑i=1nexiex1,∑i=1nexiex2,⋯,∑i=1nexiexn)⊤
对一个激活函数为softmax的单个神经元,记输入数据是由对n个特征进行m次观测所得的样本:
其中,X第一列数据全部为1,是人为加入的bias项,表示模型带有偏置(即考虑截距项)。
X
i
j
(
1
≤
i
≤
m
,
1
≤
j
≤
n
)
X_{ij}\left(1\le i\le m,1\le j\le n\right)
Xij(1≤i≤m,1≤j≤n)表示第j个变量在第i次观测时的值。
该样本对应的真实类别为:
Y的每一行只有一个值为1,其它全为0。
y
i
j
=
1
(
1
≤
i
≤
m
,
1
≤
j
≤
k
)
y_{ij}=1\left(1\le i\le m,1\le j\le k\right)
yij=1(1≤i≤m,1≤j≤k)表示第i个样本对应的类别为第j类。
记待估计的参数为
记softmax函数的自变量为:
Z是模型输入数据的加权求和,即
z
i
j
=
∑
k
=
0
n
x
i
k
ω
k
j
,
Z
=
X
z_{ij}=\sum_{k=0}^{n}x_{ik}\omega_{kj},Z=X
zij=∑k=0nxikωkj,Z=X。
记
其中
y
i
j
^
=
e
z
i
j
∑
p
=
1
k
e
z
i
p
\widehat{y_{ij}}=\frac{e^{z_{ij}}}{\sum_{p=1}^{k}e^{z_{ip}}}
yij
=∑p=1kezipezij,表示模型眼中第i个样本属于第j类的概率。
定义模型的总代价函数为
C
O
S
T
(
X
)
=
∑
i
=
0
m
(
−
∑
j
=
1
k
y
i
j
ln
y
i
j
^
)
COST\left(X\right)=\sum_{i=0}^{m}\left(-\sum_{j=1}^{k}{y_{ij}\ln{\widehat{y_{ij}}}}\right)
COST(X)=i=0∑m(−j=1∑kyijlnyij
)
将代价函数视为参数
Ω
\Omega
Ω的函数
J
Ω
J_\Omega
JΩ,这就是我们要优化的目标。
使用梯度下降求解目标函数极小值:
由链式法则可知,
∂
J
Ω
∂
ω
p
j
=
∑
i
=
1
m
∂
J
Ω
∂
z
i
j
∂
z
i
j
∂
ω
p
j
\frac{\partial J_\Omega}{\partial\omega_{pj}}=\sum_{i=1}^{m}{\frac{\partial J_\Omega}{\partial z_{ij}}\frac{\partial z_{ij}}{\partial\omega_{pj}}}
∂ωpj∂JΩ=i=1∑m∂zij∂JΩ∂ωpj∂zij
而
∂
J
Ω
∂
z
i
p
=
∂
∑
q
=
0
m
(
−
∑
j
=
1
k
ln
y
q
j
^
)
∂
z
i
p
=
−
∑
j
=
1
k
y
i
j
y
i
j
^
∂
y
i
j
^
∂
z
i
p
\frac{\partial J_\Omega}{\partial z_{ip}}=\frac{\partial\sum_{q=0}^{m}\left(-\sum_{j=1}^{k}\ln{\widehat{y_{qj}}}\right)}{\partial z_{ip}}=-\sum_{j=1}^{k}{\frac{y_{ij}}{\widehat{y_{ij}}}\frac{\partial\widehat{y_{ij}}}{\partial z_{ip}}}
∂zip∂JΩ=∂zip∂∑q=0m(−∑j=1klnyqj
)=−j=1∑kyij
yij∂zip∂yij
由于将(3)式带入(2)式,由于
∑
j
=
1
k
y
i
j
=
1
\sum_{j=1}^{k}y_{ij}=1
∑j=1kyij=1,有
∂
J
Ω
∂
z
i
p
=
y
i
p
^
−
y
i
p
\frac{\partial\ J_\Omega}{\partial\ z_{ip}}=\widehat{y_{ip}}-y_{ip}
∂ zip∂ JΩ=yip
−yip
考虑
z
i
p
=
∑
q
=
0
n
x
i
q
ω
q
p
z_{ip}=\sum_{q=0}^{n}x_{iq}\omega_{qp}
zip=∑q=0nxiqωqp,并将(4)式带入(1)式,得到:
∂
J
Ω
∂
ω
p
j
=
∑
i
=
1
m
∂
J
Ω
∂
z
i
j
x
i
p
=
∑
i
=
1
m
(
y
i
j
^
−
y
i
j
)
x
i
p
\frac{\partial J_\Omega}{\partial\omega_{pj}}=\sum_{i=1}^{m}{\frac{\partial J_\Omega}{\partial z_{ij}}x_{ip}}=\sum_{i=1}^{m}{\left(\widehat{y_{ij}}-y_{ij}\right)x_{ip}}
∂ωpj∂JΩ=i=1∑m∂zij∂JΩxip=i=1∑m(yij
−yij)xip
写回矩阵的形式,有: 梯度已经求出来了,指定步长使用梯度下降方法求解即可。
2. 基于Softmax的鸢尾花数据集分类
2.1 数据信息
鸢尾花数据集是一个经典数据集,在统计学习和机器学习领域都经常被用作例子。数据集内包含3类共150个样本,每类各50个样本,每条样本都有4个特征:花萼长度、花萼宽度、花瓣长度、花瓣宽度,可以通过这4个特征预测鸢尾花属于(iris-setosa, iris-versicolour, iris-virginica)中的哪个品种。
图
1
数据信息
图 1 数据信息
图1数据信息
2.2 计算结果分析
设定训练集占比为a=0.7,测试集占比为1-a=0.3,梯度下降算法的学习率alpha=0.05,最大循环次数为10000次,计算出测试准确度为0.9556,对应的softmax参数为:
参考文献
[1] 梯度下降处理softmax函数多分类问题 - 桃源梦 - 博客园. Cnblogs. https://www.cnblogs.com/Reader-Yu/p/10665239.html
[2] 数据集 |鸢尾花数据集 - 知乎. Zhuanlan. https://zhuanlan.zhihu.com/p/480326305
[3] 一文详解Softmax函数 - 知乎. Zhuanlan. https://zhuanlan.zhihu.com/p/105722023
附录–代码
本案例的Matlab代码如下:
%% 激活函数Softmax
% 2023.07.18
clc
clear
close all
%% 导入数据
load fisheriris;%导入matlab自带的鸢尾花数据集
x=meas;
y(1:50,1)=1;
y(51:100,1)=2;
y(101:150,1)=3;%一共是三个类别
k=3;
alpha=0.05; % 梯度下降算法的 学习因子
[theta,accuracy] = mysoftmax(x,y,k,alpha); %theta为sofamax参数,accuracy为算法准确率
fprintf('算法准确度为%5.4f',accuracy);
%% 函数编写
function [ theta, accuracy] = mysoftmax( x,y,k, alpha )
% 梯度下降法实现softmax多分类
% k为类别数
% 训练集占比为a,测试集占比1-a,这里三七分
a=0.7;%训练集占比
xx=[ones(size(x,1),1),x];%将x前加入一列x0
%对y进行处理,分类
yy=zeros(size(y,1),k);
for i=1:size(y,1)
for j=1:k
if y(i,1)==j
yy(i,j)=1;
end
end
end
rowrank = randperm(size(xx, 1));
x_xin =xx(rowrank, :);
y_xin_train =yy(rowrank, :);
y_xin_test=y(rowrank, :);% 将数据集随机打乱
x_train=x_xin(1:floor(a*size(x,1)),:); % 训练接
y_train=y_xin_train(1:floor(a*size(x,1)),:);
x_test=x_xin(floor(a*size(x,1))+1:size(x,1),:); % 测试集
y_test=y_xin_test(floor(a*size(x,1))+1:size(x,1),:);
m=size(x_train,1);%记录训练集样本总数
n=size(x,2);%记录样本特征数
theta=ones(k,n+1);
loop_max=10000; % 最大循环次数
shunxu=randperm(m);
count=0;
% 梯度下降
while count<loop_max
count=count+1;
num=unidrnd(m);
x_i=x_train(num,:);
theta_T_x=theta*x_i';%k行m列
e_theta_T_x=exp(theta_T_x);%求指数
denominator=sum(e_theta_T_x);%计算第一项的分母
numerator=e_theta_T_x;%计算第一项的分子
gradient=(numerator/denominator-y_train(num,:)')*x_i;%计算J的偏导数
theta=theta-alpha*gradient/m;
if all (abs(gradient)<0.001)
break
end
end
count=0;%记录错误的样本数
predict=theta*x_test';
for i=1:size(x_test,1)
[belief(i),class(i)]=max(predict(:,i));
if class(i) == y_test(i)
count=count+1;
end
end
accuracy=count/size(x_test,1);
end