和鲸社区深度学习基础训练营2025年关卡2(1)纯numpy

拟分3种实现方法:

1.纯numpy

2.sklearn中的MLPClassifier

3.pytorch

题目:
在 MNIST 数据集上训练 MLP 模型并比较不同的激活函数和优化算法

任务描述:

使用 MNIST 数据集中的前 20,000 个样本训练一个多层感知机 (MLP) 模型。你需要比较三种不同的激活函数(ReLU、Sigmoid、Tanh)和三种不同的优化算法(SGD、Momentum、Adam),以找到表现最好的组合。模型需要使用一层隐藏层,隐藏单元数量为 128。

要求:

加载并预处理数据,将每个图像展平成 28x28 的向量,并进行标准化(除以 255)。
使用 one-hot 编码将标签进行转换。
在训练过程中,分别使用以下激活函数和优化算法:
激活函数:ReLU、Sigmoid、Tanh
优化算法:SGD、Momentum、Adam
对每种激活函数和优化算法组合,训练模型 10000 个 epoch。
评估模型在验证集上的准确率,并输出最优的激活函数与优化算法组合。
输入:

训练数据:MNIST 数据集中的前 20,000 个样本。
每个样本是一个 28x28 的灰度图像,标签为 0-9 的分类。
输出:

输出最优激活函数与优化算法组合,以及在验证集上的准确率。
要求:

不同激活函数与优化算法的组合实现。
对模型的正确率进行评估,并选择最优方案。
提示:

你可以使用 OneHotEncoder 将标签进行 one-hot 编码。
在模型的反向传播过程中,根据不同的优化算法更新权重。
激活函数可以用 ReLU、Sigmoid 和 Tanh,确保在前向传播和反向传播时分别计算激活值及其导数。

import numpy as np
from sklearn.preprocessing import OneHotEncoder
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
np.random.seed(999)def load_data(path="mnist.npz"):# np.load加载数据文件f = np.load(path)# 提取训练集和测试集的图片和标签数据X_train, y_train = f['x_train'], f['y_train']X_test, y_test = f['x_test'], f['y_test']f.close()  # 关闭文件# 返回训练集和测试集return (X_train, y_train), (X_test, y_test)# 加载MNIST数据集
(X_train, y_train), (X_test, y_test) = load_data()X_train=X_train[:2000]
y_train=y_train[:2000]
X_test=X_test[:1000]
y_test=y_test[:1000]
# 数据预处理
X_train = X_train.reshape((-1,  28 * 28)).astype('float32') / 255
X_test = X_test.reshape((-1,  28 * 28)).astype('float32') / 255# 标签进行独热编码
def one_hot_encoding(labels, num_classes):encoded = np.zeros((len(labels),  num_classes))for i, label in enumerate(labels):encoded[i][label] = 1return encodedy_train = one_hot_encoding(y_train, 10)
y_test = one_hot_encoding(y_test, 10)# MLP类的实现
class MLP:def __init__(self, input_size, hidden_size, output_size, activation='relu'):# 初始化权重(Xavier初始化适应Sigmoid/Tanh)self.W1 = np.random.randn(input_size, hidden_size) * np.sqrt(2 / input_size)self.b1 = np.zeros((1, hidden_size))self.W2 = np.random.randn(hidden_size, output_size) * np.sqrt(2 / hidden_size)self.b2 = np.zeros((1, output_size))self.activation = activation  # 支持relu/sigmoid/tanhself.losses = []  # 记录训练损失# Adam专用初始化self.t = 0  # 时间步计数器[1,2]self.m_W1, self.v_W1 = None, None  # 一阶/二阶矩(权重1)self.m_b1, self.v_b1 = None, None  # 一阶/二阶矩(偏置1)self.m_W2, self.v_W2 = None, None  # 一阶/二阶矩(权重2)self.m_b2, self.v_b2 = None, None  # 一阶/二阶矩(偏置2)# Adam超参数(可调整)self.beta1 = 0.9    # 一阶矩衰减率self.beta2 = 0.999  # 二阶矩衰减率self.epsilon = 1e-8 # 防除零常数def _activate(self, x):"""激活函数及其导数"""if self.activation == 'relu':return np.maximum(0, x), np.where(x > 0, 1, 0)  # 函数值 + 导数elif self.activation == 'sigmoid':s = 1 / (1 + np.exp(-x))return s, s * (1 - s)elif self.activation == 'tanh':t = np.tanh(x)return t, 1 - t**2def forward(self, X):"""前向传播"""self.z1 = np.dot(X, self.W1) + self.b1self.a1, self.da1 = self._activate(self.z1)  # 隐藏层激活值及导数self.z2 = np.dot(self.a1, self.W2) + self.b2self.a2 = np.exp(self.z2) / np.sum(np.exp(self.z2), axis=1, keepdims=True)  # Softmax输出return self.a2def compute_loss(self, y_pred, y_true):"""交叉熵损失"""return -np.mean(y_true * np.log(y_pred + 1e-8))def backward(self, X, y_true, y_pred):"""反向传播"""m = X.shape[0]# 输出层梯度 (dL/dz2)error_output = y_pred - y_truedW2 = np.dot(self.a1.T, error_output) / mdb2 = np.sum(error_output, axis=0, keepdims=True) / m# 隐藏层梯度 (dL/dz1)error_hidden = np.dot(error_output, self.W2.T) * self.da1dW1 = np.dot(X.T, error_hidden) / mdb1 = np.sum(error_hidden, axis=0, keepdims=True) / mreturn dW1, db1, dW2, db2def update_params(self, dW1, db1, dW2, db2, lr=0.01, optimizer='sgd', momentum=0.9):"""参数更新(支持SGD/Momentum/Adam)"""if optimizer == 'sgd':self.W1 -= lr * dW1self.b1 -= lr * db1self.W2 -= lr * dW2self.b2 -= lr * db2elif optimizer == 'momentum':# 初始化动量缓存if not hasattr(self, 'v_dW1'):self.v_dW1, self.v_db1 = np.zeros_like(dW1), np.zeros_like(db1)self.v_dW2, self.v_db2 = np.zeros_like(dW2), np.zeros_like(db2)# 更新动量self.v_dW1 = momentum * self.v_dW1 + lr * dW1self.v_db1 = momentum * self.v_db1 + lr * db1self.v_dW2 = momentum * self.v_dW2 + lr * dW2self.v_db2 = momentum * self.v_db2 + lr * db2# 应用更新self.W1 -= self.v_dW1self.b1 -= self.v_db1self.W2 -= self.v_dW2self.b2 -= self.v_db2# Adam实现elif optimizer == 'adam':# 首次调用时初始化矩估计if self.m_W1 is None:self.m_W1, self.v_W1 = np.zeros_like(dW1), np.zeros_like(dW1)self.m_b1, self.v_b1 = np.zeros_like(db1), np.zeros_like(db1)self.m_W2, self.v_W2 = np.zeros_like(dW2), np.zeros_like(dW2)self.m_b2, self.v_b2 = np.zeros_like(db2), np.zeros_like(db2)self.t += 1  # 更新时间步# 更新W1/b1的矩估计self.m_W1 = self.beta1*self.m_W1 + (1-self.beta1)*dW1self.v_W1 = self.beta2*self.v_W1 + (1-self.beta2)*(dW1**2)self.m_b1 = self.beta1*self.m_b1 + (1-self.beta1)*db1self.v_b1 = self.beta2*self.v_b1 + (1-self.beta2)*(db1**2)# 更新W2/b2的矩估计self.m_W2 = self.beta1*self.m_W2 + (1-self.beta1)*dW2self.v_W2 = self.beta2*self.v_W2 + (1-self.beta2)*(dW2**2)self.m_b2 = self.beta1*self.m_b2 + (1-self.beta1)*db2self.v_b2 = self.beta2*self.v_b2 + (1-self.beta2)*(db2**2)# 偏差校正m_W1_hat = self.m_W1 / (1 - self.beta1**self.t)v_W1_hat = self.v_W1 / (1 - self.beta2**self.t)m_b1_hat = self.m_b1 / (1 - self.beta1**self.t)v_b1_hat = self.v_b1 / (1 - self.beta2**self.t)m_W2_hat = self.m_W2 / (1 - self.beta1**self.t)v_W2_hat = self.v_W2 / (1 - self.beta2**self.t)m_b2_hat = self.m_b2 / (1 - self.beta1**self.t)v_b2_hat = self.v_b2 / (1 - self.beta2**self.t)# 参数更新self.W1 -= lr * m_W1_hat / (np.sqrt(v_W1_hat) + self.epsilon)self.b1 -= lr * m_b1_hat / (np.sqrt(v_b1_hat) + self.epsilon)self.W2 -= lr * m_W2_hat / (np.sqrt(v_W2_hat) + self.epsilon)self.b2 -= lr * m_b2_hat / (np.sqrt(v_b2_hat) + self.epsilon)def train(self, X, y, epochs=1000, lr=0.01, optimizer='sgd'):for epoch in range(epochs):y_pred = self.forward(X)loss = self.compute_loss(y_pred, y)self.losses.append(loss)dW1, db1, dW2, db2 = self.backward(X, y, y_pred)self.update_params(dW1, db1, dW2, db2, lr, optimizer)#if epoch % 100 == 0:#print(f"Epoch {epoch}: Loss={loss:.4f}")def predict(self, X):return np.argmax(self.forward(X), axis=1)# 创建MLP模型
input_size = 28 * 28
hidden_size = 128
output_size = 10# 训练模型
lr = 0.001
epochs = 1000# 训练和评估模型
best_accuracy = 0  # 保存最佳模型的准确率
best_model = None  # 保存最佳模型
best_activation = None  # 保存最佳的激活函数
best_optimizer = None  # 保存最佳的优化器for activation in ['relu', 'sigmoid', 'tanh']:  # 激活函数分别为ReLU、Sigmoid、Tanhfor optimizer in ['sgd', 'momentum', 'adam']:  # 优化器分别为SGD、Momentum和Adamprint(f"\nTraining with {activation} activation and {optimizer} optimizer")mlp = MLP(input_size=input_size, hidden_size=hidden_size, output_size=output_size, activation=activation)mlp.train(X_train, y_train, epochs=epochs, lr=lr, optimizer=optimizer)# 评估准确率y_pred = mlp.predict(X_test)accuracy = np.mean(np.argmax(y_test, axis=1) == y_pred)print(f"测试集准确率: {accuracy * 100:.2f}%")# 保存最佳模型if accuracy > best_accuracy:best_accuracy = accuracy # 保存最佳模型的准确率best_model = None  # 保存最佳模型best_activation = activation  # 保存最佳的激活函数best_optimizer = optimizer # 保存最佳的优化器print(f"\nBest model with activation '{best_activation}' and optimizer '{best_optimizer}'")
print(f"Validation Accuracy: {best_accuracy * 100:.2f}%")

运行结果如下:

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

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

相关文章

Sequential Thinking:AI深度思考的新范式及其与CoT、ReAct的对比分析

引言:AI深度思考的演进与Sequential Thinking的崛起在人工智能技术快速发展的今天,AI模型的思考能力正经历着从简单应答到深度推理的革命性转变。这一演进过程不仅反映了技术本身的进步,更体现了人类对机器智能认知边界的持续探索。早期的大语…

云原生详解:构建现代化应用的未来

引言 在数字化转型的浪潮中,"云原生"已成为技术领域最热门的话题之一。从初创公司到全球500强企业,都在积极探索云原生技术以提升业务敏捷性和创新能力。本文将全面解析云原生的概念、核心技术、优势以及实践路径,帮助您深入理解这一改变IT格局的技术范式。 什么…

SSE事件流简单示例

文章目录1、推送-SseEmitter2、接收-EventSourceListenerSSE(Server-Sent Events,服务器推送事件)是一种基于HTTP的服务器向客户端实时推送数据的技术标准。1、推送-SseEmitter SseEmitter用于实现服务器向客户端单向、长连接的实时数据推送…

Elasticsearch RESTful API入门:基础搜索与查询DSL

Elasticsearch RESTful API入门:基础搜索与查询DSL 本文为Elasticsearch初学者详细解析RESTful API的核心操作与查询DSL语法,包含大量实战示例及最佳实践。 一、Elasticsearch与RESTful API简介 Elasticsearch(ES)作为分布式搜索…

(六)复习(OutBox Message)

文章目录 项目地址一、OutBox Message1.1 OutBox表配置1. OutBoxMessage类2. OutboxMessage表配置3. 给每个模块生成outboxmessage表1.2 发布OutBox Message1. 修改Intercepotor2. 配置Quartz3. 创建Quatz方法发布领域事件4. 创建Quatz定时任务5. 注册Quatz服务和配置6. 流程梳…

STM32-ADC内部温度

在通道16无引脚(测量温度不准确)跟ADC代码差不多;不需要使能引脚时钟;将内部温度测量打开/*** brief 启用或禁用温度传感器和内部参考电压功能* param NewState: 新的功能状态,取值为ENABLE或DISABLE* retval 无* no…

「Linux命令基础」文本模式系统关闭与重启

关机重启基本命令 直接拔掉计算机电源可能损坏内部元件;Linux系统通过命令关闭计算机则是安全流程,让所有程序有机会保存数据、释放资源。 关机命令:shutdown Linux系统提供了多种用于关闭或重启系统的命令,其中 shutdown 是最常用的一种,它可以安全地通知用户系统即将…

射频信号(大宽高比)时频图目标检测anchors配置

一、大宽高比目标YOLO检测参数设置 这是yolov7的一个label的txt文件: 1 0.500 0.201 1.000 0.091 2 0.500 0.402 1.000 0.150 3 0.500 0.604 1.000 0.093 0 0.500 0.804 1.000 0.217 对应的样本: 长宽比分别是:1/0.09110.98, 1/0.1506.67…

OpenStack 鉴权服务介绍.md

引言 OpenStack是一个开源的云计算管理平台,其中的Keystone组件承担了身份认证和授权的关键任务。Keystone的主要功能包括管理用户及其权限、维护OpenStack Services的Endpoint,以及实现认证(Authentication)和鉴权(Au…

Linux_3:进程间通信

IPC1.什么是IPC?Inter Process Communication2.进程间通信常用的几种方式1,管道通信:有名管道,无名管道2,信号- 系统开销小3,消息队列-内核的链表4,信号量-计数器5,共享内存6&#x…

【Springboot】Bean解释

在 Spring Boot 中,Bean 就像是你餐厅里的一名员工。比如,你有一名服务员(Service)、一名厨师(Chef)和一名收银员(Cashier)。这些员工都是餐厅正常运转所必需的,他们各自…

axios的post请求,数据为什么要用qs处理?什么时候不用?

为什么使用 qs 处理 POST 数据axios 的 POST 请求默认将 JavaScript 对象序列化为 JSON 格式(Content-Type: application/json)。但某些后端接口(尤其是传统表单提交)要求数据以 application/x-www-form-urlencoded 格式传输&…

【unitrix】 4.21 类型级二进制数基本结构体(types.rs)

一、源码 这段代码定义了一个类型级数值系统的 Rust 实现,主要用于在编译时表示和操作各种数值类型。 use crate::sealed::Sealed; use crate::number::{NonZero, TypedInt, Unsigned, Primitive}; // // 特殊浮点值枚举 ///// 特殊浮点值(NaN/∞&#x…

UI前端与数字孪生结合实践案例:智慧零售的库存管理优化系统

hello宝子们...我们是艾斯视觉擅长ui设计和前端数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩!一、引言:数字孪生重构零售库存的 “人 - 货 - 场” 协同在零售行业利润率持续承压的背景…

【Freertos实战】零基础制作基于stm32的物联网温湿度检测(教程非常简易)持续更新中.........

本次记录采用Freertos的第二个DIY作品,基于Onenet的物联网温湿度检测系统,此次代码依然是全部开源。通过网盘分享的文件:物联网温湿度检测.rar 链接: https://pan.baidu.com/s/1uj9UURVtGE6ZB6OsL2W8lw?pwdqm2e 提取码: qm2e 大家也可以看看…

Matplotlib-多图布局与网格显示

Matplotlib-多图布局与网格显示一、多图布局的核心组件二、基础布局:plt.subplots()快速创建网格1. 均等分网格2. 不等分网格(指定比例)三、进阶布局:GridSpec实现复杂嵌套1. 跨行列布局2. 嵌套GridSpec四、实用技巧:布…

GitHub上优秀的开源播放器项目介绍及优劣对比

ExoPlayer 项目地址:https://github.com/google/ExoPlayer 特点: 由Google开发,支持广泛的视频格式和流媒体传输协议,如DASH、HLS、SmoothStreaming。 提供灵活的媒体源架构和高级特性,如动态自适应流播放。 开发者可以轻松扩展和定制播放器组件,适应特定需求。 优点: 功…

react打包发到线上报错Minified React error #130

开发过程中遇到一个问题,记录一下 本地打包发布正常,发测试环境正常,可是通过Jenkins打包发布线上报错 报错信息 index-67fbbd81.js:39 Error: Minified React error #130; visit https://reactjs.org/docs/error-decoder.html?invariant130…

微服务项目远程调用时的负载均衡是如何实现的?

负载均衡概述 负载均衡是微服务架构中的核心组件,用于将请求合理分配到多个服务实例上,提高系统的可用性和性能。负载均衡的分类 负载均衡大致可以分为两类 1. 服务端负载均衡 实现位置:独立部署的负载均衡服务器(位于客户端和服务…

【中文核心期刊推荐】中国农业科技导报

《中国农业科技导报》是中国科技核心期刊,也是北京大学图书馆“中文核心期刊要目总览”收录的期刊。它是由中国农村技术开发中心主办,全面为科教兴农服务的综合性农业学术期刊。《中国农业科技导报》是中国农业科学院生物技术研究所承办的&a…