前言:
logistic 回归只能应用于二分类问题,softmax 可以处理多分类问题。
目录:
- 预测模型
- 求解参数
- 梯度推导过程
- 例子
一 预测模型
为n 维列向量
样本对应的标签,为1-k的整数
输出为K维的概率向量,元素和为1
分类时,将样本归类于概率最大的那个类
二 求解参数
其中 为n 维列向量,写成概率向量
三 推导过程
3.1 损失函数
依然用极大似然函数
给定一批样本,它们的似然函数为:
其中 为样本i 对应j标签的分量,只有一个为1,其它为0.
等同求 取对数似然极小值。
单样本损失函数为:
假设样本属于i类,,其它分量为0,上面可以简化为
计算 的梯度,如果i =j ,则
否则
四 例子
# -*- coding: utf-8 -*-
"""
Created on Wed Nov 6 14:49:14 2019
@author: chengxf2
"""
import numpy as np
from sklearn.datasets import load_iris #鸢尾花数据集
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
class softmax:
"""
iris 数据集,总计三类,0,1,2
Args
None
return
None
"""
def LoadData(self):
iris = load_iris()
std = StandardScaler()
trianData = std.fit_transform(iris.data)
self.trainLabel = iris.target
self.m , self.n = np.shape(trianData)
self.k = len(set(self.trainLabel))
self.w = np.ones((self.k, self.n+1))
self.trianData = np.ones((self.m, self.n+1))
print("\n m: ",self.m, "\t n : ",self.n)
self.trianData[:,1:self.n+1]=trianData
#print("\n k: \n",self.trainData)
def __init__(self):
self.m = 0 ##样本个数
self.n = 0 ##样本维度
self.W = None ##权重系数
self.LoadData()
self.maxIter = 2000
self.Err = 1e-3 ##梯度为0
"""
计算当前的梯度
Args
x: 当前的样本
y: 当前的标签
wx: 当前比例
"""
def GetGrad(self, x,y,wx):
wgrad= np.zeros((self.k, self.n+1))
for i in range(self.k):
if y==i:
rat =wx[i]
w= x*(rat-1)
else:
rat =wx[i]
w= rat*x
wgrad[i]=w
return wgrad
"""
计算e(\theta^Tx)
args
x: 样本
return
denominator: \sum e(\theta^Tx)
fraction: e(\theta^Tx)
"""
def GetS(self, x):
theta = np.dot(self.w, x) #计算theta*x
w = np.exp(theta) #计算指数
denominator = w.sum() ##分母
fraction = w/denominator
return fraction
"""
训练样本
Args
None
return
None
"""
def Train(self):
gradList =[]
for it in range(self.maxIter):
grad = np.zeros((self.k, self.n+1))
for i in range(self.m):
x = self.trianData[i] ##当前的样本 array
y = self.trainLabel[i]
wx= self.GetS(x)
wgrad = self.GetGrad(x,y,wx)
grad= grad+wgrad
gradList.append(np.linalg.norm(grad)/self.m)
self.w = self.w- grad/self.m
err = np.linalg.norm(grad/self.m)/self.k
#print("\n err ",err)
if err<self.Err: ##梯度为0 ,可以认为极小值
#print("\n ::::::::::迭代停止:::::::::::::",it)
break
# print("\n it : ",it, "grad ",np.linalg.norm(grad)/self.m)
#print("\n self.w : \n ",self.w)
# print("\n gradList ",gradList)
x = np.arange(0,it+1)
plt.plot(x, gradList,c='r')
plt.show()
self.Test()
"""
测试:
Args
None,还是使用训练集测试,为了简便
return
精度
"""
def Test(self):
error = 0
for i in range(self.m):
x= self.trianData[i]
Y = np.dot(self.w, x)
pred = np.argmax(Y)
if pred != self.trainLabel[i]:
error= error +1
print("错误率: %f %%100"%(100*error/self.m))
soft = softmax()
def Test():
x = np.array([[1,1,1,1],
[2,2,2,2]])
w = np.array([0.1,0.5,0.2,0.25])
y = np.dot(x,w)
print("\n y ",y)
#Test()
soft.Train()