逻辑回归+Python3实现

1.什么是逻辑回归

logistic回归又称logistic回归分析,是一种广义的线性回归分析模型。常用于数据挖掘,疾病自动诊断,经济预测等领域。值得一提的是该算法输出值永远在 0 到 1 之间。下面通过一个例子来了解下什么是逻辑回归。

假设现在我们有一个应用场景,根据肿瘤的大小来判断肿瘤是恶性的还是良性的。

我们从先从二元分类的问题开始讨论。

将因变量(dependent variable)可能属于的两个类分别称为负向类(negative)和正向类(positive class),因此因变量 y ∈ \in 0,1,其中0表示负向类,1标志正向类。

对于肿瘤是良性还是恶性 是个二分类问题,因此我们可以用 y = 1表示正向类,y = 0 表示负向类。因此我们可以引入逻辑回归模型,该模型的输出变量范围始终在 0 到1 之间。

逻辑回归模型的假设是: h θ   h_\theta  hθ ( x ) = g( θ T \theta^T θTX ) 其中:X 代表特征向量 g 代表逻辑函数(logistic function)是一个常用的逻辑函数为 S 型函数(Sigmoid function), 公式为:g(z) = 1 1 + e − z \frac{1}{1+ e^{-z}} 1+ez1

该函数的图像为:

image-20200906165125497

合起来,我们得到逻辑回归模型的假设:

对模型的理解:g(z) = 1 1 + e − z \frac{1}{1+e^{-z}} 1+ez1

h θ h_\theta hθ(x) 的作用是,对于给定的输入变量。根据秀安装的参数计算出书变量=1 的可能性(estimated probablity)即 h θ h_\theta hθ(x) = P(y =1|x; θ \theta θ)

例如,如果给定的 x ,通过已经确定的参数计算得出 h θ h_\theta hθ(x) =0.6,则表示有70%的几率为正向类,相应地 y 为负向类的几率为 1 - 0.7 = 0.3。

2. 逻辑回归的判定边界

现在假设我们有一个模型:

image-20200906170435264

并且参数 θ \theta θ 是向量[-3 1 1]。则当-3 + x 1 x_1 x1 + x 2 x_2 x2 >= 0,即 x 1 x_1 x1 + x 2 x_2 x2 >= 3时,模型将预测 y = 1。我们可以绘制直线 x 1 x_1 x1 + x 2 x_2 x2 = 3,这条线便是我们模型的分界线,将预测为1的区域和预测为0的区域分隔开。

image-20200906170959777

3.代价函数

现在有个问题就是我们应该如何确定参数 θ \theta θ呢?接下来将要介绍如何拟合逻辑回归模型的参数 θ \theta θ

定义逻辑回归的代价函数:

​ J( θ \theta θ) = - 1 m ∑ i = 1 m [ y ( i ) l o g ( h θ ( x ( i ) ) ) + ( 1 − y ( i ) ) l o g ( 1 − h θ ( x ( i ) ) ) ] \frac{1}{m}\sum_{i=1}^m[y^{(i)}log(h_{\theta}(x^{(i)})) +(1-y^{(i)})log(1-h_\theta(x^{(i)}))] m1i=1m[y(i)log(hθ(x(i)))+(1y(i))log(1hθ(x(i)))]

得到这样一个代价函数以后,我们便可以用梯度下降算法来求得能使代价函数最小的参数。算法为:

Repeat{ θ j : = θ j − a 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x j i \theta_j:=\theta_j - a\frac{1}{m}\sum_{i=1}^m(h_\theta(x^{(i)}) - y^{(i)})x{_j^{i}} θj:=θjam1i=1m(hθ(x(i))y(i))xji

(Simultaneously update all θ j \theta_j θj)

}

这里我就直接给出结果了,想了解推导过程的看官老爷们可以自行去查阅资料。

4.Python3实现逻辑回归

from math import exp
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

class LogisticReressionClassifier:
    def __init__(self, max_iter=5000, learning_rate=0.01):
        self.max_iter = max_iter
        self.learning_rate = learning_rate

    def sigmoid(self, x):
        return 1 / (1 + exp(-x))

    def data_matrix(self, X):
        data_mat = []
        for d in X:
            data_mat.append([1.0, *d])
        return data_mat

    def fit(self, X, y):
        # label = np.mat(y)
        data_mat = self.data_matrix(X)  # m*n
        self.weights = np.ones((len(data_mat[0]), 1), dtype=np.float32)
        for j in range(self.max_iter):
            for iter_ in range(len(self.weights)):
                error = 0
                for i in range(len(X)):
                    result = self.sigmoid(np.dot(data_mat[i], self.weights))
                    error += (result - y[i]) * data_mat[i][iter_]
                self.weights[iter_] = self.weights[iter_] - self.learning_rate * 1 / len(X) * error
        print('LogisticRegression Model(learning_rate={},max_iter={})'.format(
            self.learning_rate, self.max_iter))

    # def f(self, x):
    #     return -(self.weights[0] + self.weights[1] * x) / self.weights[2]

    def score(self, X_test, y_test):
        right = 0
        X_test = self.data_matrix(X_test)
        for x, y in zip(X_test, y_test):
            result = np.dot(x, self.weights)
            if (result > 0 and y == 1) or (result < 0 and y == 0):
                right += 1
        return right / len(X_test)


if __name__ == '__main__':

    # data
    def create_data():
        iris = load_iris()
        df = pd.DataFrame(iris.data, columns=iris.feature_names)
        df['label'] = iris.target
        df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label']
        data = np.array(df.iloc[:100, [0, 1, -1]])
        # print(data)
        return data[:, :2], data[:, -1]

    X, y = create_data()
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
    lr_clf = LogisticReressionClassifier()
    lr_clf.fit(X_train, y_train)
    print(lr_clf.score(X_test, y_test))
    x_ponits = np.arange(4, 8)
    y_ = -(lr_clf.weights[1] * x_ponits + lr_clf.weights[0]) / lr_clf.weights[2]
    plt.plot(x_ponits, y_)

    # lr_clf.show_graph()
    plt.scatter(X[:50, 0], X[:50, 1], label='0')
    plt.scatter(X[50:, 0], X[50:, 1], label='1')
    plt.legend()
    plt.show()

5.总结

了解线性回归的老爷们会惊奇的发现逻辑回归的梯度下降算法和线性回归的梯度下降算法是一样的,那么两者是同一个算法吗?答案显然不是滴,即使从更新参数的规则看起来基本相同,但由于假设的定义发生了变化,所以逻辑函数的梯度下降,跟线性回归的梯度下降时两个完全不同的东西。

各位看官老爷如果你觉得这篇文章有收获就给我点个赞吧!

下期预告:支持向量机

281599138440_.pic_hd

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值