简易机器学习笔记(四)初识卷积神经网络

news2025/1/10 11:43:59

前言

第一次写卷积神经网络,也是照着paddlepaddle的官方文档抄,这里简单讲解一下心得。

首先我们要知道之前写的那些东西都是什么,之前写的我们称之为简单神经网络,也就是简单一层连接输出和输出,通过前向计算和逆向传播,以及梯度下降的方式让结果慢慢滑向我们期望的终点。

这种方法固然好,但是它的限制也是显而易见的:

  1. 需要我们提供损失函数
  2. 需要对数据进行相当大量的计算
  3. 只能处理线性函数,而对非线性的函数处理能力有限
  4. 只能处理特定问题,扩展性很差

ok为了解决以上的这些问题,人们又研发出了全连接神经网络和卷积神经网络,当然了全连接神经网络作为老黄历,本身在paddle教程中相当于是一个对于卷积神经网络更好的理解的渐进式的介绍,这里也简单聊聊。

我们说的简单神经网络就是直接计算结果,由之前的那种方式去计算线性的方程,然后通过梯度下降的方式让数值自动调参。

那什么是全连接神经模型和卷积神经模型呢?可以参考下面这两个视频,可以让你很简单的对这两个概念有一个印象:

全连接神经模型:【五分钟机器学习】神经网络:一个小人国投票的故事

卷积神经网络: 【五分钟机器学习】什么是卷积神经网络?

全连接模型

简单的来说,全连接神经模型就像是人大代表制度,由底层的神经进行学习并向上一层层传播,比如从群众->村级->县级->市级->省级->国级 层层递进,交由全国人大最终得到议案,也就是我们的结果。

在这里插入图片描述
我们一般管输入的学习数据叫 特征(Feature),中间层层递进的信息叫隐式输出(Hidden Outcome),最终由最后一层输出层得到模型输出(Model Outcome)

实际的使用中,随着中间隐式层的不断传递,中间需要慢慢调整的层间权重、模型偏见和激活函数会越来越多,而且每层这些参数造成的影响也会越来越难以估计,实际的工作情况中,我们要做的是通过调整W和B,使得损失函数Loss最小。
在这里插入图片描述
但是问题也随之而来了,这样的模型实际上优缺点也很好看出来
全连接模型:
优点:
1.模型性能出色
2.模型中可用参数多
3.激活函数任意变化,理论上可以兼容任意分布

缺点:
1.参数多意味着训练难,训练慢。
这里说的训练难不是指的代码难写,而是指模型容易过拟合或者欠拟合。而这个缺点是非常致命的。
训练慢指的是每一个村民都需要向每一个村长汇报,这个效率想必不言而喻。

为了解决全连接神经网络的缺点,又同时继承它的优点,于是就有了卷积神经网络。

卷积神经网络CNN

什么是卷积神经网络呢?就是在原有的全连接神经网络中添加两个规则,分别是:

  1. 权力划分:
    在每一层中成立特定部门,接受特定信息。特定的任务只向特定的管理者汇报,这样就可以提高效率。

在这里插入图片描述

  1. 规则共享:
    在每一层中信息传递的方式需要共享。

在这里插入图片描述

卷积的计算就是类似像素的抽稀算法计算,如图大概是:
在这里插入图片描述
池化则也是一个局部取样的方式,大概如图:

在这里插入图片描述

实际代码

在实际开发中,其实现有的框架已经做了绝大多数事了,现在只需要简单改写一下模型即可,我这里直接放完整代码,可以看注释,写的比较详尽了

实际上唯一改动的地方是模型中关于添加了新的卷积层、池化层的定义,以及前向计算的流程。这里并不需要懂太多原理,只需要知道上面视频和图文对卷积神经的大致定义,就能明白为什么代码是这么写的了。其中具体的细节和举证则是选做内容,想知道详情可以深入学习,如果不需要,则随便玩玩即可。

#当然了,简单神经网络没有办法解决我们目前的问题,所以为此要通过别的算法来解决,这个算法就是卷积神经网络

#数据处理函数

#数据处理部分之前的代码,保持不变
import os
import random
import paddle
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

import gzip
import json

# 定义数据集读取器
def load_data(mode='train'):

    # 加载数据
    datafile = 'mnist.json.gz'
    print('loading mnist dataset from {} ......'.format(datafile))
    data = json.load(gzip.open(datafile))
    print('mnist dataset load done')

    # 读取到的数据区分训练集,验证集,测试集
    train_set, val_set, eval_set = data

    # 数据集相关参数,图片高度IMG_ROWS, 图片宽度IMG_COLS
    IMG_ROWS = 28
    IMG_COLS = 28

    if mode == 'train':
        # 获得训练数据集
        imgs, labels = train_set[0], train_set[1]
    elif mode == 'valid':
        # 获得验证数据集
        imgs, labels = val_set[0], val_set[1]
    elif mode == 'eval':
        # 获得测试数据集
        imgs, labels = eval_set[0], eval_set[1]
    else:
        raise Exception("mode can only be one of ['train', 'valid', 'eval']")

    #校验数据
    imgs_length = len(imgs)
    assert len(imgs) == len(labels), \
          "length of train_imgs({}) should be the same as train_labels({})".format(
                  len(imgs), len(labels))

    # 定义数据集每个数据的序号, 根据序号读取数据
    index_list = list(range(imgs_length))
    # 读入数据时用到的batchsize
    BATCHSIZE = 100
    

    
    # 定义数据生成器
    def data_generator():
        if mode == 'train':
            random.shuffle(index_list)
        imgs_list = []
        labels_list = []
        for i in index_list:
            img = np.array(imgs[i]).astype('float32')
            label = np.array(labels[i]).astype('float32')
            # 在使用卷积神经网络结构时,uncomment 下面两行代码
            img = np.reshape(imgs[i], [1, IMG_ROWS, IMG_COLS]).astype('float32')
            label = np.reshape(labels[i], [1]).astype('float32')
            
            imgs_list.append(img) 
            labels_list.append(label)
            if len(imgs_list) == BATCHSIZE:
                yield np.array(imgs_list), np.array(labels_list)
                imgs_list = []
                labels_list = []

        # 如果剩余数据的数目小于BATCHSIZE,
        # 则剩余数据一起构成一个大小为len(imgs_list)的mini-batch
        if len(imgs_list) > 0:
            yield np.array(imgs_list), np.array(labels_list)

    return data_generator


#输入层:将数据输入给神经网络。在该任务中,输入层的尺度为28×28的像素值。
#隐含层:增加网络深度和复杂度,隐含层的节点数是可以调整的,节点数越多,神经网络表示能力越强,参数量也会增加。
# 在该任务中,中间的两个隐含层为10×10的结构,通常隐含层会比输入层的尺寸小,以便对关键信息做抽象,激活函数使用常见的Sigmoid函数。

# 输出层:输出网络计算结果,输出层的节点数是固定的。如果是回归问题,节点数量为需要回归的数字数量。
# 如果是分类问题,则是分类标签的数量。在该任务中,模型的输出是回归一个数字,输出层的尺寸为1。

# 隐含层引入非线性激活函数Sigmoid是为了增加神经网络的非线性能力。


# 针对手写数字识别的任务,网络层的设计如下:

# 输入层的尺度为28×28,但批次计算的时候会统一加1个维度(大小为batch size)。
# 中间的两个隐含层为10×10的结构,激活函数使用常见的Sigmoid函数。
# 即:
# def sigmoid(x):
#     # 直接返回sigmoid函数
#     return 1. / (1. + np.exp(-x))
# 与房价预测模型一样,模型的输出是回归一个数字,输出层的尺寸设置成1。

import paddle.nn.functional as F
from paddle.nn import Linear
from paddle.nn import Conv2D, MaxPool2D, Linear
class MNIST(paddle.nn.Layer):
    def __init__(self):
        super(MNIST,self).__init__()
        #定义卷积层,输出特征通道out_channels设置为 20,卷积核大小kernel_size为5,卷积步长stride=1,padding=2
        self.conv1 = Conv2D(in_channels=1,out_channels=20,kernel_size=5,stride=1,padding=2)
        #定义池化层,池化核大小为 kernel_size为2,池化步长为2
        self.max_pool1=MaxPool2D(kernel_size=2,stride=2)
        # 定义卷积层,输出特征通道out_channels设置为20,卷积核的大小kernel_size为5,卷积步长stride=1,padding=2
        self.conv2 = Conv2D(in_channels=20, out_channels=20, kernel_size=5, stride=1, padding=2)
         # 定义池化层,池化核的大小kernel_size为2,池化步长为2
        self.max_pool2 = MaxPool2D(kernel_size=2, stride=2)

        #定义一层全连接层,输出的维度是1
        self.fc = Linear(in_features=980,out_features=1)
    #定义网络的前向计算,隐含层的激活函数为sigmoid,输出层不使用激活函数
        
    # 定义网络前向计算过程,卷积后紧接着使用池化层,最后使用全连接层计算最终输出
    # 卷积层激活函数使用Relu,全连接层不使用激活函数
    def forward(self,inputs):
       # inputs = paddle.reshape(inputs, [inputs.shape[0], 784])
        x = self.conv1(inputs)
        x = F.relu(x)
        x = self.max_pool1(x)
        x = self.conv2(x)
        x = F.relu(x)
        x = self.max_pool2(x)
        x = paddle.reshape(x, [x.shape[0], -1])
        x = self.fc(x)
        return x
    
#这样一个卷积神经网络就定义完毕了,接下来我们开始写训练函数,训练函数和之前保持一致
    
#网络结构部分之后的代码,保持不变
def train(model):
    model.train()
    #调用加载数据的函数,获得MNIST训练数据集
    train_loader = load_data('train')
    # 使用SGD优化器,learning_rate设置为0.01
    opt = paddle.optimizer.SGD(learning_rate=0.01, parameters=model.parameters())
    # 训练5轮
    EPOCH_NUM = 10
    # MNIST图像高和宽
    IMG_ROWS, IMG_COLS = 28, 28
    loss_list = []
    for epoch_id in range(EPOCH_NUM):
        for batch_id, data in enumerate(train_loader()):
            #准备数据
            images, labels = data
            images = paddle.to_tensor(images)
            labels = paddle.to_tensor(labels)
            
            #前向计算的过程
            predicts = model(images)
            
            #计算损失,取一个批次样本损失的平均值
            loss = F.square_error_cost(predicts, labels)
            avg_loss = paddle.mean(loss)

            #每训练200批次的数据,打印下当前Loss的情况
            if batch_id % 200 == 0:
                loss = avg_loss.numpy()
                loss_list.append(loss)
                print("epoch: {}, batch: {}, loss is: {}".format(epoch_id, batch_id, loss))
            
            #后向传播,更新参数的过程
            avg_loss.backward()
            # 最小化loss,更新参数
            opt.step()
            # 清除梯度
            opt.clear_grad()

    #保存模型参数
    paddle.save(model.state_dict(), 'mnist.pdparams')
    return loss_list


model = MNIST()
loss_list = train(model)

def plot(loss_list):
    plt.figure(figsize=(10,5))
    
    freqs = [i for i in range(len(loss_list))]
    # 绘制训练损失变化曲线
    plt.plot(freqs, loss_list, color='#e4007f', label="Train loss")
    
    # 绘制坐标轴和图例
    plt.ylabel("loss", fontsize='large')
    plt.xlabel("freq", fontsize='large')
    plt.legend(loc='upper right', fontsize='x-large')
    
    plt.show()
plot(loss_list)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1362146.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

百度地图打点性能优化(海量点、mapv)

文章目录 百度地图打点性能优化(海量点、mapv)原因优化方法数据获取方面页面加载方面 参考资料 百度地图打点性能优化(海量点、mapv) 原因 在百度地图api中,默认的点是下图的红点 而这种点位比较多的时候&#xff0c…

【AI视野·今日Sound 声学论文速览 第三十八期】Mon, 1 Jan 2024

AI视野今日CS.Sound 声学论文速览 Mon, 1 Jan 2024 Totally 5 papers 👉上期速览✈更多精彩请移步主页 Daily Sound Papers The Arrow of Time in Music -- Revisiting the Temporal Structure of Music with Distinguishability and Unique Orientability as the …

可变参数应用(C++并发编程中的joining_thread代码)

代码&#xff1a; #include "X:\Work\Share\CCode\CPlatform\Base\global_c_all.h" using namespace lf; using namespace std;class joining_thread {std::thread t; public:joining_thread() noexcept default;template<typename Callable, typename ... Args…

Python基础教程——90行Python代码让微信地球转起来!!(完整版,附源码)

今天我们来一个好玩儿的东西&#xff0c;使用90行Python代码就可以让【微信第地球】转起来&#xff0c;太有意思啦&#xff01; 1.微信地球 手机重启后打开微信的一瞬间&#xff0c;会看到一幅有名的图片&#xff0c;上面站着一个张小龙。 你可曾想过这样一个问题&#xff0c…

【QT】QStandardItemModel类的应用介绍

目录 1 概述 2 常用方法 3 QStandardItemModel的使用 3.1 界面设计与主窗口类定义 3.2 系统初始化 3.3 从文本文件导入数据 3.4 数据修改 3.5 单元格格式设置 3.6 数据另存为文件 1 概述 QStandardItemModel是标准的以项数据&#xff08;itemdata&#xff09;为基础的…

BMS电池管理系统带充放电控制过流过压保护

2.4G无线采集BMS开发板&#xff08;主从一体&#xff09; 全新升级 &#xff08;赠送上位机源码TTL 上位机&#xff0c;可以改成自己想要的界面&#xff09; 12串电池TTL上位机 CAN通信上位机源码有偿开源&#xff0c;供项目二次开发。 增加STM32平台 USB转TTL通信 CAN通信 增加…

Mac启动时候出现禁止符号

Mac启动时候出现禁止符号 启动时候出现禁止符号,意味着 选定的启动磁盘 包含 Mac 操作系统&#xff0c;但它不是 您的 Mac 可以使用的 macOS 。您应该在这个磁盘上 重新安装 macOS 。 可以尝试以下苹果提供的方法&#xff1a; Mac启动时候出现禁止符号 不要轻易抹除磁盘&am…

云原生学习系列之基础环境准备(单节点安装kubernetes)

一、环境要求 操作系统CentOS 7.x-86_x64 硬件配置&#xff1a;内存2GB或2G&#xff0c;CPU 2核或CPU 2核&#xff0c;需要在虚拟机中提前设置好&#xff0c;不然后续会报错 二、系统初始化 1、设置主机名 # 在master节点执行 hostnamectl set-hostname master01 2、配置主…

CRM如何精确控制RT设备和与UMD通信笔记

1 CRM工作职责 监控link req是否得到schedule监控link上各个device的req是否ready监控SOF或EOF的trigger信号&#xff0c;决定各个设备配置哪个req 2 CRM如何精确控制RT设备 分两步&#xff0c;一是crm知道某帧req的link dev准备好了&#xff0c;可以做apply setting。 二是…

解决vue3中watch 监听不到旧值的问题,亲测有效!

问题描述 这个问题是我在公司vue3项目的时候发现的一个问题&#xff0c;watch 在监听对象/数组变量的变化时&#xff0c;发现对象的数据变化时 旧数据 获取到的和新数据是一样的 类似于下面这样 const objref({a:我是原来的值,b:6, })obj.a改变值watch(obj,(nel,old)>{ c…

RTT打印时间戳

官方的RTT VIEWER没有打印接收时间戳的功能&#xff0c;经过查找后发现可以有以下三种打印时间戳的方法。 第三方的RTT上位机ExtraPutty自己打印 第三方的RTT上位机 码云上有一个RTT_T2的仓库&#xff0c;基于python qt包写的画面&#xff0c;通过pylink来jlink通信。 优点…

docker - 常用容器部署命令大全(MySQL、Redis、RabbitMQ、ES、Kibana、Nacos、Sentinel)

目录 一、常用容器运行指令 MySQL Redis RabbitMQ ElasticSearch & kibana Nacos Sentinel 一、常用容器运行指令 MySQL docker run -d --name mysql -p 3306:3306 -e TZAsia/Shanghai -e MYSQL_ROOT_PASSWORD1111 mysql:5.7 -e TZAsia/Shanghai&#xff1a;指定…

商智C店H5性能优化实战

前言 商智C店&#xff0c;是依托移动低码能力搭建的一个应用&#xff0c;产品面向B端商家。随着应用体量持续增大&#xff0c;考虑产品定位及用户体验&#xff0c;我们针对性能较差页面做了一次优化&#xff0c;并取得了不错的效果&#xff0c;用户体验值&#xff08;UEI&…

“智慧”千里眼助力水泵站

泵站是为水提供势能和压能&#xff0c;解决无自流条件下的排灌、供水和水资源调配问题的唯一动力来源&#xff0c;在工农业用水、防洪、排涝和抗旱减灾等方面发挥着重要作用。一旦出现异常&#xff0c;对经济生产将造成难以估量的损失&#xff0c;给水利安全管理造成负担。因此…

VMware Tools 启动脚本未能在虚拟机中成功运行。如果您在此虚拟机中配置了自定义启动脚本,请确保该脚本没有错误。您也可以提交支持请求,报告此问题。

问题描述&#xff1a;今天打开centos7虚拟机就是直接打不开了报了下面的错误&#xff0c;也没有动任何东西&#xff0c;点确定后&#xff0c;也是依然没有反应 问题原因&#xff1a;可能是虚拟机中的内存满了&#xff0c;需要清理内存 解决方法如下 首先cmd打开终端敲入如下命…

【linux笔记】top、ps

【linux笔记】top命令 top&#xff08;Table of process&#xff09;是动态变化的。而ps是静态的。 PID — 进程id USER — 进程所有者 PR — 进程优先级 NI — nice值。负值表示高优先级&#xff0c;正值表示低优先级 VIRT — 进程使用的虚拟内存总量&#xff0c;单位kb。VI…

软件测试|深入学习 Docker Logs

简介 Docker 是一种流行的容器化技术&#xff0c;它能够帮助用户将应用程序及其依赖项打包成一个可移植的容器。Docker logs 是 Docker 提供的用于管理容器日志的命令&#xff0c;本文将深入学习 Docker logs 的使用和管理&#xff0c;帮助用户更好地监测和解决容器问题。 Do…

ArkTS - 网络请求

一、Axios请求 应用通过HTTP发起一个数据请求&#xff0c;支持常见的GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT方法。 前端开发肯定都使用过一个叫axios的第三方库&#xff0c;它是是一个基于 promise 的网络请求库&#xff0c;可以用于浏览器和 node.js&…

网络实训模拟考察题目和答案(华为eNSP综合实验考试)

拓扑中四个交换机五个路由器&#xff0c;共九个设备 答案是对应的九个脚本&#xff08;从设备命名到保存&#xff09; 全部复制粘贴后&#xff0c;从PC1、PC2都是能Ping通服务器的&#xff08;保及格&#xff09;&#xff0c;其他要求没检查 题目 VLAN信息 设备名称端口链路…

labview 与三菱FX 小型PLC通信(OPC)

NI OPC服务器与三菱FX3U PLC通讯方法 一、新建通道名称为&#xff1a;MIT 二、选择三菱FX系列 三、确认端口号相关的参数&#xff08;COM端&#xff1a;7.波特率&#xff1a;9600&#xff0c;数据位&#xff1a;7&#xff0c;校验&#xff1a;奇校验&#xff0c;停止位&#xf…