机器学习入门-线性模型(一)

本次学习的内容是《机器学习》一书中的线性模型这一章节另外这一章节理论性的东西更多,所以还学习了《Machine Learning in Action》中的Logistic回归,实战了一些简单的例子作为互补参考。

代码以及测试用例:
https://github.com/CallMeSp/MachineLearning.git

正文

先说一个数学符号:
arg min f(x) 是指使得函数 f(x) 取得其最小值的所有自变量 x 的集合。比如,函数 cos(x) 在 ±π、±3π、±5π、……处取得最小值(-1),则 argmin cos(x) = {±π, ±3π, ±5π, …}。
如果函数 f(x) 只在一处取得其最小值,则 argmin f(x) 为单点集.

基本形式

给定d个属性描述的示例 x=x1;x2;...;xd) x = ( x 1 ; x 2 ; . . . ; x d ) ,其中xi是x在第i个属性的取值。线性模型试图学得一个通过属性的线性组合来进行预测的函数,即

用向量形式写成:
,其中

w和b学得之后,模型就得以确定。

线性回归

给定数据集,其中,yi∈R 。“线性回归”试图学得一个线性模型以尽可能准确的预测实值输出标记。
先考虑一种最简单的情形:输入属性的数目只有一个,线性回归试图学得

使得f(xi)≈yi。
如何确定w和b呢?显然关键是如何衡量f(x)和y之间的差别,而均方误差是回归任务中最常用的性能度量,因此我们可试图让均方误差最小化,即

均方误差有非常好的几何意义,对应了常用的欧几里得距离或简称“欧式距离”。基于均方误差最小化来进行模型求解的方法称为“最小二乘法”。在线性回归中,最小二乘法就是试图找到一条直线,使所有样本到直线上的欧式距离之和最小。
为求解w和b使E=∑ (yi-wxi-b)^2最小化的过程,称为线性回归模型的最小二乘“参数估计”,我们可以将E分别对w和b求偏导。


分别令其为0则可得到w和b的最优解的闭式解

更一般的情形是如本节开头的数据集D,样本由d个属性描述,此时试图学得
这称为多元线性回归。

类似的,可利用最小二乘法来对w和b进行估计,为便于讨论,我们把w和b吸入向量形式w=(w;b),相应的把数据集D表示为一个m*(d+1)大小的矩阵X,其中每一行对应于一个实例,该行前d个元素对应于示例的d个属性值,最后一个元素恒置为1即
再把标记也写成向量形式于是类似的有,令,对w求导得
令上式为0可得w最优解的闭式解。

对数几率回归

考虑二分任务,其输出标记y∈{0,1},而线性回归模型产生的预测值是实值,所以需要将实值z转换为0/1值。最理想的是单位阶跃函数

但是该函数不连续,所以需要找到一个函数一定程度上近似单位阶跃函数,并且单点课为,对数几率函数(logistic function)正是这样一个常用替代函数:
从而得到:(其对应模型称为对数几率回归,实际是一种分类学习方法)
于是可进一步变化为:
若将y视为样本x作为正例的可能性,则1-y是其反例的可能性,两者的比值称为“几率”,取对数则得到对数几率。

确定w和b

将y视为后验概率p(y=1|x)则可将上式重写为
显然有于是可以通过极大似然法来估计w和b:

实战

logistic回归实战。

from numpy import *
import matplotlib.pyplot as plt

def loadDataSet():
    dataMat=[]
    labelMat=[]
    fr=open('testSet.txt','r')
    for line in fr.readlines():
        lineArr=line.strip().split()
        # 每行前两个值作为x1,x2,另外加一个x0,设为1.0
        dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])])
        labelMat.append(int(lineArr[2]))
    return dataMat,labelMat

def sigmoid(inX):
    return 1.0/(1+exp(-inX))

def gradAscent(dataMatIn,classLabels):
    # 将普通矩阵转化为numpy矩阵数据类型
    dataMatrix=mat(dataMatIn)
    # 矩阵的转置,转化为列矩阵
    labelMat=mat(classLabels).transpose()
    m,n=shape(dataMatrix)
    alepha=0.001
    maxCycles=500
    weights=ones((n,1))
    for k in range(maxCycles):
        h=sigmoid(dataMatrix*weights)
        error=(labelMat-h)
        weights=weights+alepha*dataMatrix.transpose()*error
    return weights

def plotBestFit(weights):
    import matplotlib.pyplot as plt
    dataMat,labelMat=loadDataSet()
    dataArr=array(dataMat)
    n = shape(dataArr)[0]
    xcord1=[];ycord1=[]
    xcord2=[];ycord2=[]
    for i in range(n):
        if int(labelMat[i])==1:
            xcord1.append(dataArr[i,1]);ycord1.append(dataArr[i,2])
        else:
            xcord2.append(dataArr[i,1]);ycord2.append(dataArr[i,2])
    fig=plt.figure()
    ax=fig.add_subplot(111)
    ax.scatter(xcord1,ycord1,s=30,c='red',marker='s')
    ax.scatter(xcord2,ycord2,s=30,c='blue')
    x=arange(-3.0,3.0,0.1)
    y=(-weights[0]-weights[1]*x)/weights[2]
    # to make x and y's shape be same ,transpost y
    ax.plot(x,y.transpose())
    plt.xlabel('X1');plt.ylabel('X2');
    plt.show()

def stocGradAscent0(dataArr,classLabels):
    m,n=shape(dataArr)
    alpha=0.01
    weights=ones(n)
    for i in range(m):
        h=sigmoid(sum(dataArr[i]*weights))
        error=classLabels[i]-h
        weights=weights*alpha*error*dataArr[i]
    return weights

def stocGradAscent1(dataArr, classLabels, numIter=150):
    m,n = shape(dataArr)                                                #返回dataMatrix的大小。m为行数,n为列数。
    weights = ones(n)                                                       #参数初始化
    for j in range(numIter):
        dataIndex = list(range(m))
        for i in range(m):
            alpha = 4/(1.0+j+i)+0.01                                            #降低alpha的大小,每次减小1/(j+i)。
            randIndex = int(random.uniform(0,len(dataIndex)))                #随机选取样本
            h = sigmoid(sum(dataArr[randIndex]*weights))                    #选择随机选取的一个样本,计算h
            error = classLabels[randIndex] - h                                 #计算误差
            weights = weights + alpha * error * dataArr[randIndex]       #更新回归系数
            del(dataIndex[randIndex])                                         #删除已经使用的样本
    return weights 

def classifyVector(inX,weights):
    prob=sigmoid(sum(inX*weights))
    if prob>0.5:
        return 1.0
    else:
        return 0.0

def colicTest():
    frTrain=open('horseColicTraining.txt')
    frTest=open('horseColicTest.txt')
    trainingSet=[]
    trainingLabels=[]
    for line in frTrain.readlines():
        currLine=line.strip().split('\t')
        lineArr=[]
        for i in range(21):
            lineArr.append(float(currLine[i]))
        trainingSet.append(lineArr)
        trainingLabels.append(float(currLine[21]))
    trainWeights=stocGradAscent1(array(trainingSet),trainingLabels,500)
    errorCount=0
    numTestVec=0.0
    for line in frTest.readlines():
        numTestVec+=1.0
        currLine=line.strip().split('\t')
        lineArr=[]
        for i in range(21):
            lineArr.append(float(currLine[i]))
        if int(classifyVector(array(lineArr),trainWeights))!=int(currLine[21]):
            errorCount+=1
    errorRate=float(errorCount)/numTestVec
    print('the error count is : %f'%errorRate)
    return errorRate

def multiTest():
    numTest=10
    errorSum=0.0
    for i in range(numTest):
        errorSum+=colicTest()
    print('after %d iterations the average error rate is %f'%(numTest,errorSum/float(numTest)))

if(__name__=='__main__'):
    # dataArr,labelMat=loadDataSet()
    # weights=stocGradAscent1(array(dataArr),labelMat)
    # print(weights)
    # plotBestFit(weights)
    multiTest()

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