头歌——人工智能(深度学习初体验)

文章目录

什么是神经网络

一提到"神经网络"这个名词,相信你脑海里可能会浮现类似这样的图片。

神经网络正是因为我们想要去模拟人类大脑的结构和信息的处理方式去实现人工智能而得此名。

神经元们在处理信息时会根据信息的种类分别进入兴奋与抑制的状态。当进入兴奋状态时,会将此信号输送给与之连接的神经元。当进入抑制状态时则什么都不做。

神经网络就是一组粗略模仿人类大脑,用于模式识别的算法。神经网络这个术语来源于这些系统架构设计背后的灵感,这些系统是用于模拟人类大脑自身神经网络的基本结构,以便计算机能够执行特定的任务。即将数据输入到神经网络中去,经过神经网络运算后希望得到我想要的输出。

也就是说神经网络中也有神经元,这些神经元也会与其他神经元相连接,这样就形成了神经网络,而且这种网络我们称之为全连接网络。如下图所示(方块表示神经元):

从图可以看出,神经网络由一层一层的神经元所构成的,并且不同的层有不同的名字。其中输入层表示用来接收数据输入的一组神经元。输出层表示用来输出的一组神经元。隐藏层表示介于输入层与输出层之间的一组神经元。

而神经元主要由两部分组成,一部分是线性计算部分,另一部分是激活部分。

每个神经元都有自己的参数 W 和 b,神经元会接收上一层神经元的输入即 x 。这样神经元就能根据自身的参数和上一层的输入计算出一个输出。然后经过激活函数激活。激活函数的作用是模拟人脑神经元的兴奋与抑制状态,并且加上非线性变换,使得神经网络的拟合能力更强。

现在一般用得最多的激活函数是 ReLU,ReLU 函数的公式如下:

可以看出如果使用 ReLU 函数进行激活,只要当 W*x+b 大于 0 那么激活值就会大于 0 。从另一个角度来看,可以认为当线性计算部分的值大于 0 时,神经元才会感兴趣(兴奋),否则就不感兴趣(抑制)。这也是为什么将神经元称之为神经元的原因。

当然,在构建神经网络时,每一层有多少个神经元,总共有多少层,神经元之间怎样连接等一系列问题都是我们自己来决定的。其实构建神经网络时很像我们小时候玩过的搭积木。

如果我们搭积木搭得很高就变成了高楼大厦,同样,如果我们神经网络的层数比较多,我们就成为这样的神经网络为深层神经网络。如果我们用深层神经网络来完成我们想要的功能,我们就叫它为深度学习。例如:构建了 10 层的神经网络来识别图像中的植物,这叫深度学习。构建了 21 层的神经网络来写诗这也叫深度学习。

如果你跟你的朋友、家人炫耀说:"你知道吗?我现在在做深度学习!"。那么在朋友眼中你可能是这样的。

而实际上你是这样的

答案

反向传播

前向传播

根据上一关的知识我们已经知道了神经网络就是搭积木,积木搭高了就是深度学习了。那么我们来看看神经网络是怎样工作的。

神经网络和其他机器学习算法一样,同样有训练和预测的过程。如果用一句话来概括的话就是预测过程为前向传播的过程,训练过程为重复前向传播加反向传播的过程。所以理解前向传播和反向传播至关重要,我们接下来先看看前向传播。

为了简便,假设有一个非常简单的神经网络,其中黄色方块表示输入层的数据,圆圈表示神经元,连线表示参数 W ,棕色小方块表示参数 b ,圆圈的左半部分表示线性计算部分的结果,右半部分表示使用 ReLU 函数激活后的结果。如下图所示:

前向传播就是根据现在已有的输入和参数从左往右在空白处填上值的过程。填值很简单(上一关已经介绍过),比如左上角的神经元的输入为 1 和 -1 ,与输入 1 的连线上的参数 W 为 1 ,与输入 -1 的连线上的参数 W 为 -2 ,参数 b 为 1 。所以左半部分的值为 11+(-1)(-2)+1 ,即 4 。右半部分的激活函数是 ReLU ,所以为 4 。

很显然,如果这些连线上的参数 W 和参数 b 确定下来了,那么一次前向传播过程就相当于根据输入产生了预测输出。

反向传播

神经网络的训练过程就是不断地寻找合适的 W 和 b 来让预测输出与真实标签之间差异最小的过程。那么我们可以将训练过程拆开来看,首先我们需要能够衡量预测输出和真实标签之间的差异,其次我们需要能够不断地优化 W 和 b 使得预测输出与真实标签之间地差异变小。

首先,想要衡量差异,我们可以将预测输出和真实标签输入到一个函数中,然后通过这个函数的计算来量化差异的大小。像这种函数我们称之为损失函数。损失函数的种类有很多,比如面对分类问题时,通常使用交叉熵损失、面对回归问题时通常使用均方误差等。总之可以看成是一个能够量化差异的黑盒子,而且量化出的差异值越小,代表我们的神经网络的预测输出越准确。

其次,我们需要找出 W 和 b 来让差异最小,这个时候我们会使用梯度下降算法来迭代更新 W 和 b 。梯度下降算法的思想是,让 W 和 b 朝着让差异值变小的大体方向来更新,而大体方向怎样获取,就需要计算 W 和 b 对于损失函数的偏导(梯度)。但由于计算 W 和 b 对于损失函数的偏导需要知道 W 和 b 对于神经元中线性计算部分的偏导和线性计算部分对于损失函数的偏导。所以就有了反向传播算法。

答案

动手实现CNN识别手写数字

使用 Keras 构建卷积神经网络

Keras 遵从了极简主义,提供了一些简单易用的接口,使得我们能够很快的构建出属于自己的卷积神经网络。

构建卷积神经网络的步骤如下:

1 . 实例化 Sequential 对象。

2 . 往 Sequential 对象中添加层(卷积层,池化层,全连接层...)。

实例化 Sequential 对象很简单,代码如下:

python 复制代码
from keras.models import Sequential
model = Sequential()

有了 Sequential 对象之后就可以 add 了, add 的对象是 Layer 对象, Layer 对象有很多种,例如 Conv2D (卷积层), MaxPooling2D (最大池化层), Flatten (扁平层), Dense (全连接层)等。如果 add 一层全连接层,代码如下:

python 复制代码
from keras.layers import Dense
model = Sequential()
'''
units=64表示这层有64个神经元
activation='relu'表示这层的激活函数是relu
'''
model.add(Dense(units=64, activation='relu')

想要 add 一层卷积层,代码如下:

python 复制代码
from keras.layers import Conv2D
model = Sequential()
'''
16表示该卷积层有16个卷积核
kernel_size=3表示卷积核的大小为3*3
activation='relu'表示卷积层的激活函数是relu
input_shape=[IMAGE_HEIGHT, IMAGE_WIDTH, 3]表示待卷积图像为32*32的3通道图像
'''
model.add(Conv2D(16, kernel_size=3, activation='relu', input_shape=[32, 32, 3]))

想要 add 一层最大池化层,代码如下:

python 复制代码
from keras.layers import Conv2D
model = Sequential()
'''
pool_size=2表示池化窗口的大小为2*2
'''
model.add(MaxPooling2D(pool_size=2))

想要 add 一层扁平层,代码如下:

python 复制代码
from keras.layers import Conv2D
model = Sequential()
'''
卷积或者池化后想要接上全连接层之前需要接入扁平层
'''
model.add(Flatten())

所以,如果想要构建如下结构的卷积神经网络,可以编写如下代码:

python 复制代码
# 1.有32个5*5的神经元的卷积层,激活函数为relu,输入的数据为宽28高28的灰度图像
# 2.有64个5*5的神经元的卷积层,激活函数为relu
# 3.最大池化层,池化核大小为2*2
# 4.扁平
# 5.有128个神经元的全连接层,激活函数为relu
# 6.有10个神经元的全连接层,激活函数为softmax
model = Sequential()
model.add(Conv2D(32, (5, 5), activation='relu', input_shape=[28, 28, 1]))
model.add(Conv2D(64, (5, 5), activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(10, activation='softmax'))

当构建好模型后就可以使用compile函数编译模型,编译模型的作用是来指定损失函数、参数的更新方法等信息。

python 复制代码
'''
loss='categorical_crossentropy'表示使用交叉熵损失函数
optimizer=keras.optimizers.SGD(lr=0.0001)表示训练时使用mini-batch梯度下降方法来更新参数,学习率为0.0001
metrics=['accu\fracy']表示训练时模型主要考量正确率
'''
model.compile(loss='categorical_crossentropy',    optimizer=keras.optimizers.SGD(lr=0.0001),
              metrics=['accu\fracy'])

编译完模型之后,就可以使用 Keras 提供的 fit 函数来进行模型的训练了。 fit 函数的使用也十分简单,只需传入训练集的图像、训练集图像所对应的 onehot 编码、训练的迭代次数以及 batch 数量即可。

python 复制代码
'''
images表示的是训练集图像
onehot表示的是训练集图像所对应的onehot编码
epochs=5表示的是迭代5次
batch=32表示batch的数量是32
verbose=0表示在训练过程中不打印损失值、正确率等信息
'''
model.fit(images, onehot, epochs=5, batch_size=32, verbose=0)

训练好模型之后,我们就可以使用训练好的模型进行预测了。代码如下:

python 复制代码
'''
images表示待预测图像
batch_size表示batch的数量
'''
result = model.predict(images, batch_size=32)

代码

python 复制代码
from keras.models import Sequential
from keras.layers import Conv2D, MaxPool2D, Flatten, Dense
import numpy as np
# 设置随机种子
np.random.seed(1447)

def build_model():
    '''
    在Begin-End段中构建出如下结构的卷积神经网络
    1.64个5*5的卷积核组成的卷积层,激活函数为relu
...    model.add(MaxPool2D(pool_size=(2, 2)))
    model.add(Flatten())
    model.add(Dense(128, activation='relu'))
    model.add(Dense(10, activation='softmax'))

    #********* End *********#
    return model

动手实现RNN分析影评情感

什么是循环神经网络

上一关中提到的 CNN 通常用于计算机视觉领域,而现在准备介绍的循环神经网络( RNN )有什么样的神通呢?其实 RNN 通常作用于语言处理,目前最为常见的自然语言处理就是通过 RNN 或者 RNN 的变种实现的。或许你会疑问既然 CNN 已经如此强大了为什么对语言的处理不延续使用 CNN 模型呢?由于语言的数据量十分庞大使用 CNN 进行训练需要的参数存在几何倍增加,同时我们没说一句话都是存在一定的时序的,时序的不同表达的意思也不同。而且 CNN 的层与层之间是独立的,处理非时许的问题时有强大的解决能力,但是当我们遇到一个句子时这种解决能力就不行了。

比如说这个句子"我喜欢阿伦艾弗森,我平常爱和朋友打____。"当我们把这个句子输入到 CNN 中可能会得到其他结果,比如和朋友打架、和朋友打年糕等等。这些结果都忽略了之前文字带来的影响,但是输入到 RNN 中就不一样了, RNN 会"记住"之前的内容,他记下了"阿伦艾弗森"发现他是一个篮球巨星,因此 RNN 会推断输出和朋友打篮球。

那么 RNN 是如何保留这种"记忆"的呢?请观察下方左侧图, RNN 神经网络结构图, x 为输入的数据,同时右侧的圆圈也是 RNN 的输入,这部分输入的就是之前的记忆,由这两种输入共同决定最后的输出。

对于左侧图不是特别容易理解,我们将其展开进行进一步解释。看右侧图位于中间的神经元,该神经元的输入源自两个方面,一个是下方的 x ,x 代表的是当前时刻输入的外部数据也就是上文举例的句子中的汉字或者词语,另一个来自上一个神经元传递的 s,s 代表的是内部数据也就是上一个神经元经过计算后保留的记忆。将这两种输入共同作用在当前神经元上,经过计算后输出 O。这就是为什么喜欢使用 RNN 处理语言问题的主要原因。

对于影评情感分析问题来说,我们可以使用 RNN 来提取特征,然后再接上全连接层来进行情感分类。

使用 Keras 构建循环神经网络

在 Keras 中想要添加 RNN 的结构非常简单,代码如下:

python 复制代码
from keras.layers import Embedding, SimpleRNN, Dense
from keras import Sequential
model = Sequential()
# 对输入的影评进行word embedding,一般对于自然语言处理问题需要进行word embedding
model.add(Embedding(1000, 64))
# 构建一层有40个神经元的RNN层
model.add(SimpleRNN(40))
# 将RNN层的输出接到只有一个神经元全连接层
model.add(Dense(1, activation='sigmoid'))

代码

python 复制代码
在这里插入代码片

动手实现猫狗大战

数据简介

Dogs vs. Cats 比赛的训练数据集总共有 25000 张猫或者狗的大小不一的图片,该比赛的任务是训练你的模型,让模型来预测测试集中的图片是猫还是狗(狗= 1 ,猫= 0 )。

也就是说如果你的模型看到以下两张图片后,应该预测出图 1 的标签是 1 (狗),图 2 的标签是 0 (猫)。

数据的读取与预处理

数据的读取与预处理主要分为以下 3 个步骤:

1 . 读取图片;

2 . 图像归一化;

3 . onehot编码。

读取图片

读取图片可以使用 OpenCV( OpenCV 是一个开源的计算机视觉库,许多功能都有 python 接口)的 API 来实现。

想要在 python 中使用 opencv ,首先需要导入 cv2 。

import cv2

导入了 cv2 之后,可以使用 imread 函数来读取图片,其中 filename 是想要读取的图片路径。

img = cv2.imread(filename)

由于训练集中的图片大小不一,所以需要将读取到的图片强制缩放到固定的宽和高。所以需要使用 resize 函数,其中 (32, 32) 的意思是将源图像缩放成宽和高都是 32 个像素的图像。

resized_image = cv2.resize(img, (32, 32))

图像归一化

由于卷积神经网络中的参数是通过梯度下降的方式训练出来的,而图像中的每个像素都可以看成是一个特征,因此对图像中的像素值进行归一化能够提高卷积神经网络在梯度下降时的速度,减少损失的震荡程度。想要对图像进行归一化非常简单,因为 opencv 读取后的图像是使用 numpy 的 ndarray 这一数据结构来表示的,所以归一化只需要使用如下代码即可:

img = img / 255.0

onehot 编码

在遍历 train_data 目录中的图片时可以根据图片的名字来确定图片所对应的真实标签( 0 (猫),1 (狗))。但是在使用神经网络训练前,需要对标签进行 onehot 编码处理。

onehot 编码是分类变量作为二进制向量的表示。这首先要求将分类值映射到整数值。然后,每个整数值被表示为二进制向量,除了整数的索引之外,它都是零值,它被标记为 1。

在本次实训中,onehot 编码可以看成把左表转换成右表:

代码

python 复制代码
from keras.layers import Dense, Activation, Flatten, Dropout, Conv2D, MaxPooling2D
import keras
import os
import numpy as np
import cv2

# 设置随机种子
np.random.seed(1447)

IMAGE_HEIGHT = 128
IMAGE_WIDTH = 128


def get_train_data(data_path):
    '''
    读取并处理数据
    :return:处理好的图像和对应的one-hot编码
    '''
    images = []
    onehot = np.zeros((500, 2))
    #********* Begin *********#
    for i, img_name in enumerate(os.listdir(data_path)):
        if 'cat' in img_name:
            onehot[i, 0] = 1
        else:
            onehot[i, 1] = 1
        img = cv2.imread(os.path.join(data_path, img_name))
        img = cv2.resize(img, (IMAGE_HEIGHT, IMAGE_WIDTH))
        images.append(np.array(img, "float32") / 255.0)

    #********* End *********#
    return np.array(images), onehot

def build_model():
    '''
    构建模型
    :return:构建好的模型
    '''
    model = keras.Sequential()
    #********* Begin *********#
    model.add(Conv2D(32, kernel_size=3, activation='relu', input_shape=[IMAGE_HEIGHT, IMAGE_WIDTH, 3]))
    model.add(MaxPooling2D(pool_size=2))
    model.add(Conv2D(32, kernel_size=3, activation='relu'))
    model.add(MaxPooling2D(pool_size=2))
    model.add(Flatten())
    model.add(Dense(96, activation='relu'))
    model.add(Dense(2, activation='softmax'))
    #********* End *********#
    return model


def fit_and_predict(model, train_images, onehot, test_images):
    '''
    训练模型,并对测试图像进行预测
    :param model: 训练好的模型
    :param train_images: 训练集图像
    :param onehot: 训练集的one-hot编码
    :param test_images: 测试集图像
    :return: 预测结果
    '''
    #********* Begin *********#
    # 编译模型
    model.compile(loss='categorical_crossentropy', optimizer=keras.optimizers.Adam(lr=0.0001), metrics=['accuracy'])
    #********* End *********#
    model.fit(train_images, onehot, epochs=20, batch_size=32, verbose=0)
    result = model.predict(test_images, batch_size=10)
    predict_idx = np.argmax(result, axis=1)
    return predict_idx
相关推荐
武子康1 小时前
WebRTC 已经双向,语音 Agent 为什么还会抢话?
人工智能·llm·agent
甲维斯1 小时前
翻车了!GPT5.6接手Opus4.8的项目之后!
人工智能
硅谷秋水1 小时前
WAM-Nav:用于统一视觉导航的非对称潜世界动作建模
深度学习·机器学习·计算机视觉·语言模型·机器人
FIT2CLOUD飞致云1 小时前
修复安全漏洞及相关问题,MaxKB开源企业级智能体平台v2.10.5 LTS版本发布
人工智能·ai·开源·智能体·maxkb
共绩算力1 小时前
不做重资产,也能做 GPU 云
大数据·人工智能·共绩算力
数据库安全1 小时前
美创数据安全多智体获评「AI Agent标杆产品」:AI重塑数据安全运营闭环
大数据·人工智能
珐恩AI-人工智能1 小时前
2026AI检索变局:为什么传统营销失效?GEO生成式优化落地逻辑与避坑指南
大数据·人工智能·geo优化
迷迭香yy2 小时前
Python实战:涨停板“假封板”识别系统的工程实现
开发语言·人工智能·python
龍德明宇2 小时前
如何理解大语言模型的负主体性-龍德明宇
人工智能·算法·大语言模型llm·负主体性·ai存在论