├── .gitignore
├── project
├── 2 归一化
│ ├── index.html
│ └── script.js
├── 6 过拟合
│ ├── index.html
│ ├── data.js
│ └── script.js
├── 0 准备
│ ├── index2.html
│ ├── script.js
│ ├── node.js
│ └── index.html
├── 1 线性回归
│ ├── index.html
│ └── script.js
├── 10 加载已有模型-商标识别
│ ├── index.html
│ ├── utils.js
│ └── script.js
├── 8 预训练模型-图片分类
│ ├── index.html
│ ├── script.js
│ └── imagenet_classes.js
├── 9 迁移学习-商标识别
│ ├── index.html
│ ├── utils.js
│ ├── data.js
│ └── script.js
├── 11 预训练模型-语音识别
│ ├── index.html
│ └── script.js
├── 3 逻辑回归
│ ├── index.html
│ ├── data.js
│ └── script.js
├── 4 XOR
│ ├── index.html
│ ├── data.js
│ └── script.js
├── 7 手写数字识别
│ ├── index.html
│ ├── script.js
│ └── data.js
├── 5 多分类
│ ├── index.html
│ ├── script.js
│ └── data.js
├── 12 迁移学习-声控数据采集
│ ├── index.html
│ └── script.js
├── 13 加载已有数据-声控轮播图
│ ├── index.html
│ └── script.js
└── 14 python与js模型互转
│ └── note.md
├── package.json
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | .cache
4 | data
--------------------------------------------------------------------------------
/project/2 归一化/index.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/project/6 过拟合/index.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/project/0 准备/index2.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/project/1 线性回归/index.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/project/0 准备/script.js:
--------------------------------------------------------------------------------
1 | import * as tf from "@tensorflow/tfjs"
2 |
3 | const a = tf.tensor('1')
4 | a.print()
--------------------------------------------------------------------------------
/project/0 准备/node.js:
--------------------------------------------------------------------------------
1 | const tf = require("@tensorflow/tfjs-node")
2 |
3 | const a = tf.tensor([1, 2])
4 | a.print()
--------------------------------------------------------------------------------
/project/10 加载已有模型-商标识别/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/project/8 预训练模型-图片分类/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/project/9 迁移学习-商标识别/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/project/11 预训练模型-语音识别/index.html:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/project/3 逻辑回归/index.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/project/4 XOR/index.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/project/7 手写数字识别/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/project/5 多分类/index.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/project/12 迁移学习-声控数据采集/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
监听开关:
9 |
--------------------------------------------------------------------------------
/project/0 准备/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | tensorflow
9 |
10 |
11 |
12 |
13 |
14 |
15 |
19 |
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "dependencies": {
7 | "@tensorflow-models/speech-commands": "^0.4.2",
8 | "@tensorflow/tfjs-node": "^1.6.0",
9 | "@tensorflow/tfjs-vis": "^1.4.0"
10 | },
11 | "devDependencies": {},
12 | "scripts": {
13 | "test": "echo \"Error: no test specified\" && exit 1"
14 | },
15 | "author": "",
16 | "license": "ISC",
17 | "browserslist": [
18 | "last 1 Chrome version"
19 | ]
20 | }
--------------------------------------------------------------------------------
/project/10 加载已有模型-商标识别/utils.js:
--------------------------------------------------------------------------------
1 | import * as tf from '@tensorflow/tfjs';
2 |
3 | export function img2x(imgEl) {
4 | return tf.tidy(() => {
5 | const input = tf.browser.fromPixels(imgEl)
6 | .toFloat()
7 | .sub(255 / 2)
8 | .div(255 / 2)
9 | .reshape([1, 224, 224, 3]);
10 | return input;
11 | });
12 | }
13 |
14 | export function file2img(f) {
15 | return new Promise(resolve => {
16 | const reader = new FileReader();
17 | reader.readAsDataURL(f);
18 | reader.onload = (e) => {
19 | const img = document.createElement('img');
20 | img.src = e.target.result;
21 | img.width = 224;
22 | img.height = 224;
23 | img.onload = () => resolve(img);
24 | };
25 | });
26 | }
--------------------------------------------------------------------------------
/project/9 迁移学习-商标识别/utils.js:
--------------------------------------------------------------------------------
1 | import * as tf from '@tensorflow/tfjs';
2 |
3 | export function img2x(imgEl) {
4 | return tf.tidy(() => {
5 | const input = tf.browser.fromPixels(imgEl)
6 | .toFloat()
7 | .sub(255 / 2)
8 | .div(255 / 2)
9 | .reshape([1, 224, 224, 3]);
10 | return input;
11 | });
12 | }
13 |
14 | export function file2image(file) {
15 | return new Promise(resolve => {
16 | const reader = new FileReader();
17 | reader.readAsDataURL(f);
18 | reader.onload = (e) => {
19 | const img = document.createElement('img');
20 | img.src = e.target.result;
21 | img.width = 224;
22 | img.height = 224;
23 | img.onload = () => resolve(img);
24 | };
25 | })
26 | }
--------------------------------------------------------------------------------
/project/4 XOR/data.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param {*} numSamples 随机生成点的数量
3 | */
4 | export function getData(numSamples) {
5 | let points = [];
6 |
7 | function genGauss(cx, cy, label) {
8 | for (let i = 0; i < numSamples / 2; i++) {
9 | let x = normalRandom(cx);
10 | let y = normalRandom(cy);
11 | points.push({
12 | x,
13 | y,
14 | label
15 | });
16 | }
17 | }
18 |
19 | // 这里产生四类点
20 | genGauss(2, 2, 0);
21 | genGauss(-2, -2, 0);
22 | genGauss(-2, 2, 1);
23 | genGauss(2, -2, 1);
24 | return points;
25 | }
26 |
27 | /**
28 | * @description 生成正态分布随机点
29 | * @param mean 均值
30 | * @param variance 方差,值越大点分布越分散,值越小点分布越密集
31 | */
32 | function normalRandom(mean = 0, variance = 1) {
33 | let v1, v2, s;
34 | do {
35 | v1 = 2 * Math.random() - 1;
36 | v2 = 2 * Math.random() - 1;
37 | s = v1 * v1 + v2 * v2;
38 | } while (s > 1);
39 |
40 | let result = Math.sqrt(-2 * Math.log(s) / s) * v1;
41 | return mean + Math.sqrt(variance) * result;
42 | }
--------------------------------------------------------------------------------
/project/3 逻辑回归/data.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @description 二分类数据集生成函数源码
3 | * @param {*} numSamples 随机生成点的数量
4 | */
5 | export function getData(numSamples) {
6 | let points = [];
7 |
8 | function genGauss(cx, cy, label) {
9 | for (let i = 0; i < numSamples / 2; i++) {
10 | let x = normalRandom(cx);
11 | let y = normalRandom(cy);
12 | points.push({
13 | x,
14 | y,
15 | label
16 | });
17 | }
18 | }
19 |
20 | genGauss(2, 2, 1); //生成以(2,2)为中心,label为1的点
21 | genGauss(-2, -2, 0); //生成以(-2,-2)为中心,label为0的点
22 | return points;
23 | }
24 |
25 | /**
26 | * @description 生成正态分布随机点
27 | * @param mean 均值
28 | * @param variance 方差,值越大点分布越分散,值越小点分布越密集
29 | */
30 | function normalRandom(mean = 0, variance = 1) {
31 | let v1, v2, s;
32 | do {
33 | v1 = 2 * Math.random() - 1;
34 | v2 = 2 * Math.random() - 1;
35 | s = v1 * v1 + v2 * v2;
36 | } while (s > 1);
37 |
38 | let result = Math.sqrt(-2 * Math.log(s) / s) * v1;
39 | return mean + Math.sqrt(variance) * result;
40 | }
--------------------------------------------------------------------------------
/project/6 过拟合/data.js:
--------------------------------------------------------------------------------
1 | export function getData(numSamples, variance) {
2 | let points = [];
3 |
4 | function genGauss(cx, cy, label) {
5 | for (let i = 0; i < numSamples / 2; i++) {
6 | let x = normalRandom(cx, variance);
7 | let y = normalRandom(cy, variance);
8 | points.push({ x, y, label });
9 | }
10 | }
11 |
12 | genGauss(2, 2, 1);
13 | genGauss(-2, -2, 0);
14 | return points;
15 | }
16 |
17 | /**
18 | * Samples from a normal distribution. Uses the seedrandom library as the
19 | * random generator.
20 | *
21 | * @param mean The mean. Default is 0.
22 | * @param variance The variance. Default is 1.
23 | */
24 | function normalRandom(mean = 0, variance = 1) {
25 | let v1, v2, s;
26 | do {
27 | v1 = 2 * Math.random() - 1;
28 | v2 = 2 * Math.random() - 1;
29 | s = v1 * v1 + v2 * v2;
30 | } while (s > 1);
31 |
32 | let result = Math.sqrt(-2 * Math.log(s) / s) * v1;
33 | return mean + Math.sqrt(variance) * result;
34 | }
--------------------------------------------------------------------------------
/project/1 线性回归/script.js:
--------------------------------------------------------------------------------
1 | import * as tf from '@tensorflow/tfjs';
2 | import * as tfvis from '@tensorflow/tfjs-vis';
3 |
4 | window.onload = async () => {
5 | // x、y样本数据集
6 | const xs = [1, 2, 3, 4];
7 | const ys = [1, 3, 5, 7];
8 |
9 | // 使用 @tensorflow/tfjs-vis 库绘制散点图
10 | tfvis.render.scatterplot(
11 | { name: '线性回归训练集' },
12 | { values: xs.map((x, i) => ({ x, y: ys[i] })) },
13 | { xAxisDomain: [0, 5], yAxisDomain: [0, 8] }
14 | );
15 |
16 | // 定义模型。添加含有1个神经元的1层网络
17 | const model = tf.sequential();
18 | model.add(tf.layers.dense({ units: 1, inputShape: [1] }));
19 | model.compile({ loss: tf.losses.meanSquaredError, optimizer: tf.train.sgd(0.1) });
20 |
21 | const inputs = tf.tensor(xs);
22 | const labels = tf.tensor(ys);
23 |
24 | // 训练模型
25 | await model.fit(inputs, labels, {
26 | batchSize: 4,
27 | epochs: 200,
28 | callbacks: tfvis.show.fitCallbacks(
29 | { name: '训练过程' },
30 | ['loss']
31 | )
32 | });
33 |
34 | // 预测
35 | const output = model.predict(tf.tensor([5]));
36 | console.log(`如果 x 为 5,那么预测 y 为 ${output.dataSync()[0]}`);
37 | };
--------------------------------------------------------------------------------
/project/13 加载已有数据-声控轮播图/index.html:
--------------------------------------------------------------------------------
1 |
2 | 监听开关:
3 |
4 |
16 |
17 |
18 |

19 |

20 |

21 |

22 |

23 |

24 |
25 |
--------------------------------------------------------------------------------
/project/9 迁移学习-商标识别/data.js:
--------------------------------------------------------------------------------
1 | import {
2 | promises
3 | } from "dns";
4 |
5 | const IMAGE_SIZE = 224;
6 |
7 | const loadImg = src => {
8 | return new Promise(resolve => {
9 | const img = new Image()
10 | img.crossOrigin = 'anonymous'
11 | img.src = src
12 | img.width = IMAGE_SIZE;
13 | img.height = IMAGE_SIZE;
14 | img.onload = () => resolve(img)
15 | })
16 | }
17 |
18 | // 输入数据格式
19 | export const getInputs = async() => {
20 | const imgList = [],
21 | labelList = []
22 | for (let i = 0; i < 30; i++) {
23 | ['android', 'apple', 'windows'].forEach(label => {
24 | const src = `http://127.0.0.1:8081/brand/train/${label}-${i}.jpg`;
25 | const img = loadImg(src)
26 | imgList.push(img)
27 | labelList.push([
28 | label === 'android' ? 1 : 0,
29 | label === 'apple' ? 1 : 0,
30 | label === 'windows' ? 1 : 0,
31 | ])
32 | })
33 | }
34 | const inputs = await Promise.all(imgList)
35 | return {
36 | inputs,
37 | labelList
38 | }
39 | }
--------------------------------------------------------------------------------
/project/11 预训练模型-语音识别/script.js:
--------------------------------------------------------------------------------
1 | import * as speechCommands from '@tensorflow-models/speech-commands';
2 | const MODEL_PATH = 'http://127.0.0.1:8081/speech';
3 |
4 | window.onload = async() => {
5 | const recognizer = speechCommands.create(
6 | 'BROWSER_FFT', //傅里叶变换
7 | null,
8 | MODEL_PATH + '/model.json',
9 | MODEL_PATH + '/metadata.json'
10 | )
11 | await recognizer.ensureModelLoaded()
12 |
13 |
14 | const labels = recognizer.wordLabels().slice(2)
15 | const resultEl = document.querySelector('#result')
16 | resultEl.innerHTML = labels.map(l => `
17 | ${l}
18 | `).join('');
19 |
20 | // 语音识别
21 | recognizer.listen(resilt => {
22 | const {
23 | scores
24 | } = result;
25 | const maxValue = Math.max(...scores);
26 | const index = scores.indexOf(maxValue) - 2;
27 | resultEl.innerHTML = labels.map((l, i) => `
28 | ${l}
29 | `).join('');
30 | }, {
31 | overlapFactor: 0.3, //控制频率,值越大,识别的次数越多
32 | probabilityThreshold: 0.9 //准确度
33 | })
34 | }
--------------------------------------------------------------------------------
/project/10 加载已有模型-商标识别/script.js:
--------------------------------------------------------------------------------
1 | import * as tf from '@tensorflow/tfjs';
2 | import {
3 | img2x,
4 | file2img
5 | } from './utils';
6 |
7 | const MODEL_PATH = 'http://127.0.0.1:8081';
8 | const BRAND_CLASSES = ['android', 'apple', 'windows'];
9 |
10 | window.onload = async() => {
11 | const mobilenet = await tf.loadLayersModel(MODEL_PATH + '/mobilenet/web_model/model.json');
12 | mobilenet.summary();
13 | const layer = mobilenet.getLayer('conv_pw_13_relu');
14 | const truncatedMobilenet = tf.model({
15 | inputs: mobilenet.inputs,
16 | outputs: layer.output
17 | });
18 |
19 | const model = await tf.loadLayersModel(MODEL_PATH + '/brand/web_model/model.json');
20 |
21 | window.predict = async(file) => {
22 | const img = await file2img(file);
23 | document.body.appendChild(img);
24 | const pred = tf.tidy(() => {
25 | const x = img2x(img);
26 | const input = truncatedMobilenet.predict(x);
27 | return model.predict(input);
28 | });
29 |
30 | const index = pred.argMax(1).dataSync()[0];
31 | setTimeout(() => {
32 | alert(`预测结果:${BRAND_CLASSES[index]}`);
33 | }, 0);
34 | };
35 | };
--------------------------------------------------------------------------------
/project/2 归一化/script.js:
--------------------------------------------------------------------------------
1 | import * as tf from '@tensorflow/tfjs';
2 | import * as tfvis from '@tensorflow/tfjs-vis';
3 |
4 | window.onload = async () => {
5 | // 样本数据
6 | const heights = [150, 160, 170];
7 | const weights = [40, 50, 60];
8 |
9 | // 绘制散点图
10 | tfvis.render.scatterplot({
11 | name: '身高体重训练数据'
12 | }, {
13 | values: heights.map((x, i) => ({
14 | x,
15 | y: weights[i]
16 | }))
17 | }, {
18 | xAxisDomain: [140, 180],
19 | yAxisDomain: [30, 70]
20 | });
21 |
22 | // 归一化数据
23 | const inputs = tf.tensor(heights).sub(150).div(20); //压缩到0-1
24 | const labels = tf.tensor(weights).sub(40).div(20); //压缩到0-1
25 |
26 | // 构建模型
27 | const model = tf.sequential();
28 | model.add(tf.layers.dense({
29 | units: 1,
30 | inputShape: [1]
31 | }));
32 | model.compile({
33 | loss: tf.losses.meanSquaredError,
34 | optimizer: tf.train.sgd(0.1)
35 | });
36 |
37 | // 训练模型
38 | await model.fit(inputs, labels, {
39 | batchSize: 3,
40 | epochs: 200,
41 | callbacks: tfvis.show.fitCallbacks({
42 | name: '训练过程'
43 | }, ['loss'])
44 | });
45 |
46 | // 预测 反归一化
47 | const output = model.predict(tf.tensor([180]).sub(150).div(20));
48 | console.log(`如果身高为 180cm,那么预测体重为 ${output.mul(20).add(40).dataSync()[0]}kg`);
49 | };
--------------------------------------------------------------------------------
/project/4 XOR/script.js:
--------------------------------------------------------------------------------
1 | import * as tf from '@tensorflow/tfjs';
2 | import * as tfvis from '@tensorflow/tfjs-vis';
3 | import { getData } from './data.js';
4 |
5 | // 不能使用线性逻辑回归
6 | window.onload = async () => {
7 | const data = getData(400);
8 |
9 | tfvis.render.scatterplot({
10 | name: 'XOR 训练数据'
11 | }, {
12 | values: [
13 | data.filter(p => p.label === 1),
14 | data.filter(p => p.label === 0),
15 | ]
16 | });
17 |
18 | // 构建多层神经网络
19 | const model = tf.sequential();
20 | model.add(tf.layers.dense({
21 | units: 4,
22 | inputShape: [2],
23 | activation: 'relu'
24 | }));
25 | model.add(tf.layers.dense({
26 | units: 1,
27 | activation: 'sigmoid'
28 | }));
29 | model.compile({
30 | loss: tf.losses.logLoss,
31 | optimizer: tf.train.adam(0.1)
32 | });
33 |
34 | const inputs = tf.tensor(data.map(p => [p.x, p.y]));
35 | const labels = tf.tensor(data.map(p => p.label));
36 |
37 | await model.fit(inputs, labels, {
38 | epochs: 10,
39 | callbacks: tfvis.show.fitCallbacks({
40 | name: '训练效果'
41 | }, ['loss'])
42 | });
43 |
44 | window.predict = (form) => {
45 | const pred = model.predict(tf.tensor([
46 | [form.x.value * 1, form.y.value * 1]
47 | ]));
48 | console.log(`预测结果:${pred.dataSync()[0]}`);
49 | };
50 | };
--------------------------------------------------------------------------------
/project/3 逻辑回归/script.js:
--------------------------------------------------------------------------------
1 | import * as tf from '@tensorflow/tfjs';
2 | import * as tfvis from '@tensorflow/tfjs-vis';
3 | import { getData } from './data.js';
4 |
5 | window.onload = async () => {
6 | // 拿到400个数据
7 | const data = getData(400);
8 |
9 | // 绘制散点图
10 | tfvis.render.scatterplot({
11 | name: '逻辑回归训练数据'
12 | }, {
13 | values: [
14 | data.filter(p => p.label === 1),
15 | data.filter(p => p.label === 0),
16 | ]
17 | });
18 |
19 | // 构建模型,主要这里是逻辑回归,使用的损失函数为对数损失 logLoss,可参考http://wiki.fast.ai/index.php/Log_Loss
20 | const model = tf.sequential();
21 | model.add(tf.layers.dense({
22 | units: 1,
23 | inputShape: [2], //特征数量
24 | activation: 'sigmoid'
25 | }));
26 | model.compile({
27 | loss: tf.losses.logLoss, //对数损失,逻辑回归不适合使用MSE
28 | optimizer: tf.train.adam(0.1) //adam优化器,可以自动调节学习率
29 | });
30 |
31 | const inputs = tf.tensor(data.map(p => [p.x, p.y]));
32 | const labels = tf.tensor(data.map(p => p.label));
33 |
34 | // 训练模型
35 | await model.fit(inputs, labels, {
36 | batchSize: 40,
37 | epochs: 20,
38 | callbacks: tfvis.show.fitCallbacks({
39 | name: '训练效果'
40 | }, ['loss'])
41 | });
42 |
43 | // 编写界面输入预测值
44 | window.predict = (form) => {
45 | const pred = model.predict(tf.tensor([
46 | [form.x.value * 1, form.y.value * 1]
47 | ]));
48 | console.log(`预测结果:${pred.dataSync()[0]}`);
49 | };
50 | };
--------------------------------------------------------------------------------
/project/8 预训练模型-图片分类/script.js:
--------------------------------------------------------------------------------
1 | import * as tf from '@tensorflow/tfjs';
2 | import {
3 | IMAGENET_CLASSES
4 | } from './imagenet_classes';
5 |
6 | const MOBILENET_MODEL_PATH = 'http://127.0.0.1:8081/mobilenet/web_model/model.json';
7 |
8 | // file变为img标签
9 | function file2img(file) {
10 | return new Promise(resolve => {
11 | const reader = new FileReader()
12 | reader.readAsDataURL(file)
13 | reader.onload = e => {
14 | const img = document.createElement('img');
15 | img.src = e.target.result;
16 | img.width = 224;
17 | img.height = 224;
18 | img.onload = () => resolve(img);
19 | }
20 | })
21 | }
22 |
23 | window.onload = async() => {
24 | const model = await tf.loadLayersModel(MOBILENET_MODEL_PATH);
25 | window.predict = async(file) => {
26 | const img = await file2img(file);
27 | document.body.appendChild(img);
28 | const pred = tf.tidy(() => {
29 | const input = tf.browser.fromPixels(img)
30 | .toFloat()
31 | .sub(255 / 2)
32 | .div(255 / 2) //转换到[-1,1]
33 | .reshape([1, 224, 224, 3]); //彩色图片
34 | return model.predict(input);
35 | })
36 | const index = pred.argMax(1).dataSync()[0] //index的值
37 | document.getElementById('output').innerHTML = `预测结果:${IMAGENET_CLASSES[index]}`
38 | }
39 | }
--------------------------------------------------------------------------------
/project/6 过拟合/script.js:
--------------------------------------------------------------------------------
1 | import * as tf from '@tensorflow/tfjs';
2 | import * as tfvis from '@tensorflow/tfjs-vis';
3 | import {
4 | getData
5 | } from './data';
6 |
7 | window.onload = async() => {
8 | const data = getData(200, 2);
9 |
10 | tfvis.render.scatterplot({
11 | name: '训练数据'
12 | }, {
13 | values: [
14 | data.filter(p => p.label === 1),
15 | data.filter(p => p.label === 0),
16 | ]
17 | });
18 |
19 | // 解决overfit
20 | // 1、早停
21 | // 2、正则化
22 | // 3、随机丢弃
23 | const model = tf.sequential();
24 | model.add(tf.layers.dense({
25 | units: 10,
26 | inputShape: [2],
27 | activation: "tanh",
28 | // kernelRegularizer: tf.regularizers.l2({ l2: 1 })
29 | }));
30 | model.add(tf.layers.dropout({
31 | rate: 0.9
32 | }));
33 | model.add(tf.layers.dense({
34 | units: 1,
35 | activation: 'sigmoid'
36 | }));
37 | model.compile({
38 | loss: tf.losses.logLoss,
39 | optimizer: tf.train.adam(0.1)
40 | });
41 |
42 | const inputs = tf.tensor(data.map(p => [p.x, p.y]));
43 | const labels = tf.tensor(data.map(p => p.label));
44 |
45 | await model.fit(inputs, labels, {
46 | validationSplit: 0.2,
47 | epochs: 200,
48 | callbacks: tfvis.show.fitCallbacks({
49 | name: '训练效果'
50 | }, ['loss', 'val_loss'], {
51 | callbacks: ['onEpochEnd']
52 | })
53 | });
54 | };
--------------------------------------------------------------------------------
/project/5 多分类/script.js:
--------------------------------------------------------------------------------
1 | import * as tf from '@tensorflow/tfjs';
2 | import * as tfvis from '@tensorflow/tfjs-vis';
3 | import { getIrisData, IRIS_CLASSES } from './data';
4 |
5 | window.onload = async () => {
6 | // 加载数据集和验证集
7 | const [xTrain, yTrain, xTest, yTest] = getIrisData(0.15); //15%的数据用于验证集
8 |
9 | // 构建模型,这里用到的损失函数为交叉熵损失 categoricalCrossentropy,适用于多分类
10 | const model = tf.sequential();
11 | model.add(tf.layers.dense({
12 | units: 10,
13 | inputShape: [xTrain.shape[1]],
14 | activation: 'sigmoid' //也可以使用其他激活函数,如relu
15 | }));
16 | model.add(tf.layers.dense({
17 | units: 3,
18 | activation: 'softmax' //这里使用softmax激活函数,算出每个类别的概率
19 | }));
20 | model.compile({
21 | loss: 'categoricalCrossentropy', //交叉熵损失,对数损失函数的多分类版本
22 | optimizer: tf.train.adam(0.1),
23 | metrics: ['accuracy']
24 | });
25 |
26 | // 训练模型
27 | await model.fit(xTrain, yTrain, {
28 | epochs: 100,
29 | validationData: [xTest, yTest],
30 | callbacks: tfvis.show.fitCallbacks({
31 | name: '训练效果'
32 | }, ['loss', 'val_loss', 'acc', 'val_acc'], {
33 | callbacks: ['onEpochEnd']
34 | })
35 | });
36 |
37 | window.predict = (form) => {
38 | const input = tf.tensor([
39 | [
40 | form.a.value * 1,
41 | form.b.value * 1,
42 | form.c.value * 1,
43 | form.d.value * 1,
44 | ]
45 | ]);
46 | const pred = model.predict(input);
47 | console.log(`预测结果:${IRIS_CLASSES[pred.argMax(1).dataSync(0)]}`); //argmax?
48 | };
49 | };
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Tensorflow.js Converter 依赖**python3.6.8**版本
2 |
3 | **搭建虚拟环境:**
4 | 1. 安装conda
5 | 可以使用[清华镜像源](https://mirror.tuna.tsinghua.edu.cn/help/anaconda/),安装Miniconda 即可(注意配置环境变量)
6 | 2. 在终端检查conda命令是否可用,并创建指定python版本的虚拟环境
7 | `conda create -n [name] python=3.6.8` 创建虚拟环境
8 | `conda remove -n [name] --all` 删除虚拟环境
9 | `conda info --envs` 查看虚拟环境
10 | `conda activate [name]` 激活虚拟环境(可以发现python版本已经改变)
11 | `conda deactivate [name]` 退出虚拟环境
12 | 3. 安装tfjs converter
13 | `pip install tensorflowjs`安装
14 | `tensorflowjs_converter -h`检查是否安装成功
15 |
16 |
17 | **python与JavaScript模型的互转:**
18 | 1. 准备工作
19 | `conda activate [name]`激活
20 | `tensorflowjs_converter`检查
21 | 2. 开始转换——具体格式建议看文档(github tfjs-converter)
22 | 1)python模型转js模型
23 | `tensorflowjs_converter --input_format=keras --output_format=tf_layers_model [input_path] [output_path]`
24 | 2)js模型转python模型
25 | `tensorflowjs_converter --input_format=tf_layers_model --output_format=keras [input_path] [output_path]`
26 | 3. 验证模型正确性
27 |
28 | **模型加速:**
29 | 1. 分片(--weight_shared_size_bytes=[size])
30 | `tensorflowjs_converter --input_format=tf_layers_model --output_format=tf_layers_model --weight_shared_size_bytes=100000 [input_path] [output_path]`
31 | 在输出文件夹中会发现很多块分片后的模型,这样在加载模型时可以使用并发实现加速
32 | 2. 量化(--quantization_bytes=[n])
33 | `tensorflowjs_converter --input_format=tf_layers_model --output_format=tf_layers_model --quantization_bytes=2 [input_path] [output_path]`
34 | 3. 通过转为tfjs_graph_model来加速模型——内部实现了凸优化(--output_format=tf_graph_model)
35 | `tensorflowjs_converter --input_format=tf_layers_model --output_format=tf_graph_model [input_path] [output_path]`
36 |
37 | **拓展学习:**
38 | 1. 举一反三,训练不同应用场景的AI模型
39 | 2. 多看官方文档
40 | 3. 使用更多的预训练模型,如目标检测、NLP、人体姿势识别
41 | 4. 做更多智能相关的开源项目或商业项目,增加技术影响力
--------------------------------------------------------------------------------
/project/14 python与js模型互转/note.md:
--------------------------------------------------------------------------------
1 | Tensorflow.js Converter 依赖**python3.6.8**版本
2 |
3 | **搭建虚拟环境:**
4 | 1. 安装conda
5 | 可以使用[清华镜像源](https://mirror.tuna.tsinghua.edu.cn/help/anaconda/),安装Miniconda 即可(注意配置环境变量)
6 | 2. 在终端检查conda命令是否可用,并创建指定python版本的虚拟环境
7 | `conda create -n [name] python=3.6.8` 创建虚拟环境
8 | `conda remove -n [name] --all` 删除虚拟环境
9 | `conda info --envs` 查看虚拟环境
10 | `conda activate [name]` 激活虚拟环境(可以发现python版本已经改变)
11 | `conda deactivate [name]` 退出虚拟环境
12 | 3. 安装tfjs converter
13 | `pip install tensorflowjs`安装
14 | `tensorflowjs_converter -h`检查是否安装成功
15 |
16 |
17 | **python与JavaScript模型的互转:**
18 | 1. 准备工作
19 | `conda activate [name]`激活
20 | `tensorflowjs_converter`检查
21 | 2. 开始转换——具体格式建议看文档(github tfjs-converter)
22 | 1)python模型转js模型
23 | `tensorflowjs_converter --input_format=keras --output_format=tf_layers_model [input_path] [output_path]`
24 | 2)js模型转python模型
25 | `tensorflowjs_converter --input_format=tf_layers_model --output_format=keras [input_path] [output_path]`
26 | 3. 验证模型正确性
27 |
28 | **模型加速:**
29 | 1. 分片(--weight_shared_size_bytes=[size])
30 | `tensorflowjs_converter --input_format=tf_layers_model --output_format=tf_layers_model --weight_shared_size_bytes=100000 [input_path] [output_path]`
31 | 在输出文件夹中会发现很多块分片后的模型,这样在加载模型时可以使用并发实现加速
32 | 2. 量化(--quantization_bytes=[n])
33 | `tensorflowjs_converter --input_format=tf_layers_model --output_format=tf_layers_model --quantization_bytes=2 [input_path] [output_path]`
34 | 3. 通过转为tfjs_graph_model来加速模型——内部实现了凸优化(--output_format=tf_graph_model)
35 | `tensorflowjs_converter --input_format=tf_layers_model --output_format=tf_graph_model [input_path] [output_path]`
36 |
37 | **拓展学习:**
38 | 1. 举一反三,训练不同应用场景的AI模型
39 | 2. 多看官方文档
40 | 3. 使用更多的预训练模型,如目标检测、NLP、人体姿势识别
41 | 4. 做更多智能相关的开源项目或商业项目,增加技术影响力
--------------------------------------------------------------------------------
/project/13 加载已有数据-声控轮播图/script.js:
--------------------------------------------------------------------------------
1 | import * as speechCommands from '@tensorflow-models/speech-commands';
2 |
3 | const MODEL_PATH = 'http://127.0.0.1:8081';
4 | let transferRecognizer;
5 |
6 | window.onload = async() => {
7 | const recognizer = speechCommands.create(
8 | 'BROWSER_FFT',
9 | null,
10 | MODEL_PATH + '/speech/model.json',
11 | MODEL_PATH + '/speech/metadata.json',
12 | );
13 | await recognizer.ensureModelLoaded();
14 | transferRecognizer = recognizer.createTransfer('轮播图');
15 |
16 | // 在这里加载已保存的声音数据
17 | const res = await fetch(MODEL_PATH + '/slider/data.bin');
18 | const arrayBuffer = await res.arrayBuffer();
19 | transferRecognizer.loadExamples(arrayBuffer);
20 | await transferRecognizer.train({
21 | epochs: 30
22 | });
23 | console.log('done');
24 | };
25 |
26 | window.toggle = async(checked) => {
27 | if (checked) {
28 | await transferRecognizer.listen(result => {
29 | const {
30 | scores
31 | } = result;
32 | const labels = transferRecognizer.wordLabels();
33 | const index = scores.indexOf(Math.max(...scores));
34 | console.log(labels[index]); //“上一张”/“下一张”
35 | window.play(labels[index]); //变换轮播图
36 | }, {
37 | overlapFactor: 0,
38 | probabilityThreshold: 0.5
39 | });
40 | } else {
41 | transferRecognizer.stopListening();
42 | }
43 | };
44 |
45 | let curIndex = 0;
46 | const sliderCount = document.querySelectorAll('img').length
47 | window.play = label => {
48 | const div = document.querySelector('.slider>div');
49 | if (label === '上一张') {
50 | if (curIndex === 0) {
51 | return;
52 | }
53 | curIndex -= 1;
54 | } else {
55 | if (curIndex === sliderCount - 1) {
56 | return;
57 | }
58 | curIndex += 1;
59 | }
60 | div.style.transition = "transform 1s"
61 | div.style.transform = `translateX(-${100 * curIndex}%)`;
62 | }
--------------------------------------------------------------------------------
/project/12 迁移学习-声控数据采集/script.js:
--------------------------------------------------------------------------------
1 | import * as speechCommands from '@tensorflow-models/speech-commands';
2 | import * as tfvis from '@tensorflow/tfjs-vis';
3 |
4 | const MODEL_PATH = 'http://127.0.0.1:8081';
5 | let transferRecognizer; //定义迁移学习器(迁移学习语音识别器)
6 |
7 | window.onload = async() => {
8 | const recognizer = speechCommands.create(
9 | 'BROWSER_FFT',
10 | null,
11 | MODEL_PATH + '/speech/model.json',
12 | MODEL_PATH + '/speech/metadata.json'
13 | );
14 | await recognizer.ensureModelLoaded();
15 | transferRecognizer = recognizer.createTransfer('轮播图');
16 | }
17 |
18 | // 收集声音
19 | window.collect = async(btn) => {
20 | btn.disabled = true;
21 | const label = btn.innerText;
22 | await transferRecognizer.collectExample(label === '背景噪音' ? '_background_noise_' : label)
23 | btn.disabled = false;
24 | document.querySelector('$count').innerHTML = JSON.stringify(transferRecognizer.countExamples(), null, 2);
25 | }
26 |
27 | // 训练模型
28 | window.train = async() => {
29 | await transferRecognizer.train({
30 | epochs: 30,
31 | callback: tfvis.show.fitCallbacks({
32 | name: '训练效果'
33 | }, ['loss', 'acc'], {
34 | callbacks: ['onEpochEnd']
35 | })
36 | });
37 | }
38 |
39 | window.toggle = async(checked) => {
40 | if (checked) {
41 | await transferRecognizer.listen(result => {
42 | const {
43 | scores
44 | } = result;
45 | const labels = transferRecognizer.wordLabels();
46 | const index = scores.indexOf(Math.max(...scores));
47 | console.log(labels[index]);
48 | }, {
49 | overlapFactor: 0, //值越大识别越频繁
50 | probabilityThreshold: 0.75 //准确度
51 | })
52 | } else {
53 | transferRecognizer.stopListening();
54 | }
55 | }
56 |
57 | // 存储采集到的语音数据,避免每次都要录入
58 | window.save = () => {
59 | const arrayBuffer = transferRecognizer.serializeExamples()
60 | const blob = new Blob([arrayBuffer])
61 | const link = document.createElement('a')
62 | link.href = window.URL.createObjectURL(blob)
63 | link.download = 'data.bin' //定义下载名称
64 | link.click()
65 | }
--------------------------------------------------------------------------------
/project/9 迁移学习-商标识别/script.js:
--------------------------------------------------------------------------------
1 | import * as tf from '@tensorflow/tfjs';
2 | import * as tfvis from '@tensorflow/tfjs-vis';
3 | import {
4 | getInputs
5 | } from './data';
6 | import {
7 | img2x,
8 | file2img
9 | } from './utils';
10 |
11 | const MOBILENET_MODEL_PATH = 'http://127.0.0.1:8081/mobilenet/web_model/model.json';
12 | const NUM_CLASSES = 3;
13 | const BRAND_CLASSES = ['android', 'apple', 'windows'];
14 |
15 | window.onload = async() => {
16 | const {
17 | inputs,
18 | labels
19 | } = await getInputs();
20 |
21 | // 可视化商标
22 | const surface = tfvis.visor().surface({
23 | name: '输入示例',
24 | styles: {
25 | height: 250
26 | }
27 | });
28 | inputs.forEach(img => {
29 | surface.drawArea.appendChild(img);
30 | });
31 |
32 | // 加载mobilenet模型
33 | const mobilenet = await tf.loadLayersModel(MOBILENET_MODEL_PATH)
34 | mobilenet.summary(); //查看模型概况
35 | // 开始截断模型
36 | const layer = mobilenet.getLayer('conv_pw_13_relu');
37 | const truncatedMobilenet = tf.model({
38 | inputs: mobilenet.inputs,
39 | outputs: layer.output
40 | })
41 |
42 | // 添加网络
43 | const model = tf.sequential()
44 | model.add(tf.layers.flatten({
45 | inputShape: layer.outputShape.slice(1) //[null,7,7,256]
46 | }));
47 | model.add(tf.layers.dense({
48 | units: 10,
49 | activation: 'relu'
50 | }));
51 | model.add(tf.layers.dense({
52 | units: NUM_CLASSES,
53 | activation: 'softmax'
54 | }));
55 | model.compile({
56 | loss: 'categoricalCrossentropy',
57 | optimizer: tf.train.adam()
58 | })
59 |
60 | // 将训练数据输入到截断模型中
61 | const {
62 | xs,
63 | ys
64 | } = tf.tidy(() => {
65 | const xs = tf.concat(inputs.map(imgEl => truncatedMobilenet.predict(img2x(imgEl)))) //xs为truncatedMobilenet网络吐出的数据
66 | const ys = tf.tensor(labels)
67 | return {
68 | xs,
69 | ys
70 | }
71 | })
72 | await model.fit(xs, ys, {
73 | epochs: 20,
74 | callbacks: tfvis.show.fitCallbacks({
75 | name: '训练效果'
76 | }, ['loss'], {
77 | callbacks: ['onEpochEnd']
78 | })
79 | });
80 |
81 | // 预测
82 | window.predict = async(file) => {
83 | const img = await file2img(file);
84 | document.body.appendChild(img);
85 | const pred = tf.tidy(() => {
86 | const x = img2x(img);
87 | const input = truncatedMobilenet.predict(x);
88 | return model.predict(input);
89 | })
90 | const index = pred.argMax(1).dataSync()[0];
91 | document.getElementById('output').innerHTML = `预测结果:${BRAND_CLASSES[index]}`
92 | }
93 | window.download = async() => {
94 | await model.save('downloads://model'); //建议看官方文档model.save
95 | };
96 | }
--------------------------------------------------------------------------------
/project/7 手写数字识别/script.js:
--------------------------------------------------------------------------------
1 | import * as tf from '@tensorflow/tfjs';
2 | import * as tfvis from '@tensorflow/tfjs-vis';
3 | import { MnistData } from './data';
4 |
5 | window.onload = async () => {
6 | const data = new MnistData();
7 | await data.load();
8 | const examples = data.nextTestBatch(20)
9 | const surface = tfvis.visor().surface({
10 | name: '输入示例'
11 | });
12 |
13 | // 展示样本中的手写数据
14 | for (let i = 0; i < 20; i++) {
15 | // 清除tensor内存,防止内存泄漏
16 | const imageTensor = tf.tidy(() => {
17 | return examples.xs
18 | .slice([i, 0], [1, 784]) //这里详细查看文档,tf.slice()方法是使用
19 | .reshape([28, 28, 1]);
20 | })
21 |
22 | // 在浏览器中展示
23 | const canvas = document.createElement('canvas');
24 | canvas.width = 28;
25 | canvas.height = 28;
26 | canvas.style = 'margin: 4px';
27 | await tf.browser.toPixels(imageTensor, canvas);
28 |
29 | surface.drawArea.appendChild(canvas)
30 | }
31 |
32 | // 定义模型
33 | // 1. 卷积(5*5*8)
34 | // 2. 池化
35 | // 3. 卷积(5*5*16)
36 | // 4. 池化
37 | // 5. flatten
38 | // 6. softmax
39 | const model = tf.sequential()
40 | model.add(tf.layers.conv2d({
41 | inputShape: [28, 28, 1],
42 | kernelSize: 5,
43 | filters: 8,
44 | strides: 1,
45 | activation: 'relu',
46 | kernelInitializer: 'varianceScaling'
47 | }))
48 | model.add(tf.layers.maxPool2d({
49 | poolSize: [2, 2],
50 | strides: [2, 2]
51 | }))
52 | model.add(tf.layers.conv2d({
53 | kernelSize: 5,
54 | filters: 16,
55 | strides: 1,
56 | activation: 'relu',
57 | kernelInitializer: 'varianceScaling'
58 | }))
59 | model.add(tf.layers.maxPool2d({
60 | poolSize: [2, 2],
61 | strides: [2, 2]
62 | }))
63 | model.add(tf.layers.flatten())
64 | model.add(tf.layers.dense({
65 | units: 10,
66 | activation: 'softmax',
67 | kernelInitializer: 'varianceScaling'
68 | }))
69 | model.compile({
70 | loss: 'categoricalCrossentropy',
71 | optimizer: tf.train.adam(),
72 | metrics: ['accuracy']
73 | })
74 |
75 | const [trainX, trainY] = tf.tidy(() => {
76 | const d = data.nextTrainBatch(1000)
77 | return [
78 | d.xs.reshape([1000, 28, 28, 1]),
79 | d.labels
80 | ]
81 | })
82 | const [testX, testY] = tf.tidy(() => {
83 | const d = data.nextTestBatch(200)
84 | return [
85 | d.xs.reshape([200, 28, 28, 1]),
86 | d.labels
87 | ]
88 | })
89 |
90 | // 训练模型
91 | await model.fit(trainX, trainY, {
92 | validationData: [testX, testY],
93 | batchSize: 500,
94 | epochs: 50,
95 | callbacks: tfvis.show.fitCallbacks({
96 | name: '训练效果'
97 | }, ['loss', 'val_loss', 'acc', 'val_acc'], {
98 | callbacks: ['onEpochEnd']
99 | })
100 | })
101 |
102 | // 画布支持绘制,监听mousemove方法
103 | const canvas = document.querySelector('canvas')
104 | canvas.addEventListener('mousemove', e => {
105 | if (e.buttons === 1) {
106 | const ctx = canvas.getContext('2d')
107 | ctx.fillStyle = 'rgb(255,255,255)';
108 | ctx.fillRect(e.offsetX, e.offsetY, 10, 10);
109 | }
110 | })
111 | // 清楚画布
112 | window.clear = () => {
113 | const ctx = canvas.getContext('2d');
114 | ctx.fillStyle = 'rgb(0,0,0)';
115 | ctx.fillRect(0, 0, 300, 300);
116 | }
117 | clear()
118 |
119 | // 预测
120 | window.predict = () => {
121 | const input = tf.tidy(() => {
122 | return tf.image.resizeBilinear( //tf.image.resizeBilinear改变图片尺寸 (300,300)->(28,28)
123 | tf.browser.fromPixels(canvas), [28, 28], //tf.browser.fromPixels是将canvas/image转化为tensor
124 | true
125 | ).slice([0, 0, 0], [28, 28, 1]) //将彩色通道转化为黑白通道,将rgb通道切掉
126 | .toFloat()
127 | .div(255) //归一化(0,1)
128 | .reshape([1, 28, 28, 1]);
129 | });
130 | const pred = model.predict(input).argMax(1);
131 | document.getElementById('output').innerHTML = `预测结果为 ${pred.dataSync()[0]}`
132 | };
133 | }
--------------------------------------------------------------------------------
/project/7 手写数字识别/data.js:
--------------------------------------------------------------------------------
1 | import * as tf from '@tensorflow/tfjs';
2 |
3 | const IMAGE_SIZE = 784;
4 | const NUM_CLASSES = 10;
5 | const NUM_DATASET_ELEMENTS = 65000;
6 | const TRAIN_TEST_RATIO = 5 / 6;
7 | const NUM_TRAIN_ELEMENTS = Math.floor(TRAIN_TEST_RATIO * NUM_DATASET_ELEMENTS);
8 | const NUM_TEST_ELEMENTS = NUM_DATASET_ELEMENTS - NUM_TRAIN_ELEMENTS;
9 | const MNIST_IMAGES_SPRITE_PATH = 'http://127.0.0.1:8081/mnist/mnist_images.png';
10 | const MNIST_LABELS_PATH = 'http://127.0.0.1:8081/mnist/mnist_labels_uint8';
11 | export class MnistData {
12 | constructor() {
13 | this.shuffledTrainIndex = 0;
14 | this.shuffledTestIndex = 0;
15 | }
16 |
17 | async load() {
18 | const img = new Image();
19 | const canvas = document.createElement('canvas');
20 | const ctx = canvas.getContext('2d');
21 | const imgRequest = new Promise((resolve, reject) => {
22 | img.crossOrigin = '';
23 | img.onload = () => {
24 | img.width = img.naturalWidth;
25 | img.height = img.naturalHeight;
26 |
27 | const datasetBytesBuffer =
28 | new ArrayBuffer(NUM_DATASET_ELEMENTS * IMAGE_SIZE * 4);
29 |
30 | const chunkSize = 5000;
31 | canvas.width = img.width;
32 | canvas.height = chunkSize;
33 |
34 | for (let i = 0; i < NUM_DATASET_ELEMENTS / chunkSize; i++) {
35 | const datasetBytesView = new Float32Array(
36 | datasetBytesBuffer, i * IMAGE_SIZE * chunkSize * 4,
37 | IMAGE_SIZE * chunkSize);
38 | ctx.drawImage(
39 | img, 0, i * chunkSize, img.width, chunkSize, 0, 0, img.width,
40 | chunkSize);
41 |
42 | const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
43 | for (let j = 0; j < imageData.data.length / 4; j++) {
44 | datasetBytesView[j] = imageData.data[j * 4] / 255;
45 | }
46 | }
47 | this.datasetImages = new Float32Array(datasetBytesBuffer);
48 |
49 | resolve();
50 | };
51 | img.src = MNIST_IMAGES_SPRITE_PATH;
52 | });
53 |
54 | const labelsRequest = fetch(MNIST_LABELS_PATH);
55 | const [imgResponse, labelsResponse] =
56 | await Promise.all([imgRequest, labelsRequest]);
57 |
58 | this.datasetLabels = new Uint8Array(await labelsResponse.arrayBuffer());
59 | this.trainIndices = tf.util.createShuffledIndices(NUM_TRAIN_ELEMENTS);
60 | this.testIndices = tf.util.createShuffledIndices(NUM_TEST_ELEMENTS);
61 | this.trainImages = this.datasetImages.slice(0, IMAGE_SIZE * NUM_TRAIN_ELEMENTS);
62 | this.testImages = this.datasetImages.slice(IMAGE_SIZE * NUM_TRAIN_ELEMENTS);
63 | this.trainLabels = this.datasetLabels.slice(0, NUM_CLASSES * NUM_TRAIN_ELEMENTS);
64 | this.testLabels = this.datasetLabels.slice(NUM_CLASSES * NUM_TRAIN_ELEMENTS);
65 | }
66 |
67 | nextTrainBatch(batchSize) {
68 | return this.nextBatch(
69 | batchSize, [this.trainImages, this.trainLabels], () => {
70 | this.shuffledTrainIndex =
71 | (this.shuffledTrainIndex + 1) % this.trainIndices.length;
72 | return this.trainIndices[this.shuffledTrainIndex];
73 | });
74 | }
75 |
76 | nextTestBatch(batchSize) {
77 | return this.nextBatch(batchSize, [this.testImages, this.testLabels], () => {
78 | this.shuffledTestIndex =
79 | (this.shuffledTestIndex + 1) % this.testIndices.length;
80 | return this.testIndices[this.shuffledTestIndex];
81 | });
82 | }
83 |
84 | nextBatch(batchSize, data, index) {
85 | const batchImagesArray = new Float32Array(batchSize * IMAGE_SIZE);
86 | const batchLabelsArray = new Uint8Array(batchSize * NUM_CLASSES);
87 |
88 | for (let i = 0; i < batchSize; i++) {
89 | const idx = index();
90 |
91 | const image =
92 | data[0].slice(idx * IMAGE_SIZE, idx * IMAGE_SIZE + IMAGE_SIZE);
93 | batchImagesArray.set(image, i * IMAGE_SIZE);
94 |
95 | const label =
96 | data[1].slice(idx * NUM_CLASSES, idx * NUM_CLASSES + NUM_CLASSES);
97 | batchLabelsArray.set(label, i * NUM_CLASSES);
98 | }
99 |
100 | const xs = tf.tensor2d(batchImagesArray, [batchSize, IMAGE_SIZE]);
101 | const labels = tf.tensor2d(batchLabelsArray, [batchSize, NUM_CLASSES]);
102 |
103 | return {
104 | xs,
105 | labels
106 | };
107 | }
108 | }
--------------------------------------------------------------------------------
/project/5 多分类/data.js:
--------------------------------------------------------------------------------
1 | import * as tf from '@tensorflow/tfjs';
2 |
3 | export const IRIS_CLASSES = ['山鸢尾', '变色鸢尾', '维吉尼亚鸢尾'];
4 | export const IRIS_NUM_CLASSES = IRIS_CLASSES.length;
5 |
6 | // 鸢尾花数据集 https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data
7 | const IRIS_DATA = [
8 | [5.1, 3.5, 1.4, 0.2, 0],
9 | [4.9, 3.0, 1.4, 0.2, 0],
10 | [4.7, 3.2, 1.3, 0.2, 0],
11 | [4.6, 3.1, 1.5, 0.2, 0],
12 | [5.0, 3.6, 1.4, 0.2, 0],
13 | [5.4, 3.9, 1.7, 0.4, 0],
14 | [4.6, 3.4, 1.4, 0.3, 0],
15 | [5.0, 3.4, 1.5, 0.2, 0],
16 | [4.4, 2.9, 1.4, 0.2, 0],
17 | [4.9, 3.1, 1.5, 0.1, 0],
18 | [5.4, 3.7, 1.5, 0.2, 0],
19 | [4.8, 3.4, 1.6, 0.2, 0],
20 | [4.8, 3.0, 1.4, 0.1, 0],
21 | [4.3, 3.0, 1.1, 0.1, 0],
22 | [5.8, 4.0, 1.2, 0.2, 0],
23 | [5.7, 4.4, 1.5, 0.4, 0],
24 | [5.4, 3.9, 1.3, 0.4, 0],
25 | [5.1, 3.5, 1.4, 0.3, 0],
26 | [5.7, 3.8, 1.7, 0.3, 0],
27 | [5.1, 3.8, 1.5, 0.3, 0],
28 | [5.4, 3.4, 1.7, 0.2, 0],
29 | [5.1, 3.7, 1.5, 0.4, 0],
30 | [4.6, 3.6, 1.0, 0.2, 0],
31 | [5.1, 3.3, 1.7, 0.5, 0],
32 | [4.8, 3.4, 1.9, 0.2, 0],
33 | [5.0, 3.0, 1.6, 0.2, 0],
34 | [5.0, 3.4, 1.6, 0.4, 0],
35 | [5.2, 3.5, 1.5, 0.2, 0],
36 | [5.2, 3.4, 1.4, 0.2, 0],
37 | [4.7, 3.2, 1.6, 0.2, 0],
38 | [4.8, 3.1, 1.6, 0.2, 0],
39 | [5.4, 3.4, 1.5, 0.4, 0],
40 | [5.2, 4.1, 1.5, 0.1, 0],
41 | [5.5, 4.2, 1.4, 0.2, 0],
42 | [4.9, 3.1, 1.5, 0.1, 0],
43 | [5.0, 3.2, 1.2, 0.2, 0],
44 | [5.5, 3.5, 1.3, 0.2, 0],
45 | [4.9, 3.1, 1.5, 0.1, 0],
46 | [4.4, 3.0, 1.3, 0.2, 0],
47 | [5.1, 3.4, 1.5, 0.2, 0],
48 | [5.0, 3.5, 1.3, 0.3, 0],
49 | [4.5, 2.3, 1.3, 0.3, 0],
50 | [4.4, 3.2, 1.3, 0.2, 0],
51 | [5.0, 3.5, 1.6, 0.6, 0],
52 | [5.1, 3.8, 1.9, 0.4, 0],
53 | [4.8, 3.0, 1.4, 0.3, 0],
54 | [5.1, 3.8, 1.6, 0.2, 0],
55 | [4.6, 3.2, 1.4, 0.2, 0],
56 | [5.3, 3.7, 1.5, 0.2, 0],
57 | [5.0, 3.3, 1.4, 0.2, 0],
58 | [7.0, 3.2, 4.7, 1.4, 1],
59 | [6.4, 3.2, 4.5, 1.5, 1],
60 | [6.9, 3.1, 4.9, 1.5, 1],
61 | [5.5, 2.3, 4.0, 1.3, 1],
62 | [6.5, 2.8, 4.6, 1.5, 1],
63 | [5.7, 2.8, 4.5, 1.3, 1],
64 | [6.3, 3.3, 4.7, 1.6, 1],
65 | [4.9, 2.4, 3.3, 1.0, 1],
66 | [6.6, 2.9, 4.6, 1.3, 1],
67 | [5.2, 2.7, 3.9, 1.4, 1],
68 | [5.0, 2.0, 3.5, 1.0, 1],
69 | [5.9, 3.0, 4.2, 1.5, 1],
70 | [6.0, 2.2, 4.0, 1.0, 1],
71 | [6.1, 2.9, 4.7, 1.4, 1],
72 | [5.6, 2.9, 3.6, 1.3, 1],
73 | [6.7, 3.1, 4.4, 1.4, 1],
74 | [5.6, 3.0, 4.5, 1.5, 1],
75 | [5.8, 2.7, 4.1, 1.0, 1],
76 | [6.2, 2.2, 4.5, 1.5, 1],
77 | [5.6, 2.5, 3.9, 1.1, 1],
78 | [5.9, 3.2, 4.8, 1.8, 1],
79 | [6.1, 2.8, 4.0, 1.3, 1],
80 | [6.3, 2.5, 4.9, 1.5, 1],
81 | [6.1, 2.8, 4.7, 1.2, 1],
82 | [6.4, 2.9, 4.3, 1.3, 1],
83 | [6.6, 3.0, 4.4, 1.4, 1],
84 | [6.8, 2.8, 4.8, 1.4, 1],
85 | [6.7, 3.0, 5.0, 1.7, 1],
86 | [6.0, 2.9, 4.5, 1.5, 1],
87 | [5.7, 2.6, 3.5, 1.0, 1],
88 | [5.5, 2.4, 3.8, 1.1, 1],
89 | [5.5, 2.4, 3.7, 1.0, 1],
90 | [5.8, 2.7, 3.9, 1.2, 1],
91 | [6.0, 2.7, 5.1, 1.6, 1],
92 | [5.4, 3.0, 4.5, 1.5, 1],
93 | [6.0, 3.4, 4.5, 1.6, 1],
94 | [6.7, 3.1, 4.7, 1.5, 1],
95 | [6.3, 2.3, 4.4, 1.3, 1],
96 | [5.6, 3.0, 4.1, 1.3, 1],
97 | [5.5, 2.5, 4.0, 1.3, 1],
98 | [5.5, 2.6, 4.4, 1.2, 1],
99 | [6.1, 3.0, 4.6, 1.4, 1],
100 | [5.8, 2.6, 4.0, 1.2, 1],
101 | [5.0, 2.3, 3.3, 1.0, 1],
102 | [5.6, 2.7, 4.2, 1.3, 1],
103 | [5.7, 3.0, 4.2, 1.2, 1],
104 | [5.7, 2.9, 4.2, 1.3, 1],
105 | [6.2, 2.9, 4.3, 1.3, 1],
106 | [5.1, 2.5, 3.0, 1.1, 1],
107 | [5.7, 2.8, 4.1, 1.3, 1],
108 | [6.3, 3.3, 6.0, 2.5, 2],
109 | [5.8, 2.7, 5.1, 1.9, 2],
110 | [7.1, 3.0, 5.9, 2.1, 2],
111 | [6.3, 2.9, 5.6, 1.8, 2],
112 | [6.5, 3.0, 5.8, 2.2, 2],
113 | [7.6, 3.0, 6.6, 2.1, 2],
114 | [4.9, 2.5, 4.5, 1.7, 2],
115 | [7.3, 2.9, 6.3, 1.8, 2],
116 | [6.7, 2.5, 5.8, 1.8, 2],
117 | [7.2, 3.6, 6.1, 2.5, 2],
118 | [6.5, 3.2, 5.1, 2.0, 2],
119 | [6.4, 2.7, 5.3, 1.9, 2],
120 | [6.8, 3.0, 5.5, 2.1, 2],
121 | [5.7, 2.5, 5.0, 2.0, 2],
122 | [5.8, 2.8, 5.1, 2.4, 2],
123 | [6.4, 3.2, 5.3, 2.3, 2],
124 | [6.5, 3.0, 5.5, 1.8, 2],
125 | [7.7, 3.8, 6.7, 2.2, 2],
126 | [7.7, 2.6, 6.9, 2.3, 2],
127 | [6.0, 2.2, 5.0, 1.5, 2],
128 | [6.9, 3.2, 5.7, 2.3, 2],
129 | [5.6, 2.8, 4.9, 2.0, 2],
130 | [7.7, 2.8, 6.7, 2.0, 2],
131 | [6.3, 2.7, 4.9, 1.8, 2],
132 | [6.7, 3.3, 5.7, 2.1, 2],
133 | [7.2, 3.2, 6.0, 1.8, 2],
134 | [6.2, 2.8, 4.8, 1.8, 2],
135 | [6.1, 3.0, 4.9, 1.8, 2],
136 | [6.4, 2.8, 5.6, 2.1, 2],
137 | [7.2, 3.0, 5.8, 1.6, 2],
138 | [7.4, 2.8, 6.1, 1.9, 2],
139 | [7.9, 3.8, 6.4, 2.0, 2],
140 | [6.4, 2.8, 5.6, 2.2, 2],
141 | [6.3, 2.8, 5.1, 1.5, 2],
142 | [6.1, 2.6, 5.6, 1.4, 2],
143 | [7.7, 3.0, 6.1, 2.3, 2],
144 | [6.3, 3.4, 5.6, 2.4, 2],
145 | [6.4, 3.1, 5.5, 1.8, 2],
146 | [6.0, 3.0, 4.8, 1.8, 2],
147 | [6.9, 3.1, 5.4, 2.1, 2],
148 | [6.7, 3.1, 5.6, 2.4, 2],
149 | [6.9, 3.1, 5.1, 2.3, 2],
150 | [5.8, 2.7, 5.1, 1.9, 2],
151 | [6.8, 3.2, 5.9, 2.3, 2],
152 | [6.7, 3.3, 5.7, 2.5, 2],
153 | [6.7, 3.0, 5.2, 2.3, 2],
154 | [6.3, 2.5, 5.0, 1.9, 2],
155 | [6.5, 3.0, 5.2, 2.0, 2],
156 | [6.2, 3.4, 5.4, 2.3, 2],
157 | [5.9, 3.0, 5.1, 1.8, 2],
158 | ];
159 |
160 | // 转化为tensor
161 | function convertToTensors(data, targets, testSplit) {
162 | const numExamples = data.length;
163 | if (numExamples !== targets.length) {
164 | throw new Error('data and split have different numbers of examples');
165 | }
166 |
167 | const indices = [];
168 | for (let i = 0; i < numExamples; ++i) {
169 | indices.push(i);
170 | }
171 | tf.util.shuffle(indices);
172 |
173 | const shuffledData = [];
174 | const shuffledTargets = [];
175 | for (let i = 0; i < numExamples; ++i) {
176 | shuffledData.push(data[indices[i]]);
177 | shuffledTargets.push(targets[indices[i]]);
178 | }
179 |
180 | const numTestExamples = Math.round(numExamples * testSplit);
181 | const numTrainExamples = numExamples - numTestExamples;
182 | const xDims = shuffledData[0].length;
183 | const xs = tf.tensor2d(shuffledData, [numExamples, xDims]);
184 | const ys = tf.oneHot(tf.tensor1d(shuffledTargets).toInt(), IRIS_NUM_CLASSES);
185 | const xTrain = xs.slice([0, 0], [numTrainExamples, xDims]);
186 | const xTest = xs.slice([numTrainExamples, 0], [numTestExamples, xDims]);
187 | const yTrain = ys.slice([0, 0], [numTrainExamples, IRIS_NUM_CLASSES]);
188 | const yTest = ys.slice([0, 0], [numTestExamples, IRIS_NUM_CLASSES]);
189 | return [xTrain, yTrain, xTest, yTest];
190 | }
191 |
192 | // 获取鸢尾花数据集(带分类)
193 | export function getIrisData(testSplit) {
194 | return tf.tidy(() => {
195 | const dataByClass = [];
196 | const targetsByClass = [];
197 | for (let i = 0; i < IRIS_CLASSES.length; ++i) {
198 | dataByClass.push([]);
199 | targetsByClass.push([]);
200 | }
201 | for (const example of IRIS_DATA) {
202 | const target = example[example.length - 1];
203 | const data = example.slice(0, example.length - 1);
204 | dataByClass[target].push(data);
205 | targetsByClass[target].push(target);
206 | }
207 |
208 | const xTrains = [];
209 | const yTrains = [];
210 | const xTests = [];
211 | const yTests = [];
212 | for (let i = 0; i < IRIS_CLASSES.length; ++i) {
213 | const [xTrain, yTrain, xTest, yTest] =
214 | convertToTensors(dataByClass[i], targetsByClass[i], testSplit);
215 | xTrains.push(xTrain);
216 | yTrains.push(yTrain);
217 | xTests.push(xTest);
218 | yTests.push(yTest);
219 | }
220 |
221 | const concatAxis = 0;
222 | return [
223 | tf.concat(xTrains, concatAxis), tf.concat(yTrains, concatAxis),
224 | tf.concat(xTests, concatAxis), tf.concat(yTests, concatAxis)
225 | ];
226 | });
227 | }
--------------------------------------------------------------------------------
/project/8 预训练模型-图片分类/imagenet_classes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2017 Google LLC. All Rights Reserved.
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | * =============================================================================
16 | */
17 |
18 | export const IMAGENET_CLASSES = {
19 | 0: 'tench, Tinca tinca',
20 | 1: 'goldfish, Carassius auratus',
21 | 2: 'great white shark, white shark, man-eater, man-eating shark, ' +
22 | 'Carcharodon carcharias',
23 | 3: 'tiger shark, Galeocerdo cuvieri',
24 | 4: 'hammerhead, hammerhead shark',
25 | 5: 'electric ray, crampfish, numbfish, torpedo',
26 | 6: 'stingray',
27 | 7: 'cock',
28 | 8: 'hen',
29 | 9: 'ostrich, Struthio camelus',
30 | 10: 'brambling, Fringilla montifringilla',
31 | 11: 'goldfinch, Carduelis carduelis',
32 | 12: 'house finch, linnet, Carpodacus mexicanus',
33 | 13: 'junco, snowbird',
34 | 14: 'indigo bunting, indigo finch, indigo bird, Passerina cyanea',
35 | 15: 'robin, American robin, Turdus migratorius',
36 | 16: 'bulbul',
37 | 17: 'jay',
38 | 18: 'magpie',
39 | 19: 'chickadee',
40 | 20: 'water ouzel, dipper',
41 | 21: 'kite',
42 | 22: 'bald eagle, American eagle, Haliaeetus leucocephalus',
43 | 23: 'vulture',
44 | 24: 'great grey owl, great gray owl, Strix nebulosa',
45 | 25: 'European fire salamander, Salamandra salamandra',
46 | 26: 'common newt, Triturus vulgaris',
47 | 27: 'eft',
48 | 28: 'spotted salamander, Ambystoma maculatum',
49 | 29: 'axolotl, mud puppy, Ambystoma mexicanum',
50 | 30: 'bullfrog, Rana catesbeiana',
51 | 31: 'tree frog, tree-frog',
52 | 32: 'tailed frog, bell toad, ribbed toad, tailed toad, Ascaphus trui',
53 | 33: 'loggerhead, loggerhead turtle, Caretta caretta',
54 | 34: 'leatherback turtle, leatherback, leathery turtle, Dermochelys coriacea',
55 | 35: 'mud turtle',
56 | 36: 'terrapin',
57 | 37: 'box turtle, box tortoise',
58 | 38: 'banded gecko',
59 | 39: 'common iguana, iguana, Iguana iguana',
60 | 40: 'American chameleon, anole, Anolis carolinensis',
61 | 41: 'whiptail, whiptail lizard',
62 | 42: 'agama',
63 | 43: 'frilled lizard, Chlamydosaurus kingi',
64 | 44: 'alligator lizard',
65 | 45: 'Gila monster, Heloderma suspectum',
66 | 46: 'green lizard, Lacerta viridis',
67 | 47: 'African chameleon, Chamaeleo chamaeleon',
68 | 48: 'Komodo dragon, Komodo lizard, dragon lizard, giant lizard, ' +
69 | 'Varanus komodoensis',
70 | 49: 'African crocodile, Nile crocodile, Crocodylus niloticus',
71 | 50: 'American alligator, Alligator mississipiensis',
72 | 51: 'triceratops',
73 | 52: 'thunder snake, worm snake, Carphophis amoenus',
74 | 53: 'ringneck snake, ring-necked snake, ring snake',
75 | 54: 'hognose snake, puff adder, sand viper',
76 | 55: 'green snake, grass snake',
77 | 56: 'king snake, kingsnake',
78 | 57: 'garter snake, grass snake',
79 | 58: 'water snake',
80 | 59: 'vine snake',
81 | 60: 'night snake, Hypsiglena torquata',
82 | 61: 'boa constrictor, Constrictor constrictor',
83 | 62: 'rock python, rock snake, Python sebae',
84 | 63: 'Indian cobra, Naja naja',
85 | 64: 'green mamba',
86 | 65: 'sea snake',
87 | 66: 'horned viper, cerastes, sand viper, horned asp, Cerastes cornutus',
88 | 67: 'diamondback, diamondback rattlesnake, Crotalus adamanteus',
89 | 68: 'sidewinder, horned rattlesnake, Crotalus cerastes',
90 | 69: 'trilobite',
91 | 70: 'harvestman, daddy longlegs, Phalangium opilio',
92 | 71: 'scorpion',
93 | 72: 'black and gold garden spider, Argiope aurantia',
94 | 73: 'barn spider, Araneus cavaticus',
95 | 74: 'garden spider, Aranea diademata',
96 | 75: 'black widow, Latrodectus mactans',
97 | 76: 'tarantula',
98 | 77: 'wolf spider, hunting spider',
99 | 78: 'tick',
100 | 79: 'centipede',
101 | 80: 'black grouse',
102 | 81: 'ptarmigan',
103 | 82: 'ruffed grouse, partridge, Bonasa umbellus',
104 | 83: 'prairie chicken, prairie grouse, prairie fowl',
105 | 84: 'peacock',
106 | 85: 'quail',
107 | 86: 'partridge',
108 | 87: 'African grey, African gray, Psittacus erithacus',
109 | 88: 'macaw',
110 | 89: 'sulphur-crested cockatoo, Kakatoe galerita, Cacatua galerita',
111 | 90: 'lorikeet',
112 | 91: 'coucal',
113 | 92: 'bee eater',
114 | 93: 'hornbill',
115 | 94: 'hummingbird',
116 | 95: 'jacamar',
117 | 96: 'toucan',
118 | 97: 'drake',
119 | 98: 'red-breasted merganser, Mergus serrator',
120 | 99: 'goose',
121 | 100: 'black swan, Cygnus atratus',
122 | 101: 'tusker',
123 | 102: 'echidna, spiny anteater, anteater',
124 | 103: 'platypus, duckbill, duckbilled platypus, duck-billed platypus, ' +
125 | 'Ornithorhynchus anatinus',
126 | 104: 'wallaby, brush kangaroo',
127 | 105: 'koala, koala bear, kangaroo bear, native bear, Phascolarctos cinereus',
128 | 106: 'wombat',
129 | 107: 'jelly fish',
130 | 108: 'sea anemone, anemone',
131 | 109: 'brain coral',
132 | 110: 'flatworm, platyhelminth',
133 | 111: 'nematode, nematode worm, roundworm',
134 | 112: 'conch',
135 | 113: 'snail',
136 | 114: 'slug',
137 | 115: 'sea slug, nudibranch',
138 | 116: 'chiton, coat-of-mail shell, sea cradle, polyplacophore',
139 | 117: 'chambered nautilus, pearly nautilus, nautilus',
140 | 118: 'Dungeness crab, Cancer magister',
141 | 119: 'rock crab, Cancer irroratus',
142 | 120: 'fiddler crab',
143 | 121: 'king crab, Alaska crab, Alaskan king crab, Alaska king crab, ' +
144 | 'Paralithodes camtschatica',
145 | 122: 'American lobster, Northern lobster, Maine lobster, Homarus americanus',
146 | 123: 'spiny lobster, langouste, rock lobster, crawfish, crayfish, sea ' +
147 | 'crawfish',
148 | 124: 'crayfish, crawfish, crawdad, crawdaddy',
149 | 125: 'hermit crab',
150 | 126: 'isopod',
151 | 127: 'white stork, Ciconia ciconia',
152 | 128: 'black stork, Ciconia nigra',
153 | 129: 'spoonbill',
154 | 130: 'flamingo',
155 | 131: 'little blue heron, Egretta caerulea',
156 | 132: 'American egret, great white heron, Egretta albus',
157 | 133: 'bittern',
158 | 134: 'crane',
159 | 135: 'limpkin, Aramus pictus',
160 | 136: 'European gallinule, Porphyrio porphyrio',
161 | 137: 'American coot, marsh hen, mud hen, water hen, Fulica americana',
162 | 138: 'bustard',
163 | 139: 'ruddy turnstone, Arenaria interpres',
164 | 140: 'red-backed sandpiper, dunlin, Erolia alpina',
165 | 141: 'redshank, Tringa totanus',
166 | 142: 'dowitcher',
167 | 143: 'oystercatcher, oyster catcher',
168 | 144: 'pelican',
169 | 145: 'king penguin, Aptenodytes patagonica',
170 | 146: 'albatross, mollymawk',
171 | 147: 'grey whale, gray whale, devilfish, Eschrichtius gibbosus, ' +
172 | 'Eschrichtius robustus',
173 | 148: 'killer whale, killer, orca, grampus, sea wolf, Orcinus orca',
174 | 149: 'dugong, Dugong dugon',
175 | 150: 'sea lion',
176 | 151: 'Chihuahua',
177 | 152: 'Japanese spaniel',
178 | 153: 'Maltese dog, Maltese terrier, Maltese',
179 | 154: 'Pekinese, Pekingese, Peke',
180 | 155: 'Shih-Tzu',
181 | 156: 'Blenheim spaniel',
182 | 157: 'papillon',
183 | 158: 'toy terrier',
184 | 159: 'Rhodesian ridgeback',
185 | 160: 'Afghan hound, Afghan',
186 | 161: 'basset, basset hound',
187 | 162: 'beagle',
188 | 163: 'bloodhound, sleuthhound',
189 | 164: 'bluetick',
190 | 165: 'black-and-tan coonhound',
191 | 166: 'Walker hound, Walker foxhound',
192 | 167: 'English foxhound',
193 | 168: 'redbone',
194 | 169: 'borzoi, Russian wolfhound',
195 | 170: 'Irish wolfhound',
196 | 171: 'Italian greyhound',
197 | 172: 'whippet',
198 | 173: 'Ibizan hound, Ibizan Podenco',
199 | 174: 'Norwegian elkhound, elkhound',
200 | 175: 'otterhound, otter hound',
201 | 176: 'Saluki, gazelle hound',
202 | 177: 'Scottish deerhound, deerhound',
203 | 178: 'Weimaraner',
204 | 179: 'Staffordshire bullterrier, Staffordshire bull terrier',
205 | 180: 'American Staffordshire terrier, Staffordshire terrier, American pit ' +
206 | 'bull terrier, pit bull terrier',
207 | 181: 'Bedlington terrier',
208 | 182: 'Border terrier',
209 | 183: 'Kerry blue terrier',
210 | 184: 'Irish terrier',
211 | 185: 'Norfolk terrier',
212 | 186: 'Norwich terrier',
213 | 187: 'Yorkshire terrier',
214 | 188: 'wire-haired fox terrier',
215 | 189: 'Lakeland terrier',
216 | 190: 'Sealyham terrier, Sealyham',
217 | 191: 'Airedale, Airedale terrier',
218 | 192: 'cairn, cairn terrier',
219 | 193: 'Australian terrier',
220 | 194: 'Dandie Dinmont, Dandie Dinmont terrier',
221 | 195: 'Boston bull, Boston terrier',
222 | 196: 'miniature schnauzer',
223 | 197: 'giant schnauzer',
224 | 198: 'standard schnauzer',
225 | 199: 'Scotch terrier, Scottish terrier, Scottie',
226 | 200: 'Tibetan terrier, chrysanthemum dog',
227 | 201: 'silky terrier, Sydney silky',
228 | 202: 'soft-coated wheaten terrier',
229 | 203: 'West Highland white terrier',
230 | 204: 'Lhasa, Lhasa apso',
231 | 205: 'flat-coated retriever',
232 | 206: 'curly-coated retriever',
233 | 207: 'golden retriever',
234 | 208: 'Labrador retriever',
235 | 209: 'Chesapeake Bay retriever',
236 | 210: 'German short-haired pointer',
237 | 211: 'vizsla, Hungarian pointer',
238 | 212: 'English setter',
239 | 213: 'Irish setter, red setter',
240 | 214: 'Gordon setter',
241 | 215: 'Brittany spaniel',
242 | 216: 'clumber, clumber spaniel',
243 | 217: 'English springer, English springer spaniel',
244 | 218: 'Welsh springer spaniel',
245 | 219: 'cocker spaniel, English cocker spaniel, cocker',
246 | 220: 'Sussex spaniel',
247 | 221: 'Irish water spaniel',
248 | 222: 'kuvasz',
249 | 223: 'schipperke',
250 | 224: 'groenendael',
251 | 225: 'malinois',
252 | 226: 'briard',
253 | 227: 'kelpie',
254 | 228: 'komondor',
255 | 229: 'Old English sheepdog, bobtail',
256 | 230: 'Shetland sheepdog, Shetland sheep dog, Shetland',
257 | 231: 'collie',
258 | 232: 'Border collie',
259 | 233: 'Bouvier des Flandres, Bouviers des Flandres',
260 | 234: 'Rottweiler',
261 | 235: 'German shepherd, German shepherd dog, German police dog, alsatian',
262 | 236: 'Doberman, Doberman pinscher',
263 | 237: 'miniature pinscher',
264 | 238: 'Greater Swiss Mountain dog',
265 | 239: 'Bernese mountain dog',
266 | 240: 'Appenzeller',
267 | 241: 'EntleBucher',
268 | 242: 'boxer',
269 | 243: 'bull mastiff',
270 | 244: 'Tibetan mastiff',
271 | 245: 'French bulldog',
272 | 246: 'Great Dane',
273 | 247: 'Saint Bernard, St Bernard',
274 | 248: 'Eskimo dog, husky',
275 | 249: 'malamute, malemute, Alaskan malamute',
276 | 250: 'Siberian husky',
277 | 251: 'dalmatian, coach dog, carriage dog',
278 | 252: 'affenpinscher, monkey pinscher, monkey dog',
279 | 253: 'basenji',
280 | 254: 'pug, pug-dog',
281 | 255: 'Leonberg',
282 | 256: 'Newfoundland, Newfoundland dog',
283 | 257: 'Great Pyrenees',
284 | 258: 'Samoyed, Samoyede',
285 | 259: 'Pomeranian',
286 | 260: 'chow, chow chow',
287 | 261: 'keeshond',
288 | 262: 'Brabancon griffon',
289 | 263: 'Pembroke, Pembroke Welsh corgi',
290 | 264: 'Cardigan, Cardigan Welsh corgi',
291 | 265: 'toy poodle',
292 | 266: 'miniature poodle',
293 | 267: 'standard poodle',
294 | 268: 'Mexican hairless',
295 | 269: 'timber wolf, grey wolf, gray wolf, Canis lupus',
296 | 270: 'white wolf, Arctic wolf, Canis lupus tundrarum',
297 | 271: 'red wolf, maned wolf, Canis rufus, Canis niger',
298 | 272: 'coyote, prairie wolf, brush wolf, Canis latrans',
299 | 273: 'dingo, warrigal, warragal, Canis dingo',
300 | 274: 'dhole, Cuon alpinus',
301 | 275: 'African hunting dog, hyena dog, Cape hunting dog, Lycaon pictus',
302 | 276: 'hyena, hyaena',
303 | 277: 'red fox, Vulpes vulpes',
304 | 278: 'kit fox, Vulpes macrotis',
305 | 279: 'Arctic fox, white fox, Alopex lagopus',
306 | 280: 'grey fox, gray fox, Urocyon cinereoargenteus',
307 | 281: 'tabby, tabby cat',
308 | 282: 'tiger cat',
309 | 283: 'Persian cat',
310 | 284: 'Siamese cat, Siamese',
311 | 285: 'Egyptian cat',
312 | 286: 'cougar, puma, catamount, mountain lion, painter, panther, ' +
313 | 'Felis concolor',
314 | 287: 'lynx, catamount',
315 | 288: 'leopard, Panthera pardus',
316 | 289: 'snow leopard, ounce, Panthera uncia',
317 | 290: 'jaguar, panther, Panthera onca, Felis onca',
318 | 291: 'lion, king of beasts, Panthera leo',
319 | 292: 'tiger, Panthera tigris',
320 | 293: 'cheetah, chetah, Acinonyx jubatus',
321 | 294: 'brown bear, bruin, Ursus arctos',
322 | 295: 'American black bear, black bear, Ursus americanus, Euarctos ' +
323 | 'americanus',
324 | 296: 'ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus',
325 | 297: 'sloth bear, Melursus ursinus, Ursus ursinus',
326 | 298: 'mongoose',
327 | 299: 'meerkat, mierkat',
328 | 300: 'tiger beetle',
329 | 301: 'ladybug, ladybeetle, lady beetle, ladybird, ladybird beetle',
330 | 302: 'ground beetle, carabid beetle',
331 | 303: 'long-horned beetle, longicorn, longicorn beetle',
332 | 304: 'leaf beetle, chrysomelid',
333 | 305: 'dung beetle',
334 | 306: 'rhinoceros beetle',
335 | 307: 'weevil',
336 | 308: 'fly',
337 | 309: 'bee',
338 | 310: 'ant, emmet, pismire',
339 | 311: 'grasshopper, hopper',
340 | 312: 'cricket',
341 | 313: 'walking stick, walkingstick, stick insect',
342 | 314: 'cockroach, roach',
343 | 315: 'mantis, mantid',
344 | 316: 'cicada, cicala',
345 | 317: 'leafhopper',
346 | 318: 'lacewing, lacewing fly',
347 | 319: 'dragonfly, darning needle, devil\'s darning needle, sewing needle, ' +
348 | 'snake feeder, snake doctor, mosquito hawk, skeeter hawk',
349 | 320: 'damselfly',
350 | 321: 'admiral',
351 | 322: 'ringlet, ringlet butterfly',
352 | 323: 'monarch, monarch butterfly, milkweed butterfly, Danaus plexippus',
353 | 324: 'cabbage butterfly',
354 | 325: 'sulphur butterfly, sulfur butterfly',
355 | 326: 'lycaenid, lycaenid butterfly',
356 | 327: 'starfish, sea star',
357 | 328: 'sea urchin',
358 | 329: 'sea cucumber, holothurian',
359 | 330: 'wood rabbit, cottontail, cottontail rabbit',
360 | 331: 'hare',
361 | 332: 'Angora, Angora rabbit',
362 | 333: 'hamster',
363 | 334: 'porcupine, hedgehog',
364 | 335: 'fox squirrel, eastern fox squirrel, Sciurus niger',
365 | 336: 'marmot',
366 | 337: 'beaver',
367 | 338: 'guinea pig, Cavia cobaya',
368 | 339: 'sorrel',
369 | 340: 'zebra',
370 | 341: 'hog, pig, grunter, squealer, Sus scrofa',
371 | 342: 'wild boar, boar, Sus scrofa',
372 | 343: 'warthog',
373 | 344: 'hippopotamus, hippo, river horse, Hippopotamus amphibius',
374 | 345: 'ox',
375 | 346: 'water buffalo, water ox, Asiatic buffalo, Bubalus bubalis',
376 | 347: 'bison',
377 | 348: 'ram, tup',
378 | 349: 'bighorn, bighorn sheep, cimarron, Rocky Mountain bighorn, Rocky ' +
379 | 'Mountain sheep, Ovis canadensis',
380 | 350: 'ibex, Capra ibex',
381 | 351: 'hartebeest',
382 | 352: 'impala, Aepyceros melampus',
383 | 353: 'gazelle',
384 | 354: 'Arabian camel, dromedary, Camelus dromedarius',
385 | 355: 'llama',
386 | 356: 'weasel',
387 | 357: 'mink',
388 | 358: 'polecat, fitch, foulmart, foumart, Mustela putorius',
389 | 359: 'black-footed ferret, ferret, Mustela nigripes',
390 | 360: 'otter',
391 | 361: 'skunk, polecat, wood pussy',
392 | 362: 'badger',
393 | 363: 'armadillo',
394 | 364: 'three-toed sloth, ai, Bradypus tridactylus',
395 | 365: 'orangutan, orang, orangutang, Pongo pygmaeus',
396 | 366: 'gorilla, Gorilla gorilla',
397 | 367: 'chimpanzee, chimp, Pan troglodytes',
398 | 368: 'gibbon, Hylobates lar',
399 | 369: 'siamang, Hylobates syndactylus, Symphalangus syndactylus',
400 | 370: 'guenon, guenon monkey',
401 | 371: 'patas, hussar monkey, Erythrocebus patas',
402 | 372: 'baboon',
403 | 373: 'macaque',
404 | 374: 'langur',
405 | 375: 'colobus, colobus monkey',
406 | 376: 'proboscis monkey, Nasalis larvatus',
407 | 377: 'marmoset',
408 | 378: 'capuchin, ringtail, Cebus capucinus',
409 | 379: 'howler monkey, howler',
410 | 380: 'titi, titi monkey',
411 | 381: 'spider monkey, Ateles geoffroyi',
412 | 382: 'squirrel monkey, Saimiri sciureus',
413 | 383: 'Madagascar cat, ring-tailed lemur, Lemur catta',
414 | 384: 'indri, indris, Indri indri, Indri brevicaudatus',
415 | 385: 'Indian elephant, Elephas maximus',
416 | 386: 'African elephant, Loxodonta africana',
417 | 387: 'lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens',
418 | 388: 'giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca',
419 | 389: 'barracouta, snoek',
420 | 390: 'eel',
421 | 391: 'coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus ' +
422 | 'kisutch',
423 | 392: 'rock beauty, Holocanthus tricolor',
424 | 393: 'anemone fish',
425 | 394: 'sturgeon',
426 | 395: 'gar, garfish, garpike, billfish, Lepisosteus osseus',
427 | 396: 'lionfish',
428 | 397: 'puffer, pufferfish, blowfish, globefish',
429 | 398: 'abacus',
430 | 399: 'abaya',
431 | 400: 'academic gown, academic robe, judge\'s robe',
432 | 401: 'accordion, piano accordion, squeeze box',
433 | 402: 'acoustic guitar',
434 | 403: 'aircraft carrier, carrier, flattop, attack aircraft carrier',
435 | 404: 'airliner',
436 | 405: 'airship, dirigible',
437 | 406: 'altar',
438 | 407: 'ambulance',
439 | 408: 'amphibian, amphibious vehicle',
440 | 409: 'analog clock',
441 | 410: 'apiary, bee house',
442 | 411: 'apron',
443 | 412: 'ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, ' +
444 | 'dustbin, trash barrel, trash bin',
445 | 413: 'assault rifle, assault gun',
446 | 414: 'backpack, back pack, knapsack, packsack, rucksack, haversack',
447 | 415: 'bakery, bakeshop, bakehouse',
448 | 416: 'balance beam, beam',
449 | 417: 'balloon',
450 | 418: 'ballpoint, ballpoint pen, ballpen, Biro',
451 | 419: 'Band Aid',
452 | 420: 'banjo',
453 | 421: 'bannister, banister, balustrade, balusters, handrail',
454 | 422: 'barbell',
455 | 423: 'barber chair',
456 | 424: 'barbershop',
457 | 425: 'barn',
458 | 426: 'barometer',
459 | 427: 'barrel, cask',
460 | 428: 'barrow, garden cart, lawn cart, wheelbarrow',
461 | 429: 'baseball',
462 | 430: 'basketball',
463 | 431: 'bassinet',
464 | 432: 'bassoon',
465 | 433: 'bathing cap, swimming cap',
466 | 434: 'bath towel',
467 | 435: 'bathtub, bathing tub, bath, tub',
468 | 436: 'beach wagon, station wagon, wagon, estate car, beach waggon, station ' +
469 | 'waggon, waggon',
470 | 437: 'beacon, lighthouse, beacon light, pharos',
471 | 438: 'beaker',
472 | 439: 'bearskin, busby, shako',
473 | 440: 'beer bottle',
474 | 441: 'beer glass',
475 | 442: 'bell cote, bell cot',
476 | 443: 'bib',
477 | 444: 'bicycle-built-for-two, tandem bicycle, tandem',
478 | 445: 'bikini, two-piece',
479 | 446: 'binder, ring-binder',
480 | 447: 'binoculars, field glasses, opera glasses',
481 | 448: 'birdhouse',
482 | 449: 'boathouse',
483 | 450: 'bobsled, bobsleigh, bob',
484 | 451: 'bolo tie, bolo, bola tie, bola',
485 | 452: 'bonnet, poke bonnet',
486 | 453: 'bookcase',
487 | 454: 'bookshop, bookstore, bookstall',
488 | 455: 'bottlecap',
489 | 456: 'bow',
490 | 457: 'bow tie, bow-tie, bowtie',
491 | 458: 'brass, memorial tablet, plaque',
492 | 459: 'brassiere, bra, bandeau',
493 | 460: 'breakwater, groin, groyne, mole, bulwark, seawall, jetty',
494 | 461: 'breastplate, aegis, egis',
495 | 462: 'broom',
496 | 463: 'bucket, pail',
497 | 464: 'buckle',
498 | 465: 'bulletproof vest',
499 | 466: 'bullet train, bullet',
500 | 467: 'butcher shop, meat market',
501 | 468: 'cab, hack, taxi, taxicab',
502 | 469: 'caldron, cauldron',
503 | 470: 'candle, taper, wax light',
504 | 471: 'cannon',
505 | 472: 'canoe',
506 | 473: 'can opener, tin opener',
507 | 474: 'cardigan',
508 | 475: 'car mirror',
509 | 476: 'carousel, carrousel, merry-go-round, roundabout, whirligig',
510 | 477: 'carpenter\'s kit, tool kit',
511 | 478: 'carton',
512 | 479: 'car wheel',
513 | 480: 'cash machine, cash dispenser, automated teller machine, automatic ' +
514 | 'teller machine, automated teller, automatic teller, ATM',
515 | 481: 'cassette',
516 | 482: 'cassette player',
517 | 483: 'castle',
518 | 484: 'catamaran',
519 | 485: 'CD player',
520 | 486: 'cello, violoncello',
521 | 487: 'cellular telephone, cellular phone, cellphone, cell, mobile phone',
522 | 488: 'chain',
523 | 489: 'chainlink fence',
524 | 490: 'chain mail, ring mail, mail, chain armor, chain armour, ring armor, ' +
525 | 'ring armour',
526 | 491: 'chain saw, chainsaw',
527 | 492: 'chest',
528 | 493: 'chiffonier, commode',
529 | 494: 'chime, bell, gong',
530 | 495: 'china cabinet, china closet',
531 | 496: 'Christmas stocking',
532 | 497: 'church, church building',
533 | 498: 'cinema, movie theater, movie theatre, movie house, picture palace',
534 | 499: 'cleaver, meat cleaver, chopper',
535 | 500: 'cliff dwelling',
536 | 501: 'cloak',
537 | 502: 'clog, geta, patten, sabot',
538 | 503: 'cocktail shaker',
539 | 504: 'coffee mug',
540 | 505: 'coffeepot',
541 | 506: 'coil, spiral, volute, whorl, helix',
542 | 507: 'combination lock',
543 | 508: 'computer keyboard, keypad',
544 | 509: 'confectionery, confectionary, candy store',
545 | 510: 'container ship, containership, container vessel',
546 | 511: 'convertible',
547 | 512: 'corkscrew, bottle screw',
548 | 513: 'cornet, horn, trumpet, trump',
549 | 514: 'cowboy boot',
550 | 515: 'cowboy hat, ten-gallon hat',
551 | 516: 'cradle',
552 | 517: 'crane',
553 | 518: 'crash helmet',
554 | 519: 'crate',
555 | 520: 'crib, cot',
556 | 521: 'Crock Pot',
557 | 522: 'croquet ball',
558 | 523: 'crutch',
559 | 524: 'cuirass',
560 | 525: 'dam, dike, dyke',
561 | 526: 'desk',
562 | 527: 'desktop computer',
563 | 528: 'dial telephone, dial phone',
564 | 529: 'diaper, nappy, napkin',
565 | 530: 'digital clock',
566 | 531: 'digital watch',
567 | 532: 'dining table, board',
568 | 533: 'dishrag, dishcloth',
569 | 534: 'dishwasher, dish washer, dishwashing machine',
570 | 535: 'disk brake, disc brake',
571 | 536: 'dock, dockage, docking facility',
572 | 537: 'dogsled, dog sled, dog sleigh',
573 | 538: 'dome',
574 | 539: 'doormat, welcome mat',
575 | 540: 'drilling platform, offshore rig',
576 | 541: 'drum, membranophone, tympan',
577 | 542: 'drumstick',
578 | 543: 'dumbbell',
579 | 544: 'Dutch oven',
580 | 545: 'electric fan, blower',
581 | 546: 'electric guitar',
582 | 547: 'electric locomotive',
583 | 548: 'entertainment center',
584 | 549: 'envelope',
585 | 550: 'espresso maker',
586 | 551: 'face powder',
587 | 552: 'feather boa, boa',
588 | 553: 'file, file cabinet, filing cabinet',
589 | 554: 'fireboat',
590 | 555: 'fire engine, fire truck',
591 | 556: 'fire screen, fireguard',
592 | 557: 'flagpole, flagstaff',
593 | 558: 'flute, transverse flute',
594 | 559: 'folding chair',
595 | 560: 'football helmet',
596 | 561: 'forklift',
597 | 562: 'fountain',
598 | 563: 'fountain pen',
599 | 564: 'four-poster',
600 | 565: 'freight car',
601 | 566: 'French horn, horn',
602 | 567: 'frying pan, frypan, skillet',
603 | 568: 'fur coat',
604 | 569: 'garbage truck, dustcart',
605 | 570: 'gasmask, respirator, gas helmet',
606 | 571: 'gas pump, gasoline pump, petrol pump, island dispenser',
607 | 572: 'goblet',
608 | 573: 'go-kart',
609 | 574: 'golf ball',
610 | 575: 'golfcart, golf cart',
611 | 576: 'gondola',
612 | 577: 'gong, tam-tam',
613 | 578: 'gown',
614 | 579: 'grand piano, grand',
615 | 580: 'greenhouse, nursery, glasshouse',
616 | 581: 'grille, radiator grille',
617 | 582: 'grocery store, grocery, food market, market',
618 | 583: 'guillotine',
619 | 584: 'hair slide',
620 | 585: 'hair spray',
621 | 586: 'half track',
622 | 587: 'hammer',
623 | 588: 'hamper',
624 | 589: 'hand blower, blow dryer, blow drier, hair dryer, hair drier',
625 | 590: 'hand-held computer, hand-held microcomputer',
626 | 591: 'handkerchief, hankie, hanky, hankey',
627 | 592: 'hard disc, hard disk, fixed disk',
628 | 593: 'harmonica, mouth organ, harp, mouth harp',
629 | 594: 'harp',
630 | 595: 'harvester, reaper',
631 | 596: 'hatchet',
632 | 597: 'holster',
633 | 598: 'home theater, home theatre',
634 | 599: 'honeycomb',
635 | 600: 'hook, claw',
636 | 601: 'hoopskirt, crinoline',
637 | 602: 'horizontal bar, high bar',
638 | 603: 'horse cart, horse-cart',
639 | 604: 'hourglass',
640 | 605: 'iPod',
641 | 606: 'iron, smoothing iron',
642 | 607: 'jack-o\'-lantern',
643 | 608: 'jean, blue jean, denim',
644 | 609: 'jeep, landrover',
645 | 610: 'jersey, T-shirt, tee shirt',
646 | 611: 'jigsaw puzzle',
647 | 612: 'jinrikisha, ricksha, rickshaw',
648 | 613: 'joystick',
649 | 614: 'kimono',
650 | 615: 'knee pad',
651 | 616: 'knot',
652 | 617: 'lab coat, laboratory coat',
653 | 618: 'ladle',
654 | 619: 'lampshade, lamp shade',
655 | 620: 'laptop, laptop computer',
656 | 621: 'lawn mower, mower',
657 | 622: 'lens cap, lens cover',
658 | 623: 'letter opener, paper knife, paperknife',
659 | 624: 'library',
660 | 625: 'lifeboat',
661 | 626: 'lighter, light, igniter, ignitor',
662 | 627: 'limousine, limo',
663 | 628: 'liner, ocean liner',
664 | 629: 'lipstick, lip rouge',
665 | 630: 'Loafer',
666 | 631: 'lotion',
667 | 632: 'loudspeaker, speaker, speaker unit, loudspeaker system, speaker ' +
668 | 'system',
669 | 633: 'loupe, jeweler\'s loupe',
670 | 634: 'lumbermill, sawmill',
671 | 635: 'magnetic compass',
672 | 636: 'mailbag, postbag',
673 | 637: 'mailbox, letter box',
674 | 638: 'maillot',
675 | 639: 'maillot, tank suit',
676 | 640: 'manhole cover',
677 | 641: 'maraca',
678 | 642: 'marimba, xylophone',
679 | 643: 'mask',
680 | 644: 'matchstick',
681 | 645: 'maypole',
682 | 646: 'maze, labyrinth',
683 | 647: 'measuring cup',
684 | 648: 'medicine chest, medicine cabinet',
685 | 649: 'megalith, megalithic structure',
686 | 650: 'microphone, mike',
687 | 651: 'microwave, microwave oven',
688 | 652: 'military uniform',
689 | 653: 'milk can',
690 | 654: 'minibus',
691 | 655: 'miniskirt, mini',
692 | 656: 'minivan',
693 | 657: 'missile',
694 | 658: 'mitten',
695 | 659: 'mixing bowl',
696 | 660: 'mobile home, manufactured home',
697 | 661: 'Model T',
698 | 662: 'modem',
699 | 663: 'monastery',
700 | 664: 'monitor',
701 | 665: 'moped',
702 | 666: 'mortar',
703 | 667: 'mortarboard',
704 | 668: 'mosque',
705 | 669: 'mosquito net',
706 | 670: 'motor scooter, scooter',
707 | 671: 'mountain bike, all-terrain bike, off-roader',
708 | 672: 'mountain tent',
709 | 673: 'mouse, computer mouse',
710 | 674: 'mousetrap',
711 | 675: 'moving van',
712 | 676: 'muzzle',
713 | 677: 'nail',
714 | 678: 'neck brace',
715 | 679: 'necklace',
716 | 680: 'nipple',
717 | 681: 'notebook, notebook computer',
718 | 682: 'obelisk',
719 | 683: 'oboe, hautboy, hautbois',
720 | 684: 'ocarina, sweet potato',
721 | 685: 'odometer, hodometer, mileometer, milometer',
722 | 686: 'oil filter',
723 | 687: 'organ, pipe organ',
724 | 688: 'oscilloscope, scope, cathode-ray oscilloscope, CRO',
725 | 689: 'overskirt',
726 | 690: 'oxcart',
727 | 691: 'oxygen mask',
728 | 692: 'packet',
729 | 693: 'paddle, boat paddle',
730 | 694: 'paddlewheel, paddle wheel',
731 | 695: 'padlock',
732 | 696: 'paintbrush',
733 | 697: 'pajama, pyjama, pj\'s, jammies',
734 | 698: 'palace',
735 | 699: 'panpipe, pandean pipe, syrinx',
736 | 700: 'paper towel',
737 | 701: 'parachute, chute',
738 | 702: 'parallel bars, bars',
739 | 703: 'park bench',
740 | 704: 'parking meter',
741 | 705: 'passenger car, coach, carriage',
742 | 706: 'patio, terrace',
743 | 707: 'pay-phone, pay-station',
744 | 708: 'pedestal, plinth, footstall',
745 | 709: 'pencil box, pencil case',
746 | 710: 'pencil sharpener',
747 | 711: 'perfume, essence',
748 | 712: 'Petri dish',
749 | 713: 'photocopier',
750 | 714: 'pick, plectrum, plectron',
751 | 715: 'pickelhaube',
752 | 716: 'picket fence, paling',
753 | 717: 'pickup, pickup truck',
754 | 718: 'pier',
755 | 719: 'piggy bank, penny bank',
756 | 720: 'pill bottle',
757 | 721: 'pillow',
758 | 722: 'ping-pong ball',
759 | 723: 'pinwheel',
760 | 724: 'pirate, pirate ship',
761 | 725: 'pitcher, ewer',
762 | 726: 'plane, carpenter\'s plane, woodworking plane',
763 | 727: 'planetarium',
764 | 728: 'plastic bag',
765 | 729: 'plate rack',
766 | 730: 'plow, plough',
767 | 731: 'plunger, plumber\'s helper',
768 | 732: 'Polaroid camera, Polaroid Land camera',
769 | 733: 'pole',
770 | 734: 'police van, police wagon, paddy wagon, patrol wagon, wagon, black ' +
771 | 'Maria',
772 | 735: 'poncho',
773 | 736: 'pool table, billiard table, snooker table',
774 | 737: 'pop bottle, soda bottle',
775 | 738: 'pot, flowerpot',
776 | 739: 'potter\'s wheel',
777 | 740: 'power drill',
778 | 741: 'prayer rug, prayer mat',
779 | 742: 'printer',
780 | 743: 'prison, prison house',
781 | 744: 'projectile, missile',
782 | 745: 'projector',
783 | 746: 'puck, hockey puck',
784 | 747: 'punching bag, punch bag, punching ball, punchball',
785 | 748: 'purse',
786 | 749: 'quill, quill pen',
787 | 750: 'quilt, comforter, comfort, puff',
788 | 751: 'racer, race car, racing car',
789 | 752: 'racket, racquet',
790 | 753: 'radiator',
791 | 754: 'radio, wireless',
792 | 755: 'radio telescope, radio reflector',
793 | 756: 'rain barrel',
794 | 757: 'recreational vehicle, RV, R.V.',
795 | 758: 'reel',
796 | 759: 'reflex camera',
797 | 760: 'refrigerator, icebox',
798 | 761: 'remote control, remote',
799 | 762: 'restaurant, eating house, eating place, eatery',
800 | 763: 'revolver, six-gun, six-shooter',
801 | 764: 'rifle',
802 | 765: 'rocking chair, rocker',
803 | 766: 'rotisserie',
804 | 767: 'rubber eraser, rubber, pencil eraser',
805 | 768: 'rugby ball',
806 | 769: 'rule, ruler',
807 | 770: 'running shoe',
808 | 771: 'safe',
809 | 772: 'safety pin',
810 | 773: 'saltshaker, salt shaker',
811 | 774: 'sandal',
812 | 775: 'sarong',
813 | 776: 'sax, saxophone',
814 | 777: 'scabbard',
815 | 778: 'scale, weighing machine',
816 | 779: 'school bus',
817 | 780: 'schooner',
818 | 781: 'scoreboard',
819 | 782: 'screen, CRT screen',
820 | 783: 'screw',
821 | 784: 'screwdriver',
822 | 785: 'seat belt, seatbelt',
823 | 786: 'sewing machine',
824 | 787: 'shield, buckler',
825 | 788: 'shoe shop, shoe-shop, shoe store',
826 | 789: 'shoji',
827 | 790: 'shopping basket',
828 | 791: 'shopping cart',
829 | 792: 'shovel',
830 | 793: 'shower cap',
831 | 794: 'shower curtain',
832 | 795: 'ski',
833 | 796: 'ski mask',
834 | 797: 'sleeping bag',
835 | 798: 'slide rule, slipstick',
836 | 799: 'sliding door',
837 | 800: 'slot, one-armed bandit',
838 | 801: 'snorkel',
839 | 802: 'snowmobile',
840 | 803: 'snowplow, snowplough',
841 | 804: 'soap dispenser',
842 | 805: 'soccer ball',
843 | 806: 'sock',
844 | 807: 'solar dish, solar collector, solar furnace',
845 | 808: 'sombrero',
846 | 809: 'soup bowl',
847 | 810: 'space bar',
848 | 811: 'space heater',
849 | 812: 'space shuttle',
850 | 813: 'spatula',
851 | 814: 'speedboat',
852 | 815: 'spider web, spider\'s web',
853 | 816: 'spindle',
854 | 817: 'sports car, sport car',
855 | 818: 'spotlight, spot',
856 | 819: 'stage',
857 | 820: 'steam locomotive',
858 | 821: 'steel arch bridge',
859 | 822: 'steel drum',
860 | 823: 'stethoscope',
861 | 824: 'stole',
862 | 825: 'stone wall',
863 | 826: 'stopwatch, stop watch',
864 | 827: 'stove',
865 | 828: 'strainer',
866 | 829: 'streetcar, tram, tramcar, trolley, trolley car',
867 | 830: 'stretcher',
868 | 831: 'studio couch, day bed',
869 | 832: 'stupa, tope',
870 | 833: 'submarine, pigboat, sub, U-boat',
871 | 834: 'suit, suit of clothes',
872 | 835: 'sundial',
873 | 836: 'sunglass',
874 | 837: 'sunglasses, dark glasses, shades',
875 | 838: 'sunscreen, sunblock, sun blocker',
876 | 839: 'suspension bridge',
877 | 840: 'swab, swob, mop',
878 | 841: 'sweatshirt',
879 | 842: 'swimming trunks, bathing trunks',
880 | 843: 'swing',
881 | 844: 'switch, electric switch, electrical switch',
882 | 845: 'syringe',
883 | 846: 'table lamp',
884 | 847: 'tank, army tank, armored combat vehicle, armoured combat vehicle',
885 | 848: 'tape player',
886 | 849: 'teapot',
887 | 850: 'teddy, teddy bear',
888 | 851: 'television, television system',
889 | 852: 'tennis ball',
890 | 853: 'thatch, thatched roof',
891 | 854: 'theater curtain, theatre curtain',
892 | 855: 'thimble',
893 | 856: 'thresher, thrasher, threshing machine',
894 | 857: 'throne',
895 | 858: 'tile roof',
896 | 859: 'toaster',
897 | 860: 'tobacco shop, tobacconist shop, tobacconist',
898 | 861: 'toilet seat',
899 | 862: 'torch',
900 | 863: 'totem pole',
901 | 864: 'tow truck, tow car, wrecker',
902 | 865: 'toyshop',
903 | 866: 'tractor',
904 | 867: 'trailer truck, tractor trailer, trucking rig, rig, articulated ' +
905 | 'lorry, semi',
906 | 868: 'tray',
907 | 869: 'trench coat',
908 | 870: 'tricycle, trike, velocipede',
909 | 871: 'trimaran',
910 | 872: 'tripod',
911 | 873: 'triumphal arch',
912 | 874: 'trolleybus, trolley coach, trackless trolley',
913 | 875: 'trombone',
914 | 876: 'tub, vat',
915 | 877: 'turnstile',
916 | 878: 'typewriter keyboard',
917 | 879: 'umbrella',
918 | 880: 'unicycle, monocycle',
919 | 881: 'upright, upright piano',
920 | 882: 'vacuum, vacuum cleaner',
921 | 883: 'vase',
922 | 884: 'vault',
923 | 885: 'velvet',
924 | 886: 'vending machine',
925 | 887: 'vestment',
926 | 888: 'viaduct',
927 | 889: 'violin, fiddle',
928 | 890: 'volleyball',
929 | 891: 'waffle iron',
930 | 892: 'wall clock',
931 | 893: 'wallet, billfold, notecase, pocketbook',
932 | 894: 'wardrobe, closet, press',
933 | 895: 'warplane, military plane',
934 | 896: 'washbasin, handbasin, washbowl, lavabo, wash-hand basin',
935 | 897: 'washer, automatic washer, washing machine',
936 | 898: 'water bottle',
937 | 899: 'water jug',
938 | 900: 'water tower',
939 | 901: 'whiskey jug',
940 | 902: 'whistle',
941 | 903: 'wig',
942 | 904: 'window screen',
943 | 905: 'window shade',
944 | 906: 'Windsor tie',
945 | 907: 'wine bottle',
946 | 908: 'wing',
947 | 909: 'wok',
948 | 910: 'wooden spoon',
949 | 911: 'wool, woolen, woollen',
950 | 912: 'worm fence, snake fence, snake-rail fence, Virginia fence',
951 | 913: 'wreck',
952 | 914: 'yawl',
953 | 915: 'yurt',
954 | 916: 'web site, website, internet site, site',
955 | 917: 'comic book',
956 | 918: 'crossword puzzle, crossword',
957 | 919: 'street sign',
958 | 920: 'traffic light, traffic signal, stoplight',
959 | 921: 'book jacket, dust cover, dust jacket, dust wrapper',
960 | 922: 'menu',
961 | 923: 'plate',
962 | 924: 'guacamole',
963 | 925: 'consomme',
964 | 926: 'hot pot, hotpot',
965 | 927: 'trifle',
966 | 928: 'ice cream, icecream',
967 | 929: 'ice lolly, lolly, lollipop, popsicle',
968 | 930: 'French loaf',
969 | 931: 'bagel, beigel',
970 | 932: 'pretzel',
971 | 933: 'cheeseburger',
972 | 934: 'hotdog, hot dog, red hot',
973 | 935: 'mashed potato',
974 | 936: 'head cabbage',
975 | 937: 'broccoli',
976 | 938: 'cauliflower',
977 | 939: 'zucchini, courgette',
978 | 940: 'spaghetti squash',
979 | 941: 'acorn squash',
980 | 942: 'butternut squash',
981 | 943: 'cucumber, cuke',
982 | 944: 'artichoke, globe artichoke',
983 | 945: 'bell pepper',
984 | 946: 'cardoon',
985 | 947: 'mushroom',
986 | 948: 'Granny Smith',
987 | 949: 'strawberry',
988 | 950: 'orange',
989 | 951: 'lemon',
990 | 952: 'fig',
991 | 953: 'pineapple, ananas',
992 | 954: 'banana',
993 | 955: 'jackfruit, jak, jack',
994 | 956: 'custard apple',
995 | 957: 'pomegranate',
996 | 958: 'hay',
997 | 959: 'carbonara',
998 | 960: 'chocolate sauce, chocolate syrup',
999 | 961: 'dough',
1000 | 962: 'meat loaf, meatloaf',
1001 | 963: 'pizza, pizza pie',
1002 | 964: 'potpie',
1003 | 965: 'burrito',
1004 | 966: 'red wine',
1005 | 967: 'espresso',
1006 | 968: 'cup',
1007 | 969: 'eggnog',
1008 | 970: 'alp',
1009 | 971: 'bubble',
1010 | 972: 'cliff, drop, drop-off',
1011 | 973: 'coral reef',
1012 | 974: 'geyser',
1013 | 975: 'lakeside, lakeshore',
1014 | 976: 'promontory, headland, head, foreland',
1015 | 977: 'sandbar, sand bar',
1016 | 978: 'seashore, coast, seacoast, sea-coast',
1017 | 979: 'valley, vale',
1018 | 980: 'volcano',
1019 | 981: 'ballplayer, baseball player',
1020 | 982: 'groom, bridegroom',
1021 | 983: 'scuba diver',
1022 | 984: 'rapeseed',
1023 | 985: 'daisy',
1024 | 986: 'yellow lady\'s slipper, yellow lady-slipper, Cypripedium calceolus, ' +
1025 | 'Cypripedium parviflorum',
1026 | 987: 'corn',
1027 | 988: 'acorn',
1028 | 989: 'hip, rose hip, rosehip',
1029 | 990: 'buckeye, horse chestnut, conker',
1030 | 991: 'coral fungus',
1031 | 992: 'agaric',
1032 | 993: 'gyromitra',
1033 | 994: 'stinkhorn, carrion fungus',
1034 | 995: 'earthstar',
1035 | 996: 'hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola ' +
1036 | 'frondosa',
1037 | 997: 'bolete',
1038 | 998: 'ear, spike, capitulum',
1039 | 999: 'toilet tissue, toilet paper, bathroom tissue'
1040 | };
--------------------------------------------------------------------------------