第12关 老司机带你去赏花_逻辑回归算法_人工智能课程 - 小象学院

课程目录 小象学院 - 人工智能

关注公众号【Python家庭】领取1024G整套教材交流群学习商务合作。整理分享了数套四位数培训机构的教材,现免费分享交流学习,并提供解答、交流群

你要的白嫖培训教程,这里可能都有喔~

Hello,小伙伴你好!本关老司机又来和你见面啦^_^

场景引入

今天老司机心情异常的好,也不知道是上次买彩票又中了五块钱,还是出门捡了5毛钱,反正老司机今天要带着你去赏花!

老司机最近对一种叫做鸢(yuan)尾花的花特别感兴趣,但是他又不是特别知道怎么区分鸢尾花、月季花、菊花...

老司机只认识狗尾巴花!简直就是个花盲!

扫描二维码关注公众号,回复: 12908810 查看本文章

老司机准备在赏花之前,准备先搞个算法模型,然后带着这个算法模型去赏花,让机器帮他鉴别鸢尾花,防止他露怯。

老司机还是没有改变他野路子的风格,这次不知道从哪又搞来了一批鸢尾花的数据,准备用这些数据作为训练和测试模型的数据集。

查看数据集信息

那我们先看看这批鸢尾花数据集里的样本数据有什么特点。

AI_12_0_1_引入sklearn提供的数据集

# 引入sklearn提供的数据集
from sklearn import datasets

#使用sklearn提供的鸢尾花数据集
iris = datasets.load_iris()

X = iris.data   # 样本特征集
y = iris.target # 样本标签集

# 查看X和y的结构
print("X.shape",X.shape) # 150行(150个样本) 4列的二维数组(矩阵)
print("y.shape",y.shape) # 包含150个样本标签的一维向量
X.shape (150, 4)
y.shape (150,)

我们再看看特征集X里的数据长什么样子?

AI_12_0_2

from sklearn import datasets

iris = datasets.load_iris()
X = iris.data   # 样本特征集
y = iris.target # 样本标签集

# 打印X中的前5个样本,样本的所有列都打印出来
print(X[:5,:])
[[5.1 3.5 1.4 0.2]
 [4.9 3.  1.4 0.2]
 [4.7 3.2 1.3 0.2]
 [4.6 3.1 1.5 0.2]
 [5.  3.6 1.4 0.2]]

特征集X中的每一个样本有4列,也就是每个样本有4个特征,从左向右分别是花萼长度(cm)、花萼宽度(cm)、花瓣长度(cm)、花瓣宽度(cm)。

我们再看看标签集y里的数据长什么样子?

AI_12_0_3

from sklearn import datasets

iris = datasets.load_iris()
X = iris.data   # 样本特征集
y = iris.target # 样本标签集

print(y)
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2]

从打印结果可以看出,标签数据集y里有三种类型的鸢尾花,分别用0、1、2三个数字表示。

了解了数据的特点之后,老司机开始选择合适的算法,老司机想肯定要从分类算法里选,而且要可解释性强,万一遇到个跟我一样的花盲,我得能跟他解释清楚。

老司机想来想去,逻辑回归算法是最佳选择,因为逻辑回归可以解决分类问题,关键是它的原理简单可解释性强,遇到个花盲,我就跟他说我这个神器可以根据鸢尾花的特征,计算出它属于哪个品种的概率,这么一说他就能明白。

算法选好了,接下来就要开始干活了。

数据预处理

由于逻辑回归更擅长解决二分类问题,而且老司机自己能认出来第3个品种的鸢尾花,于是老司机决定对数据集进行一次处理,去掉数据集中的第3个品种的鸢尾花数据,只保留0和1分别表示的两个品种鸢尾花。

AI_12_0_4

from sys import path
path.append(r"../data/course_util")
from ai_course_12_1 import *

import matplotlib.pyplot as plt
%matplotlib inline

X = X[y<2,:]
y = y[y<2]

print("X.shape",X.shape) 
print(X[:5,:])

print("-----------分割线----------")
print("y.shape",y.shape) 
print(y)

plt.scatter(X[y==0,0],X[y==0,1],color="purple")
plt.scatter(X[y==1,0],X[y==1,1],color="orange")
plt.show()
X.shape (100, 4)
[[5.1 3.5 1.4 0.2]
 [4.9 3.  1.4 0.2]
 [4.7 3.2 1.3 0.2]
 [4.6 3.1 1.5 0.2]
 [5.  3.6 1.4 0.2]]
-----------分割线----------
y.shape (100,)
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]

经过处理之后,特征集X中还剩下100个样本数据,标签集y中也对应的剩下100个样本对应的标签(0和1表示的鸢尾花品种)

数据我们已经了解清楚了,接下来我们把上一关自定义的使用梯度下降法求解逻辑回归的过程封装到一个类中,这样方便我们在任何地方调用这个模型。

用类封装算法

AI_12_0_5

import numpy as np

'''
自定义的逻辑回归算法
'''
class LogisticRegression:
    '''初始化LogisticRegression模型'''
    def __init__(self):
        self.theta_ = None
        
    '''用于训练逻辑回归模型'''
    def fit(self, X_train, y_train):
        # 给训练数据集X_train添加一列全1的特征,这样做的目的是给每一个样本添加一个X0特征,X0恒等于1
        X_train_new = np.hstack([np.ones((len(X_train), 1)), X_train])

        # 设置theta的初始值全为0
        initial_theta = np.zeros(X_train_new.shape[1])

        # 设置学习率eta初始值
        eta = 0.01

        # 调用上面定义的使用梯度下降法求出损失函数取最小值时的theta
        self.theta_ = self.gradient_descent(X_train_new, y_train, initial_theta, eta)
    
    '''使用梯度下降法求出损失函数取最小值时的theta'''
    def gradient_descent(self, X, y, initial_theta, eta, n_iters=1e2, epsilon=1e-8):
        theta = initial_theta
        i_iter = 0
        while i_iter < n_iters:
            # 计算梯度
            gradient = self.dJ(theta, X, y)  # 调用上面定义的计算梯度的函数dJ

            #保存上一次的theta
            last_theta = theta

            #计算本次的theta
            theta = theta - eta * gradient #本次theta = 上一次的theta - 学习率 * 梯度

            #最近的两次损失值进行对比,如果两次的损失差值无限接近0,就证明已经找到了损失函数的最小值
            if (abs(self.J(theta, X, y) - self.J(last_theta, X, y)) < epsilon):
                #如果找到了损失函数的最小值,直接跳出while循环
                break
            i_iter += 1
        # 返回取损失函数最小值时的theta
        return theta
    
    '''sigmoid函数'''
    def sigmoid(self, t):
        return 1. / (1. + np.exp(-t)) 
    
    '''逻辑回归的损失函数J'''
    def J(self, theta, X, y):
        # 调用sigmoid函数,得到样本的预测概率值p_hat
        t = X.dot(theta)
        p_hat = self.sigmoid(t)

        # 根据损失函数公式计算
        return - np.sum(y*np.log(p_hat) + (1-y)*np.log(1-p_hat)) / len(y) 
    
    '''计算梯度'''
    def dJ(self, theta, X, y):
        t = X.dot(theta)
        return X.T.dot(self.sigmoid(t) - y) / len(y)
    
    '''逻辑回归预测函数'''
    def predict(self, X_predict):
        # 给样本添加一个全1列,目的是为了方便矩阵运算
        x_predict_new = np.hstack([np.ones((len(X_predict), 1)), X_predict])

        #通过sigmoid函数计算概率,p_hat向量里的元素是针对每个预测样本的预测概率值,概率值是0到1之间的浮点数
        p_hat = self.sigmoid(x_predict_new.dot(self.theta_))

        # 根据p_hat的概率值,划分预测样本对应的类别是0或1
        return np.array(p_hat >= 0.5,dtype='int')
    
    '''通过准确率判断模型的好坏'''
    def score(self, x_test, y_test):
        y_predict = self.predict(x_test)
        #预测结果与真实值相等的数量/真实值的数量
        return sum(y_predict == y_test)/len(y_test)

封装的这个LogisticRegression类里的方法全部都是上一关我们已经定义过的方法,唯一改变的地方就是把theta提出来放到__init__构造方法中,这样做的目的是方便LogisticRegression类中的其他方法调用。

老司机已经把能够分辨鸢尾花品种的逻辑回归算法定义好了,接下来就是要用已有的样本数据训练这个算法模型,让它达到一个比较好的预测效果,这样就可以带着它出去显摆了。

训练集和测试集划分

我们先对样本数据集进行划分,按照训练数据集:测试数据集 = 8:2的规则划分,也就是测试数据集占总数据集的20%。

AI_12_0_6

from sys import path
path.append(r"../data/course_util")
from ai_course_12_2 import *

from sklearn.model_selection import train_test_split

#划分数据集,传入的参数test_size=0.2表示使用总数据集的20%作为测试数据集
X_train,X_test,y_train,y_test = train_test_split(X, y, test_size=0.2, random_state=111)

print("X_train shape:",X_train.shape)
print("y_train shape:",y_train.shape)
print("X_test shape:",X_test.shape)
print("y_test shape:",y_test.shape)

所有的准备工作都已经就绪了,接下来就是见证奇迹的时刻了!

使用自定义类训练模型

使用我们自定义的逻辑回归算法LogisticRegression类创建一个模型对象,使用训练数据集训练这个模型

AI_12_0_7

from sys import path
path.append(r"../data/course_util")
from ai_course_12_2 import *

from sklearn.model_selection import train_test_split

#划分数据集,传入的参数test_size=0.2表示使用总数据集的20%作为测试数据集
X_train,X_test,y_train,y_test = train_test_split(X, y, test_size=0.2, random_state=111)

# 创建LogisticRegression模型对象
log_reg = LogisticRegression()

# 调用log_reg对象的fit方法,使用训练数据集对模型进行训练
log_reg.fit(X_train,y_train)

print("训练完成,已找到最佳theta=",log_reg.theta_)

计算模型准确率

模型训练好以后,我们就要使用测试数据集对模型对模型的好坏进行测试,这里我们使用准确率来评价模型的好坏,也就是将预测样本特征集输入给已经训练好的逻辑回归模型,看看模型预测正确的鸢尾花品种占总的测试样本的真实鸢尾花品种的百分比。

AI_12_0_8

from sys import path
path.append(r"../data/course_util")
from ai_course_12_3 import *

print("   y_test:",y_test)
#使用训练好的模型对测试集进行预测
y_predict = log_reg.predict(X_test) #预测的分类(使用1,0表示)
print("y_predict:", y_predict)

#通过准确率判断模型的好坏
print("score of LogisticRegression : ",log_reg.score(X_test,y_test))

通过测试结果我们可以看出,模型的预测效果很好,达到了100%的准确率,简直堪称完美,老司机可以带着它出门嘚瑟去了...

老司机看到这样的预测效果有些膨胀,非要把他写的这个逻辑回归跟sklearn提供的逻辑回归比试比试。

使用sklearn库训练模型

接下来我们使用sklearn提供的逻辑回归再对鸢尾花进行一次预测。

AI_12_0_9

from sys import path
path.append(r"../data/course_util")
from ai_course_12_4 import *

# 引入sklearn中的逻辑回归算法
from sklearn.linear_model import LogisticRegression

# 创建一个LogisticRegression对象
lr_model = LogisticRegression()

# 调用lr_model对象的fit方法,使用训练数据集训练模型
lr_model.fit(X_train, y_train)

# 使用测试数据集测试模型的准确率
test_score = lr_model.score(X_test, y_test) #sklearn提供的LogisticRegression默认的评价方法也是准确率

# 打印测试的准确率
print("score of sklearn LogisticRegression : ", test_score)
y_train
score of sklearn LogisticRegression :  1.0

array([1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,
       0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0,
       1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1,
       0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1])

从运行结果看,sklearn提供的逻辑回归算法应用到鸢尾花数据集上,预测效果也非常好,准确率达到了100%。

老司机对这样的对比结果还算满意,毕竟是打了个平手,自己没占到便宜也没丢脸,哈哈哈哈...

此时,老司机可以非常自信的出门去赏花了,只要遇到鸢尾花,拿出他的逻辑回归模型,就可以准确地分辨出它是什么品种。厉害了,我的老司机!

联系我们,一起学Python吧

分享Python实战代码,入门资料,进阶资料,基础语法,爬虫,数据分析,web网站,机器学习,深度学习等等。


​关注公众号「Python家庭领取1024G整套教材交流群学习商务合作

猜你喜欢

转载自blog.csdn.net/qq_34409973/article/details/115125028