https://amirabbas.me
تنسورفلو ۱۳: دسته بندی ویدئو
سلام
بعد از چند ماه یه آموزش جدید به سری تنسورفلو اضافه می کنم :-)
در این آموزش می خواهیم ویدئو های دیتاست IXMAS Actions رو دسته بندی کنیم.
این دیتاست یکی از دیتاست های مورد استفاده در زمینه HAR یا تشخیص فعالیت های انسانی هست

در این دیتاست تعدادی ویدئو از چند فرد با چند دوربین در جهت های مختلف ضبط شده که افراد ۱۱ تا فعالیت مختلف رو انجام می دن.
قدم اول
دیتاست رو از اینجا دانلود کنید و محیط توسعه رو فراهم کنید :)
قدم دوم
در این قدم قصد داریم ویدئو رو به یک سری فریم تبدیل کنیم برای اینکار از openCV استفاده می کنیم
برای نصب openCV از خط زیر استفاده کنید:
1pip install opencv-python
یک فایل پایتون به اسم vid-img-convertor.py بسازید و تکه کد زیر رو داخلش قرار بدید این کد کمک میکنه تا چند فریم از هر کدوم از clip ها استخراج کنیم:
1234567891011121314151617181920212223242526272829import cv2 from os import listdir folder_name = "nixmas" def getFrame(sec, vid_name): vidcap.set(cv2.CAP_PROP_POS_MSEC, sec*1000) hasFrames, image = vidcap.read() if hasFrames: # save frame as JPG file cv2.imwrite(folder_name+"-img/"+vid_name+"_"+str(count)+".jpg", image) return hasFrames for item in listdir(folder_name): print(item) if item.endswith('.avi'): vidcap = cv2.VideoCapture(folder_name+'/' + item) vid_name = item.replace('.avi', '') sec = 0 frameRate = 0.5 # //it will capture image in each 0.5 second count = 1 success = getFrame(sec, vid_name) while success: count = count + 1 sec = sec + frameRate sec = round(sec, 2) success = getFrame(sec, vid_name) vidcap.release()
قدم سوم
از الان میتونیم شروع کنیم که با تنسورفلو کار کنیم. ابتدا کتابخانه های لازم رو وارد می کنیم
12345678910111213import tensorflow as tf from tensorflow.keras import layers, models from tensorflow.keras.models import Model from sklearn.preprocessing import LabelEncoder import matplotlib.pyplot as plt from PIL import Image import os import numpy as np colors = plt.rcParams['axes.prop_cycle'].by_key()['color']
یک تابع تعریف می کنیم که تغییرات loss function رو چاپ کنیم
123456789def plot_loss(history, label, n): # Use a log scale to show the wide range of values. plt.semilogy(history.epoch, history.history['loss'], color=colors[n], label='Train '+label) plt.semilogy(history.epoch, history.history['val_loss'], color=colors[n], label='Val '+label, linestyle="--") plt.xlabel('Epoch') plt.ylabel('Loss') plt.legend()
بعد دیتا ها رو load می کنیم
123456789101112data_x = [] data_y = [] for path in os.listdir('./nixmas-img'): img = Image.open('nixmas-img/'+path) data_x.append(np.array(img)) data_y.append(path.split('_')[3]) print({i:data_y.count(i) for i in data_y}) le = LabelEncoder() a = le.fit_transform(data_y) b = np.zeros((a.size, a.max()+1)) b[np.arange(a.size),a] = 1 data_y = a
فرمت دیتا ها رو اطلاح می کنیم و همچنین دیتا ها رو تقسیم بر 255 می کنیم چون هر پیکسل مقداری بین 0 تا 255 داره و می خواهیم مقادیر بین 0 تا 1 قرار بگیره
123data_x = np.array(data_x) data_x = data_x.astype(np.float32) data_x /= 255.0
دیتا ها رو به فرمت دیتاست تنسورفلو تبدیل می کنیم
12dataset = tf.data.Dataset.from_tensor_slices((data_x, data_y)) dataset = dataset.cache().shuffle(10000)
دیتاستمون رو به چند قسمت برای test, validate و train تقسیم میکنیم
1test_dataset = dataset.take(30).batch(10)
1val_dataset = dataset.skip(30).take(100).batch(10)
1train_dataset = dataset.skip(130).batch(100)
حالا که دیتا آماده است سعی می کنیم مدل رو بسازیم. برای این تسک از الگوریتم CNN استفاده میکنیم توی این پست در مورد CNN صحبت کردم
123456789model = models.Sequential() model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(64, 48, 3))) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Conv2D(64, (3, 3), activation='relu')) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Conv2D(64, (3, 3), activation='relu')) model.add(layers.Flatten()) model.add(layers.Dense(64, activation='relu')) model.add(layers.Dense(11))
الان دیگه میتونیم مدل رو compile کنیم و نتیجه ساختار مدل رو مشاهده کنیم
1234model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy']) model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 62, 46, 32) 896
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 31, 23, 32) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 29, 21, 64) 18496
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 14, 10, 64) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 12, 8, 64) 36928
_________________________________________________________________
flatten (Flatten) (None, 6144) 0
_________________________________________________________________
dense (Dense) (None, 64) 393280
_________________________________________________________________
dense_1 (Dense) (None, 11) 715
=================================================================
Total params: 450,315
Trainable params: 450,315
Non-trainable params: 0
خب بالاخره میتونیم مدل رو train کنیم
1history = model.fit(train_dataset, validation_data=val_dataset, epochs=60)
بیایید نمودار بکشیم :-)
1plot_loss(history, "history", 1)

ببینید نمودار نزولی هست و همزمان loss دیتاست validate و train در حال کاهش هست. نکته مهم اینه که نمودار val تقریبا همزمان با train در حال کاهش هست و معنی این رو میده که مدل overfit نشده اما نوسانات آخر میتونه معنی بده شاید چون دیتا کمه. شاید اگه از الگوریتم دیگه مثل RNN استفاده کنیم چونکه ورودی ما ویدئو هست نتیجه بهتر هم بشه
در آخر هم بر روی دیتاست تست خروجی رو تست می کنیم
1model.evaluate(test_dataset)
خروجی که من از این مدل گرفتم به صورت زیر است:
train_loss: 0.0541 - train_accuracy: 0.9819
val_loss: 0.0097 - val_accuracy: 1.0000
test_loss: 0.0829 - test_accuracy: 0.9667
مطلبی دیگر از این انتشارات
شبکه کپسول (مقدمه)
مطلبی دیگر از این انتشارات
دیتاست بنچ مارک یادگیری عمیق(بخش اول)
مطلبی دیگر از این انتشارات
ماجرای اخیر درز اطلاعات فیسبوک چیست؟