{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Video Classification with a CNN-RNN Architecture" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Original Author:** Sayak Paul \n", "**Date created:** 2021/05/28 \n", "**Last modified:** 2021/06/05 \n", "**Description:** Training a video classifier with transfer learning and a recurrent model on the UCF101 dataset. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example demonstrates video classification, an important use-case with applications in recommendations, security, and so on. We will be using the UCF101 dataset to build our video classifier. The dataset consists of videos categorized into different actions, like cricket shot, punching, biking, etc. This dataset is commonly used to build action recognizers, which are an application of video classification.\n", "\n", "A video consists of an ordered sequence of frames. Each frame contains spatial information, and the sequence of those frames contains temporal information. To model both of these aspects, we use a hybrid architecture that consists of convolutions (for spatial processing) as well as recurrent layers (for temporal processing). Specifically, we'll use a Convolutional Neural Network (CNN) and a Recurrent Neural Network (RNN) consisting of GRU layers. This kind of hybrid architecture is popularly known as a CNN-RNN." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "from tensorflow_docs.vis import embed\n", "from tensorflow import keras\n", "from imutils import paths\n", "\n", "import matplotlib.pyplot as plt\n", "import tensorflow as tf\n", "import pandas as pd\n", "import numpy as np\n", "import imageio\n", "import cv2\n", "import os" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "IMG_SIZE = 224\n", "BATCH_SIZE = 64\n", "EPOCHS = 12\n", "\n", "MAX_SEQ_LENGTH = 20\n", "NUM_FEATURES = 2048" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Data Collection \n", "\n", "In order to keep the runtime of this example relatively short, we will be using a subsampled version of the original UCF101 dataset. You can refer to this notebook to know how the subsampling was done." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "!wget -q https://git.io/JGc31 -O ucf101_top5.tar.gz\n", "!tar xf ucf101_top5.tar.gz" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Data Preparation\n", "\n", "*P.S. I already did the preparation and saved it to npy files in order to make the training faster if you want to skip data preparation part.*" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Total videos for training: 594\n", "Total videos for testing: 224\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
video_nametag
495v_TennisSwing_g10_c06.aviTennisSwing
160v_PlayingCello_g14_c02.aviPlayingCello
455v_ShavingBeard_g22_c06.aviShavingBeard
532v_TennisSwing_g16_c01.aviTennisSwing
332v_Punch_g22_c02.aviPunch
341v_Punch_g23_c04.aviPunch
280v_Punch_g14_c02.aviPunch
11v_CricketShot_g09_c05.aviCricketShot
486v_TennisSwing_g09_c04.aviTennisSwing
445v_ShavingBeard_g21_c03.aviShavingBeard
\n", "
" ], "text/plain": [ " video_name tag\n", "495 v_TennisSwing_g10_c06.avi TennisSwing\n", "160 v_PlayingCello_g14_c02.avi PlayingCello\n", "455 v_ShavingBeard_g22_c06.avi ShavingBeard\n", "532 v_TennisSwing_g16_c01.avi TennisSwing\n", "332 v_Punch_g22_c02.avi Punch\n", "341 v_Punch_g23_c04.avi Punch\n", "280 v_Punch_g14_c02.avi Punch\n", "11 v_CricketShot_g09_c05.avi CricketShot\n", "486 v_TennisSwing_g09_c04.avi TennisSwing\n", "445 v_ShavingBeard_g21_c03.avi ShavingBeard" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "train_df = pd.read_csv(\"train.csv\")\n", "test_df = pd.read_csv(\"test.csv\")\n", "\n", "print(f\"Total videos for training: {len(train_df)}\")\n", "print(f\"Total videos for testing: {len(test_df)}\")\n", "\n", "train_df.sample(10)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "# The following two methods are taken from this tutorial:\n", "# https://www.tensorflow.org/hub/tutorials/action_recognition_with_tf_hub\n", "\n", "\n", "def crop_center_square(frame):\n", " y, x = frame.shape[0:2]\n", " min_dim = min(y, x)\n", " start_x = (x // 2) - (min_dim // 2)\n", " start_y = (y // 2) - (min_dim // 2)\n", " return frame[start_y : start_y + min_dim, start_x : start_x + min_dim]\n", "\n", "\n", "def load_video(path, max_frames=0, resize=(IMG_SIZE, IMG_SIZE)):\n", " cap = cv2.VideoCapture(path)\n", " frames = []\n", " try:\n", " while True:\n", " ret, frame = cap.read()\n", " if not ret:\n", " break\n", " frame = crop_center_square(frame)\n", " frame = cv2.resize(frame, resize)\n", " frame = frame[:, :, [2, 1, 0]]\n", " frames.append(frame)\n", "\n", " if len(frames) == max_frames:\n", " break\n", " finally:\n", " cap.release()\n", " return np.array(frames)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "def build_feature_extractor():\n", " feature_extractor = keras.applications.InceptionV3(\n", " weights=\"imagenet\",\n", " include_top=False,\n", " pooling=\"avg\",\n", " input_shape=(IMG_SIZE, IMG_SIZE, 3),\n", " )\n", " preprocess_input = keras.applications.inception_v3.preprocess_input\n", "\n", " inputs = keras.Input((IMG_SIZE, IMG_SIZE, 3))\n", " preprocessed = preprocess_input(inputs)\n", "\n", " outputs = feature_extractor(preprocessed)\n", " return keras.Model(inputs, outputs, name=\"feature_extractor\")\n", "\n", "\n", "feature_extractor = build_feature_extractor()" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['CricketShot', 'PlayingCello', 'Punch', 'ShavingBeard', 'TennisSwing']\n" ] } ], "source": [ "label_processor = keras.layers.StringLookup(\n", " num_oov_indices=0, vocabulary=np.unique(train_df[\"tag\"])\n", ")\n", "print(label_processor.get_vocabulary())" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Frame features in train set: (594, 20, 2048)\n", "Frame masks in train set: (594, 20)\n" ] } ], "source": [ "def prepare_all_videos(df, root_dir):\n", " num_samples = len(df)\n", " video_paths = df[\"video_name\"].values.tolist()\n", " labels = df[\"tag\"].values\n", " labels = label_processor(labels[..., None]).numpy()\n", "\n", " # `frame_masks` and `frame_features` are what we will feed to our sequence model.\n", " # `frame_masks` will contain a bunch of booleans denoting if a timestep is\n", " # masked with padding or not.\n", " frame_masks = np.zeros(shape=(num_samples, MAX_SEQ_LENGTH), dtype=\"bool\")\n", " frame_features = np.zeros(\n", " shape=(num_samples, MAX_SEQ_LENGTH, NUM_FEATURES), dtype=\"float32\"\n", " )\n", "\n", " # For each video.\n", " for idx, path in enumerate(video_paths):\n", " # Gather all its frames and add a batch dimension.\n", " frames = load_video(os.path.join(root_dir, path))\n", " frames = frames[None, ...]\n", "\n", " # Initialize placeholders to store the masks and features of the current video.\n", " temp_frame_mask = np.zeros(shape=(1, MAX_SEQ_LENGTH,), dtype=\"bool\")\n", " temp_frame_features = np.zeros(\n", " shape=(1, MAX_SEQ_LENGTH, NUM_FEATURES), dtype=\"float32\"\n", " )\n", "\n", " # Extract features from the frames of the current video.\n", " for i, batch in enumerate(frames):\n", " video_length = batch.shape[0]\n", " length = min(MAX_SEQ_LENGTH, video_length)\n", " for j in range(length):\n", " temp_frame_features[i, j, :] = feature_extractor.predict(\n", " batch[None, j, :]\n", " )\n", " temp_frame_mask[i, :length] = 1 # 1 = not masked, 0 = masked\n", "\n", " frame_features[idx,] = temp_frame_features.squeeze()\n", " frame_masks[idx,] = temp_frame_mask.squeeze()\n", "\n", " return (frame_features, frame_masks), labels\n", "\n", "\n", "train_data, train_labels = prepare_all_videos(train_df, \"train\")\n", "test_data, test_labels = prepare_all_videos(test_df, \"test\")\n", "\n", "print(f\"Frame features in train set: {train_data[0].shape}\")\n", "print(f\"Frame masks in train set: {train_data[1].shape}\")" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "from datetime import datetime\n", "from pathlib import Path\n", "\n", "def get_sequence_model():\n", " class_vocab = label_processor.get_vocabulary()\n", "\n", " frame_features_input = keras.Input((MAX_SEQ_LENGTH, NUM_FEATURES))\n", " mask_input = keras.Input((MAX_SEQ_LENGTH,), dtype=\"bool\")\n", "\n", " # Refer to the following tutorial to understand the significance of using `mask`:\n", " # https://keras.io/api/layers/recurrent_layers/gru/\n", " x = keras.layers.GRU(16, return_sequences=True)(\n", " frame_features_input, mask=mask_input\n", " )\n", " x = keras.layers.GRU(8)(x)\n", " x = keras.layers.Dropout(0.4)(x)\n", " x = keras.layers.Dense(8, activation=\"relu\")(x)\n", " output = keras.layers.Dense(len(class_vocab), activation=\"softmax\")(x)\n", "\n", " rnn_model = keras.Model([frame_features_input, mask_input], output)\n", "\n", " rnn_model.compile(\n", " loss=\"sparse_categorical_crossentropy\", optimizer=\"adam\", metrics=[\"accuracy\"]\n", " )\n", " return rnn_model\n", "\n", "logdir = f\"logs/scalars/{datetime.now().strftime('%Y%m%d-%H%M%S')}\"\n", "tensorboard_callback = keras.callbacks.TensorBoard(log_dir=logdir)\n", "\n", "def run_experiment():\n", " filepath = Path.cwd()\n", " checkpoint = keras.callbacks.ModelCheckpoint(\n", " filepath, save_weights_only=True, save_best_only=True, verbose=1\n", " )\n", "\n", " seq_model = get_sequence_model()\n", " history = seq_model.fit(\n", " [train_data[0], train_data[1]],\n", " train_labels,\n", " batch_size=BATCH_SIZE,\n", " validation_split=0.3,\n", " epochs=EPOCHS,\n", " callbacks=[\n", " checkpoint,\n", " tensorboard_callback,\n", " ],\n", " )\n", "\n", " seq_model.load_weights(filepath)\n", " _, accuracy = seq_model.evaluate([test_data[0], test_data[1]], test_labels)\n", " print(f\"Test accuracy: {round(accuracy * 100, 2)}%\")\n", "\n", " return history, seq_model" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1/12\n", "7/7 [==============================] - 6s 349ms/step - loss: 1.6094 - accuracy: 0.2458 - val_loss: 1.8301 - val_accuracy: 0.0000e+00\n", "\n", "Epoch 00001: val_loss improved from inf to 1.83010, saving model to /home/chainyo/code/video-classification-cnn-rnn\n", "Epoch 2/12\n", "7/7 [==============================] - 0s 16ms/step - loss: 1.5141 - accuracy: 0.3108 - val_loss: 1.7990 - val_accuracy: 0.0000e+00\n", "\n", "Epoch 00002: val_loss improved from 1.83010 to 1.79903, saving model to /home/chainyo/code/video-classification-cnn-rnn\n", "Epoch 3/12\n", "7/7 [==============================] - 0s 16ms/step - loss: 1.3297 - accuracy: 0.4964 - val_loss: 1.6561 - val_accuracy: 0.0447\n", "\n", "Epoch 00003: val_loss improved from 1.79903 to 1.65611, saving model to /home/chainyo/code/video-classification-cnn-rnn\n", "Epoch 4/12\n", "7/7 [==============================] - 0s 16ms/step - loss: 1.1856 - accuracy: 0.5904 - val_loss: 1.5015 - val_accuracy: 0.2291\n", "\n", "Epoch 00004: val_loss improved from 1.65611 to 1.50152, saving model to /home/chainyo/code/video-classification-cnn-rnn\n", "Epoch 5/12\n", "7/7 [==============================] - 0s 16ms/step - loss: 1.0936 - accuracy: 0.6867 - val_loss: 1.5995 - val_accuracy: 0.0615\n", "\n", "Epoch 00005: val_loss did not improve from 1.50152\n", "Epoch 6/12\n", "7/7 [==============================] - 0s 16ms/step - loss: 1.0538 - accuracy: 0.6795 - val_loss: 1.5169 - val_accuracy: 0.2123\n", "\n", "Epoch 00006: val_loss did not improve from 1.50152\n", "Epoch 7/12\n", "7/7 [==============================] - 0s 16ms/step - loss: 0.9736 - accuracy: 0.7253 - val_loss: 1.5049 - val_accuracy: 0.2346\n", "\n", "Epoch 00007: val_loss did not improve from 1.50152\n", "Epoch 8/12\n", "7/7 [==============================] - 0s 16ms/step - loss: 0.9598 - accuracy: 0.7566 - val_loss: 1.4934 - val_accuracy: 0.2626\n", "\n", "Epoch 00008: val_loss improved from 1.50152 to 1.49344, saving model to /home/chainyo/code/video-classification-cnn-rnn\n", "Epoch 9/12\n", "7/7 [==============================] - 0s 16ms/step - loss: 0.9171 - accuracy: 0.7807 - val_loss: 1.5091 - val_accuracy: 0.2626\n", "\n", "Epoch 00009: val_loss did not improve from 1.49344\n", "Epoch 10/12\n", "7/7 [==============================] - 0s 15ms/step - loss: 0.8867 - accuracy: 0.8193 - val_loss: 1.4956 - val_accuracy: 0.3017\n", "\n", "Epoch 00010: val_loss did not improve from 1.49344\n", "Epoch 11/12\n", "7/7 [==============================] - 0s 17ms/step - loss: 0.8291 - accuracy: 0.8819 - val_loss: 1.4954 - val_accuracy: 0.3017\n", "\n", "Epoch 00011: val_loss did not improve from 1.49344\n", "Epoch 12/12\n", "7/7 [==============================] - 0s 17ms/step - loss: 0.7979 - accuracy: 0.8530 - val_loss: 1.5198 - val_accuracy: 0.3128\n", "\n", "Epoch 00012: val_loss did not improve from 1.49344\n", "7/7 [==============================] - 1s 4ms/step - loss: 1.1010 - accuracy: 0.6696\n", "Test accuracy: 66.96%\n" ] } ], "source": [ "history, sequence_model = run_experiment()" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Test video path: v_Punch_g03_c01.avi\n", " Punch: 71.19%\n", " TennisSwing: 17.20%\n", " PlayingCello: 5.47%\n", " ShavingBeard: 3.29%\n", " CricketShot: 2.85%\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def prepare_single_video(frames):\n", " frames = frames[None, ...]\n", " frame_mask = np.zeros(shape=(1, MAX_SEQ_LENGTH,), dtype=\"bool\")\n", " frame_features = np.zeros(shape=(1, MAX_SEQ_LENGTH, NUM_FEATURES), dtype=\"float32\")\n", "\n", " for i, batch in enumerate(frames):\n", " video_length = batch.shape[0]\n", " length = min(MAX_SEQ_LENGTH, video_length)\n", " for j in range(length):\n", " frame_features[i, j, :] = feature_extractor.predict(batch[None, j, :])\n", " frame_mask[i, :length] = 1 # 1 = not masked, 0 = masked\n", "\n", " return frame_features, frame_mask\n", "\n", "\n", "def sequence_prediction(path):\n", " class_vocab = label_processor.get_vocabulary()\n", "\n", " frames = load_video(os.path.join(\"test\", path))\n", " frame_features, frame_mask = prepare_single_video(frames)\n", " probabilities = sequence_model.predict([frame_features, frame_mask])[0]\n", "\n", " for i in np.argsort(probabilities)[::-1]:\n", " print(f\" {class_vocab[i]}: {probabilities[i] * 100:5.2f}%\")\n", " return frames\n", "\n", "\n", "# This utility is for visualization.\n", "# Referenced from:\n", "# https://www.tensorflow.org/hub/tutorials/action_recognition_with_tf_hub\n", "def to_gif(images):\n", " converted_images = images.astype(np.uint8)\n", " imageio.mimsave(\"animation.gif\", converted_images, fps=10)\n", " return embed.embed_file(\"animation.gif\")\n", "\n", "\n", "test_video = np.random.choice(test_df[\"video_name\"].values.tolist())\n", "print(f\"Test video path: {test_video}\")\n", "test_frames = sequence_prediction(test_video)\n", "to_gif(test_frames[:MAX_SEQ_LENGTH])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Export to Hugging Face Hub" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/chainyo/code/video-classification-cnn-rnn is already a clone of https://huggingface.co/ChainYo/video-classification-cnn-rnn. Make sure you pull the latest changes with `repo.git_pull()`.\n", "WARNING:huggingface_hub.repository:/home/chainyo/code/video-classification-cnn-rnn is already a clone of https://huggingface.co/ChainYo/video-classification-cnn-rnn. Make sure you pull the latest changes with `repo.git_pull()`.\n", "WARNING:absl:Found untraced functions such as gru_cell_6_layer_call_and_return_conditional_losses, gru_cell_6_layer_call_fn, gru_cell_7_layer_call_and_return_conditional_losses, gru_cell_7_layer_call_fn, gru_cell_6_layer_call_fn while saving (showing 5 of 10). These functions will not be directly callable after loading.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "INFO:tensorflow:Assets written to: /home/chainyo/code/video-classification-cnn-rnn/assets\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "INFO:tensorflow:Assets written to: /home/chainyo/code/video-classification-cnn-rnn/assets\n", "Several commits (2) will be pushed upstream.\n", "WARNING:huggingface_hub.repository:Several commits (2) will be pushed upstream.\n", "The progress bars may be unreliable.\n", "WARNING:huggingface_hub.repository:The progress bars may be unreliable.\n", "Upload file saved_model.pb: 81%|████████ | 4.53M/5.60M [00:01<00:00, 4.71MB/s]remote: -------------------------------------------------------------------------\u001b[31m \n", "remote: Your push was rejected because it contains binary files. \n", "remote: Please use https://git-lfs.github.com/ to store binary files. \n", "remote: See also: https://hf.co/docs/hub/adding-a-model#uploading-your-files\u001b(B\u001b[m \n", "remote: ------------------------------------------------------------------------- \n", "remote: Offending files: \n", "remote: - variables/variables.data-00000-of-00001 (ref: refs/heads/main) \n", "To https://huggingface.co/ChainYo/video-classification-cnn-rnn\n", " ! [remote rejected] main -> main (pre-receive hook declined)\n", "error: failed to push some refs to 'https://huggingface.co/ChainYo/video-classification-cnn-rnn'\n", "\n", "WARNING:huggingface_hub.repository:remote: -------------------------------------------------------------------------\u001b[31m \n", "remote: Your push was rejected because it contains binary files. \n", "remote: Please use https://git-lfs.github.com/ to store binary files. \n", "remote: See also: https://hf.co/docs/hub/adding-a-model#uploading-your-files\u001b(B\u001b[m \n", "remote: ------------------------------------------------------------------------- \n", "remote: Offending files: \n", "remote: - variables/variables.data-00000-of-00001 (ref: refs/heads/main) \n", "To https://huggingface.co/ChainYo/video-classification-cnn-rnn\n", " ! [remote rejected] main -> main (pre-receive hook declined)\n", "error: failed to push some refs to 'https://huggingface.co/ChainYo/video-classification-cnn-rnn'\n", "\n", "Upload file saved_model.pb: 100%|██████████| 5.60M/5.60M [00:05<00:00, 1.17MB/s]\n" ] }, { "ename": "OSError", "evalue": "remote: -------------------------------------------------------------------------\u001b[31m \nremote: Your push was rejected because it contains binary files. \nremote: Please use https://git-lfs.github.com/ to store binary files. \nremote: See also: https://hf.co/docs/hub/adding-a-model#uploading-your-files\u001b(B\u001b[m \nremote: ------------------------------------------------------------------------- \nremote: Offending files: \nremote: - variables/variables.data-00000-of-00001 (ref: refs/heads/main) \nTo https://huggingface.co/ChainYo/video-classification-cnn-rnn\n ! [remote rejected] main -> main (pre-receive hook declined)\nerror: failed to push some refs to 'https://huggingface.co/ChainYo/video-classification-cnn-rnn'\n", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mCalledProcessError\u001b[0m Traceback (most recent call last)", "File \u001b[0;32m~/miniconda3/envs/tf-training/lib/python3.8/site-packages/huggingface_hub/repository.py:1018\u001b[0m, in \u001b[0;36mRepository.git_push\u001b[0;34m(self, upstream, blocking, auto_lfs_prune)\u001b[0m\n\u001b[1;32m 1017\u001b[0m \u001b[39mif\u001b[39;00m return_code:\n\u001b[0;32m-> 1018\u001b[0m \u001b[39mraise\u001b[39;00m subprocess\u001b[39m.\u001b[39mCalledProcessError(\n\u001b[1;32m 1019\u001b[0m return_code, process\u001b[39m.\u001b[39margs, output\u001b[39m=\u001b[39mstdout, stderr\u001b[39m=\u001b[39mstderr\n\u001b[1;32m 1020\u001b[0m )\n\u001b[1;32m 1022\u001b[0m \u001b[39mexcept\u001b[39;00m subprocess\u001b[39m.\u001b[39mCalledProcessError \u001b[39mas\u001b[39;00m exc:\n", "\u001b[0;31mCalledProcessError\u001b[0m: Command '['git', 'push']' returned non-zero exit status 1.", "\nDuring handling of the above exception, another exception occurred:\n", "\u001b[0;31mOSError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m/home/chainyo/code/video-classification-cnn-rnn/main.ipynb Cell 18'\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 3\u001b[0m local_path \u001b[39m=\u001b[39m Path\u001b[39m.\u001b[39mcwd()\n\u001b[1;32m 4\u001b[0m logdir_path \u001b[39m=\u001b[39m local_path\u001b[39m.\u001b[39mjoinpath(\u001b[39m\"\u001b[39m\u001b[39mlogs\u001b[39m\u001b[39m\"\u001b[39m)\n\u001b[0;32m----> 6\u001b[0m push_to_hub_keras(\n\u001b[1;32m 7\u001b[0m sequence_model, \n\u001b[1;32m 8\u001b[0m repo_path_or_name\u001b[39m=\u001b[39;49mlocal_path,\n\u001b[1;32m 9\u001b[0m repo_url\u001b[39m=\u001b[39;49m\u001b[39m\"\u001b[39;49m\u001b[39mhttps://huggingface.co/ChainYo/video-classification-cnn-rnn\u001b[39;49m\u001b[39m\"\u001b[39;49m,\n\u001b[1;32m 10\u001b[0m )\n", "File \u001b[0;32m~/miniconda3/envs/tf-training/lib/python3.8/site-packages/huggingface_hub/keras_mixin.py:158\u001b[0m, in \u001b[0;36mpush_to_hub_keras\u001b[0;34m(model, repo_path_or_name, repo_url, commit_message, organization, private, api_endpoint, use_auth_token, git_user, git_email, config)\u001b[0m\n\u001b[1;32m 156\u001b[0m repo\u001b[39m.\u001b[39mgit_add(auto_lfs_track\u001b[39m=\u001b[39m\u001b[39mTrue\u001b[39;00m)\n\u001b[1;32m 157\u001b[0m repo\u001b[39m.\u001b[39mgit_commit(commit_message)\n\u001b[0;32m--> 158\u001b[0m \u001b[39mreturn\u001b[39;00m repo\u001b[39m.\u001b[39;49mgit_push()\n", "File \u001b[0;32m~/miniconda3/envs/tf-training/lib/python3.8/site-packages/huggingface_hub/repository.py:1023\u001b[0m, in \u001b[0;36mRepository.git_push\u001b[0;34m(self, upstream, blocking, auto_lfs_prune)\u001b[0m\n\u001b[1;32m 1018\u001b[0m \u001b[39mraise\u001b[39;00m subprocess\u001b[39m.\u001b[39mCalledProcessError(\n\u001b[1;32m 1019\u001b[0m return_code, process\u001b[39m.\u001b[39margs, output\u001b[39m=\u001b[39mstdout, stderr\u001b[39m=\u001b[39mstderr\n\u001b[1;32m 1020\u001b[0m )\n\u001b[1;32m 1022\u001b[0m \u001b[39mexcept\u001b[39;00m subprocess\u001b[39m.\u001b[39mCalledProcessError \u001b[39mas\u001b[39;00m exc:\n\u001b[0;32m-> 1023\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mEnvironmentError\u001b[39;00m(exc\u001b[39m.\u001b[39mstderr)\n\u001b[1;32m 1025\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mnot\u001b[39;00m blocking:\n\u001b[1;32m 1027\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39mstatus_method\u001b[39m():\n", "\u001b[0;31mOSError\u001b[0m: remote: -------------------------------------------------------------------------\u001b[31m \nremote: Your push was rejected because it contains binary files. \nremote: Please use https://git-lfs.github.com/ to store binary files. \nremote: See also: https://hf.co/docs/hub/adding-a-model#uploading-your-files\u001b(B\u001b[m \nremote: ------------------------------------------------------------------------- \nremote: Offending files: \nremote: - variables/variables.data-00000-of-00001 (ref: refs/heads/main) \nTo https://huggingface.co/ChainYo/video-classification-cnn-rnn\n ! [remote rejected] main -> main (pre-receive hook declined)\nerror: failed to push some refs to 'https://huggingface.co/ChainYo/video-classification-cnn-rnn'\n" ] } ], "source": [ "from huggingface_hub import push_to_hub_keras\n", "\n", "local_path = Path.cwd()\n", "logdir_path = local_path.joinpath(\"logs\")\n", "\n", "push_to_hub_keras(\n", " sequence_model, \n", " repo_path_or_name=local_path,\n", " repo_url=\"https://huggingface.co/ChainYo/video-classification-cnn-rnn\",\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "interpreter": { "hash": "88462ed31613cbbfe2bc6fefb08a3f371fbdeddc6af012ed3c71a7d204f8427e" }, "kernelspec": { "display_name": "Python 3.8.12 ('tf-training')", "language": "python", "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.8.12" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 }