Skip to content

Instantly share code, notes, and snippets.

@kechan
Created May 20, 2018 20:31
Show Gist options
  • Save kechan/f3fea62279ac847e9adc100351b7e9e8 to your computer and use it in GitHub Desktop.
Save kechan/f3fea62279ac847e9adc100351b7e9e8 to your computer and use it in GitHub Desktop.
Keras Transfer Learning.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "Keras Transfer Learning.ipynb",
"version": "0.3.2",
"provenance": [],
"collapsed_sections": [
"urGMQ4iPmDJ3"
]
},
"kernelspec": {
"name": "python2",
"display_name": "Python 2"
},
"accelerator": "GPU"
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"[View in Colaboratory](https://colab.research.google.com/gist/kechan/f3fea62279ac847e9adc100351b7e9e8/keras-transfer-learning.ipynb)"
]
},
{
"metadata": {
"id": "eZvBWtxiCi8a",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"#import tensorflow as tf\n",
"#device_name = tf.test.gpu_device_name()\n",
"#if device_name != '/device:GPU:0':\n",
"# raise SystemError('GPU device not found')\n",
"#print('Found GPU at: {}'.format(device_name))"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "_E5UZBR68pk4",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 85
},
"outputId": "372fd6dc-192e-4380-a247-a0e5817909d7"
},
"cell_type": "code",
"source": [
"ls -l "
],
"execution_count": 3,
"outputs": [
{
"output_type": "stream",
"text": [
"total 12\r\n",
"drwxr-xr-x 2 root root 4096 May 20 18:54 \u001b[0m\u001b[01;34mdata\u001b[0m/\r\n",
"drwxr-xr-x 1 root root 4096 May 20 18:39 \u001b[01;34mdatalab\u001b[0m/\r\n",
"drwxr-xr-x 6 root root 4096 May 20 18:55 \u001b[01;34mKerasVision\u001b[0m/\r\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "QQaQeFlgC_Ug",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"!git clone https://github.com/kechan/KerasVision.git"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "-TXBtb6f9KVj",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"!pip install -U -q PyDrive"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "LphM4GVCJSH3",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"def download_data_from_gdrive(ids, filenames):\n",
" \n",
" for id, filename in zip(ids, filenames):\n",
" uploaded = drive.CreateFile({'id': id})\n",
" uploaded.GetContentFile(filename)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "bf9SIOGeDHFc",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"#from google.colab import files\n",
"#uploaded = files.upload()\n",
"\n",
"from pydrive.auth import GoogleAuth\n",
"from pydrive.drive import GoogleDrive\n",
"from google.colab import auth\n",
"from oauth2client.client import GoogleCredentials\n",
"\n",
"auth.authenticate_user()\n",
"gauth = GoogleAuth()\n",
"gauth.credentials = GoogleCredentials.get_application_default()\n",
"drive = GoogleDrive(gauth)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "A2xwaDl49ZOm",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"# upload train, dev, and test set\n",
"#uploaded = drive.CreateFile({'id': '1Zdt10Q1Jn-hrq2o1mmvQ1j4DgBTxxGIq'})\n",
"#uploaded.GetContentFile('??')\n"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "bydE_h8SDJAB",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"download_data_from_gdrive(['1Zdt10Q1Jn-hrq2o1mmvQ1j4DgBTxxGIq', '1FgVh2oGqH9Pr4Ze2NETyLnBTPtC0hTui', '1X6ijkgbWCzATPCJLx0rBCy5jtUkjo2KG'], \n",
" ['train_224_224.hdf5.gz', 'validation_224_224.hdf5.gz', 'test_224_224.hdf5.gz'])"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "Xa9WLQ9b5D5J",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"# make a dir to put the hdf5s into.\n",
"#!mkdir data\n",
"\n",
"# unzip and move hdf5s into /content/data\n",
"\n",
"!gunzip train_224_224.hdf5.gz\n",
"!mv train_224_224.hdf5 /content/data\n",
"\n",
"!gunzip validation_224_224.hdf5.gz\n",
"!mv validation_224_224.hdf5 /content/data\n",
"\n",
"!gunzip test_224_224.hdf5.gz\n",
"!mv test_224_224.hdf5 /content/data"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "PfP9DJaF583W",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 85
},
"outputId": "b94e543e-22aa-48f1-fea8-2ba95180de79"
},
"cell_type": "code",
"source": [
"ls -l /content/data"
],
"execution_count": 12,
"outputs": [
{
"output_type": "stream",
"text": [
"total 614208\r\n",
"-rw-r--r-- 1 root root 90326544 May 20 18:51 test_224_224.hdf5\r\n",
"-rw-r--r-- 1 root root 448286882 May 20 18:50 train_224_224.hdf5\r\n",
"-rw-r--r-- 1 root root 90326544 May 20 18:51 validation_224_224.hdf5\r\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "IKPa0ZKkN-pH",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"outputId": "18c6e481-9037-47b9-ba99-896d1b99a104"
},
"cell_type": "code",
"source": [
"cd KerasVision/"
],
"execution_count": 4,
"outputs": [
{
"output_type": "stream",
"text": [
"/content/KerasVision\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "mc6Mh6mSDWhO",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"#### Imports"
]
},
{
"metadata": {
"id": "w9oO1OQuC0y6",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"outputId": "7f7c62b3-114f-48b7-e7b5-622aac1ad7c4"
},
"cell_type": "code",
"source": [
"from keras.models import Sequential\n",
"\n",
"from keras.layers import Dense, Conv2D, MaxPooling2D, Dropout, Flatten\n",
"from keras.layers import BatchNormalization, Activation\n",
"\n",
"from keras import optimizers\n",
"from keras.utils import to_categorical\n",
"from keras.models import load_model\n",
"from keras.applications import VGG16, MobileNet\n",
"\n",
"from keras.preprocessing.image import ImageDataGenerator\n",
"\n",
"from data.augmentation.CustomImageDataGenerator import * \n",
"\n",
"from data.data_util import *\n",
"from data.load_data import from_splitted_hdf5\n",
"from train import *\n",
"\n",
"import h5py"
],
"execution_count": 5,
"outputs": [
{
"output_type": "stream",
"text": [
"Using TensorFlow backend.\n"
],
"name": "stderr"
}
]
},
{
"metadata": {
"id": "52oUkaMr_SEK",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"outputId": "6f5498d3-3886-4c55-a021-3fd8574795e1"
},
"cell_type": "code",
"source": [
"keras.__version__"
],
"execution_count": 3,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"'2.1.6'"
]
},
"metadata": {
"tags": []
},
"execution_count": 3
}
]
},
{
"metadata": {
"id": "X08LE52uC47C",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"train_set_x, train_set_y, dev_set_x, dev_set_y, _, _, classes = \\\n",
"from_splitted_hdf5('../data')"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "1jWCBdKG6HcW",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"# rescale here such that image generator doesn't to\n",
"train_set_x = train_set_x.astype('float32')/255.\n",
"dev_set_x = dev_set_x.astype('float32')/255."
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "7Kv3DflYFgD-",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"# one-hot the y\n",
"train_set_y = to_categorical(train_set_y)\n",
"dev_set_y = to_categorical(dev_set_y)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "p29aPHafJaCB",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"outputId": "e61b13a0-fd12-4808-bd77-69ab46de81ed"
},
"cell_type": "code",
"source": [
"train_set_x.shape, train_set_y.shape, dev_set_x.shape, dev_set_y.shape, "
],
"execution_count": 10,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"((2978, 224, 224, 3), (2978, 7), (600, 224, 224, 3), (600, 7))"
]
},
"metadata": {
"tags": []
},
"execution_count": 10
}
]
},
{
"metadata": {
"id": "Xu_OjHyDDdW4",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 88
},
"outputId": "63be3065-fa8c-4f20-cedd-01b97a38717b"
},
"cell_type": "code",
"source": [
"#conv_base = MobileNet(weights='imagenet', include_top=False, input_shape=(224, 224, 3))\n",
"conv_base = VGG16(weights='imagenet', include_top=False, input_shape=(224, 224, 3))"
],
"execution_count": 23,
"outputs": [
{
"output_type": "stream",
"text": [
"Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5\n",
"58892288/58889256 [==============================] - 6s 0us/step\n",
"58900480/58889256 [==============================] - 6s 0us/step\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "P4OdoTG-Fvd6",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"#Adding a densely connected classifier on top of the convolutional base\n",
"model = Sequential()\n",
"model.add(conv_base)\n",
"model.add(Flatten())\n",
"model.add(Dense(1024))\n",
"model.add(BatchNormalization())\n",
"model.add(Activation('relu'))\n",
"model.add(Dropout(0.5))\n",
"model.add(Dense(7, activation='softmax'))"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "i9IK6oDvHMon",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"model.summary()"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "bVwahR_E9WcN",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"outputId": "dfbb55dc-3673-4d44-d3e6-cf065236a2d3"
},
"cell_type": "code",
"source": [
"print('This is the number of trainable weights '\n",
" 'before freezing the conv base:', len(model.trainable_weights))\n"
],
"execution_count": 8,
"outputs": [
{
"output_type": "stream",
"text": [
"('This is the number of trainable weights before freezing the conv base:', 87)\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "w0ItIE7XHTSJ",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"# Freeze conv_base\n",
"conv_base.trainable = False\n",
"for layer in conv_base.layers:\n",
" layer.trainable = False"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "zGxz4mJQ9m46",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"outputId": "9c4e4099-df67-4fec-8923-ebf58e6932c8"
},
"cell_type": "code",
"source": [
"print('This is the number of trainable weights '\n",
" 'after freezing the conv base:', len(model.trainable_weights))"
],
"execution_count": 10,
"outputs": [
{
"output_type": "stream",
"text": [
"('This is the number of trainable weights after freezing the conv base:', 6)\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "kb4CrdX1HowC",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"model.summary()\n"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "KALBj_4QHqph",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"#model.compile(loss='categorical_crossentropy', optimizer=optimizers.RMSprop(lr=1e-4), metrics=['accuracy'])\n",
"model.compile(optimizer=optimizers.Adam(lr=1e-5), loss='categorical_crossentropy', metrics=['accuracy'])"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "4lT30Zh9K-0n",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"batch_size = 32\n",
"\n",
"train_datagen = ImageDataGenerator()\n",
"test_datagen = ImageDataGenerator()"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "fnWWwgmYB8hI",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"'''\n",
"train_datagen = CustomImageDataGenerator(rescale=1./255, \n",
"\t\t\t\t\t rotation_range=90.0,\n",
" gaussian_blur_range=1.0, \n",
"\t\t\t\t\theight_shift_range=0.2, \n",
"\t\t\t\t\twidth_shift_range=0.2, \n",
"\t\t\t\t\tshear_range=0.1,\n",
"\t\t\t\t\tzoom_range=0.4,\n",
"\t\t\t\t\tcolor_shift=[15, 15, 15],\n",
"\t\t\t\t\trot90=True, \n",
"\t\t\t\t\tcut_out=(20, 7),\n",
"\t\t\t\t\tcontrast_stretching=True\n",
"\t\t\t\t\t)\n",
"\n",
"'''\n",
"\n",
"'''\n",
"train_datagen = CustomImageDataGenerator(rescale=1./255,\n",
" rotation_range=90,\n",
" height_shift_range=0.2,\n",
" width_shift_range=0.2,\n",
" shear_range=0.05,\n",
" zoom_range=0.4)\n",
"'''\n",
"\n",
"\n",
"#test_datagen = ImageDataGenerator(rescale=1./255)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "z57klyGeLY7D",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"train_generator = train_datagen.flow(train_set_x, train_set_y, batch_size=batch_size)\n",
"validation_generator = test_datagen.flow(dev_set_x, dev_set_y, batch_size=batch_size)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "8YXtzBCU70ZJ",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"import matplotlib.pyplot as plt\n",
"%matplotlib inline"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "l-zEzqi77kdK",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"for inputs_batch, labels_batch in train_generator:\n",
" current_image = inputs_batch[0]\n",
" target = labels_batch[0]\n",
" print(current_image.shape)\n",
" print(current_image.dtype)\n",
" print(target)\n",
" \n",
" plt.figure(figsize=(6, 6))\n",
" plt.imshow(current_image)\n",
"\n",
" #print(current_image)\n",
" break"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "mgpg-4aoLeCY",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 377
},
"outputId": "2996226e-0a1a-48d0-d2bc-961f2bfca947"
},
"cell_type": "code",
"source": [
"history = model.fit_generator(train_generator, steps_per_epoch=len(train_set_y)//batch_size, epochs=10, \n",
" validation_data=validation_generator, validation_steps=len(dev_set_y)//batch_size)"
],
"execution_count": 33,
"outputs": [
{
"output_type": "stream",
"text": [
"Epoch 1/10\n",
"93/93 [==============================] - 39s 418ms/step - loss: 1.7581 - acc: 0.4033 - val_loss: 1.5214 - val_acc: 0.4549\n",
"Epoch 2/10\n",
"93/93 [==============================] - 34s 370ms/step - loss: 1.0517 - acc: 0.6264 - val_loss: 1.3700 - val_acc: 0.5330\n",
"Epoch 3/10\n",
"93/93 [==============================] - 34s 370ms/step - loss: 0.8336 - acc: 0.7131 - val_loss: 1.5467 - val_acc: 0.5104\n",
"Epoch 4/10\n",
"76/93 [=======================>......] - ETA: 5s - loss: 0.6867 - acc: 0.7648"
],
"name": "stdout"
},
{
"output_type": "stream",
"text": [
"93/93 [==============================] - 34s 370ms/step - loss: 0.6839 - acc: 0.7661 - val_loss: 1.4118 - val_acc: 0.5365\n",
"Epoch 5/10\n",
"93/93 [==============================] - 34s 370ms/step - loss: 0.5629 - acc: 0.8108 - val_loss: 1.3521 - val_acc: 0.5399\n",
"Epoch 6/10\n",
"93/93 [==============================] - 34s 370ms/step - loss: 0.5102 - acc: 0.8283 - val_loss: 1.3032 - val_acc: 0.5625\n",
"Epoch 7/10\n",
"93/93 [==============================] - 34s 371ms/step - loss: 0.4244 - acc: 0.8559 - val_loss: 1.3148 - val_acc: 0.5677\n",
"Epoch 8/10\n",
" 2/93 [..............................] - ETA: 28s - loss: 0.3841 - acc: 0.9219"
],
"name": "stdout"
},
{
"output_type": "stream",
"text": [
"93/93 [==============================] - 34s 371ms/step - loss: 0.4190 - acc: 0.8684 - val_loss: 1.2968 - val_acc: 0.5694\n",
"Epoch 9/10\n",
"93/93 [==============================] - 34s 369ms/step - loss: 0.3242 - acc: 0.9005 - val_loss: 1.4212 - val_acc: 0.5642\n",
"Epoch 10/10\n",
"93/93 [==============================] - 34s 369ms/step - loss: 0.3197 - acc: 0.9033 - val_loss: 1.2694 - val_acc: 0.5799\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "jtgRi_2HzR4P",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"my_model_weights = model.layers[0].layers[6].get_weights()[0]"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "ugEQcXVrBLCY",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"mobilenet_base = MobileNet(weights='imagenet', include_top=False, input_shape=(224, 224, 3))"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "rK-aEummBRQ1",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"outputId": "8af487ff-a718-40d6-814f-e798aed4456d"
},
"cell_type": "code",
"source": [
"mobilenet_base_weights = mobilenet_base.layers[6].get_weights()[0]\n",
"mobilenet_base_weights.shape"
],
"execution_count": 65,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"(3, 3, 32, 1)"
]
},
"metadata": {
"tags": []
},
"execution_count": 65
}
]
},
{
"metadata": {
"id": "UTObi3NzezLJ",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"outputId": "71907ced-df2d-4b9e-99f1-a5f3588ccd7e"
},
"cell_type": "code",
"source": [
"np.sum(my_model_weights - mobilenet_base_weights)"
],
"execution_count": 66,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"0.0"
]
},
"metadata": {
"tags": []
},
"execution_count": 66
}
]
},
{
"metadata": {
"id": "1cr_RZT8L3Rm",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"!mkdir /content/experiments\n",
"model.save('/content/experiments/gpu_model_and_weights.h5', overwrite=True, include_optimizer=True)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "Nq_NmXaefCjq",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
""
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "urGMQ4iPmDJ3",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"#### Test PyDrive"
]
},
{
"metadata": {
"id": "7BD7yfyVmFMO",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"!pip install -U -q PyDrive"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "szPLsyEStKrp",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"from pydrive.auth import GoogleAuth\n",
"from pydrive.drive import GoogleDrive\n",
"from google.colab import auth\n",
"from oauth2client.client import GoogleCredentials"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "SBKONyL-tPtU",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"auth.authenticate_user()\n",
"gauth = GoogleAuth()\n",
"gauth.credentials = GoogleCredentials.get_application_default()\n",
"drive = GoogleDrive(gauth)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "jbNyBiJUtS5E",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"outputId": "a376d253-e807-4e3a-d9d8-9c324ba85c2b"
},
"cell_type": "code",
"source": [
"uploaded = drive.CreateFile({'title': 'gpu_model_and_weights.h5.gz'})\n",
"uploaded.SetContentFile('/content/experiments/gpu_model_and_weights.h5.gz')\n",
"uploaded.Upload()\n",
"print('Uploaded file with ID {}'.format(uploaded.get('id')))"
],
"execution_count": 66,
"outputs": [
{
"output_type": "stream",
"text": [
"Uploaded file with ID 16RhMjtRlnZaeIMbMzjZJ1k_KuY8gb3dD\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "jMVMH_8Gvdvf",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
""
],
"execution_count": 0,
"outputs": []
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment