React Native包体积优化之图片优化

React-Native之可配置化的图片资源预加载方案 背景 在RN开发过程中,我们深受Rn包体积的扩大而困扰。为了优化包体积,最直接的方式莫过于减少本地资源的引用(将资源上传到云端)。然而虽然包的体积大大减小,但伴随而来的则是由于网络延时导致的加载缓慢,进而引发严重的体验问题,结果自然就是得不偿失。那么如何解决这样的问题呢,就需要一套可行的资源预加载方案。下面我们将着重讨论图片资源的预加载方案。 解决方案 1、图片预加载 React-Native官方... 阅读详情

简介

由于随着项目业务的增加,导致包越来越大,大概有10M,每次发热更下载都比较久,而且会消耗较多的下载资源,在分析包内容的时候,发现图片占据了约80%的体积,因此提出优化图片的方案。

分析包内容

首先我们先看下包内容构成,以安卓包为例,如下所示

|-- dist 10MB
   |-- drawable-hdpi 8K
   |-- drawable-mdpi 8.2MB 
   |-- drawable-xhdpi 8K
   |-- drawable-xxhdpi 8K
   |-- index.android.bundle 1.8MB

从上图可以看出,图片跟bundle文件大概各占据了80%,优化掉了图片,可以减少80%的体积,相当可观的优化,当然bundle文件也是大头,但是这不是本篇文章要介绍的。

解决方案

压缩图片

我们用tinypng 进行批量压缩drawable-mdpi(共678张)下的所有图片,压缩完重新打包,结果如下

|—— dist  6.5MB

优化体积为 (10 - 6.5) = 3.5MB,可以看到图片体积减少了一部分,但包还是挺大的。

本地图片转成OSS图片

另外一种思路为将本地图片上传到OSS,然后本地图片替换为网络图片。这样我们就能去掉所有图片的体积, 大约有8M。显然这是一个巨大的改进效果。

而且图片是有缓存的,也就是图片缓存在本地后,app就不会在发起请求,那么就不会消耗OSS资源。

下文会详细介绍如何将本地图片转成OSS图片。

实现思路

第一步 上传本地图片

我们需要将本地图片上传至阿里云OSS,假设我们现在有以下目录下的几张图片:

|-- src
    |-- images
        |-- a.png
        |-- b.png
    |-- pages
        |-- images
            |-- c.png
        

考虑到图片有可能重复的可能,文件名取文件md5值。上传成功后记录文件映射表,映射表为json格式,如下所示

{
    "src/images/a.png": "4a8da6930cae6e4cae54d7bae3498fbc.png",
    "src/images/b.png": "d21c595c585f11d8bc24bdc5dc0c9b18.png",
    "src/pages/images/c.png": "674303925428601900ed2e58fdc7cbb6.png"
}

表key为图片的路径,值为md5值,假设阿里云地址为https://my.oss-cn-beijing.aliyuncs.com (下文会多次用到这个地址)。

我们随便挑md5表中的一个图片,如src/images/a.png,那么这张图对应的OSS地址如下

https://my.oss-cn-beijing.aliyuncs.com/4a8da6930cae6e4cae54d7bae3498fbc.png

第二步 本地图片替换成OSS图片

将本地图片代码,替换成引用OSS图片。比如有如下代码

<Image src={require('/src/images/a.png')}/>

然后替换成第一步md5表中的值

<Image src={{uri: "https://my.oss-cn-beijing.aliyuncs.com/4a8da6930cae6e4cae54d7bae3498fbc.png"}}/>

这一步需要用到的技术有Babel插件及AST抽象树。

AST抽象语法树介绍

首先我们的源代码编译成可执行代码,并不是一步生成的。而是源代码先解析成AST抽象语法树,然后再从AST抽象语法树转换成可执行代码。我们先看一下AST语法树长得什么样。

已知源代码如下:

let a = require('/src/images/a.png');
let b = {uri: "https://my.oss-cn-beijing.aliyuncs.com/4a8da6930cae6e4cae54d7bae3498fbc.png" }

会解析成以下语法树 

{
  "type": "File",
  "program": {
    "type": "Program",
    "body": [
      {
        "type": "VariableDeclaration",
        "declarations": [
          {
            "id": {
              "type": "Identifier",
              "name": "a"
            },
            "init": {
              "type": "CallExpression",
              "callee": {
                "type": "Identifier",
                "loc": {
                  "identifierName": "require"
                },
                "name": "require"
              },
              "arguments": [
                {
                  "type": "StringLiteral",
                  "value": "/src/images/ic_cp.png"
                }
              ]
            }
          }
        ]
      },
      {
        "type": "VariableDeclaration",
        "declarations": [
          {
            "id": {
              "type": "Identifier",
              "name": "b"
            },
            "init": {
              "type": "ObjectExpression",
              "properties": [
                {
                  "type": "ObjectProperty",
                  "key": {
                    "type": "Identifier",
                    "name": "uri"
                  },
                  "value": {
                    "type": "StringLiteral",
                    "value": "https://my.oss-cn-beijing.aliyuncs.com/4a8da6930cae6e4cae54d7bae3498fbc.png"
                  }
                }
              ]
            }
          }
        ]
      }
    ]
  }
}

语法树相对简单,就不逐行介绍了,可以使用在线AST语法树对应,从上我们可以看出AST语法树是一个个节点的树,我们可以替换节点以实现代码的替换。

实现细节

第一步:上传图片

遍历src下的所有图片,然后上传至OSS( 如何上传OSS,参考上传本地文件),代码如下

const klaw = require('klaw');
const fs = require("fs");
const path = require("path");
let OSS = require('ali-oss');
const crypto = require('crypto');

// 记录
let record = {};
// 需要上传的图片
let uploadItems = [];
// 上传下标,按下标逐一上传
let uploadIndex = 0;


let client = new OSS({
    // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
    region: 'oss-cn-beijing',
    // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
    accessKeyId: '你的keyId',
    accessKeySecret: '你的secret',
    // 填写Bucket名称。
    bucket: '你的bucket'
});

//遍历所有图片
klaw(path.resolve(process.cwd(), "./src"))
    .on('data', (item) => {
        if (/\.(jpg|jpeg|png)$/.test(item.path)) {
            const filePath = item.path;
            uploadItems.push(filePath);
        }
    })
    .on('end', async () => {
        if (uploadItems.length > 0) {
            uploadItem();
        }
    })

/**
 * 上传单个文件
 */
async function uploadItem() {

    const filePath = uploadItems[uploadIndex];
    let fileExtension = filePath.substring(filePath.lastIndexOf('.'))
    // fileKey = /src/images/a.png
    const fileKey = filePath.replace(process.cwd(), "");
    const buffer = fs.readFileSync(filePath);
    const hash = crypto.createHash('md5');
    hash.update(buffer);
    const md5 = hash.digest('hex');
    // recordValue = 4a8da6930cae6e4cae54d7bae3498fbc.png
    const recordValue = md5 + fileExtension;

    // 填写OSS文件完整路径和本地文件的完整路径。OSS文件完整路径中不能包含Bucket名称。
    // 如果本地文件的完整路径中未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
    const result = await client.put(recordValue, path.normalize(filePath));

    if(result && result.res && result.res.statusCode == 200){
        //  "/src/images/a.png": "4a8da6930cae6e4cae54d7bae3498fbc.png",
        record[fileKey] = recordValue;
    }

    uploadIndex++;
    if (uploadIndex < uploadItems.length) {
        uploadItem();
    } else {
        const uploadRecordPath =  path.resolve(process.cwd(), "./upload-image-record.json")
        fs.writeFileSync(uploadRecordPath, JSON.stringify(record, null, "\t"));
    }

}

 上传成功后,会生成上传记录文件upload-image-record.json,如下所示

{
    "src/images/a.png": "4a8da6930cae6e4cae54d7bae3498fbc.png",
    "src/images/b.png": "d21c595c585f11d8bc24bdc5dc0c9b18.png",
    "src/pages/images/c.png": "674303925428601900ed2e58fdc7cbb6.png"
}

第二步:替换本地文件为OSS图片

这一步实现将本地图片替换成OSS图片,要用到上一步生成的记录表upload-image-record.json,代码如下所示:

const t = require('@babel/types');
const p = require('path');

module.exports = function () {

  return {
    visitor: {

      CallExpression(path, ref = { opts: {} }) {
        const node = path.node;
        if (node.callee.type === 'Identifier' && node.callee.name === 'require') {
          const value = node.arguments[0].value;
          if (typeof (value) === 'string' && /\.(jpg|jpeg|png)$/.test(value)) {
            /**
             * 以假设存在项目,/Users/zhangsan/rn-app/index.js代码为例,/Users/zhangsan/rn-app为项目在我电脑的绝对地址
              class HelloWorld extends React.Component {
                render() {
                  return (
                    <View style={styles.container}>
                      <Image source={require('./src/images/a.png')}/>
                    </View>
                  );
                }
              }
             */
            // upload-image-record.json 即上一步产生的md5表
            const uploadRecordPath = p.resolve(process.cwd(), "./upload-image-record.json")
            // filename = /Users/zhangsan/rn-app/index.js
            let filename = path.hub.file.opts.filename;
            // fileDir = /Users/zhangsan/rn-app
            let fileDir = filename.substring(0, filename.lastIndexOf("/") + 1);
            // imagePath = /Users/zhangsan/rn-app/src/images/ic_bjx.png
            let imagePath = pathP.resolve(fileDir, value);
            // rootPath = /Users/zhangsan/rn-app
            let rootPath = path.hub.file.opts.root;
            // imagePath = /src/images/a.png
            imagePath = imagePath.replace(rootPath, "");
            // foundPath = 4a8da6930cae6e4cae54d7bae3498fbc.png
            let foundPath = require(uploadRecordPath)[imagePath];
            const uriValue = "https://my.oss-cn-beijing.aliyuncs.com/" + foundPath;
            const objectExpression = t.objectExpression([
              t.objectProperty(
                t.identifier('uri'),
                t.stringLiteral(uriValue)
              )
            ]);
            // 替换节点,require('/src/images/a.png') 替换成
            // {uri: https://my.oss-cn-beijing.aliyuncs.com/4a8da6930cae6e4cae54d7bae3498fbc.png}
            path.replaceWith(objectExpression);
          }
        }
      }

    }
  }
}

至此图片替换的操作就完成了,再看下包大小

包大小
优化前10MB
优化后2MB

至此已完成体积优化,当然有些细节没处理,可以参考源码。

React Native构建电商App完整指南:系统学习路径 从零开始用React Native搭建功能完整的电商App,涵盖环境配置、组件封装、状态管理、API对接及真机调试全流程。聚焦React Native核心能力,结合真实业务场景打磨高性能跨平台实践方案。 阅读详情

相关推荐

CodePush优化之减小更新包体积

欢迎大家关注【跨平台开发那些事】公众号,定期推送跨平台开发技术实践。 述 还有 10 天就要迎来 2019 新年,感慨 18 年过的好快,恍恍惚惚。2018 年经历了很多,人生最重要的事情,很开心。闲余时间浏览了这一年写过的博客,9 篇相对 17 年少了很多。时间不等人,什么事还是要提前计划往前做。本来是要等新年再和大家分享新的内容,回头看看还是以整数结尾这一年,也算欣慰。 这篇博...

... 1518

React native 照片压缩上传

在用React native做项目的时候,遇到了照片的压缩上传问题。在很多RN技术交流群中,询问到的结果也是让用原生。但这里就遇到了RN和原生之间的兼容问题。在不懈努力之下,终于找到了一个ImagePicker这个组件。当执行这个组件时,可以开启相机,拍照后就把图片改成您设置的最大宽或者高 像素的图片,另一个属性会自动适应。例如:openCamera() { //在开启相机,拍照时,把照片...

LQ0611的博客 9748

react-native-image-resizer:with使用React Native调整本地图像的大小

React Native Image Resizer 一个React Native模块可以创建本地图像的缩放版本(也支持iOS上的资产库)。 React性的 React本机图像调整器 ≤0.60 1.1.0 0.61 1.2.0 建立 安装软件包: React本机> = 0.60 yarn add react-native-image-resizer cd ios && pod install React本机<= 0.59 yarn add react-native-image-resizer react-native link react-native-image-resizer 安卓 注意:在最新版本的React Native上,您可能会在Android上的Gradle构建过程中出错( com.android.dex.DexException: Multiple dex files define Landroid/support/v7/appcompat/R$anim )。 运行cd android && ./gradlew clean修复此问题。 手动链接 And

React-Native之如何迅速缩小包体积而不影响性能

React-Native作为reactjs的一个延伸,以H5和Native之间的中间地带角色存在于我们的项目中。 由于支撑了大量的业务场景,不容置喙的导致体积迅速增大,当然对RN来说,这也许不会导致严重的性能问题,甚至还有可能提升性能(因为大量的资源存在本地,所以加载较快),但是从节省用户流量、网络带宽的角度讲,还是能产生很大的用户价值。毕竟谁也不想在启动App的时候就耗费几兆甚至几十兆流量加载一...

HGC2016的博客 2044

react-native-image-picker 的使用方法demo

react-native-image-picker 使用demo 详见:https://github.com/pheromone/mycamera

reactnativeimagecard一个用于ReactNative框架的纯javascript图片Card

react-native-image-card:一个用于React Native框架的纯javascript图片Card

React Native性能优化:应该做和不应该做的

翻译原文:https://medium.com/crowdbotics/react-native-performance-do-and-dont-88424e873bbd 在使用一些框架例如React Native去实际开发移动端应用的时候,性能是一个重要的问题。React Native默认情况下的性能是没有问题的,但是在实际开发React Native的时候,我们也可能会遇到一些性能相关的问题。 这些问题是很难通过组件本身修复去解决的。在这篇文章中,我们会提供一些建议来优化开发React Native.

Geek技术前线 929

react-native-lightbox:React Native的全屏灯箱弹出窗口中的图像等

react-native-lightbox 安装 yarn add react-native-lightbox 用法 navigator属性是可选的,但在iOS上建议使用,请参阅下一部分的Navigator配置。 import Lightbox from 'react-native-lightbox' ; const LightboxView ( { navigator } ) => ( < Lightbox xss=removed> < Image style = { { height : 300 } } source = { { uri : 'http://knittingisawesome.com/wp-content/uploads/2012/12/cat-wearing-a-reindeer-hat1.jpg'

7个实用React Native图片优化技巧:从包体积到加载速度的全面优化指南

React Native作为构建跨平台移动应用的流行JavaScript框架,图片资源往往占据应用体积的30%以上,也是影响加载性能的关键因素。本文将分享7个经过实战验证的图片优化策略,帮助开发者显著减少包体积并提升加载速度,打造更流畅的用户体验。 ## 1. 合理选择图片格式:现代格式带来的性能飞跃 🚀 选择合适的图片格式是优化的第一步。React Native支持多种图片格式,每种格式都

gitblog_00407的博客 484

React Native 包体积优化实践

Android Apk大小和App性能一直是React Native Developers的主要关注点。 我们的应用程序是用React Native编写,目前Android版本的Apk Size已经达到80MB左右。 因此,想出一个不错的减小Apk Size解决方案来并提高应用程序性能是一个挑战。 在此博客中,我们将逐步介绍减小apk大小以及性能提高和应用程序启动时间减少的步骤。 一、JSBundle 及 Asset 随着0.59的发布,同时发布了新版本的JSC,新版0.59的最大优势在于,可以为64位架构生成APK。但是,随之带来的问题是包体积的增加,目前RN团队也正在努力从React Na

嵌入式八股文-ARM

嵌入式八股文总结(ARM篇)-优快云博客现象:I2C死锁就是时钟线SCL一直处于高电平,数据线SDA一直处于低电平。从机拉低数据线SDA时(发送应答信号给主机时或发送数据0时)主机意外复位,主机复位后时钟线SCL就为高电平了,此时,SCL为高电平而SDA为低电平,主机就以为有其他设备占有了总线,而SCL为高电平时 数据位SDA不允许有变化,意思是:主机就一直等待时钟线SDA拉高,而从机就一直等待时钟线SCL拉高 就造成了死锁的现象。解决方法:1.选择带有复位功能的从设备,复位后SDA被拉高。

m0_63127436的博客 1261

鸿蒙跨平台项目实战篇52:React Native Bundle包体积优化详解

包体积优化是一场持久战,需要开发者在代码规范、资源管理和架构设计上进行精细化运营。在鸿蒙生态中,合理的分包策略和资源分离不仅能减小体积,更能充分发挥鸿蒙“一次开发,多端部署”的弹性优势。

2401_83061978的博客 633

VN5620硬件接口介绍

VECTOR, VN5620, 诊断

Fecostar的博客 7486

OpenHarmony + RN:Bundle包体积优化

在React Native跨平台开发中,Bundle包体积是影响应用性能的关键因素之一。对于OpenHarmony平台而言,由于设备资源相对有限(尤其是入门级设备),优化Bundle包体积显得尤为重要。过大的Bundle包会导致应用启动时间延长、内存占用增加、网络下载缓慢,甚至可能触发系统资源限制,影响用户体验。本文详细探讨了React Native应用在OpenHarmony 6.0.0 (API 20)平台上的Bundle包体积优化策略。

2501_91746149的博客 227

蓝桥杯嵌入式(基础教程)STM32G431RBT6——创建工程以及点灯

首先选择正确的芯片类型:STM32G431RBT6工程的创建主要有配置时钟以及烧录的方式。在配置好之后需要对时钟进行配置,由于蓝桥杯的外部晶振是24MHz因此需要对时钟树进行相应的配置。第一步先点击时钟配置之后就可以对时钟进行相应的配置了最后一步,需要对工程起一个名字,并且要选择KEIL做为其相应的软件之后再需要再生成代码那里进行相应的控制。当然这样根据生成的工程不能直接使用会有一个报错,所以需要添加一个启动文件。这个启动文件可以在官方的LCD文件夹下复制到自己的工程中。

m0_74051113的博客 1093

MuJoCo 动捕接口 Mocap 直接操控机械臂(附代码)

动作捕捉(Motion Capture,简称 Mocap)是一种记录并处理人或物体动作的技术,在影视、游戏、机器人等领域应用广泛。通过上下左右以及alt_l,alt_r可以控制hand这个hody跟着mocap进行同步,这里将quat固定为Z朝下。首先在 scene.xml 中修改添加 mocap 和 equality。下面介绍如何配置 Mocap 以及使用按键进行末端控制。控制核心代码,通过按键控制mocap的pos和quat。

darcsdn 879

ReactNative性能优化实战指南(2026最新版)

2026 年的 React Native 已经非常强大,但性能优化永远是开发者必修课。先用工具定位问题(推荐 Flipper Performance),再针对性优化,往往事半功倍。

wayne214的博客 1509

5分钟搞定!用Cursor和.NET 9.0快速搭建串口通讯上位机(附VS Code插件配置)

本文分享了如何利用Cursor AI编程助手与.NET 9.0,在5分钟内快速构建一个功能完整的串口通讯上位机程序。通过自然语言描述需求,AI自动生成WinForms界面和核心代码,极大提升了硬件调试工具的定制开发效率。文章详细介绍了环境配置、AI协作编码、功能实现与调试的全过程。

weixin_28366353的博客 277

Conference App in a Box性能优化技巧:提升React Native应用体验

Conference App in a Box是一款功能强大的全栈跨平台应用,专为各类活动和会议打造。然而,随着应用功能的不断丰富,性能问题可能会影响用户体验。本文将分享10个实用的性能优化技巧,帮助你打造流畅高效的React Native会议应用。 ## 1. 图片优化:减少加载时间和内存占用 图片是会议应用中不可或缺的元素,但也是性能瓶颈的常见来源。在Conference App in a

gitblog_00009的博客 549

【100%通过率】华为OD机试真题 Python 实现【打印机队列】【2022.11 Q4 新题】

有5台打印机打印文件,每台打印机有自己的待打印队列。因为打印的文件内容有轻重缓急之分,所以队列中的文件有1~10不同的代先级,其中数字越大优先级越高。打印机会从自己的待打印队列中选择优先级最高的文件来打印。如果存在两个优先级一样的文件,则选择最早进入队列的那个文件。现在请你来模拟这5台打印机的打印过程。

MISAYAONE的博客 1万+

TC3XX - MCAL知识点(三十三):基于EB Tresos配置Tc3xx的MCAL代码如何产生中心对称的三相六路发波波形

本文用于记录如何在英飞凌 tc3xx 芯片的应用开发中,借助 EB Tresos 配置工具生成的配置代码与 MCAL 源码相结合,进而实现三相六路中心对称互补的 PWM 输出效果。外部资源需求:EB Tresos23.0以上、Tasking\Hightec编译器、示波器\逻辑分析仪。

梦想技术家 1215

如何用Gogs Webhooks打通Slack、Discord与钉钉:Git事件推送与签名验证实战教程

Gogs Webhooks 是把你的 Git 仓库动态实时推送到 Slack、Discord 与钉钉群的利器:每当有人 push 代码、提 Issue 或发起 Pull Request,Gogs 就会自动向预设的 URL 发送一次 HTTP POST 请求。本文手把手带你完成三大平台的接入配置,并讲透 `X-Gogs-Signature` 签名验证实战方法,让团队通知又快又安全。 [![Gogs

gitblog_00035的博客 351

YOLO26优化:注意力魔改 | EMA:基于跨空间学习的高效多尺度注意力,效果优于ECA、CBAM、CA

加入EMA注意力,一种基于跨空间学习的高效多尺度注意力,效果优于ECA、CBAM、CA等经典注意力。

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 334

ReactNative开发实战——ReactNative 开发中的图标管理方案:基于 Iconfont 的自定义图标库实现

React Native 应用开发中,采用 Iconfont 方案管理业务图标具有显著优势。该方案通过矢量特性实现多分辨率适配,支持动态颜色调整,且体积小巧。实现步骤包括:1) 在 Iconfont 官网创建项目并生成字体文件;2) 编写自动下载脚本生成 TypeScript 定义;3) 封装可复用的图标组件,支持动态大小和颜色配置。该方案解决了移动端图标管理的核心问题,包括渲染性能、包体积优化和跨平台一致性,相比传统图片方案更高效易维护。

羲和实验室 1235

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

从零到一构建移动应用:React Native与微服务架构实战解析

移动应用开发涉及前端与后端技术的协同,其中跨平台框架与微服务架构是当前主流的技术选型。React Native作为跨平台解决方案,允许开发者使用JavaScript构建接近原生体验的iOS和Android应用,其核心原理是通过桥接技术将JavaScript代码转换为原生组件,从而在开发效率和性能之间取得平衡。后端微服务架构则将单体应用拆分为独立部署、可伸缩的小型服务,每个服务专注于单一业务能力,通过API或消息队列进行通信,这显著提升了系统的可维护性和扩展性。在工程实践中,这种前后端分离的架构模式能够有效支

weixin_32570803的博客 291

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

上一篇: Retrofit的初步使用
下一篇: React Native三端同构
土豆爱吃西瓜
博客等级 码龄10年 0粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值