线性模型softmax _ 机器学习

前言:

        logistic 回归只能应用于二分类问题,softmax 可以处理多分类问题。

 

目录:

  1.       预测模型
  2.       求解参数
  3.       梯度推导过程
  4.       例子

 

一  预测模型

       x_i 为n 维列向量

      y_i  样本对应的标签,为1-k的整数

 

      h(x)=\frac{1}{\sum_{i=1}^{k}e^{\theta_I^Tx}}\begin{bmatrix} e^{\theta^Tx}\\ ... \\ ... \\ e^{\theta_k^Tx} \end{bmatrix}

    输出为K维的概率向量,元素和为1

   分类时,将样本归类于概率最大的那个类

   

二  求解参数

    \theta=\begin{bmatrix} \theta_1^T\\ \theta_2^T\\ ....\\ \theta_k^T \end{bmatrix}

   其中\theta_i 为n 维列向量,写成概率向量

    y^*=\frac{1}{\sum_{i=1}^{k}e^{\theta_i^Tx}}\begin{bmatrix} e^{\theta_i^Tx}\\ ...\\ ... \\ e^{\theta_k^Tx} \end{bmatrix}

 

三  推导过程

      3.1 损失函数

           依然用极大似然函数

           J= \prod_{i=1}^{k}(y_i^*)^{y_i}

 

      给定一批样本,它们的似然函数为:

     

     其中y_{ij} 为样本i 对应j标签的分量,只有一个为1,其它为0.

     等同求 取对数似然极小值。

     L =-\sum_{i=1}^{m}\sum_{j=1}^{k}y_{ij}ln \frac{e^{\theta_j^Tx_i}}{\sum_{t=1}^k e^{\theta_t^Tx_i}}

 

     单样本损失函数为:

      L(x,y,\theta)=-\sum_{j=1}^{k} y_j(\theta_j^Tx-ln\sum_{t=1}^{K}e^{\theta_t^Tx})

 

     假设样本属于i类,y_i=1,其它分量为0,上面可以简化为

     L(x, y, \theta)=-(\theta_I^Tx-ln(\sum_{t=1}^{k}e^{\theta_t^Tx}))

 

    计算\theta_j 的梯度,如果i =j ,则

   \bigtriangledown_{\theta_j}L=x[\frac{e^{\theta_j^tx}}{\sum_{t=1}^{k}e^{\theta^Tx}}-1]

 

  否则

   \bigtriangledown_{\theta_j}L=[\frac{e^{\theta_j^tx}}{\sum_{t=1}^{k}e^{\theta^Tx}}]x

 

 

四  例子

     

# -*- 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()
        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值