forked from flutter/codelabs
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new TensorFlow Serving + Flutter text classification codelabs (fl…
- Loading branch information
Showing
309 changed files
with
54,319 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# tfserving_flutter | ||
|
||
This folder contains the codelabs for the TensorFlow Serving Text Classification Learning Pathway (TODO: update link). | ||
|
||
The folder is organized as: | ||
- `codelab1` contains the first codelab code to train a spam detection model | ||
- `codelab2` contains the second codelab code to connect Flutter frontend to TensorFlow Serving backend | ||
- `codelab3` contains the third codelab code to enhance the spam detection model to detect specific spam phrases |
194 changes: 194 additions & 0 deletions
194
tfserving-flutter/codelab1/SpamCommentsModelMaker.ipynb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
{ | ||
"nbformat": 4, | ||
"nbformat_minor": 0, | ||
"metadata": { | ||
"colab": { | ||
"name": "SpamCommentsModelMaker.ipynb", | ||
"provenance": [], | ||
"collapsed_sections": [] | ||
}, | ||
"kernelspec": { | ||
"name": "python3", | ||
"display_name": "Python 3" | ||
}, | ||
"accelerator": "GPU" | ||
}, | ||
"cells": [ | ||
{ | ||
"cell_type": "code", | ||
"metadata": { | ||
"id": "Awq8sMaIFHJ1" | ||
}, | ||
"source": [ | ||
"# Install Model maker\n", | ||
"!pip install -q tflite-model-maker &> /dev/null" | ||
], | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"metadata": { | ||
"id": "2fEAqoLLF6O9" | ||
}, | ||
"source": [ | ||
"# Imports and check that we are using TF2.x\n", | ||
"import numpy as np\n", | ||
"import os\n", | ||
"\n", | ||
"from tflite_model_maker import configs\n", | ||
"from tflite_model_maker import ExportFormat\n", | ||
"from tflite_model_maker import model_spec\n", | ||
"from tflite_model_maker import text_classifier\n", | ||
"from tflite_model_maker.text_classifier import DataLoader\n", | ||
"\n", | ||
"import tensorflow as tf\n", | ||
"assert tf.__version__.startswith('2')\n", | ||
"tf.get_logger().setLevel('ERROR')" | ||
], | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"metadata": { | ||
"id": "lsuDZvjgREsS" | ||
}, | ||
"source": [ | ||
"# Download the dataset as a CSV and store as data_file\n", | ||
"data_file = tf.keras.utils.get_file(fname='comment-spam.csv', origin='https://storage.googleapis.com/laurencemoroney-blog.appspot.com/lmblog_comments.csv', extract=False)" | ||
], | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"metadata": { | ||
"id": "pbew43TbG9HQ" | ||
}, | ||
"source": [ | ||
"# Use a model spec from model maker. Options are 'mobilebert_classifier', 'bert_classifier' and 'average_word_vec'\n", | ||
"# The first 2 use the BERT model, which is accurate, but larger and slower to train\n", | ||
"# Average Word Vec is kinda like transfer learning where there are pre-trained word weights\n", | ||
"# and dictionaries\n", | ||
"spec = model_spec.get('average_word_vec')\n", | ||
"spec.num_words = 2000\n", | ||
"spec.seq_len = 20\n", | ||
"spec.wordvec_dim = 7" | ||
], | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"metadata": { | ||
"id": "-WdQmzTKHFVn" | ||
}, | ||
"source": [ | ||
"# Load the CSV using DataLoader.from_csv to make the training_data\n", | ||
"data = DataLoader.from_csv(\n", | ||
" filename=data_file,\n", | ||
" text_column='commenttext', \n", | ||
" label_column='spam', \n", | ||
" model_spec=spec,\n", | ||
" delimiter=',',\n", | ||
" shuffle=True,\n", | ||
" is_training=True)\n", | ||
"\n", | ||
"train_data, test_data = data.split(0.9)" | ||
], | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"metadata": { | ||
"id": "qThBoIIyG_Du" | ||
}, | ||
"source": [ | ||
"# Build the model\n", | ||
"model = text_classifier.create(train_data, model_spec=spec, epochs=50, validation_data=test_data)" | ||
], | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"metadata": { | ||
"id": "5QXEwKYxdPzs" | ||
}, | ||
"source": [ | ||
"loss, accuracy = model.evaluate(train_data)" | ||
], | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"metadata": { | ||
"id": "In-1-rzW-_9b" | ||
}, | ||
"source": [ | ||
"# This will export to SavedModel format with the model, vocabulary and labels. \n", | ||
"model.export(export_dir='/mm_spam_savedmodel/', export_format=[ExportFormat.LABEL, ExportFormat.VOCAB, ExportFormat.SAVED_MODEL])\n", | ||
"\n", | ||
"# You can find your files in colab by clicking the 'folder' tab to the left of\n", | ||
"# this code window, and then navigating 'up' a directory to find the root\n", | ||
"# directory listing -- and from there you should see /mm_spam_savedmodel/" | ||
], | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": [ | ||
"# Rename the SavedModel subfolder to a version number\n", | ||
"!mv /mm_spam_savedmodel/saved_model /mm_spam_savedmodel/123\n", | ||
"!zip -r mm_spam_savedmodel.zip /mm_spam_savedmodel/ " | ||
], | ||
"metadata": { | ||
"id": "mIhBu3pI_2Xz" | ||
}, | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"metadata": { | ||
"id": "3UNNrCWbKbxh" | ||
}, | ||
"source": [ | ||
"# Optional extra\n", | ||
"# You can use this cell to export details for projector.tensorflow.org\n", | ||
"# Where you can explore the embeddings that were learned for this dataset\n", | ||
"embeddings = model.model.layers[0]\n", | ||
"weights = embeddings.get_weights()[0]\n", | ||
"tokenizer = model.model_spec.vocab\n", | ||
"\n", | ||
"import io\n", | ||
"\n", | ||
"out_v = io.open('vecs.tsv', 'w', encoding='utf-8')\n", | ||
"out_m = io.open('meta.tsv', 'w', encoding='utf-8')\n", | ||
"for word in tokenizer:\n", | ||
" #word = tokenizer.decode([word_num])\n", | ||
" value = tokenizer[word]\n", | ||
" embeddings = weights[value]\n", | ||
" out_m.write(word + \"\\n\")\n", | ||
" out_v.write('\\t'.join([str(x) for x in embeddings]) + \"\\n\")\n", | ||
"out_v.close()\n", | ||
"out_m.close()\n", | ||
"\n", | ||
"\n", | ||
"try:\n", | ||
" from google.colab import files\n", | ||
"except ImportError:\n", | ||
" pass\n", | ||
"else:\n", | ||
" files.download('vecs.tsv')\n", | ||
" files.download('meta.tsv')" | ||
], | ||
"execution_count": null, | ||
"outputs": [] | ||
} | ||
] | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
9 changes: 9 additions & 0 deletions
9
tfserving-flutter/codelab1/mm_spam_savedmodel/123/keras_metadata.pb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
|
||
�*root"_tf_keras_sequential*�*{"name": "sequential_2", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "must_restore_from_config": false, "class_name": "Sequential", "config": {"name": "sequential_2", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 20]}, "dtype": "int32", "sparse": false, "ragged": false, "name": "input_3"}}, {"class_name": "Embedding", "config": {"name": "embedding_2", "trainable": true, "batch_input_shape": {"class_name": "__tuple__", "items": [null, 20]}, "dtype": "float32", "input_dim": 2003, "output_dim": 7, "embeddings_initializer": {"class_name": "RandomUniform", "config": {"minval": -0.05, "maxval": 0.05, "seed": null}}, "embeddings_regularizer": null, "activity_regularizer": null, "embeddings_constraint": null, "mask_zero": false, "input_length": 20}}, {"class_name": "GlobalAveragePooling1D", "config": {"name": "global_average_pooling1d_2", "trainable": true, "dtype": "float32", "data_format": "channels_last", "keepdims": false}}, {"class_name": "Dense", "config": {"name": "dense_4", "trainable": true, "dtype": "float32", "units": 7, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dropout", "config": {"name": "dropout_2", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}}, {"class_name": "Dense", "config": {"name": "dense_5", "trainable": true, "dtype": "float32", "units": 2, "activation": "softmax", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}]}, "shared_object_id": 11, "input_spec": [{"class_name": "InputSpec", "config": {"dtype": null, "shape": {"class_name": "__tuple__", "items": [null, 20]}, "ndim": 2, "max_ndim": null, "min_ndim": null, "axes": {}}}], "build_input_shape": {"class_name": "TensorShape", "items": [null, 20]}, "is_graph_network": true, "full_save_spec": {"class_name": "__tuple__", "items": [[{"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 20]}, "int32", "input_3"]}], {}]}, "save_spec": {"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 20]}, "int32", "input_3"]}, "keras_version": "2.7.0", "backend": "tensorflow", "model_config": {"class_name": "Sequential", "config": {"name": "sequential_2", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 20]}, "dtype": "int32", "sparse": false, "ragged": false, "name": "input_3"}, "shared_object_id": 0}, {"class_name": "Embedding", "config": {"name": "embedding_2", "trainable": true, "batch_input_shape": {"class_name": "__tuple__", "items": [null, 20]}, "dtype": "float32", "input_dim": 2003, "output_dim": 7, "embeddings_initializer": {"class_name": "RandomUniform", "config": {"minval": -0.05, "maxval": 0.05, "seed": null}, "shared_object_id": 1}, "embeddings_regularizer": null, "activity_regularizer": null, "embeddings_constraint": null, "mask_zero": false, "input_length": 20}, "shared_object_id": 2}, {"class_name": "GlobalAveragePooling1D", "config": {"name": "global_average_pooling1d_2", "trainable": true, "dtype": "float32", "data_format": "channels_last", "keepdims": false}, "shared_object_id": 3}, {"class_name": "Dense", "config": {"name": "dense_4", "trainable": true, "dtype": "float32", "units": 7, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 4}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 5}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 6}, {"class_name": "Dropout", "config": {"name": "dropout_2", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}, "shared_object_id": 7}, {"class_name": "Dense", "config": {"name": "dense_5", "trainable": true, "dtype": "float32", "units": 2, "activation": "softmax", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 8}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 9}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 10}]}}, "training_config": {"loss": "sparse_categorical_crossentropy", "metrics": [[{"class_name": "MeanMetricWrapper", "config": {"name": "accuracy", "dtype": "float32", "fn": "sparse_categorical_accuracy"}, "shared_object_id": 13}]], "weighted_metrics": null, "loss_weights": null, "optimizer_config": {"class_name": "RMSprop", "config": {"name": "RMSprop", "learning_rate": 0.0010000000474974513, "decay": 0.0, "rho": 0.8999999761581421, "momentum": 0.0, "epsilon": 1e-07, "centered": false}}}}2 | ||
�root.layer_with_weights-0"_tf_keras_layer*�{"name": "embedding_2", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": {"class_name": "__tuple__", "items": [null, 20]}, "stateful": false, "must_restore_from_config": false, "class_name": "Embedding", "config": {"name": "embedding_2", "trainable": true, "batch_input_shape": {"class_name": "__tuple__", "items": [null, 20]}, "dtype": "float32", "input_dim": 2003, "output_dim": 7, "embeddings_initializer": {"class_name": "RandomUniform", "config": {"minval": -0.05, "maxval": 0.05, "seed": null}, "shared_object_id": 1}, "embeddings_regularizer": null, "activity_regularizer": null, "embeddings_constraint": null, "mask_zero": false, "input_length": 20}, "shared_object_id": 2, "build_input_shape": {"class_name": "TensorShape", "items": [null, 20]}}2 | ||
�root.layer-1"_tf_keras_layer*�{"name": "global_average_pooling1d_2", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "GlobalAveragePooling1D", "config": {"name": "global_average_pooling1d_2", "trainable": true, "dtype": "float32", "data_format": "channels_last", "keepdims": false}, "shared_object_id": 3, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": 3, "max_ndim": null, "min_ndim": null, "axes": {}}, "shared_object_id": 14}}2 | ||
�root.layer_with_weights-1"_tf_keras_layer*�{"name": "dense_4", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dense", "config": {"name": "dense_4", "trainable": true, "dtype": "float32", "units": 7, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 4}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 5}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 6, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 7}}, "shared_object_id": 15}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 7]}}2 | ||
�root.layer-3"_tf_keras_layer*�{"name": "dropout_2", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dropout", "config": {"name": "dropout_2", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}, "shared_object_id": 7}2 | ||
�root.layer_with_weights-2"_tf_keras_layer*�{"name": "dense_5", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dense", "config": {"name": "dense_5", "trainable": true, "dtype": "float32", "units": 2, "activation": "softmax", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 8}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 9}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 10, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 7}}, "shared_object_id": 16}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 7]}}2 | ||
�Hroot.keras_api.metrics.0"_tf_keras_metric*�{"class_name": "Mean", "name": "loss", "dtype": "float32", "config": {"name": "loss", "dtype": "float32"}, "shared_object_id": 17}2 | ||
�Iroot.keras_api.metrics.1"_tf_keras_metric*�{"class_name": "MeanMetricWrapper", "name": "accuracy", "dtype": "float32", "config": {"name": "accuracy", "dtype": "float32", "fn": "sparse_categorical_accuracy"}, "shared_object_id": 13}2 |
Binary file not shown.
Binary file added
BIN
+114 KB
tfserving-flutter/codelab1/mm_spam_savedmodel/123/variables/variables.data-00000-of-00001
Binary file not shown.
Binary file added
BIN
+1.33 KB
tfserving-flutter/codelab1/mm_spam_savedmodel/123/variables/variables.index
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
false | ||
true |
Oops, something went wrong.