From 8db5f8207a01188e49492d040c52f35529910cab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E8=BF=9B=E7=A6=84?= Date: Thu, 1 Apr 2021 20:30:07 +0800 Subject: [PATCH] =?UTF-8?q?TensorFlow.js=E5=88=9D=E8=A7=81(1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- images/算法/DataType.jpg | Bin 0 -> 11152 bytes images/算法/DataTypeMap.jpg | Bin 0 -> 17236 bytes images/算法/训练素材.jpg | Bin 0 -> 8355 bytes source/_posts/算法/TensorFlow.js初见(1).md | 242 +++++++++++++++++++++ 4 files changed, 242 insertions(+) create mode 100644 images/算法/DataType.jpg create mode 100644 images/算法/DataTypeMap.jpg create mode 100644 images/算法/训练素材.jpg create mode 100644 source/_posts/算法/TensorFlow.js初见(1).md diff --git a/images/算法/DataType.jpg b/images/算法/DataType.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d618fff62070e10087f51a4fe59050dbd59507fa GIT binary patch literal 11152 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 literal 0 HcmV?d00001 diff --git a/images/算法/DataTypeMap.jpg b/images/算法/DataTypeMap.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8b39bd02778237f741697e63bf52e2b77c4c8c96 GIT binary patch literal 17236 zcmdVBcT`i~x9A(BDIMt@DS{v%NUsV~0s_)&K%|Dydq+V)dJ~Wqq}LEBp%>{*KnMf~ z(tGa^sh970=iGOHzca?Y@4f%t&R%0DW3Qd8x!1}ppE>v4^xYzWOjQY}1i-?=0=&O} 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 NZ}$HWN4dM1{{eArS%d%p literal 0 HcmV?d00001 diff --git a/images/算法/训练素材.jpg b/images/算法/训练素材.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fa6dc11b566774422f96761326e24a92a1f75f13 GIT binary patch literal 8355 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 literal 0 HcmV?d00001 diff --git a/source/_posts/算法/TensorFlow.js初见(1).md b/source/_posts/算法/TensorFlow.js初见(1).md new file mode 100644 index 0000000..d4cafba --- /dev/null +++ b/source/_posts/算法/TensorFlow.js初见(1).md @@ -0,0 +1,242 @@ +--- +title: TensorFlow.js初见(1) +date: 2021-4-1 15:00:28 +tags: + - TensorFlow + - 机器学习 +categories: + - 算法 +--- + +`TensorFlow`是Google发布的一个机器学习框架,可以构建和训练机器学习模型 +把机器学习的应用门槛降低了很多 +并且有对应的js版本,可以在nodejs或者浏览器环境运行 + + + +### 基础知识准备 + +#### 张量(Tensors) +`tf.Tensor`是TensorFlow.js中的最重要的数据单元,它是一个形状为一维或多维数组组成的数值的集合。tf.Tensor和多维数组其实非常的相似。 +一个tf.Tensor还包含如下属性: + ++ `rank`: 张量的维度 ++ `shape`: 每个维度的数据大小,代表了张量的形状 ++ `dtype`: 张量中的数据类型 + +```typescript +import * as tf from '@tensorflow/tfjs-node' + +const a = tf.tensor([[1, 2], [3, 4], [5, 6, 7]]) +console.log('rank:', a.rank) // 2 +console.log('shape:', a.shape) // [3,2] +console.log('dtype:', a.dtype) // float32 +a.print() +/* + [[1, 2], + [3, 4], + [5, 6]] +*/ +``` +从上述执行结果可以发现,超出边界的数据会被舍弃 +**tf.tensor**函数包含三个参数,后两个参数是可选的 ++ values: 原始数据 ++ shape: 数组,指定每个维度的数据大小(不指定则根据原始数据的多维数组层级决定) ++ dtype: 数据类型,只能是下面的几种值 +> ![DataType](/images/算法/DataType.jpg) +> ![DataTypeMap](/images/算法/DataTypeMap.jpg) + +#### 操作 +张量可以进行一些处理和运算,但是张量对象本身是**不可变**的 +这些操作都会产生新的张量对象 + +**改变形状** +```typescript +const a = tf.tensor([[1, 2], [3, 4]]); +const b = a.reshape([4, 1]); +b.print(); +/* + [[1], + [2], + [3], + [4]] +*/ +``` +上述代码表示将张量改变为第一层维度的长度为4,第二层维度的长度为1 + +**运算** +```typescript +// 对所有数据平方 +const x = tf.tensor([1, 2, 3, 4]) +const y = x.square() // 相当于 tf.square(x) +y.print() +``` + +```typescript +// 将两个张量逐个相加 +const a = tf.tensor([1, 2, 3, 4]) +const b = tf.tensor([10, 20, 30, 40]) +const y = a.add(b) // 相当于 tf.add(a, b) +y.print() +``` +执行add的情况两个张量的形状和数据类型必须一致 + + +### 模型训练 +作为一个初见HelloWorld,这是一个垃圾分类识别图片的demo +使用nodejs环境来执行这个过程 + +#### 1、安装nodejs版本的TensorFlow + +``` +npm install @tensorflow/tfjs-node +``` +当然它底层是在调用C++库,在windows环境需要使用node-gyp进行编译 +相比之下,mac和linux环境安装会顺利很多 + +> 为了代码的编写方便,我也添加了TypeScript的基础环境 +```json +"dependencies": { + "@tensorflow/tfjs-node": "^3.3.0", + "typescript": "^4.2.3" +}, +"devDependencies": { + "ts-node": "^9.1.1" +} +``` + +#### 2、准备训练素材 +[下载地址](https://cdn.colorfulsweet.site/resources/train.zip) +![训练素材](/images/算法/训练素材.jpg) +这里有4种类型的垃圾,每一种里面都有大量的图片 + +#### 3、读取训练素材 +这里主要就是一些nodejs当中读写文件的API +```typescript +/* +根据实际情况定义 trainDir 和 outputDir +也就是读取训练素材的目录和产出输出的目录 +*/ +// 读取目录,获取到的是固定顺序的4种类型的名称 +const types = fs.readdirSync(trainDir) +// 写入到文件,为后续的模型使用做准备 +fs.writeFileSync(`${outputDir}/types.json`, JSON.stringify(types)) + +const imageData: {imagePath: string, dirIndex: number}[] = [] +types.forEach((dir: string, dirIndex: number) => { + // 获取每个类型当中所有的图片名称 + const imgNames = fs.readdirSync(`${trainDir}/${dir}`) + imgNames.forEach(imgName => { + imageData.push({ + imagePath: `${trainDir}/${dir}/${imgName}`, + dirIndex // 这个index用于区分该图片属于哪种类型 + }) + }) +}) +``` +这里拿到的imageData是一个包含所有训练素材路径和类别索引的数组 + +#### 4、图片数据转化为张量 +```typescript +/** + * 图片数据处理 + * @param buffer 图片数据Buffer + * @returns + */ +const img2x = (buffer: Buffer) => { + // tf.tidy 执行后就会清除所有的中间张量,并释放它们的GPU内存(相当于优化运行过程, 这一层包装也可以不要) + return tf.tidy(() => { + // 图片格式转换 + const imgTs = tf.node.decodeImage(new Uint8Array(buffer)) + // 图片尺寸转换 + const imgTsResized = tf.image.resizeBilinear(imgTs, [224, 224]) + // 将像素值归一化到[-1, 1] + /** + * 图片像素值是[0, 255] + * 先减去 255 / 2, 此时区间是[-127.5, 127.5] + * 再除以 255 / 2, 此时区间是[-1, 1] + * reshape进行模型转换 + * 224,224代表尺寸 3代表RGB图片 1代表把图片放在数字1(拓展一维) + */ + return imgTsResized.toFloat().sub(255 / 2).div(255 / 2).reshape([1, 224, 224, 3]) + }) +} +``` + +#### 5、对大量训练素材进行处理 +由于直接把所有图片读取后转化为张量,会占用大量内存 +TensorFlow支持使用生成器函数进行分批处理 +> `imageData`为第3步中得到的图片路径数据 +```typescript +// 将图片数据打乱顺序 便于观察训练效果 +tf.util.shuffle(imageData) +// 防止数据过多全部读入内存无法容纳 +// 所以使用生成器函数进行分批读取 +const dataset = tf.data.generator(function* () { + const batchSize = 32 + for(let index = 0 ; index < imageData.length ; index += batchSize) { + const end = Math.min(index + batchSize, imageData.length) + yield tf.tidy(() => { + const inputs = [] + const labels: number[] = [] + for(let readIndex = index ; readIndex < end ; readIndex ++) { + // 同步读取图片,得到Buffer对象 + const imgBuffer = fs.readFileSync(imageData[readIndex].imagePath) + inputs.push(img2x(imgBuffer)) + labels.push(imageData[readIndex].dirIndex) + } + // 封装为Tensor的嵌套数组 + const xs = tf.concat(inputs) + const ys = tf.tensor(labels) + return {xs, ys} + }) + } +}) +``` + +#### 6、加载模型进行复用 +这里使用MobileNet这个模型进行复用 +所需文件: +[model.json](https://cdn.colorfulsweet.site/resources/MobileNet/model.json) +[group1-shard1of1.bin](https://cdn.colorfulsweet.site/resources/MobileNet/group1-shard1of1.bin) +```typescript +// 加载模型 +const mobilenet = await tf.loadLayersModel(`file://${process.cwd()}/resource/model.json`) +// 复用该模型 并截断部分 +const model = tf.sequential() // 定义一个连续的模型 +for(let i = 0 ; i <= 86 ; i++) { + const layer = mobilenet.layers[i] + layer.trainable = false + model.add(layer) +} +model.add(tf.layers.flatten()) // 数据扁平化 +model.add(tf.layers.dense({ // 隐藏层 + units: 10, // 神经元个数 + activation: 'relu', // 激活函数 +})) +model.add(tf.layers.dense({ // 输出层 + units: types.length, + activation: 'softmax' +})) +// 训练模型 + +// 定义损失函数和优化器 +model.compile({ + loss: 'sparseCategoricalCrossentropy', // 损失函数 + optimizer: tf.train.adam(), // 优化器 + metrics: ['acc'/* 准确度的度量 */] // 度量单位 +}) +``` + +#### 7、执行训练 +如果是一次性读取所有文件,直接使用`fit`方法 +如果是生成器函数分批读取的,使用`fitDataset`方法 +```typescript +// 使用fit方法进行训练(让模型参数尽可能拟合图片数据) +await model.fitDataset(dataset, { + epochs: 20 // 执行多少轮训练 +}) +// 使用save方法保存模型文件 +await model.save(`file://${process.cwd()}/output`) +``` +执行完毕后,就在output里面得到了训练好的模型文件 \ No newline at end of file