逻辑回归--代码实现(不使用scikit-learn)

参考:https://blog.csdn.net/chibangyuxun/article/details/53148005

1 逻辑回归和线性回归的区别

线性回归算法是使用线性方程对数据集进行拟合的算法,通常情况下使用线性回归算法可以对某些事物进行预测。例如:房价预测,身高预测,体重预测等等。https://blog.csdn.net/qq_37879432/article/details/79825772多元线性回归实现预测的demo。
逻辑回归算法虽然名字里面也带有“回归”二字,但实际上逻辑回归算法是用来解决分类问题的算法。
这里写图片描述

2. 逻辑回归的优缺点

优点:
1)速度快,适合二分类问题
2)简单易于理解,直接看到各个特征的权重
3)能容易地更新模型吸收新的数据
缺点:
对数据和场景的适应能力有局限性,不如决策树算法适应性那么强

3. 逻辑回归和多重线性回归的区别

Logistic回归与多重线性回归实际上有很多相同之处,最大的区别就在于它们的因变量不同,其他的基本都差不多。正是因为如此,这两种回归可以归于同一个家族,即广义线性模型(generalizedlinear model)。
这一家族中的模型形式基本上都差不多,不同的就是因变量不同。这一家族中的模型形式基本上都差不多,不同的就是因变量不同。

如果是连续的,就是多重线性回归
如果是二项分布,就是Logistic回归
如果是Poisson分布,就是Poisson回归
如果是负二项分布,就是负二项回归

4. 逻辑回归用途

寻找危险因素:寻找某一疾病的危险因素等;
预测:根据模型,预测在不同的自变量情况下,发生某病或某种情况的概率有多大;
判别:实际上跟预测有些类似,也是根据模型,判断某人属于某病或属于某种情况的概率有多大,也就是看一下这个人有多大的可能性是属于某病。

5. Regression 常规步骤

寻找h函数(即预测函数)
构造J函数(损失函数)
想办法使得J函数最小并求得回归参数(θ)

6. 构造预测函数h(x)

1) Logistic函数(或称为Sigmoid函数),函数形式为:
这里写图片描述
这里写图片描述

对于线性边界的情况,边界形式如下:
这里写图片描述

其中,训练数据为向量
这里写图片描述
最佳参数
这里写图片描述

构造预测函数为:
这里写图片描述

函数h(x)的值有特殊的含义,它表示结果取1的概率,因此对于输入x分类结果为类别1和类别0的概率分别为:
P(y=1│x;θ)=h_θ (x)
P(y=0│x;θ)=1-h_θ (x)

7.构造损失函数J(m个样本,每个样本具有n个特征)

Cost函数和J函数如下,它们是基于最大似然估计推导得到的。
这里写图片描述

8. 损失函数详细推导过程

1) 求代价函数
概率综合起来写成:
这里写图片描述
取似然函数为:
这里写图片描述
对数似然函数为:
这里写图片描述

最大似然估计就是求使l(θ)取最大值时的θ,其实这里可以使用梯度上升法求解,求得的θ就是要求的最佳参数。

在Andrew Ng的课程中将J(θ)取为下式,即:
这里写图片描述

2) 梯度下降法求解最小值
这里写图片描述

θ更新过程可以写成:
这里写图片描述

9. 向量化

ectorization是使用矩阵计算来代替for循环,以简化计算过程,提高效率。
向量化过程:
约定训练数据的矩阵形式如下,x的每一行为一条训练样本,而每一列为不同的特称取值:

这里写图片描述
g(A)的参数A为一列向量,所以实现g函数时要支持列向量作为参数,并返回列向量。
θ更新过程可以改为:
这里写图片描述

综上所述,Vectorization后θ更新的步骤如下:

求 A=x*θ
求 E=g(A)-y
求这里写图片描述

10.正则化

(1) 过拟合问题
过拟合即是过分拟合了训练数据,使得模型的复杂度提高,繁华能力较差(对未知数据的预测能力)
下面左图即为欠拟合,中图为合适的拟合,右图为过拟合。
这里写图片描述

(2)过拟合主要原因
过拟合问题往往源自过多的特征
解决方法
1)减少特征数量(减少特征会失去一些信息,即使特征选的很好)
• 可用人工选择要保留的特征;
• 模型选择算法;
2)正则化(特征较多时比较有效)
• 保留所有特征,但减少θ的大小

(3)正则化方法
正则化是结构风险最小化策略的实现,是在经验风险上加一个正则化项或惩罚项。正则化项一般是模型复杂度的单调递增函数,模型越复杂,正则化项就越大。

正则项可以取不同的形式,在回归问题中取平方损失,就是参数的L2范数,也可以取L1范数。取平方损失时,模型的损失函数变为:

这里写图片描述

lambda是正则项系数:
• 如果它的值很大,说明对模型的复杂度惩罚大,对拟合数据的损失惩罚小,这样它就不会过分拟合数据,在训练数据上的偏差较大,在未知数据上的方差较小,但是可能出现欠拟合的现象;
• 如果它的值很小,说明比较注重对训练数据的拟合,在训练数据上的偏差会小,但是可能会导致过拟合。
正则化后的梯度下降算法θ的更新变为:
这里写图片描述

11 不使用Scikit-learn

import matplotlib.pyplot as plt
import numpy as np
from numpy import genfromtxt

dataPath = r"data1.txt"
# 加上r就会将后面当做一个完整的字符串,而不会认为里面有什么转义之类的。
deliveryData = genfromtxt(dataPath, delimiter=',')

print("data")
print(deliveryData)

X = deliveryData[:, :-1]
y = deliveryData[:, -1]

label = np.array(y)
index_0 = np.where(label==0)
plt.scatter(X[index_0,0],X[index_0,1],marker='x',color = 'b',label = '0',s = 15)
index_1 =np.where(label==1)
plt.scatter(X[index_1,0],X[index_1,1],marker='o',color = 'r',label = '1',s = 15)

plt.xlabel('X1')
plt.ylabel('X2')
plt.legend(loc = 'upper left')
plt.show()


class logistic(object):
    def __init__(self):
        self.W = None

    def train(self, X, y, learn_rate=0.001, num_iters=1000000):
        num_train, num_feature = X.shape
        # init the weight
        self.W = 0.001 * np.random.randn(num_feature, 1).reshape((-1, 1))
        loss = []

        for i in range(num_iters):
            error, dW = self.compute_loss(X, y)
            self.W += -learn_rate * dW

            loss.append(error)
            if i % 200 == 0:
                print('i=%d,error=%f' % (i, error))
        return loss

    def compute_loss(self, X, y):
        num_train = X.shape[0]
        h = self.output(X)
        loss = -np.sum((y * np.log(h) + (1 - y) * np.log((1 - h))))
        loss = loss / num_train

        dW = X.T.dot((h - y)) / num_train

        return loss, dW

    def output(self, X):
        g = np.dot(X, self.W)
        return self.sigmod(g)

    def sigmod(self, X):
        return 1 / (1 + np.exp(-X))

    def predict(self, X_test):
        h = self.output(X_test)
        y_pred = np.where(h >= 0.5, 1, 0)
        return y_pred

import matplotlib.pyplot as plt

y = y.reshape((-1,1))
#add the x0=1
one = np.ones((X.shape[0],1))
X_train = np.hstack((one,X))
classify = logistic()
loss = classify.train(X_train,y)
print(classify.W)

plt.plot(loss)
plt.xlabel('Iteration number')
plt.ylabel('Loss value')


plt.show()

label = np.array(y)
index_0 = np.where(label==0)
plt.scatter(X[index_0,0],X[index_0,1],marker='x',color = 'b',label = '0',s = 15)
index_1 =np.where(label==1)
plt.scatter(X[index_1,0],X[index_1,1],marker='o',color = 'r',label = '1',s = 15)

#show the decision boundary
x1 = np.arange(30,100,1)
x2 = (- classify.W[0] - classify.W[1]*x1) / classify.W[2]
plt.plot(x1,x2,color = 'black')
plt.xlabel('X1')
plt.ylabel('X2')
plt.legend(loc = 'upper left')
plt.show()

执行结果

这里写图片描述
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_37879432/article/details/79826052
今日推荐