2018 年 7 月 2 日 — 发布者:Zaid Alyafeai
我们将创建一个简单的工具,可以识别绘图并输出当前绘图的名称。此应用程序将直接在浏览器上运行,无需任何安装。我们将使用 Google Colab 训练模型,并将使用 TensorFlow.js 在浏览器上部署它。
代码和演示在 GitHub 上找到实时 演示 和 代码。 另外,请务必在 Google 上测试笔记本...
类别的子集 |
管道 |
import os
import glob
import numpy as np
from tensorflow.keras import layers
from tensorflow import keras
import tensorflow as tf
[N,784]
的 numpy 数组,其中 N
是该特定类别的图像数量。 我们首先下载数据集import urllib.request
def download():
base = 'https://storage.googleapis.com/quickdraw_dataset/full/numpy_bitmap/'
for c in classes:
cls_url = c.replace('_', '%20')
path = base+cls_url+'.npy'
print(path)
urllib.request.urlretrieve(path, 'data/'+c+'.npy')
由于我们的内存有限,我们只加载每个类别的 5000 张图像到内存中。 我们还保留了 20% 的未见数据用于测试def load_data(root, vfold_ratio=0.2, max_items_per_class= 5000 ):
all_files = glob.glob(os.path.join(root, '*.npy'))
#initialize variables
x = np.empty([0, 784])
y = np.empty([0])
class_names = []
#load a subset of the data to memory
for idx, file in enumerate(all_files):
data = np.load(file)
data = data[0: max_items_per_class, :]
labels = np.full(data.shape[0], idx)
x = np.concatenate((x, data), axis=0)
y = np.append(y, labels)
class_name, ext = os.path.splitext(os.path.basename(file))
class_names.append(class_name)
data = None
labels = None
#separate into training and testing
permutation = np.random.permutation(y.shape[0])
x = x[permutation, :]
y = y[permutation]
vfold_size = int(x.shape[0]/100*(vfold_ratio*100))
x_test = x[0:vfold_size, :]
y_test = y[0:vfold_size]
x_train = x[vfold_size:x.shape[0], :]
y_train = y[vfold_size:y.shape[0]]
return x_train, y_train, x_test, y_test, class_names
[N, 28, 28, 1]
的批次,并输出形状为 [N, 100]
的概率# Reshape and normalize
x_train = x_train.reshape(x_train.shape[0], image_size, image_size, 1).astype('float32')
x_test = x_test.reshape(x_test.shape[0], image_size, image_size, 1).astype('float32')
x_train /= 255.0
x_test /= 255.0
# Convert class vectors to class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
# Define model
model = keras.Sequential()
model.add(layers.Convolution2D(16, (3, 3),
padding='same',
input_shape=x_train.shape[1:], activation='relu'))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Convolution2D(32, (3, 3), padding='same', activation= 'relu'))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Convolution2D(64, (3, 3), padding='same', activation= 'relu'))
model.add(layers.MaxPooling2D(pool_size =(2,2)))
model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(100, activation='softmax'))
# Train model
adam = tf.train.AdamOptimizer()
model.compile(loss='categorical_crossentropy',
optimizer=adam,
metrics=['top_k_categorical_accuracy'])
print(model.summary())
5
个 epoch,256
个批次,并使用 10%
的验证分割#fit the model
model.fit(x = x_train, y = y_train, validation_split=0.1, batch_size = 256, verbose=2, epochs=5)
#evaluate on unseen data
score = model.evaluate(x_test, y_test, verbose=0)
print('Test accuarcy: {:0.2f}%'.format(score[1] * 100))
92.20%
,前 5
个精度。model.save('keras.h5')
我们安装 tfjs 包以进行转换!pip install tensorflowjs
然后我们转换模型!mkdir model
!tensorflowjs_converter --input_format keras keras.h5 model/
这将创建一些权重文件和包含模型架构的 json 文件。!zip -r model.zip model
最后,下载模型from google.colab import files
files.download('model.zip')
300 x 300
的画布。 我将不会详细介绍界面,而是专注于 TensorFlow.js 部分。<script src="https://cdn.jsdelivr.net.cn/npm/@tensorflow/tfjs@latest"> </script>
您将需要在本地机器上运行一个服务器来托管权重文件。 您可以创建一个 apache 服务器或在 GitHub 上托管页面,就像我在我的 项目 中做的那样。model = await tf.loadLayersModel('model/model.json')
await
关键字将等待浏览器加载模型。//the minimum boudning box around the current drawing
const mbb = getMinBox()
//cacluate the dpi of the current window
const dpi = window.devicePixelRatio
//extract the image data
const imgData = canvas.contextContainer.getImageData(mbb.min.x * dpi, mbb.min.y * dpi,
(mbb.max.x - mbb.min.x) * dpi, (mbb.max.y - mbb.min.y) * dpi);
getMinBox()
将在后面解释。 变量 dpi
用于根据屏幕像素密度拉伸画布的裁剪。function preprocess(imgData)
{
return tf.tidy(()=>{
//convert the image data to a tensor
let tensor = tf.browser.fromPixels(imgData, numChannels= 1)
//resize to 28 x 28
const resized = tf.image.resizeBilinear(tensor, [28, 28]).toFloat()
// Normalize the image
const offset = tf.scalar(255.0);
const normalized = tf.scalar(1.0).sub(resized.div(offset));
//We add a dimension to get a batch shape
const batched = normalized.expandDims(0)
return batched
})
}
为了进行预测,我们使用 model.predict
,这将返回形状为 [N, 100]
的概率const pred = model.predict(preprocess(imgData)).dataSync()
然后,我们可以使用简单的函数来查找前 5 个概率。[N, 28, 28,1]
的张量。 我们拥有的绘图画布大小为 300 x 300
,对于绘图来说可能太大,或者用户可能绘制了一个小图形。 最好只裁剪包含当前绘图的框。 为此,我们通过查找左上角和右下角点来提取绘图周围的最小边界框//record the current drawing coordinates
function recordCoor(event)
{
//get current mouse coordinate
var pointer = canvas.getPointer(event.e);
var posX = pointer.x;
var posY = pointer.y;
//record the point if withing the canvas and the mouse is pressed
if(posX >=0 && posY >= 0 && mousePressed)
{
coords.push(pointer)
}
}
//get the best bounding box by finding the top left and bottom right cornders
function getMinBox(){
var coorX = coords.map(function(p) {return p.x});
var coorY = coords.map(function(p) {return p.y});
//find top left corner
var min_coords = {
x : Math.min.apply(null, coorX),
y : Math.min.apply(null, coorY)
}
//find right bottom corner
var max_coords = {
x : Math.max.apply(null, coorX),
y : Math.max.apply(null, coorY)
}
return {
min : min_coords,
max : max_coords
}
}
2018 年 7 月 2 日 — 发布者:Zaid Alyafeai
我们将创建一个简单的工具,可以识别绘图并输出当前绘图的名称。 此应用程序将直接在浏览器上运行,无需任何安装。 我们将使用 Google Colab 训练模型,并将使用 TensorFlow.js 在浏览器上部署它。
代码和演示在 GitHub 上找到实时 演示 和 代码。 另外,请务必在 Google 上测试笔记本...