SoftMax回归简介及python代码实现

1、SoftMax回归概率分布模型:

对于K分类,第 k 类的参数为 θk , 组成二维矩阵 θK×(n+1) K 是总共的类别数目, n 是特征数目。
P(c=k|x;θ)=exp(θTkx)l=1Kexp(θTlx) k=123K

2、目标函数

似然函数:

L(θ)=i=1mk=1KP(c=k|x(i);θ)=i=1mk=1Kexp(θTkx(i))l=1Kexp(θTlx(i))y(i)k

对数似然函数:

Jm(θ)=log(L(θ))=i=1mk=1Ky(i)k(θTkx(i)logl=1Kexp(θTlx(i)))

J(θ)=k=1Kyk(θTkx(i)logl=1Kexp(θTlx(i)))

对对数似然函数求偏导:

J(θ)θk=ykθTkxl=1Kexp(θTlx)x

3、引入权重衰减项

为防止参数过大,引入权重衰减项改变代价函数,引入的衰减项会惩罚过大的参数:

Jm(θ)=log(L(θ))=i=1mk=1Ky(i)k(θTkx(i)logl=1Kexp(θTlx(i)))+λ2i=1mk=1Kθ2ik .

4、参数 θ 优化

使用梯度上升法: α 是学习率

θk=θk+α((ykP(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)

测试结果:
SoftMax回归简介及python代码实现_第1张图片

参考:
《统计学习方法》 李航
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 代码参考

你可能感兴趣的:(机器学习)