1、SoftMax回归概率分布模型:
对于K分类,第 k 类的参数为 θk , 组成二维矩阵 θK×(n+1) , K 是总共的类别数目, n 是特征数目。
P(c=k|x;θ)=exp(θTkx)∑l=1Kexp(θTlx) , k=1、2、3、、、K
2、目标函数
似然函数:
L(θ)=∏i=1m∏k=1KP(c=k|x(i);θ)=∏i=1m∏k=1K⎛⎝⎜exp(θTkx(i))∑l=1Kexp(θTlx(i))⎞⎠⎟y(i)k 。
对数似然函数:
Jm(θ)=log(L(θ))=∑i=1m∑k=1Ky(i)k∗(θTkx(i)−log∑l=1Kexp(θTlx(i)))
J(θ)=∑k=1Kyk∗(θTkx(i)−log∑l=1Kexp(θTlx(i)))
对对数似然函数求偏导:
∂J(θ)∂θk=⎛⎝⎜yk−θTkx∑l=1Kexp(θTlx)⎞⎠⎟∗x
3、引入权重衰减项
为防止参数过大,引入权重衰减项改变代价函数,引入的衰减项会惩罚过大的参数:
Jm(θ)=log(L(θ))=∑i=1m∑k=1Ky(i)k∗(θTkx(i)−log∑l=1Kexp(θTlx(i)))+λ2∑i=1m∑k=1Kθ2ik .
4、参数 θ 优化
使用梯度上升法: α 是学习率
θk=θk+α((yk−P(yk|x;θ))∗x+λθk)
代码实现问题:
一、在求取 θ 时,每次求取的是一个向量。
二、代码实现步骤:对每个样本,要执行 K 次迭代,K是类别数目。当样本标签 = k 时, yk=1 , 否则, yk=0 。 详细解释参考SoftMax
三、在计算 P(yk|x;θ) 时,需要先计算 exp(θTkx(i)) 和 ∑l=1Kexp(θTkx) 两项
代码:测试数据鸢尾花数据集:
# -*- coding:utf-8 -*-
from numpy import *
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
def loadData(): # 数据读入处理
data = pd.read_csv("iris.data", header=None)
m, n = shape(data)
y = pd.Categorical(data[4]).codes # 对不同的标签进行编码
x_prime = mat(data[range(n - 1)]) # 将所有的样本特征复制给x_prime, 最后一列是标签
x = mat(ones((m, n))) # x0 是1,其余列是特征
for i in range(n-2):
x[:, i + 1] = x_prime[:, i]
x_train, x_test, y_train, y_test = train_test_split(x, y, train_size=0.6, random_state=0) # 训练集和测试集划分
return x_train, x_test, y_train, y_test
def Cal_OnePredect(thetaI,x): # 计算概率模型中的分子项
return exp(thetaI*x.T)
def cal_Predect(theta,x,K,k): # 有概率模型计算发生的概率
Numerator = Cal_OnePredect(theta[k],x) # 分子项
Denominator = sum(Cal_OnePredect(theta[i],x) for i in range(K)) # 分母项
return Numerator/Denominator
def Cal_Theta(x_train,y_train): # x_train 已经包括了 x0 = 1 项
m,n = shape(x_train) # m 样本数目, n = 特征数目 + 1
K = len(set(y_train)) # 类别数目
theta = mat(zeros((K,n))) # theta 是 K 行 n 列的矩阵
alpha = 0.001
weight_lambda = 0.01
for i in range(500): # 设置迭代次数
for j in range(m): # 对每个样本
for k in range(K):
y_trun = int(y_train[j]==k) # 是否属于当前类别
Predect = cal_Predect(theta,x_train[j],K,k)
theta[k] = theta[k] + alpha*((y_trun - Predect)*x_train[j] - weight_lambda*theta[k])
return theta
def ModelPredect(theta,x_test): # 预测函数, 返回预测的结果
labels = []
for x in (x_test):
result = theta * x.T
m = argmax(result)
labels.append(m)
return labels
def Accuracy_Score(Text,Predect): # 计算正确率
m = len(Text)
j = 0.0
for i in range(m):
if Text[i] == Predect[i]:
j += 1.0
return j/m
if __name__=="__main__":
x_train, x_test, y_train, y_test = loadData()
# y_train 数据类型 numpy.ndarray, 类别标签
# 输入:x_train 数据类型 m x n 的 Matrix, m = 样本数目, n = 特征数目 + 1
theta = Cal_Theta(x_train, y_train)
print "theta =\n", theta # theta 是 k 行 n 的矩阵,k 是类别数目,n 是特征数目加1
# 训练集上的预测结果
y_train_pred = ModelPredect(theta,x_train)
acc_Train = Accuracy_Score(y_train,y_train_pred)
print '\t训练集准确率: %.4f%%' % (100 * acc_Train)
#测试集上的预测结果
y_test_pred = ModelPredect(theta,x_test)
acc_Test = Accuracy_Score(y_test,y_test_pred)
print '\t测试集准确率: %.4f%%\n' % (100 * acc_Test)
参考:
《统计学习方法》 李航
http://ufldl.stanford.edu/wiki/index.php/Softmax%E5%9B%9E%E5%BD%92 理论参考
http://blog.csdn.net/wds2006sdo/article/details/53699778?utm_source=itdadao&utm_medium=referral 代码参考