机器学习十大算法---2 .逻辑回归

本文介绍了逻辑回归的基本概念,包括其作为分类算法而非回归算法的角色,以及如何通过拟合逻辑函数预测离散型因变量的概率。文章还探讨了逻辑回归的优点和局限性,并通过实例详细解释了如何使用梯度上升法确定最佳回归系数。
摘要由CSDN通过智能技术生成

逻辑回归

  逻辑回归其实是一个分类算法而不是回归算法。通常是利用已知的自变量来预测一个离散型因变量的值(像二进制值0/1,是/否,真/假)。简单来说,它就是通过拟合一个逻辑函数(logit fuction)来预测一个事件发生的概率。所以它预测的是一个概率值,自然,它的输出值应该在0到1之间。

此时可以看看一个博客,推导公式:http://www.cnblogs.com/daguankele/p/6549891.html 

它的核心思想是,如果线性回归的结果输出是一个连续值,而值的范围是无法限定的,那我们有没有办法把这个结果值映射为可以帮助我们判断的结果呢。而如果输出结果是 (0,1) 的一个概率值,这个问题就很清楚了。我们在数学上找了一圈,还真就找着这样一个简单的函数了,就是很神奇的sigmoid函数(如下):

    如果把sigmoid函数图像画出来,是如下的样子:




   
  假设你的一个朋友让你回答一道题。可能的结果只有两种:你答对了或没有答对。为了研究你最擅长的题目领域,你做了各种领域的题目。那么这个研究的结果可能是这样的:如果是一道十年级的三角函数题,你有70%的可能性能解出它。但如果是一道五年级的历史题,你会的概率可能只有30%。逻辑回归就是给你这样的概率结果。 
   
  Logistic回归简单分析

  优点:计算代价不高,易于理解和实现 
  缺点:容易欠拟合,分类精度可能不高 
  适用数据类型:数值型和标称型数据

  我们都知道逻辑回归是和Sigmod函数一起的,为了实现逻辑回归分类器,我们可以在每一个特征上都乘以一个回归系数,然后将所有的结果值相加,将总和代入S函数,进而得到一个范围在0~1之间的数值。任何大于0.5的数据被分人1类,小于0.5被归为0类。 
  而现在有了分类器的函数了,那么上面提到的最佳回归系数怎么求呢?这里就出现了基于最优化方法的最佳回归系数的确定。 
   
  梯度上升法:要找到某函数的最大值,最好的方法就是沿着该函数的梯度方向探寻。梯度上升法用来求函数的最大值,梯度下降法用来求函数的最小值

梯度上升法伪代码:

//每个回归系数初始化为1
//重复R次:
    //计算整个数据集的梯度
    //使用alpha*gradient更新回归系数的向量
    //返回回归系数

算法思想:

1、训练

1.1、初始化权重:

1.2、加载数据;

1.3、计算hypothesis


1.4、计算Loss


1.5、计算损失函数J(theta):如果明白变化可以看看极大似然推导公式


1.6、想要最小化损失函数minJ(theta),更新theta(梯度下降法)




即:倒数求解可以私下导一导



2、测试:


练习代码:

#! /usr/bin/python 
# -*- coding: utf-8 -*-

import os 
import string 
import sys
import math


class LogisticRegression :
    def __init__ ( self ) :
        self.__X = []   #特征集合
        self.__Y = []    #标签
        self.__theta = []  #权重
        self.__LEARNING_RATE = 7   #学习率
        self.__FEATURE_CNT = 1 + 2   #特征数
        self.__load_training_data ()  #加载数据
        self.__SAMPLE_CNT = len ( self.__Y )   #样本数
        self.__feature_scaling ()   #特征缩放

        for idx in range ( 0, self.__FEATURE_CNT ) :
            self.__theta.append(0)

    def __load_training_data(self) :
        fp = open ( "testSet.txt", "r" )
        for line in fp.readlines() :
            (x1, x2,y) = line.strip('\r\n').split ( '\t' )
            self.__X.append ( [1, float(x1), float(x2)] )
            self.__Y.append(float(y))
        fp.close()        

    def __feature_scaling(self) :
        max_value = []
        min_value = []
        for fidx in range ( 0, self.__FEATURE_CNT ) :
            max_value.append(0)
            min_value.append(100)

        for idx in range ( 0, self.__SAMPLE_CNT) :
            for fidx in range ( 1, self.__FEATURE_CNT ) :
                if max_value[fidx] < self.__X[idx][fidx] :
                    max_value[fidx] = self.__X[idx][fidx]
                if min_value[fidx] > self.__X[idx][fidx] :
                    min_value[fidx] = self.__X[idx][fidx]
        for idx in range ( 0, self.__SAMPLE_CNT) :
            x = self.__X[idx]
            for fidx in range ( 1, self.__FEATURE_CNT ) :
                self.__X[idx][fidx] = ( x[fidx] - min_value[fidx] ) / ( max_value[fidx] - min_value[fidx] )  


    def batch_learning_alogrithm (self) :
        last_loss = 0
        for  itr in range ( 1, 100000 ) :
            #1、训练数据
            self.__training ()
            loss = self.__get_loss ()
            sys.stdout.write ( "After %s iteratorion loss = %lf\n" % (itr, loss) )

            if math.fabs ( loss - last_loss)  <= 0.01 :
                break;
            last_loss = loss

        sys.stdout.write ( "The coef of the logistic model :\n")
        for idx in range ( 0, self.__FEATURE_CNT ) :
            sys.stdout.write ( "theta[%d] = %lf\n" % ( idx, self.__theta[idx]) )

    def __training (self) :
        #初始化权重为[0 0 0]
        weight = []
        for idx in range ( 0, self.__FEATURE_CNT ) :
            weight.append(0) 
    
        """计算loss"""
        for idx in range ( 0, self.__SAMPLE_CNT) :
            x = self.__X[idx]
            y = self.__Y[idx]
            h = self.__sigmoid( x ) 
            for fidx in range ( 0, self.__FEATURE_CNT ) :
                weight[fidx] +=  ( h - y ) * x[fidx]

        """更新权重"""
        for idx in range ( 0, self.__FEATURE_CNT ) :
            self.__theta[idx] -= self.__LEARNING_RATE * weight[idx] / self.__SAMPLE_CNT

    def __sigmoid ( self, x ) :
        logit = 0
        for idx in range ( 0, self.__FEATURE_CNT):
            logit += self.__theta[idx] * x[idx]
        return 1.0 / ( 1.0 + math.exp ( -logit ) )
        
    def __get_loss (self ) :
        loss = 0
        for idx in range ( 0, self.__SAMPLE_CNT) :
            x = self.__X[idx]
            y = self.__Y[idx]
            h = self.__sigmoid( x ) 
            loss += y * math.log (h) + ( 1 - y ) * math.log ( 1 - h )
        return loss
 

    def test ( self ) :
        wrong_ans = 0
        for idx in range ( 0, self.__SAMPLE_CNT) :
            x = self.__X[idx]
            y = self.__Y[idx]
            h = self.__sigmoid( x ) 
            check = 0
            if y > 0.5 and h< 0.5  :
                check = -1
            if y < 0.5 and h > 0.5 :
                check = -1
            sys.stdout.write ( "样本 %d : 真值 = %.2lf, 预测 = %.2lf check = %d\n" % ( idx, y, h, check ))
            wrong_ans -= check    
        print "错误 = %d" % wrong_ans
            
if __name__ == "__main__" :
    lr = LogisticRegression()
    lr.batch_learning_alogrithm ()
    lr.test()


补充:

对于数据输入一般讲数据和标签分开:

 def __load_training_data(self):
        fp = open("./ex4x.dat", "r")
        for line in fp.readlines():
            (x1, x2) = line.strip('\r\n').split()
            self.__X.append([1, float(x1), float(x2)])
        fp.close()

        fp = open("./ex4y.dat", "r")
        for line in fp.readlines():
            y = line.strip('\r\n\t')
            self.__Y.append(float(y))
        fp.close()
ex4x.dat  ex4y.dat 

testSet.txt

-0.017612	14.053064	0
-1.395634	4.662541	1
-0.752157	6.538620	0
-1.322371	7.152853	0
0.423363	11.054677	0
0.406704	7.067335	1
0.667394	12.741452	0
-2.460150	6.866805	1
0.569411	9.548755	0
-0.026632	10.427743	0
0.850433	6.920334	1
1.347183	13.175500	0
1.176813	3.167020	1
-1.781871	9.097953	0
-0.566606	5.749003	1
0.931635	1.589505	1
-0.024205	6.151823	1
-0.036453	2.690988	1
-0.196949	0.444165	1
1.014459	5.754399	1
1.985298	3.230619	1
-1.693453	-0.557540	1
-0.576525	11.778922	0
-0.346811	-1.678730	1
-2.124484	2.672471	1
1.217916	9.597015	0
-0.733928	9.098687	0
-3.642001	-1.618087	1
0.315985	3.523953	1
1.416614	9.619232	0
-0.386323	3.989286	1
0.556921	8.294984	1
1.224863	11.587360	0
-1.347803	-2.406051	1
1.196604	4.951851	1
0.275221	9.543647	0
0.470575	9.332488	0
-1.889567	9.542662	0
-1.527893	12.150579	0
-1.185247	11.309318	0
-0.445678	3.297303	1
1.042222	6.105155	1
-0.618787	10.320986	0
1.152083	0.548467	1
0.828534	2.676045	1
-1.237728	10.549033	0
-0.683565	-2.166125	1
0.229456	5.921938	1
-0.959885	11.555336	0
0.492911	10.993324	0
0.184992	8.721488	0
-0.355715	10.325976	0
-0.397822	8.058397	0
0.824839	13.730343	0
1.507278	5.027866	1
0.099671	6.835839	1
-0.344008	10.717485	0
1.785928	7.718645	1
-0.918801	11.560217	0
-0.364009	4.747300	1
-0.841722	4.119083	1
0.490426	1.960539	1
-0.007194	9.075792	0
0.356107	12.447863	0
0.342578	12.281162	0
-0.810823	-1.466018	1
2.530777	6.476801	1
1.296683	11.607559	0
0.475487	12.040035	0
-0.783277	11.009725	0
0.074798	11.023650	0
-1.337472	0.468339	1
-0.102781	13.763651	0
-0.147324	2.874846	1
0.518389	9.887035	0
1.015399	7.571882	0
-1.658086	-0.027255	1
1.319944	2.171228	1
2.056216	5.019981	1
-0.851633	4.375691	1
-1.510047	6.061992	0
-1.076637	-3.181888	1
1.821096	10.283990	0
3.010150	8.401766	1
-1.099458	1.688274	1
-0.834872	-1.733869	1
-0.846637	3.849075	1
1.400102	12.628781	0
1.752842	5.468166	1
0.078557	0.059736	1
0.089392	-0.715300	1
1.825662	12.693808	0
0.197445	9.744638	0
0.126117	0.922311	1
-0.679797	1.220530	1
0.677983	2.556666	1
0.761349	10.693862	0
-2.168791	0.143632	1
1.388610	9.341997	0
0.317029	14.739025	0


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

女王の专属领地

您的鼓励是我最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值