From 061fde4eafa72a2c148340d0913d08ed58b6b050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E8=BF=9B=E7=A6=84?= Date: Wed, 7 Jul 2021 18:59:42 +0800 Subject: [PATCH] =?UTF-8?q?ts=E5=AE=9E=E7=94=A8=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gulpfile.js | 13 +-- .../_posts/前端杂烩/TypeScript实用工具类型.md | 97 +++++++++++++++++++ source/_posts/算法/TensorFlow.js初见(2).md | 74 ++++++++++++++ 3 files changed, 178 insertions(+), 6 deletions(-) create mode 100644 source/_posts/前端杂烩/TypeScript实用工具类型.md create mode 100644 source/_posts/算法/TensorFlow.js初见(2).md diff --git a/gulpfile.js b/gulpfile.js index bc26f54..f9f5ab1 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,8 +1,9 @@ const gulp = require('gulp'), - htmlmin = require('gulp-htmlmin'), //html压缩组件 - htmlclean = require('gulp-htmlclean'), //html清理组件 - plumber = require('gulp-plumber'), //容错组件(发生错误不跳出任务,并报出错误内容) - Hexo = require('hexo') + htmlmin = require('gulp-htmlmin'), // html压缩组件 + htmlclean = require('gulp-htmlclean'), // html清理组件 + plumber = require('gulp-plumber'), // 容错组件(发生错误不跳出任务,并报出错误内容) + Hexo = require('hexo'), + log = require('fancy-log') // gulp的日志输出 // 程序执行的传参 const argv = require('optimist') @@ -55,7 +56,7 @@ gulp.task('compressHtml', () => { gulp.task('syncImages', () => { const listImages = require('./deploy_utils/list_images') if(!argv.accessKey || !argv.accessSecret) { - return Promise.resolve('未获得accessKey以及accessSecret, 跳过图片同步').then(console.log) + return Promise.resolve('未获得accessKey以及accessSecret, 跳过图片同步').then(log) } // 同步当前本地存在的所有图片 const rootPath = `${process.cwd()}/`.replace(/\\/g, '/') @@ -76,7 +77,7 @@ gulp.task('syncImages', () => { gulp.task('deploy', () => { if(!argv.deployPath) { - return Promise.resolve('未获得deployPath, 跳过发布').then(console.log) + return Promise.resolve('未获得deployPath, 跳过发布').then(log) } const deploy = require('./deploy_utils/deploy') return deploy.exec('./public', argv.deployPath, false) diff --git a/source/_posts/前端杂烩/TypeScript实用工具类型.md b/source/_posts/前端杂烩/TypeScript实用工具类型.md new file mode 100644 index 0000000..d45b950 --- /dev/null +++ b/source/_posts/前端杂烩/TypeScript实用工具类型.md @@ -0,0 +1,97 @@ +--- +title: TypeScript实用工具类型 +date: 2021-05-11 15:22:09 +tags: + - TypeScript +categories: + - 前端杂烩 +--- + +TypeScript当中有一些内置的类型,适用于编译过程 + + +### Partial\ +将Type的所有属性都设置为可选的,表示输入类型的所有子类型 +```typescript +interface Person { + name: string + code: number +} + +function show1(person: Partial) { + console.log(person) +} + +function show2(person: Person) { + console.log(person) +} + +show1({name: 'sookie'}) +show2({name: 'sookie'}) // ERROR: Argument of type '{ name: string; }' is not assignable to parameter of type 'Person'. +``` + +### Readonly\ +将Type的所有属性都设置为`readonly` + +```typescript +interface Person { + name: string + code: number +} + +const person: Readonly = { + name: 'sookie', + code: 1 +} + +person.code = 2 // ERROR: Cannot assign to 'code' because it is a read-only property. +``` + +### Record\ +用来将某个类型的属性映射到另一个类型上 +```typescript +interface PageInfo { + title: string +} +// 必须满足 string | number | symbol +type Page = 'home' | 'about' | 'contact' + +const item: Record = { + about: { title: 'about' }, + contact: { title: 'contact' }, + home: { title: 'home' }, +} +``` + +### Pick\ +从类型Type中挑选部分属性Keys来构造类型 +```typescript +interface Person { + name: string + age: number + remark: string +} +// 这里的第二个泛型值必须是属于 keyof Person +type PersonPick = Pick + +const p: PersonPick = { + name: 'sookie', + age: 10 +} +``` + +### Omit\ +与Pick用法类似,作用是相反的,用于从中剔除若干个key +```typescript +interface Person { + name: string + age: number + remark: string +} +type PersonOmit = Omit + +const p: PersonOmit = { + name: 'sookie', + age: 10 +} +``` \ No newline at end of file diff --git a/source/_posts/算法/TensorFlow.js初见(2).md b/source/_posts/算法/TensorFlow.js初见(2).md new file mode 100644 index 0000000..ec9ac48 --- /dev/null +++ b/source/_posts/算法/TensorFlow.js初见(2).md @@ -0,0 +1,74 @@ +--- +title: TensorFlow.js初见(2) +date: 2021-04-27 17:13:57 +tags: + - TensorFlow + - 机器学习 +categories: + - 算法 +--- + +模型训练好之后,就可以使用该模型进行预测了 +代码依然是nodejs环境的运行方式 + + + +```typescript +import * as tf from '@tensorflow/tfjs-node' +import * as fs from 'fs' + +(async function(){ + // 加载之前训练好的模型 + const model = await tf.loadLayersModel('http://localhost:8080/model.json') + // 打印模型的摘要信息 + model.summary() + + const imgBuffer = fs.readFileSync(`${process.cwd()}/resource/test/可回收物-帆布鞋.jpg`) + // 对图片数据的处理方式和训练的过程一样 + const x = img2x(imgBuffer) + // 执行预测 + const pred = model.predict(x) + pred.print() + console.log(pred.arraySync()[0]) +})() + +/** + * 图片数据处理 + * @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]) + }) +} +``` +这里在本地使用`http-server`启动了一个HTTP服务,方便加载模型 +上面代码最后输出的执行结果是 +``` +[ + 0.03434975817799568, + 0.001036567147821188, + 0.9645556211471558, + 0.00005802588930237107 +] +``` +与4种类型相对应 +``` +["其他垃圾","厨余垃圾","可回收物","有害垃圾"] +``` +显然与可回收物的匹配度较高,其他几种的匹配度较低 +> 实际预测的结果与模型的设定以及训练的素材数量相关 \ No newline at end of file