My Machine Learn(二): 逻辑回归(Logistic Regression)

一、简介

老规矩,先来看看度娘她老人家是如何描述逻辑回归的:

logistic回归又称logistic回归分析,是一种广义的线性回归分析模型,常用于数据挖掘,疾病自动诊断,经济预测等领域 。

也就是说,你也可以把逻辑回归看做是线性回归的一个分支或特例, 就好像“正方形”是“矩形”的特例一样。

我在网上也瞧了不少与逻辑回归相关的文章,基本上一上来就是一堆让人头大的词语: 模型啊,参数啊,分布函数,密度函数,最小二乘, 极大似然评估等等。

这里只是介绍笔者能够理解的,最简单的逻辑回归形式。

上一篇中介绍了线性回归,它的能力或者说用途是拟合数据,也就是说有一堆数据,咱们要做的就是找到一个根直线, 让所有数据和这根直线距离最短(也就是拟合),以便预测新的数据出现时,映射到这根直线上的预期值是多少。

逻辑回归于线性回归的能力正好相反,它的作用的分类,也就是说至少有两堆或以上的数据,我们需要做的就是找到一根直线(当然,情况多种多样,不一定是直线,很多时候它是一条曲线,或者圆圈), 这条直线在两堆数据之间,我们要做的就是让两堆数据和这个直线的距离越长越好。以便预测新数据属于两堆数据中的哪一个堆。

简单来说,逻辑回归,就是在线性回归的基础上(线性回归的输出端)添加了一个非线性部分,一般来说会是sigmoid函数,其形式如下所示:

f ( x ) = 1 1 + e x

其函数图形如下所示:

sigmoid

二、结构

上一节中说到逻辑回归是在线性回归的基础上添加了一个非线性部分。 根据这个结论,我们可以得到逻辑回归的逻辑结构如下所示:

logistic regression structure

前面圆形部分就相当于线性回归

g ( x ) = w x + b

后一部分就类似于神经网络中单个神经元的激活函数
f ( x ) = 1 1 + e g ( x )

三、实现

因为这部分和神经网络的单个神经元很相似,所以只会大致简单的介绍,而不会大书特书。

本次逻辑回归的实现代码使用Python完成的,之所以没有用c++,首先是因为只是做简单介绍,而Python能进行快速开发,也会有很多参考代码。其次,Python在产生数据集,读取和预处理数据集,绘制图形等方面都是非常出色的,如果要用c++实现,那就非常麻烦了。

3.1 产生数据集

这里使用Python来随机产生我们需要的数据集,包括训练数据集和测试数据集。

使用到的Python库包括 numpy,sklearn, pandas等

  • numpy: Python中非常好的数学运算库

  • sklearn: 机器学习裤,这里我们只是用它来产生用于逻辑回归的分类数据集,并使用它对数据集进行切分,

    ​ 分为:训练数据和测试数据

  • pandas:是基于numpy的一个工具库,这里用它来将数据输出为csv格式的文件

具体代码如下所示:


#导入需要的库和函数
import numpy as np
from sklearn.datasets.samples_generator import make_classification
from sklearn.model_selection import train_test_split
import pandas as pd

#创建分类数据集,其样本数量为200
X,labels = make_classification(n_samples=200, n_features=2, n_redundant=0, n_informative=2,
                               random_state=1, n_clusters_per_class=2)
rng = np.random.RandomState(2)
X += 2*rng.uniform(size=X.shape)


print(X.shape)
print(labels.shape)

#切分数据集为训练和测试两部分,其中测试数据的比例为20%
X_train, X_test, y_train, y_test = train_test_split(X, labels, test_size=0.2)


#字典中的key值即为csv中列名
dataframe = pd.DataFrame({'x1':X_train[:,0], 'x2':X_train[:, 1] , 'y':y_train})

#将DataFrame存储为csv,index表示是否显示行名,default=True
dataframe.to_csv("d:\\train_data.csv",index=False, sep=',', float_format='%10f')

#字典中的key值即为csv中列名
dataframe = pd.DataFrame({'x1':X_test[:,0], 'x2':X_test[:, 1] , 'y':y_test})

#将DataFrame存储为csv,index表示是否显示行名,default=True
dataframe.to_csv("d:\\test_data.csv",index=False, sep=',', float_format='%10f')

3.2 逻辑回归算法

这部分包括逻辑回归本身的算法实现以及训练和测试部分的代码实现。

这里并未去详细的说明逻辑回归算法相关的数学公式推导过程,以及训练过程中,逻辑回归的损失函数是什么形式,以及反向传播误差是如何推导的等等。

所以这里需要注意几个点:

  • 这里只是简单的demo实现,并未关注训练结果的好坏(笔者测试的结果准确率大概在72.5%左右)
  • 这里并没有使用最大似然,对数似然等作为逻辑回归的损失函数,而是使用了和线性回归一样的算法
  • 这里在更新权重时也是使用了线性回归一样的算法
  • 这里和线性回归不同的地方就是添加了sigmoid激活函数,使结果非线性话,以达到分类效果。

具体的实现代码如下:

#导入需要的库
import numpy as np
import pandas as pd

#读取训练数据集和测试数据集
train_data = pd.read_csv("train_data.csv")
test_data = pd.read_csv("test_data.csv")

X= train_data[['x1', 'x2']].values
labels = train_data['y'].values

test_X = test_data[['x1', 'x2']].values
test_labels = test_data['y'].values

#print(X[0])
#print(type(labels))

epochs = 1000
learning_rate = 0.001

#激活函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

#逻辑回归算法(包含训练)
def logistic_regression(x, y):
    w = np.array([1, 1], dtype=np.float)
    b = 0.0
    #print(type(w[0]))
    for epoch in range(epochs):
        for i in range(len(x)):
            y_hat = sigmoid(np.dot(w , x[i]) + b)
            #print(x[i])

            delt = learning_rate * (y[i] - y_hat)

            #print(type(delt))
            #print(type(w))
            #tem = w * delt
            w += w * delt
            b += delt
    return w, b

#预测算法
def predict(x, w, b):
    y_hat = sigmoid(np.dot(w, x) + b)
    if y_hat >= 0.5:
        return 1
    return 0

#使用训练数据集训练逻辑回归算法
w, b = logistic_regression(X, labels)

print(w)
print(b)

acturly_cnt = 0
#预测(测试逻辑回归算法)
for i in range(len(test_labels)):
    pred = predict(test_X[i], w, b)

    if (pred == test_labels[i]):
        acturly_cnt += 1


print("the ration is: %f" % (acturly_cnt / len(test_labels)))

3.3 图形绘制

这里用Python实现了绘制训练数据集的图形化表示,以及逻辑回归结果的图形化显示,其具体代码实现如下所示。

#导入需要的库
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

#读取训练数据集
dataframe = pd.read_csv("train_data.csv")

X= dataframe[['x1', 'x2']].values
labels = dataframe['y'].values

#绘制分类数据的图形
unique_lables=set(labels)
colors = plt.cm.Spectral(np.linspace(0,1,len(unique_lables)))
for k,col in zip(unique_lables,colors):
    x_k = X[labels==k]
    plt.plot(x_k[:,0],x_k[:,1],'o',markerfacecolor=col,markeredgecolor="k",
             markersize=14)


plt.title('data by make_classification()')

#############################################################
#绘制逻辑回归结果的直线
#其中weight和b的数据来源于逻辑回归算法训练之后的结果
weight = [0.45688252, 0.45688252]
b = -0.7686426869590841

x = np.arange(-3.0, 5.0, 0.1)
y = (-weight[0] - weight[1] * x) / b
plt.plot(x, y, color = 'g')

#如果将这部分屏蔽起来就只是绘制分类数据,打开之后就是绘制带有分类直线的图形
################################################################

#显示图形
plt.show()
  • 绘制分类数据集的图形如下所示:

    分类数据集

  • 绘制逻辑回归训练后的结果

逻辑回归

四、附录

所有的源码和数据文件均在 开源中国的 码云当中, 其地址如下:

https://gitee.com/xunawolanxue.com/my_demo_code/tree/master/My_Machine_Learn/%E9%80%BB%E8%BE%91%E5%9B%9E%E5%BD%92

猜你喜欢

转载自blog.csdn.net/xuanwolanxue/article/details/80581410
今日推荐