国科大模式识别导论作业3:神经网络

news2024/11/24 6:10:06

目录

  • 题目
  • 代码
    • data.py
    • utils.py
    • network.py
    • main.py
    • 结果

整理一下近期作业中的编程题,仅供交流学习

题目

本题使用的数据如下:
第一类 10 个样本(三维空间):

[ 1.58, 2.32, -5.8], [ 0.67, 1.58, -4.78], [ 1.04, 1.01, -3.63], 
[-1.49, 2.18, -3.39], [-0.41, 1.21, -4.73], [1.39, 3.16, 2.87],
[ 1.20, 1.40, -1.89], [-0.92, 1.44, -3,22], [ 0.45, 1.33, -4.38],
[-0.76, 0.84, -1.96]

第二类 10 个样本(三维空间):

[ 0.21, 0.03, -2.21], [ 0.37, 0.28, -1.8], [ 0.18, 1.22, 0.16], 
[-0.24, 0.93, -1.01], [-1.18, 0.39, -0.39], [0.74, 0.96, -1.16],
[-0.38, 1.94, -0.48], [0.02, 0.72, -0.17], [ 0.44, 1.31, -0.14],
[ 0.46, 1.49, 0.68]

第三类 10 个样本(三维空间):

[-1.54, 1.17, 0.64], [5.41, 3.45, -1.33], [ 1.55, 0.99, 2.69], 
[1.86, 3.19, 1.51], [1.68, 1.79, -0.87], [3.51, -0.22, -1.39],
[1.40, -0.44, -0.92], [0.44, 0.83, 1.97], [ 0.25, 0.68, -0.99],
[ 0.66, -0.45, 0.08]
  1. 请编写两个通用的三层前向神经网络反向传播算法程序,一个采用批量方式更新权
    重,另一个采用单样本方式更新权重。其中,隐含层结点的激励函数采用双曲正切
    函数,输出层的激励函数采用 sigmoid 函数。目标函数采用平方误差准则函数。
  2. 请利用上面的数据验证你写的程序,分析如下几点:
    (a) 隐含层不同结点数目对训练精度的影响;
    (b) 观察不同的梯度更新步长对训练的影响,并给出一些描述或解释;
    (c) 在网络结构固定的情况下,绘制出目标函数值随着迭代步数增加的变化曲线

代码

以下文件在同一目录下

data.py

# 存储处理好的数据

import numpy as np
from numpy import ones, zeros_like

# 每类取7个作为训练数据,3个作为测试数据
x1 = np.array([[1.58, 2.32, -5.8], [0.67, 1.58, -4.78], [1.04, 1.01, -3.63], [-1.49, 2.18, -3.39], [-0.41, 1.21, -4.73],
               [1.39, 3.16, 2.87], [1.20, 1.40, -1.89], [-0.92, 1.44, -3.22], [0.45, 1.33, -4.38],
               [-0.76, 0.84, -1.96]], dtype=float).reshape(-1, 3)

y1 = np.zeros_like(x1)
y1[:, 0] = ones([len(y1)], dtype=float)
x1 = np.hstack((x1, y1))

ext = np.ones(len(x1))
ext = ext.reshape(10, -1)
x1 = np.hstack((ext, x1))

x2 = np.array([[0.21, 0.03, -2.21], [0.37, 0.28, -1.8], [0.18, 1.22, 0.16], [-0.24, 0.93, -1.01], [-1.18, 0.39, -0.39],
               [0.74, 0.96, -1.16], [-0.38, 1.94, -0.48], [0.02, 0.72, -0.17], [0.44, 1.31, -0.14],
               [0.46, 1.49, 0.68]]).reshape(-1, 3)

y2 = zeros_like(x2)
y2[:, 1] = ones([len(y2)], dtype=float)
x2 = np.hstack((ext, x2, y2))

x3 = np.array([[-1.54, 1.17, 0.64], [5.41, 3.45, -1.33], [1.55, 0.99, 2.69],
                   [1.86, 3.19, 1.51], [1.68, 1.79, -0.87], [3.51, -0.22, -1.39],
                   [1.40, -0.44, -0.92], [0.44, 0.83, 1.97], [0.25, 0.68, -0.99],
                   [0.66, -0.45, 0.08]]).reshape(-1, 3)

y3 = zeros_like(x3)
y3[:, 2] = ones([len(y3)], dtype=float)
x3 = np.hstack((ext, x3, y3))

train_data = np.vstack((x1[:7], x2[:7], x3[:7]))
test_data = np.vstack((x1[7:], x2[7:], x3[7:]))

utils.py

# 记录需要用到的公式

from numpy import exp, ones_like
import math


# 双曲正切函数
def tan_h(x):
    return math.tanh(x)


def diff_tang_h(x):
    return 1.0 / (1 + pow(x, 2))


# sigmoid
def sigmoid(x):
    return 1.0 / (1 + exp(-x))


# sigmoid 求导
def diff_sigmoid(x):
    out = sigmoid(x)
    return out * (1 - out)


# 线性函数
def linear(x):
    return x


# 线性函数求导
def diff_linear(x):
    return ones_like(x)  # 对线性函数求导 结果全是1

network.py

# 定义神经网络

from numpy import dot, zeros, random, multiply
import matplotlib.pyplot as plt

from data import *
from utils import *


class Network:
    # 参数列表:输入层、隐藏层、输出层的节点数
    def __init__(self, input_layer_num, hidden_layer_num, output_layer_num):

        self.input_layer_num = input_layer_num
        self.hidden_layer_num = hidden_layer_num
        self.output_layer_num = output_layer_num

        self.data_i = ones(self.input_layer_num)
        self.data_net_hidden = ones(self.hidden_layer_num)
        self.data_net_output = ones(self.output_layer_num)

        self.data_y = ones(self.hidden_layer_num)
        self.data_z = ones(self.output_layer_num)

        self.f0_net_k = ones(self.output_layer_num)
        self.delta_k = ones(self.output_layer_num)

        # 初始化权重
        self.wi = random.random((self.hidden_layer_num, self.input_layer_num))
        self.wo = random.random((self.hidden_layer_num, self.output_layer_num))

        self.delta_wi_temp = self.wi
        self.delta_wo_temp = self.wo

    # 正向计算过程
    def forward(self, input):

        self.data_i = input
        self.data_net_hidden = dot(self.wi, self.data_i)  # nxd x dx1 -- nx1
        self.data_y = np.array(list(map(tan_h, self.data_net_hidden)))
        self.data_net_output = dot(self.data_y, self.wo)  # 1xn nxc
        self.data_z = list(map(sigmoid, self.data_net_output))
        return self.data_z

    # 反向传播
    def BP(self, target, updata_flag, rate_1, rate_2):
        loss_t_k = target - self.data_z
        for i in range(self.output_layer_num):
            self.f0_net_k[i] = diff_sigmoid(self.data_net_output[i])

        self.delta_k = np.multiply(self.f0_net_k, loss_t_k)
        data_y_temp = self.data_y.reshape(-1, 1)
        delta_wo = dot(data_y_temp, self.delta_k.reshape(1, 3))

        epsilon = zeros(self.hidden_layer_num).reshape(-1, 1)

        for i in range(self.hidden_layer_num):
            epsilon[i] = multiply(self.delta_k, self.wo[i:i + 1][0]).sum()
        delta_wi = rate_2 * dot(epsilon, self.data_i.reshape(1, -1))

        self.delta_wo_temp = self.delta_wo_temp + delta_wo
        self.delta_wi_temp = self.delta_wi_temp + delta_wi

        if updata_flag == 1:
            self.wo = self.wo + rate_2 * delta_wo
            self.wi = self.wi + rate_1 * delta_wi
        loss = 0.5 * dot((target - self.data_z), (target - self.data_z).reshape(-1, 1))

        return loss

    def train(self, patterns, input_data, rate_1, rate_2):
        loss_set = []
        acc_set = []
        step = 0
        sample_len = len(patterns)
        sample_num = 0
        rate_temp = 0

        for m in range(5000):
            step += 1
            updata_flag = 1
            for p in patterns:
                sample_num += 1
                inputs = p[1:4].reshape(-1, 1)
                targets = p[4:]
                if sample_num == sample_len:
                    updata_flag = 1
                self.forward(inputs)
                loss = self.BP(targets, updata_flag, rate_1, rate_2)

            rate = self.test(input_data)
            rate_temp = rate_temp + rate

            # 每100步输出一次当前状态
            if step % 100 == 0:
                loss_set.append(loss)
                print("loss:", loss, "acc:", rate)
            if step % 10 == 0:
                rate_temp = rate_temp / 10
                acc_set.append(rate_temp)
                rate_temp = 0

        return loss_set, acc_set

    def test(self, input_data):
        correct_num = 1
        for p in input_data:
            inputs = p[1:4].reshape(-1, 1)
            targets = p[4:]
            output = self.forward(inputs)
            out_class = np.where(output == np.max(output))
            if targets[out_class] == 1:
                correct_num = correct_num + 1
        rate = correct_num / len(input_data)
        return rate

    def plot_plot(self, loss_set0, loss_set1, loss_set2):
        set_len = len(loss_set1)
        plt.plot(range(set_len), loss_set0, range(set_len), loss_set1, range(set_len), loss_set2)
        plt.legend(['rate=0.001', 'rate=0.005', 'rate=0.1'])
        # plt.title('learning_rate:'+name_num)
        plt.show()

main.py

此处为了多画不同的图,需要调整Network()括号内的参数并运行

from network import *

if __name__ == '__main__':
    rate_1 = 0.001
    rate_2 = 0.005
    rate_3 = 0.1

    # 输入层  隐藏层  输出层
    network1 = Network(3, 6, 3)
    loss_set0, acc0 = network1.train(train_data, test_data, rate_1, rate_1)

    network2 = Network(3, 6, 3)
    loss_set1, acc1 = network2.train(train_data, test_data, rate_2, rate_2)

    network3 = Network(3, 6, 3)
    loss_set2, acc2 = network2.train(train_data, test_data, rate_3, rate_3)

    network3.plot_plot(loss_set0, loss_set1, loss_set2)

结果

通过调整学习率与隐藏层节点数量,运行编写得到的main.py(如附录),可以得到以下三幅图像:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

通过分析以上图像,我们可以简单归纳以下结论:
1) 在一定范围内,隐藏层结点个数越多,虽然网络复杂度提升了,但是训练精度也提高了;
2) 在一定范围内,梯度更新步长会使目标函数值收敛速度加快,但是一旦步长过大,会变得难以收敛;
3) 同一种结构的目标函数值变化曲线如下图所示。

在这里插入图片描述

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

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

相关文章

OpenCV 图像旋转、平移、缩放

本文是 OpenCV图像视觉入门之路的第7篇文章,本文详细的进行了图像的缩放 cv2.resize()、旋转 cv2.flip()、平移 cv2.warpAffine()等操作。 OpenCV 图像旋转、平移、缩放目录 1 缩放图片 2 翻转图片 2.1 垂直翻转 2.2 水平翻转 2.3 水平垂直翻转 ​编辑 3 平移…

百度离线人脸识别SDK

1,采坑备忘 (1)8.1版本的SDK在spring-boot接口访问第一次正常,第二次之后JVM会奔溃,可能是java gc 处理C开出的内存有问题。 换6.1.3版本的SDK。 javaWindows百度离线人脸识别SDK6.1.3-Java文档类资源-CSDN下载javaW…

Harmony/OpenHarmony应用开发-转场动画页面间转场

在全局pageTransition方法内配置页面入场和页面退场时的自定义转场动效。 说明:从API Version 7开始支持。开发语言ets. 名称 参数 参数描述 PageTransitionEnter { type: RouteType, duration: number, curve: Curve | string, delay: number } 设置当前页面…

1998-2014年企业绿色发展数据库

1998-2014年工业企业的排放排污和环境治理等信息数据 1、时间:1998-2014年 2、数据来源:原环保部。 3、统计字段:主要有企业基本信息、生产信息、水环境、大气环境,内容涵盖了资源利用类指标(工业用水量、煤炭消费量…

YGG 与 Thirdverse 达成合作,将《足球小将》IP 带入 Web3

YGG 与 Thirdverse 建立了合作关系,Thirdverse 是一家专注于多人 VR 和 Web3 游戏的游戏工作室,在日本和美国分别设有办事处。 YGG 通过购买未来股权的简单协议(SAFE)参与了 Thirdverse 近期的 1500 万美元融资。这种合作关系将使…

FastAPI从入门到实战(16)——依赖项

依赖注入是耳熟能详的一个词了,听起来很复杂,实际上并没那么复杂,正常的访问需要接受各种参数来构造一个对象,依赖注入就变成了只接收一个实例化对象,主要用于共享业务逻辑、共享数据库连接、实现安全、验证、权限等相…

原油投资怎么样赚钱?原油投资赚钱技巧有哪些?

以前没有交易过原油的投资者,看到其他投资者从中获得了较好的盈利,也想通过原油投资来赚钱。那么原油投资到底能不能赚钱,是很多新手投资者比较想了解的问题。其实原油投资想盈利并不能全部依靠运气,只有掌握了原油投资赚钱技巧&a…

【Java基础】Java日志—什么是日志级别?如何配置数据源到不同的位置?配置文件内容都是什么含义?

目录 一、log4j1详情:记录器和日志级别 二、 log4j1详情:输出源【输出到不同的位置】 1、ConsoleAppender【将日志输出到控制台】 2、FileAppender【将日志输出到文件】 3、DailyRollingFileAppender【每日输出到一个新文件】 4、JDBCAppender【输…

FineReport开源报表系统-JS实现切换Tab块时进行数据联动

1. 概述 1.1 预期效果 在决策报表中,希望 Tab 块轮播切换时,可实现与报表块的数据联动。如下图所示: 1.2 实现思路 通过 JS 获取每个 Tab 块的轮播标题,转换为参数值,再通过控件进行界面传参,实现联动效果…

程序员工作五年后一般会怎样?

最近看到一些吐血言论“一个程序员工作5年后还没成为大牛,是不是该考虑别的路子了?”还有“程序员入行五年,有可能攒够80吗?”不是,程序员工作五年,是戳中了谁的痛点吗??大家对五年经…

128页4万字某智慧能源集团数字化管理平台项目建议书

【版权声明】本资料来源网络,仅用于行业知识分享,供个人学习参考,请勿商用。【侵删致歉】如有侵权请联系小编,将在收到信息后第一时间进行删除!完整资料领取见文末,部分资料内容: 方案设计 在当…

公司新来的软件测试工程师接私活被抓了,难怪他天天加班到凌晨

昨天和我一起进公司的测试部门同事上班接私活被老板抓了,这人才来不到两个月,每天加班到凌晨。刚开始还以为他是个卷王,没想到此人上班时间接单,用加班时间来完成公司需求,造成努力的假象。被老板在办公室骂了俩小时&a…

v$asm_disk中free_mb低于300m导致加盘报ora-15041

背景: 某项目扩容加盘到磁盘组中报磁盘组空间耗尽的错误,如下 明明是加盘,却报空间不足的错误,令人费解 报错的磁盘组为normal冗余,且Usable_file_MB为负,且Free_MB剩余很少或为0 问题排查: …

MS 训练笔记【2】:nnFormer

文章目录前言1. 安装2. 训练与测试2.1. 数据处理2.1.1. 整理数据路径2.1.2. 设置 nnFormer 读取文件的路径2.1.3. 数据集预处理2.2. 训练2.2.1. 训练代码2.2.2. 可能出现的问题及解决办法2.3. 预测总结前言 本文主要记载 nnFormer 从安装到训练再到推理的过程。nnFormer 的环境…

invokeBeanFactoryPostProcessors的理解

invokeBeanFactoryPostProcessors的理解 Spring中有两个非常重要的扩展点: BeanFactoryPostProcessorBeanPostProcessor 其中第一个是可以对BeanDefinition注册时进行扩展,而第二个是对spring中IOC容器中的对象进行实例化的时候进行扩展。 今天主要谈一…

【安全漏洞】水平权限漏洞和垂直权限漏洞

前言 权限校验非常重要。如果不对水平、垂直权限做校验,就会发生泄漏用户数据的事故,造成P0故障。 一、水平权限漏洞 1、水平权限漏洞基本概念 什么是水平权限漏洞呢? 简单来说,水平权限漏洞是用户CURD了本不属于他的资源。以上图…

复活天若OCR的谷歌翻译接口

文章目录1. 资源2. 效果3. 前言4. 网络相关4.1. 网络判断4.2. 网络设置5. 修改5.1. 代码修改原理5.2. 代码修改1. 资源 这里直接放出来我已经修改编译好的天若OCR,开箱即用:https://www.lanzoui.com/ifT8t0jfv1gd 访问码:24647 不过需要说明…

性能优化系列之如何为不同格式的图片选择合适的应用场景?

文章の目录一、JPEG(Joint Photographic Experts Group)1、介绍2、不适合情形3、非常适合的情形二、PNG(Portable Network Graphics)1、介绍2、不适合的情形3、非常适合的情形三、GIF(Graphics Interchange Format&…

【nowcoder】笔试强训Day9

目录 一、选择题 二、编程题 2.1另类加法 2.2走方格的方案数 一、选择题 1.下面程序的输出是:() String x"fmn"; x.toUpperCase(); String yx.replace(f,F); yy"wxy"; System.out.println(y); A FmNwxy B fmnwxy C wxyfmn D Fmnwxy String x “…

决胜「年货时代」:一场关于零食的品质突围

“都说冰糖葫芦儿酸,酸里面它裹着甜;都说冰糖葫芦儿甜,可甜里面它透着那酸。” 1995年春节,伴随着《冰糖葫芦》唱响大街小巷,小贩骑着自行车,后车座的草靶子上插满冰糖葫芦,或摆在集市上&#…