OLDER BROTHER

大家好,我是你们的机房老哥!

“机器学习进阶”

「前言

机器学习和深度学习是很早前就埋下的坑,最近决定整合写一篇,利用机器学习的经典算法朴素贝叶斯和深度学习的经典算法神经网络对鸢尾花数据集进行测试,综合对比两种经典算法的异同。后台回复6月24日获得完整代码。

相关入门教程:

  • 深度学习:Tensorflow 2.0简明入门

  • 人工智能 | 最简单的语言理解神经网络

  • 10分钟:开启你的机器学习&可视化之路

01

二者关系

AI

器学习是人工智能的重要子领域,它聚焦于如何构建随着经验而自动改进的算法,可以从数据中提取模式、规律和趋势。为什么叫做「学习」呢?一般编程语言的做法是人类给予指令,机器负责执行。而机器学习则相反,先定义好输出,然后程序自动「学习」出达到目标的「步骤」。机器学习最常见的应用领域:

  • 分类(新闻分类)

  • 预测(股票预测)

  • 聚类(自动分组)

  • 规则提取(数据挖掘)

然而机器学习却并非那么智能,数据和特征决定了机器学习的上限,需要人工不停的调整输入特征,使算法不断逼近该上限,这个过程叫特征工程。在算法一致的情况下,特征工程会极大的影响结果,因此准确率很难达到很高。

深度学习是机器学习的子类,通过模拟人脑的神经元,实现自动提取要素的复杂特征,减去了人工调整的烦恼。

机器学习与深度学习的关系

02

机器学习

Machine Learning,ML

哥先用sklearn测试机器学习经典算法之朴素贝叶斯。朴素贝叶斯是一个分类算法,通俗地讲分类算法就是把大量已知特征及类别的样本对象输入计算机,让计算机根据这些已知的类别与特征归纳出类别与特征之间的规律,最终目的是运用得到的分类模型对新输入的对象判断出该对象所属分类。

「朴素」的涵义是假设各特征之间相互独立,这意味着该算法很简单,但是会牺牲一定的准确性。其本质思想是判断输入的条件参数对结果影响的概率,相关公式在10分钟:开启你的机器学习&可视化之路一文中已经阐释,这里不再赘述。

from sklearn.datasets import load_irisimport pandas as pdx_data = load_iris().datay_data = load_iris().targetx_data = pd.DataFrame(x_data, columns = ['花萼长','花萼宽','花瓣长','花瓣宽'])x_data['标签'] = y_datapd.set_option('display.unicode.east_asian_width',True)print(x_data)

先从sklearn的datasets中导入iris数据集。load_iris().data可以得到数据集的特征项,load_iris().target可以得到标签项。老哥用pandas的DataFrame将数据集变成表格输出,可视化相关参数。pd.set_option()的作用是美化DataFrame的打印效果,使列名与数据对齐。

iris数据集

数据共150个,有4个特征,标签有3类,代表鸢尾花的种类。目标是希望利用朴素贝叶斯算法,实现输入数据后,机器自动判断鸢尾花的种类。

from sklearn.model_selection import train_test_splitx_train, x_test, y_train, y_test = train_test_split(x_data,y_data,test_size=30, random_state=25)

利用train_test_split工具将数据集划分为训练集和测试集。输入特征项x_data、标签项y_data,该工具会自动随机划分数据集。test_size即划分比例,如果是小数,指测试集的百分比,如果是大于1的整数,则指测试集的数据个数,我们这里选择30个数据作为测试集。random_state是随机种子,种子一样,则每次的随机划分结果都一致,否则每一次对数据集的划分都是随机的。

本次为了对比机器学习和深度学习算法,设定随机种子,保证两算法用的数据集划分结果一致。

from sklearn.model_selection import train_test_splitfrom sklearn.naive_bayes import MultinomialNBfrom sklearn.datasets import load_irisimport timedef naviebayes(x_train, x_test, y_train, y_test):    """    朴素贝叶斯进行鸢尾花分类    """    mlt = MultinomialNB(alpha=1)    mltStart = time.time()    mlt.fit(x_train, y_train)    mltCostTime = time.time() - mltStart    print("朴素贝叶斯建模%.2f秒" % mltCostTime)    y_score_test = mlt.score(x_test, y_test)    print(y_score_test)if __name__ == "__main__":    x_data = load_iris().data    y_data = load_iris().target    x_train, x_test, y_train, y_test = train_test_split(x_data, y_data, test_size=30, random_state=25)    naviebayes(x_train, x_test, y_train, y_test)

完整代码如上,为测试特征工程对机器学习结果的影响,先不进行特征工程,直接对数据集进行训练。训练的方法也非常简单,从sklearn.naive_bayes中导入MultinomialNB算法,这里也可以导入GaussianNB(先验为高斯分布的朴素贝叶斯)和BernoulliNB(先验为伯努利分布的朴素贝叶斯),单纯的改个名字即可,大家可以自己测试。

首先将MultinomialNB(alpha=1)实例化为mlt,方便后续调用,参数alpha为拉普拉斯平滑参数,该参数为1代表默认每个特征至少出现一次(避免大量出现0概率的情况)。然后将训练集的x和y传入mlt.fit()中计算,得到模型。将测试集的x和y传入mlt.score()函数中,自动进行预测,并输出准确率。利用time模块计算算法运行时间。

结果可知,在未进行特征工程的情况下,预测准确率为80%。接下来我们测试加入数据预处理后的预测准确率,代码如下:

from sklearn.model_selection import train_test_splitfrom sklearn.preprocessing import Normalizerfrom sklearn.preprocessing import PolynomialFeaturesfrom sklearn.preprocessing import MinMaxScalerfrom sklearn.preprocessing import StandardScalerfrom sklearn.preprocessing import OneHotEncoderfrom sklearn.preprocessing import Binarizerfrom sklearn.naive_bayes import MultinomialNBfrom sklearn.datasets import load_irisimport timedef naviebayes(x_train, x_test, y_train, y_test):    for preprocessing_method in [Normalizer(),PolynomialFeatures(),MinMaxScaler(),StandardScaler(),Binarizer(),OneHotEncoder()]:        try:            method = preprocessing_method            method.fit(x_train)            x_train = method.transform(x_train)            x_test = method.transform(x_test)            print('特征工程算法:',str(preprocessing_method).split('(')[0])            mlt = MultinomialNB(alpha=1)            mltStart = time.time()            mlt.fit(x_train, y_train)            mltCostTime = time.time() - mltStart            print("建模时长%.2f秒" % mltCostTime)            y_score_test = mlt.score(x_test, y_test)            print(y_score_test)        except:            print(str(preprocessing_method).split('(')[0],'算法无法在本例使用')if __name__ == "__main__":    x_data = load_iris().data    y_data = load_iris().target    x_train, x_test, y_train, y_test = train_test_split(x_data, y_data, test_size=30, random_state=25)    naviebayes(x_train, x_test, y_train, y_test)

sklearn将所有预处理算法都封装到了preprocessing函数中,如上述代码所示,老哥用for循环分别测试了六个算法的训练准确率。算法如下:

预处理算法

功能

Normalizer()

正则化

将每个样本缩放到单位范数

PolynomialFeatures()

多项式转换

构造特征值,例如有 a、b 两个特征,那么它的 2 次多项式为

[1,a,b,a2,ab,b2]

MinMaxScaler()

区间缩放

将属性缩放到指定的极值(通常是1-0)之间

StandardScaler()

中心化

令所有数据的中心为(0,0)

Binarizer()

二值化

设定一个阈值,大于阈值的赋值为1,小于等于阈值的赋值为0

OneHotEncoder()

向量化

对离散特征进行独热编码

测试结果如下:

  • 正则化和多项式转换降低了预测准确率

  • 区间缩放提高了准确率

  • 中心化因为会生成负数,所以无法在朴素贝叶斯中使用

  • 二值化和独热编码未改变准确率

至此朴素贝叶斯算法的准确率最高为90%,接下来看看神经网络模型。

03

深度学习

Deep Learning, DL

下来老哥搭建一个最最简单的,只有一层的神经网络模型,相关介绍请参考人工智能 | 最简单的语言理解神经网络。TensorFlow将深度学习算法很好的封装进了Keras,该函数被工业界和学术界广泛使用,仅需20行代码即可搭建一个简单的神经网络。但是这种方法会失去对神经网络的深入理解。因此本案例中,老哥将纯手工实现神经网络所有的数学公式。

如果你能完整的从头到尾跟完本次教程,那么你已经对神经网络有了入门级的理解。老哥会尽可能详细的逐步讲解,那我们开始吧!

import tensorflow as tffrom matplotlib import pyplot as plt

首先导入tensorflow和matplotlib库完成公式搭建和绘图。

x_train = tf.cast(x_train, dtype=tf.float32)x_test = tf.cast(x_test, dtype=tf.float32)

转换x的数据类型,否则后面矩阵相乘时会因数据类型不一致报错。

train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(30)test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(30)

分别将测试集和训练集分批次(Batch),每一批次为32个数据。测试集有120个数据,所以测试集会被分为4批。这4批数据会分批次喂入神经网络结构。分Batch的好处是减少内存的损耗,增加迭代次数有助于实现参数的修正,提高收敛效果。Batch的选择可能影响最终的结果。

w1 = tf.Variable(tf.random.truncated_normal([4, 3], stddev=0.1, seed=1))b1 = tf.Variable(tf.random.truncated_normal([3], stddev=0.1, seed=1))

生成神经网络的参数,因为有4个输入特征,故输入层为4个输入节点;因为y为3分类,故输出层为3个神经元。用tf.Variable()标记参数可训练,只有标记的数据才会在梯度下降中反向传播。使用truncated_normal随机生成符合截断正态分布随机初始参数w和b。使用seed使每次生成的随机数相同(方便教学,使大家结果和老哥一致,可以不写seed)。打印生成的随机初始值w和b如下:

现在老哥已经搭建出了如下图所示的神经网络结构了。

lr = 0.05 train_loss_results = [] test_acc = [] epoch = 500 loss_all = 0

接下来初始化梯度循环所需的参数。设定学习率lr为0.05;构造空列表train_loss_results,记录每轮的loss损失函数值,为后续画loss曲线提供数据;test_acc同理;循环500轮;因为分了Batch,数据集被划分为4批,因此会生成4个loss,用loss_all记录这4批生成的4个loss的和。

for epoch in range(epoch):     for step, (x_train, y_train) in enumerate(train_db):         with tf.GradientTape() as tape:             y = tf.matmul(x_train, w1) + b1             y = tf.nn.softmax(y)            y_ = tf.one_hot(y_train, depth=3)             loss = tf.reduce_mean(tf.square(y_ - y))            loss_all += loss.numpy()         grads = tape.gradient(loss, [w1, b1])        w1 = w1 - lr * w1_grad    b = b - lr * b_grad        w1.assign_sub(lr * grads[0])        b1.assign_sub(lr * grads[1])    print("Epoch {}, loss: {}".format(epoch, loss_all/4))    train_loss_results.append(loss_all / 4)     loss_all = 0

接下来这段代码用来构造梯度下降,是参数自更新的核心。最外层是数据集级别的循环,每个epoch循环一次数据集,一共循环500轮;第二层是batch级别的循环 ,每个step循环一个batch,一共循环4个batch。循环的内部则是用with结构记录梯度信息,整个神经网络的计算过程图如下:

接下来重点解释神经网络公式的实现。

首先实现公式的前半部分,w和b的乘加运算。tf.matmul()函数可以实现两个矩阵相乘,生成两个矩阵的乘积。

为方便理解,我们将生成的y打印,可以看到我们生成了30行3列的y值,这就是根据上述公式计算出的结果:

接下来用tf.nn.softmax(y)函数使输出得y符合概率分布。运算结果如下所示,每一行的y值相加为1,体现了预测值中每个类别所占的比例。

将标准答案y_train转化为独热编码,方便计算loss和accuracy。

根据均方误差公式,计算标准答案y_train与预测答案y之间的差距,即为loss值。均方误差公式如下,先对每个差距平方,然后求和,最后除以总个数。在代码中,先用tf.square()函数求解y与y_的差的平方,然后用tf.reduce_mean()求解均值。

loss值计算如下:

现在我们得到了每一个预测值与标准值之间的均方差,接下来通过梯度下降的方式,找到使loss值最小的w和b参数。梯度下降公式如下。我们先利用tape.gradient()函数计算每一个tape中的loss对各个参数的梯度(导数)。然后用assign_sub()函数实现w和b参数的自减,从而实现参数的自更新:w1 = w1 - lr * w1_grad    b = b - lr * b_grad。

公式写完后,将将4个step的loss求平均记录在train_loss_results中,并将loss_all归零,为记录下一个epoch的loss做准备。

通过上述操作,我们已经纯手工写完了所有神经网络的计算公式。接下来,我们用测试集来测试该训练结果的准确度。

total_correct, total_number = 0, 0for x_test, y_test in test_db:    y = tf.matmul(x_test, w1) + b1    y = tf.nn.softmax(y)    pred = tf.argmax(y, axis=1)    pred = tf.cast(pred, dtype=y_test.dtype)    correct = tf.cast(tf.equal(pred, y_test), dtype=tf.int32)    correct = tf.reduce_sum(correct)    total_correct += int(correct)    total_number += x_test.shape[0]    acc = total_correct / total_number    test_acc.append(acc)    print("Test_acc:", acc)

total_correct为预测对的样本个数, total_number为测试的总样本数,将这两个变量都初始化为0。使用更新后的w,b参数对测试集进行预测。最开始两步的计算和softmax刚才已经解释过了。这样我们得到了预测结果y。tf.argmax()函数可以得到预测结果中得分最高的结果的索引值,而索引值等同于分类结果。预测的分类结果如下图所示:

将预测结果pred转换为y_test的数据类型。用tf.equal()函数判断预测值与标准答案是否一致,一致则输出True,不一致则为False。利用tf.cast()函数将布尔值转化为0,1的整数形式。因为分了batch,所以要将每一个batch的判断正确的数量相加,得到总的正确数量。则总的准确率等于total_correct / total_number。这样我们就可以得到预测准确率了。

至此,整个神经网络模型的代码就写完了。

plt.title('Loss Function Curve')  # 图片标题plt.xlabel('Epoch')  # x轴变量名称plt.ylabel('Loss')  # y轴变量名称plt.plot(train_loss_results, label="$Loss$")  # 逐点画出trian_loss_results值并连线,连线图标是Lossplt.legend()  # 画出曲线图标plt.show()  # 画出图像plt.title('Acc Curve')  # 图片标题plt.xlabel('Epoch')  # x轴变量名称plt.ylabel('Acc')  # y轴变量名称plt.plot(test_acc, label="$Accuracy$")  # 逐点画出test_acc值并连线,连线图标是Accuracyplt.legend()plt.show()

最后我们用折线图将损失函数和准确率绘制出来,进行可视化。如下所示,loss函数稳定减小,acc准确率稳步上升,最后达到了93.333%的准确率。

调整学习率和迭代次数,将学习率改为0.04,迭代次数增加到1000,改进后准确率达到了96.66%。

综上所述,本次对比了机器学习与深度学习计算的整个过程,可以看出深度学习的准确率相对更高,但是耗时较长。如果数据量更大,深度学习的效果会更好。本次测评到此结束,完整代码回复6月24日即可获得。

- END -

关注老哥,一起充电!

机房老哥

欢迎扫码关注!

机器学习和深度学习_算法测评 | 机器学习VS深度学习相关推荐

  1. 机器学习模型 知乎_算法有没有价值观?知乎内容推荐算法解析

    [IT168 技术]今年,我们已经听到了多家内容平台整改的消息,对于标题党.蹭热点等行为,用户早已经见怪不怪.同样是知识分享平台,知乎倒是躲过了每一次整改,肯定有人会说是幸运,也肯定有人会从理性的角度 ...

  2. 范数在机器学习中的作用_设计在机器学习中的作用

    范数在机器学习中的作用 Today, machine learning (ML) is a component of practically all new software products. Fo ...

  3. 机器学习模型管理平台_如何管理机器学习模型

    机器学习模型管理平台 Michael Berthold是KNIME的创始人兼首席执行官. 在当今快节奏的分析开发环境中,数据科学家通常承担的任务远不只是建立机器学习模型并将其部署到生产中. 现在,他们 ...

  4. 机器学习 大数据 数据挖掘_什么是机器学习? 来自数据的情报

    机器学习 大数据 数据挖掘 机器学习的定义 机器学习是人工智能的一个分支,其中包括用于自动根据数据创建模型的方法或算法. 与通过遵循明确的规则执行任务的系统不同,机器学习系统从经验中学习. 基于规则的 ...

  5. 证券投资深度学习_基于风险中性的深度学习选股策略

    今天我们为大家带来最新的研报内容,来自广发证券金工团队的<风险中性的深度学习选股策略>.下面让我们来一起学习吧!https://mp.weixin.qq.com/s?__biz=MzAxN ...

  6. 人工智能 java 坦克机器人系列: 强化学习_人工智能 Java 坦克机器人系列: 强化学习 | 学步园...

    本文中,我们将使用强化学习来实现一个机器人.使用强化学习能创建一个自适应的战斗机器人.这个机器人能在战斗中根据环境取得最好的策略,并尽力使战斗行为最佳.并在此过程中不断学习以完善自身不足. Roboc ...

  7. 多智能体强化学习_基于多智能体强化学习主宰星际争霸游戏

    大家好,今天我们来介绍基于多智能体强化学习主宰星际争霸游戏这篇论文 Grandmaster level in StarCraft II using multi-agent reinforcement ...

  8. 人工智能 java 坦克机器人系列: 强化学习_人工智能 Java 坦克机器人系列: 强化学习...

    人工智能 Java 坦克机器人系列: 强化学习 发表于:2007-05-24来源:作者:点击数: 本文中,我们将使用强化学习来实现一个机器人.使用强化学习能创建一个自适应的战斗机器人.这个机器人能在战 ...

  9. 机器学习自动化 要学习什么_从电视节目“先生”中学习自动化网络安全。 机器人'

    机器学习自动化 要学习什么 电视可以教给您有关IT / OT融合的知识 (Here's What Television Can Teach You About IT/OT Convergence) A ...

最新文章

  1. fork() || fork() || fork() 与 fork() fork() fork()
  2. String、StringBuffer、与StringBuilder的区别
  3. springboot整合spring Cache(redis)
  4. 查linux有哪些task_Java面试手册:Linux高频考点
  5. sklearn特征的提取(下)
  6. Eclipse常用的快捷方式
  7. 信息学奥赛C++语言:枪声问题
  8. .net mysql 工作流_一个适合于.NET Core的超轻量级工作流引擎:Workflow-Core
  9. Spring Cloud Config - RSA简介以及使用RSA加密配置文件
  10. vscode右键没有open in browser
  11. Qt 获取qrc文件列表
  12. flutter显示图标_如何自动调整Flutter中的图标大小
  13. java string通配符_java通配符
  14. 【Windows】实现微信双开或多开
  15. TPS65217DRSLR 电源管理IC 设计用于便携式设备
  16. 【2021-01-05】JS逆向之B站模拟登入(含极验点选)
  17. Python爬虫:让“蜘蛛”帮我们工作
  18. 大数据就业前景如何?马云曾经说过大数据是未来顶峰时代应验了
  19. Transformer8
  20. 基于Kinect Azure的多相机数据采集(二)

热门文章

  1. 2017.2.19 loli测试
  2. Java程序员晋升之路:“Java高级核心知识全面解析
  3. css贝塞尔曲线 多个点_贝塞尔曲线实践
  4. 两波形相位差的计算值_如何将您的计算机用作任意波形发生器
  5. Linux 工程师技术 系统服务管理进阶
  6. CSS学习笔记(四)CSS字体属性
  7. ikvm.net简介
  8. WPF之Manipulation
  9. VMWare 全屏后最小化死机
  10. TOP10十大GPS导航手机(有车一族必备手机)