Skip to content

Commit 75d21fa

Browse files
authored
[quantization] Add calculation of gzip compression ratio (#289)
* Upgrade to tfjs-node(-gpu) 1.2.3; Improve plotting script * [quantization] Add calculation of gzip compression ratio * Improve script printout and README.md
1 parent d50d0b6 commit 75d21fa

File tree

6 files changed

+113
-44
lines changed

6 files changed

+113
-44
lines changed

quantization/README.md

+34-2
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,46 @@ quantizing the weights to 8 bits leads to a significant deterioration in
4141
accuracy, as measured by the top-1 and top-5 accuracies. See example results
4242
in the table below:
4343

44-
| Dataset and Mdoel | Original (no-quantization) | 16-bit quantization | 8-bit quantization |
44+
| Dataset and Model | Original (no-quantization) | 16-bit quantization | 8-bit quantization |
4545
| ---------------------- | -------------------------- | ------------------- | ------------------ |
4646
| housing: multi-layer regressor | MAE=0.311984 | MAE=0.311983 | MAE=0.312780 |
4747
| MNIST: convnet | accuracy=0.9952 | accuracy=0.9952 | accuracy=0.9952 |
4848
| Fashion MNIST: convnet | accuracy=0.922 | accuracy=0.922 | accuracy=0.9211 |
4949
| MobileNetV2 | top-1 accuracy=0.618; top-5 accuracy=0.788 | top-1 accuracy=0.624; top-5 accuracy=0.789 | top-1 accuracy=0.280; top-5 accuracy=0.490 |
5050

51-
MAE Stands for mean absolute error.
51+
MAE Stands for mean absolute error (lower is better).
5252

5353
They demonstrate different effects of the same quantization technique
5454
on different problems.
5555

56+
### Effect of quantization on gzip compression ratio
57+
58+
An additional factor affecting the over-the-wire size of models
59+
under quantization is the gzip ratio. This factor should be taken into
60+
account because gzip is widely used to transmit large files over the
61+
web.
62+
63+
Most non-quantized models (i.e.,
64+
models with 32-bit float weights) are not very compressible, due to
65+
the noise-like variation in their weight parameters, which contain
66+
few repeating patterns. The same is true for models with weights
67+
quantized at the 16-bit precision. However, when models are quantized
68+
at the 8-bit precision, there is usually a significant increase in the
69+
gzip compression ratio. The `yarn quantize-and-evalute*` commands in
70+
this example (see sections below) not only evaluates accuracy, but also
71+
calculates the gzip compression ratio of model files under different
72+
levels of quantization. The table below summarizes the compression ratios
73+
from the four models covered by this example (higher is better):
74+
75+
gzip compression ratio:
76+
`(total size of the model.json and weight files) / (size of gzipped tar ball)`
77+
| Model | Original (no-quantization) | 16-bit quantization | 8-bit quantization |
78+
| ---------- | -------------------------- | ------------------- | ------------------ |
79+
| housing: multi-layer regressor | 1.121 | 1.161 | 1.388 |
80+
| MNIST: convnet | 1.082 | 1.037 | 1.184 |
81+
| Fashion MNIST: convnet | 1.078 | 1.048 | 1.229 |
82+
| MobileNetV2 | 1.085 | 1.063 | 1.271 |
83+
5684
## Running the housing quantization demo
5785

5886
In preparation, do:
@@ -105,6 +133,10 @@ and evaluate the effects on the model's test accuracy, do:
105133
yarn quantize-and-evaluate-mnist
106134
```
107135

136+
The command also calculates the ratio of gzip compression for the
137+
model's saved artifacts under the three different levels of quantization
138+
(no-quantization, 16-bit, and 8-bit).
139+
108140
## Running the Fashion-MNIST quantization demo
109141

110142
In preparation, do:

quantization/draw_quantization.py

+1-5
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def main():
8181
# Number of points along the x-axis used to draw the sine wave.
8282
n_points = 1e6
8383
xs = np.linspace(-np.pi, np.pi, n_points).astype(np.float64)
84-
w = np.sin(xs)
84+
w = xs
8585

8686
w_16bit = dequantize(*quantize(w, 16))
8787
w_8bit = dequantize(*quantize(w, 8))
@@ -90,10 +90,6 @@ def main():
9090
plot_range = range(int(n_points * (0.5 - plot_delta)),
9191
int(n_points * (0.5 + plot_delta)))
9292

93-
print(w[plot_range])
94-
print(w_16bit[plot_range])
95-
print(w_8bit[plot_range])
96-
9793
plt.figure(figsize=(20, 6))
9894
plt.subplot(1, 3, 1)
9995
plt.plot(xs[plot_range], w[plot_range], '-')

quantization/eval_mobilenetv2.js

-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ async function main() {
8383

8484
const imageH = model.inputs[0].shape[2];
8585
const imageW = model.inputs[0].shape[2];
86-
console.log(`imageH = ${imageH}; imageW = ${imageW}`);
8786

8887
// Load the images into a tensor.
8988
const dirContent = fs.readdirSync(args.imageDir);

quantization/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
"quantize-and-evaluate-MobileNetV2": "./quantize_evaluate.sh MobileNetV2"
2424
},
2525
"devDependencies": {
26-
"@tensorflow/tfjs-node": "^1.1.2",
27-
"@tensorflow/tfjs-node-gpu": "^1.1.2",
26+
"@tensorflow/tfjs-node": "^1.2.3",
27+
"@tensorflow/tfjs-node-gpu": "^1.2.3",
2828
"argparse": "^1.0.10",
2929
"babel-cli": "^6.26.0",
3030
"babel-core": "^6.26.3",

quantization/quantize_evaluate.sh

+36
Original file line numberDiff line numberDiff line change
@@ -101,23 +101,59 @@ if [[ "${MODEL_NAME}" == "MobileNetV2" ]]; then
101101
fi
102102

103103
# Evaluate accuracy under no quantization (i.e., full 32-bit weight precision).
104+
echo "=== Accuracy evalution: No quantization ==="
104105
yarn "eval-${MODEL_NAME}" "${MODEL_JSON_PATH}" \
105106
"${IMAGENET_1000_SAMPLES_DIR}"
106107

108+
107109
# Evaluate accuracy under 16-bit quantization.
110+
echo "=== Accuracy evalution: 16-bit quantization ==="
108111
yarn "eval-${MODEL_NAME}" "${MODEL_PATH_16BIT}/model.json" \
109112
"${IMAGENET_1000_SAMPLES_DIR}"
110113

111114
# Evaluate accuracy under 8-bit quantization.
115+
echo "=== Accuracy evalution: 8-bit quantization ==="
112116
yarn "eval-${MODEL_NAME}" "${MODEL_PATH_8BIT}/model.json" \
113117
"${IMAGENET_1000_SAMPLES_DIR}"
114118
else
115119
# Evaluate accuracy under no quantization (i.e., full 32-bit weight precision).
120+
echo "=== Accuracy evalution: No quantization ==="
116121
yarn "eval-${MODEL_NAME}" "${MODEL_JSON_PATH}"
117122

118123
# Evaluate accuracy under 16-bit quantization.
124+
echo "=== Accuracy evalution: 16-bit quantization ==="
119125
yarn "eval-${MODEL_NAME}" "${MODEL_PATH_16BIT}/model.json"
120126

121127
# Evaluate accuracy under 8-bit quantization.
128+
echo "=== Accuracy evalution: 8-bit quantization ==="
122129
yarn "eval-${MODEL_NAME}" "${MODEL_PATH_8BIT}/model.json"
123130
fi
131+
132+
function calc_gzip_ratio() {
133+
ORIGINAL_FILES_SIZE_BYTES="$(ls -lAR ${1} | grep -v '^d' | awk '{total += $5} END {print total}')"
134+
TEMP_TARBALL="$(mktemp)"
135+
tar czf "${TEMP_TARBALL}" "${1}"
136+
TARBALL_SIZE="$(wc -c < ${TEMP_TARBALL})"
137+
ZIP_RATIO="$(awk "BEGIN { print(${ORIGINAL_FILES_SIZE_BYTES} / ${TARBALL_SIZE}) }")"
138+
rm "${TEMP_TARBALL}"
139+
140+
echo " Total file size: ${ORIGINAL_FILES_SIZE_BYTES} bytes"
141+
echo " gzipped tarball size: ${TARBALL_SIZE} bytes"
142+
echo " gzip ratio: ${ZIP_RATIO}"
143+
echo
144+
}
145+
146+
echo
147+
echo "=== gzip ratios ==="
148+
149+
# Calculate the gzip ratio of the original (unquantized) model.
150+
echo "Original model (No quantization):"
151+
calc_gzip_ratio "${MODEL_PATH}"
152+
153+
# Calculate the gzip ratio of the 16-bit-quantized model.
154+
echo "16-bit-quantized model:"
155+
calc_gzip_ratio "${MODEL_PATH_16BIT}"
156+
157+
# Calculate the gzip ratio of the 8-bit-quantized model.
158+
echo "8-bit-quantized model:"
159+
calc_gzip_ratio "${MODEL_PATH_8BIT}"

quantization/yarn.lock

+40-34
Original file line numberDiff line numberDiff line change
@@ -262,16 +262,17 @@
262262
dependencies:
263263
core-js "^2.5.7"
264264

265-
"@tensorflow/tfjs-converter@1.1.2":
266-
version "1.1.2"
267-
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-converter/-/tfjs-converter-1.1.2.tgz#2400ac77b30f973f1fcb26c912b28271f7f4d605"
268-
integrity sha512-KuLIIJYzmRmtJXcjBH3inQVhTHbABj2TNAVS3ss12hzDiEE/RiRb/LZKo8XV2WczuZXTq+gxep84PWXSH/HQXA==
265+
"@tensorflow/tfjs-converter@1.2.2":
266+
version "1.2.2"
267+
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-converter/-/tfjs-converter-1.2.2.tgz#c95e2f79b1de830b8079c7704dc8463ced2d2b79"
268+
integrity sha512-NM2NcPRHpCNeJdBxHcYpmW9ZHTQ2lJFJgmgGpQ8CxSC9CtQB05bFONs3SKcwMNDE/69QBRVom5DYqLCVUg+A+g==
269269

270-
"@tensorflow/tfjs-core@1.1.2":
271-
version "1.1.2"
272-
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-1.1.2.tgz#efb8b3688fbff353e51d41a3d832dde8c1bc321d"
273-
integrity sha512-xCAUIAh14OFnHt+IQUUZIH/P/jH/EWvewL0Ty6q6USUx4YZ+HvKwNw1G7h/gKki4A31BJ0avD04ylBKc75laGg==
270+
"@tensorflow/tfjs-core@1.2.2":
271+
version "1.2.2"
272+
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-1.2.2.tgz#2efa89e323612a26aeccee9b3ae9f5ac5a635bbe"
273+
integrity sha512-2hCHMKjh3UNpLEjbAEaurrTGJyj/KpLtMSAraWgHA1vGY0kmk50BBSbgCDmXWUVm7lyh/SkCq4/GrGDZktEs3g==
274274
dependencies:
275+
"@types/offscreencanvas" "~2019.3.0"
275276
"@types/seedrandom" "2.4.27"
276277
"@types/webgl-ext" "0.0.30"
277278
"@types/webgl2" "0.0.4"
@@ -280,54 +281,54 @@
280281
optionalDependencies:
281282
rollup-plugin-visualizer "~1.1.1"
282283

283-
"@tensorflow/tfjs-data@1.1.2":
284-
version "1.1.2"
285-
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-data/-/tfjs-data-1.1.2.tgz#f37809aa89946a834f3566bd090db852f2c4244e"
286-
integrity sha512-K30QdocXd5zn3rpGbRTC4sO42q8tK1SGqDHE2IEkvYzcg0PAU3cEMODGTLjKt0z1Lfy1JKgs0FPcvazqmxpjGA==
284+
"@tensorflow/tfjs-data@1.2.2":
285+
version "1.2.2"
286+
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-data/-/tfjs-data-1.2.2.tgz#bd802b4096df04277d302d66598aef47fbffef85"
287+
integrity sha512-oHGBoGdnCl2RyouLKplQqo+iil0iJgPbi/aoHizhpO77UBuJXlKMblH8w5GbxVAw3hKxWlqzYpxPo6rVRgehNA==
287288
dependencies:
288289
"@types/node-fetch" "^2.1.2"
289290
node-fetch "~2.1.2"
290291

291-
"@tensorflow/tfjs-layers@1.1.2":
292-
version "1.1.2"
293-
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-layers/-/tfjs-layers-1.1.2.tgz#29393221446a877962b71084305597295504801e"
294-
integrity sha512-iP9mJz/79nK+sXBWdxQkeNIqn9p+O/x3g15ntIXpEaLXOGjQEE12iKtLCWgG3qH+FltOVt5hTbAXkj/yDym1Xg==
292+
"@tensorflow/tfjs-layers@1.2.2":
293+
version "1.2.2"
294+
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-layers/-/tfjs-layers-1.2.2.tgz#3365dbbca7cfa4fcc6cacc9fffc90d664606bd4e"
295+
integrity sha512-yzWZaZrCVpEyTkSrzMe4OOP4aGUfaaROE/zR9fPsPGGF8wLlbLNZUJjeYUmjy3G3pXGaM0mQUbLR5Vd707CVtQ==
295296

296-
"@tensorflow/tfjs-node-gpu@^1.1.2":
297-
version "1.1.2"
298-
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-node-gpu/-/tfjs-node-gpu-1.1.2.tgz#c532ab9ca84745ffe27af8b7cef40d329eace221"
299-
integrity sha512-OvLCngIfqdPuYqGrUDnwTLnolOVrS7Zr5ufHWBA+gxesNFHXgfOm0nBFPhXHtfIaaYdMcM8Gsos4frXzqRzsiQ==
297+
"@tensorflow/tfjs-node-gpu@^1.2.3":
298+
version "1.2.3"
299+
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-node-gpu/-/tfjs-node-gpu-1.2.3.tgz#3786d814bc5ca4c10e88a4a490feea65a39bd8cf"
300+
integrity sha512-y8A1dF4WZZ+IvCCv/hrEUVV9O1ua0f5rZVzaMnJx+xv8o51DwTGk7h6tsnE/F2N6pf9mKLsY8roUBviIasVEmQ==
300301
dependencies:
301-
"@tensorflow/tfjs" "~1.1.2"
302+
"@tensorflow/tfjs" "~1.2.2"
302303
adm-zip "^0.4.11"
303304
bindings "~1.3.0"
304305
https-proxy-agent "^2.2.1"
305306
progress "^2.0.0"
306307
rimraf "^2.6.2"
307308
tar "^4.4.6"
308309

309-
"@tensorflow/tfjs-node@^1.1.2":
310-
version "1.1.2"
311-
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-node/-/tfjs-node-1.1.2.tgz#b5979c94fc80351ef2f5fe2a58c58f385cabaaf0"
312-
integrity sha512-QBEnptTDccUZXU1z2P++ZXJflZi+qh915uOu8BAHvBYujBmVp/rL3+HyZhJpgHn8GXz88z0dsXMNem5p4zJnvw==
310+
"@tensorflow/tfjs-node@^1.2.3":
311+
version "1.2.3"
312+
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-node/-/tfjs-node-1.2.3.tgz#b2a6c3051da080a853be34b4bdc6649479139852"
313+
integrity sha512-6/V3JfoxnvUJhZle8+7V0ln7KjUIJOlDCk43EBQg+XoGudvp3L1x0RXcfCQ1nXFIlZVYixNJYd3XTIOHZBECSA==
313314
dependencies:
314-
"@tensorflow/tfjs" "~1.1.2"
315+
"@tensorflow/tfjs" "~1.2.2"
315316
adm-zip "^0.4.11"
316317
bindings "~1.3.0"
317318
https-proxy-agent "^2.2.1"
318319
progress "^2.0.0"
319320
rimraf "^2.6.2"
320321
tar "^4.4.6"
321322

322-
"@tensorflow/tfjs@~1.1.2":
323-
version "1.1.2"
324-
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs/-/tfjs-1.1.2.tgz#9a1c2bbc4d82f9d18f250ab4a4d7c8ad43e2d432"
325-
integrity sha512-b+ekLNEfMzaBszti6uGcS3pJoPNQuv1hxKEoY9Q3ix52fFJzI86nSvM1lwOcvUZy6DjPFDoyB8MO+dJHqecG5w==
323+
"@tensorflow/tfjs@~1.2.2":
324+
version "1.2.2"
325+
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs/-/tfjs-1.2.2.tgz#e0cc7f1c4139e7c38f3ea478999f0972d354c948"
326+
integrity sha512-HfhSzL2eTWhlT0r/A5wmo+u3bHe+an16p5wsnFH3ujn21fQ8QtGpSfDHQZjWx1kVFaQnV6KBG+17MOrRHoHlLA==
326327
dependencies:
327-
"@tensorflow/tfjs-converter" "1.1.2"
328-
"@tensorflow/tfjs-core" "1.1.2"
329-
"@tensorflow/tfjs-data" "1.1.2"
330-
"@tensorflow/tfjs-layers" "1.1.2"
328+
"@tensorflow/tfjs-converter" "1.2.2"
329+
"@tensorflow/tfjs-core" "1.2.2"
330+
"@tensorflow/tfjs-data" "1.2.2"
331+
"@tensorflow/tfjs-layers" "1.2.2"
331332

332333
"@types/node-fetch@^2.1.2":
333334
version "2.3.4"
@@ -341,6 +342,11 @@
341342
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.2.tgz#3452a24edf9fea138b48fad4a0a028a683da1e40"
342343
integrity sha512-5tabW/i+9mhrfEOUcLDu2xBPsHJ+X5Orqy9FKpale3SjDA17j5AEpYq5vfy3oAeAHGcvANRCO3NV3d2D6q3NiA==
343344

345+
"@types/offscreencanvas@~2019.3.0":
346+
version "2019.3.0"
347+
resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz#3336428ec7e9180cf4566dfea5da04eb586a6553"
348+
integrity sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q==
349+
344350
345351
version "2.4.27"
346352
resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.27.tgz#9db563937dd86915f69092bc43259d2f48578e41"

0 commit comments

Comments
 (0)