{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "m7hbib3bSGO9" }, "source": [ "**Copyright 2020 The TensorFlow Authors.**" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "cellView": "form", "execution": { "iopub.execute_input": "2021-02-13T03:04:50.776694Z", "iopub.status.busy": "2021-02-13T03:04:50.775997Z", "iopub.status.idle": "2021-02-13T03:04:50.778613Z", "shell.execute_reply": "2021-02-13T03:04:50.778098Z" }, "id": "mEE8NFIMSGO-" }, "outputs": [], "source": [ "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# https://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License." ] }, { "cell_type": "markdown", "metadata": { "id": "SyiSRgdtSGPC" }, "source": [ "# Keras での重みクラスタリングの例" ] }, { "cell_type": "markdown", "metadata": { "id": "kW3os956SGPD" }, "source": [ "
![]() | \n",
" ![]() | \n",
" ![]() | \n",
" ![]() | \n",
"
strip_clustering
と標準圧縮アルゴリズム(gzip など)の適用は、クラスタリングの圧縮のメリットを確認する上で必要です。\n",
"\n",
"まず、TensorFlow の圧縮可能なモデルを作成します。ここで、`strip_clustering` は、クラスタリングがトレーニング中にのみ必要とするすべての変数(クラスタの重心とインデックスを格納する `tf.Variable` など)を除去します。そうしない場合、推論中にモデルサイズが増加してしまいます。"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"execution": {
"iopub.execute_input": "2021-02-13T03:05:44.933239Z",
"iopub.status.busy": "2021-02-13T03:05:44.932527Z",
"iopub.status.idle": "2021-02-13T03:05:44.971887Z",
"shell.execute_reply": "2021-02-13T03:05:44.971339Z"
},
"id": "4h6tSvMzSGPd"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Saving clustered model to: /tmp/tmpz9c4ugbj.h5\n"
]
}
],
"source": [
"final_model = tfmot.clustering.keras.strip_clustering(clustered_model)\n",
"\n",
"_, clustered_keras_file = tempfile.mkstemp('.h5')\n",
"print('Saving clustered model to: ', clustered_keras_file)\n",
"tf.keras.models.save_model(final_model, clustered_keras_file, \n",
" include_optimizer=False)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "jZcotzPSVBtu"
},
"source": [
"次に、TFLite の圧縮可能なモデルを作成します。クラスタモデルをターゲットバックエンドで実行可能な形式に変換できます。TensorFlow Lite は、モバイルデバイスにデプロイするために使用できる例です。"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"execution": {
"iopub.execute_input": "2021-02-13T03:05:44.980463Z",
"iopub.status.busy": "2021-02-13T03:05:44.978531Z",
"iopub.status.idle": "2021-02-13T03:05:45.523567Z",
"shell.execute_reply": "2021-02-13T03:05:45.522955Z"
},
"id": "v2N47QW6SGPh"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"INFO:tensorflow:Assets written to: /tmp/tmp41s2kzub/assets\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Saved clustered TFLite model to: /tmp/clustered_mnist.tflite\n"
]
}
],
"source": [
"clustered_tflite_file = '/tmp/clustered_mnist.tflite'\n",
"converter = tf.lite.TFLiteConverter.from_keras_model(final_model)\n",
"tflite_clustered_model = converter.convert()\n",
"with open(clustered_tflite_file, 'wb') as f:\n",
" f.write(tflite_clustered_model)\n",
"print('Saved clustered TFLite model to:', clustered_tflite_file)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "S7amG_9XV-w9"
},
"source": [
"実際に gzip でモデルを圧縮し、zip 圧縮されたサイズを測定するヘルパー関数を定義します。"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"execution": {
"iopub.execute_input": "2021-02-13T03:05:45.529525Z",
"iopub.status.busy": "2021-02-13T03:05:45.528601Z",
"iopub.status.idle": "2021-02-13T03:05:45.531197Z",
"shell.execute_reply": "2021-02-13T03:05:45.530666Z"
},
"id": "1XJ4QBMpW5JB"
},
"outputs": [],
"source": [
"def get_gzipped_model_size(file):\n",
" # It returns the size of the gzipped model in bytes.\n",
" import os\n",
" import zipfile\n",
"\n",
" _, zipped_file = tempfile.mkstemp('.zip')\n",
" with zipfile.ZipFile(zipped_file, 'w', compression=zipfile.ZIP_DEFLATED) as f:\n",
" f.write(file)\n",
"\n",
" return os.path.getsize(zipped_file)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "INeAOWRBSGPj"
},
"source": [
"比較して、モデルがクラスタリングによって **6 倍**小さくなっていることを確認します。"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"execution": {
"iopub.execute_input": "2021-02-13T03:05:45.535704Z",
"iopub.status.busy": "2021-02-13T03:05:45.534968Z",
"iopub.status.idle": "2021-02-13T03:05:45.551903Z",
"shell.execute_reply": "2021-02-13T03:05:45.551383Z"
},
"id": "SG1MgZCeSGPk"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Size of gzipped baseline Keras model: 78047.00 bytes\n",
"Size of gzipped clustered Keras model: 12419.00 bytes\n",
"Size of gzipped clustered TFlite model: 11920.00 bytes\n"
]
}
],
"source": [
"print(\"Size of gzipped baseline Keras model: %.2f bytes\" % (get_gzipped_model_size(keras_file)))\n",
"print(\"Size of gzipped clustered Keras model: %.2f bytes\" % (get_gzipped_model_size(clustered_keras_file)))\n",
"print(\"Size of gzipped clustered TFlite model: %.2f bytes\" % (get_gzipped_model_size(clustered_tflite_file)))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "5TOgpEGfSGPn"
},
"source": [
"## 重みクラスタリングとポストトレーニング量子化を組み合わせて、**8 倍**小さな TFLite モデルを作成する"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "BQb50aC3SGPn"
},
"source": [
"さらにメリットを得るために、ポストトレーニング量子化をクラスタモデルに適用できます。"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"execution": {
"iopub.execute_input": "2021-02-13T03:05:45.558135Z",
"iopub.status.busy": "2021-02-13T03:05:45.557044Z",
"iopub.status.idle": "2021-02-13T03:05:46.068429Z",
"shell.execute_reply": "2021-02-13T03:05:46.067759Z"
},
"id": "XyHC8euLSGPo"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"INFO:tensorflow:Assets written to: /tmp/tmpg3y6r2ll/assets\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO:tensorflow:Assets written to: /tmp/tmpg3y6r2ll/assets\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Saved quantized and clustered TFLite model to: /tmp/tmp6p9j3n3w.tflite\n",
"Size of gzipped baseline Keras model: 78047.00 bytes\n",
"Size of gzipped clustered and quantized TFlite model: 9045.00 bytes\n"
]
}
],
"source": [
"converter = tf.lite.TFLiteConverter.from_keras_model(final_model)\n",
"converter.optimizations = [tf.lite.Optimize.DEFAULT]\n",
"tflite_quant_model = converter.convert()\n",
"\n",
"_, quantized_and_clustered_tflite_file = tempfile.mkstemp('.tflite')\n",
"\n",
"with open(quantized_and_clustered_tflite_file, 'wb') as f:\n",
" f.write(tflite_quant_model)\n",
"\n",
"print('Saved quantized and clustered TFLite model to:', quantized_and_clustered_tflite_file)\n",
"print(\"Size of gzipped baseline Keras model: %.2f bytes\" % (get_gzipped_model_size(keras_file)))\n",
"print(\"Size of gzipped clustered and quantized TFlite model: %.2f bytes\" % (get_gzipped_model_size(quantized_and_clustered_tflite_file)))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "U-yBcocGSGPv"
},
"source": [
"## TF から TFLite への精度の永続性を確認する"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Jh_pcf0XSGPv"
},
"source": [
"テストデータセットで TFLite モデルを評価するヘルパー関数を定義します。"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"execution": {
"iopub.execute_input": "2021-02-13T03:05:46.076658Z",
"iopub.status.busy": "2021-02-13T03:05:46.075624Z",
"iopub.status.idle": "2021-02-13T03:05:46.078478Z",
"shell.execute_reply": "2021-02-13T03:05:46.077852Z"
},
"id": "EJ9B7pRISGPw"
},
"outputs": [],
"source": [
"def eval_model(interpreter):\n",
" input_index = interpreter.get_input_details()[0][\"index\"]\n",
" output_index = interpreter.get_output_details()[0][\"index\"]\n",
"\n",
" # Run predictions on every image in the \"test\" dataset.\n",
" prediction_digits = []\n",
" for i, test_image in enumerate(test_images):\n",
" if i % 1000 == 0:\n",
" print('Evaluated on {n} results so far.'.format(n=i))\n",
" # Pre-processing: add batch dimension and convert to float32 to match with\n",
" # the model's input data format.\n",
" test_image = np.expand_dims(test_image, axis=0).astype(np.float32)\n",
" interpreter.set_tensor(input_index, test_image)\n",
"\n",
" # Run inference.\n",
" interpreter.invoke()\n",
"\n",
" # Post-processing: remove batch dimension and find the digit with highest\n",
" # probability.\n",
" output = interpreter.tensor(output_index)\n",
" digit = np.argmax(output()[0])\n",
" prediction_digits.append(digit)\n",
"\n",
" print('\\n')\n",
" # Compare prediction results with ground truth labels to calculate accuracy.\n",
" prediction_digits = np.array(prediction_digits)\n",
" accuracy = (prediction_digits == test_labels).mean()\n",
" return accuracy"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "0swuxbPmSGPy"
},
"source": [
"クラスタ化および量子化されたモデルを評価し、TensorFlow の精度が TFLite バックエンドに持続することを確認します。"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"execution": {
"iopub.execute_input": "2021-02-13T03:05:46.084434Z",
"iopub.status.busy": "2021-02-13T03:05:46.083344Z",
"iopub.status.idle": "2021-02-13T03:05:47.685522Z",
"shell.execute_reply": "2021-02-13T03:05:47.685988Z"
},
"id": "RFD4LXjpSGPz"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Evaluated on 0 results so far.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Evaluated on 1000 results so far.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Evaluated on 2000 results so far.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Evaluated on 3000 results so far.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Evaluated on 4000 results so far.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Evaluated on 5000 results so far.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Evaluated on 6000 results so far.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Evaluated on 7000 results so far.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Evaluated on 8000 results so far.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Evaluated on 9000 results so far.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"Clustered and quantized TFLite test_accuracy: 0.9698\n",
"Clustered TF test accuracy: 0.9702000021934509\n"
]
}
],
"source": [
"interpreter = tf.lite.Interpreter(model_content=tflite_quant_model)\n",
"interpreter.allocate_tensors()\n",
"\n",
"test_accuracy = eval_model(interpreter)\n",
"\n",
"print('Clustered and quantized TFLite test_accuracy:', test_accuracy)\n",
"print('Clustered TF test accuracy:', clustered_model_accuracy)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "JgXTEXC7SGP1"
},
"source": [
"## まとめ"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "7JhbpowqSGP1"
},
"source": [
"このチュートリアルでは、TensorFlow Model Optimization Toolkit API を使用してクラスタモデルを作成する方法を確認しました。より具体的には、精度の違いを最小限に抑えて MNIST の 8 倍の小さいモデルを作成する、エンドツーエンドの例を確認しました。この新しい機能を試すことをお勧めします。これは、リソースに制約のある環境でのデプロイに特に重要な機能です。\n"
]
}
],
"metadata": {
"colab": {
"collapsed_sections": [],
"name": "clustering_example.ipynb",
"toc_visible": true
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.9"
}
},
"nbformat": 4,
"nbformat_minor": 0
}