40 گام به سوی آینده‌ای هوشمند - مجموعه وبینارهای رایگان در حوزه هوش مصنوعی
Filter by دسته‌ها
chatGTP
آموزش هوش مصنوعی و انواع آن
آموزش‌های پایه‌ای هوش مصنوعی
اصول هوش مصنوعی
پایتون و ابزارهای یادگیری عمیق
کتابخانه‌ های یادگیری عمیق
یادگیری با نظارت
یادگیری بدون نظارت
یادگیری تقویتی
یادگیری عمیق
یادگیری نیمه نظارتی
آموزش‌های پیشرفته هوش مصنوعی
بینایی ماشین
پردازش زبان طبیعی
پردازش گفتار
چالش‌های عملیاتی
داده کاوی و بیگ دیتا
رایانش ابری و HPC
سیستم‌‌های امبدد
علوم شناختی
دیتاست
اخبار
تیتر یک
رسانه‌ها
آموزش پردازش زبان طبیعی
آموزش علوم داده
اینفوگرافیک
پادکست
ویدیو
رویدادها
کاربردهای هوش مصنوعی
کسب‌و‌کار
تحلیل بازارهای هوش مصنوعی
کارآفرینی
هوش مصنوعی در ایران
هوش مصنوعی در جهان
 مدل تشخیص چهره ای که می توانید در کمتر از ۳۰ دقیقه آن را بسازید

مدل تشخیص چهره ای که می توانید در کمتر از ۳۰ دقیقه آن را بسازید

مقدمه

در این نوشتار قصد دارم به جزئیات پیاده‌سازی مدل تشخیص چهره بپردازم. اخیراً یک رابط کاربری در جستجوگر
Browser-based UI
طراحی کردم که برای افزودن یک فرد جدید به پایگاه داده کاربرد دارد. توضیحات مربوط به توسعه‌ی شبکه
Web-development
از حوصله‌ی این بحث خارج است.
نویسنده‌ی این متن فرض را بر شناخت مخاطب از مدل شبکه‌‎ی Siamese و تابع زیان سه‌گانه قرار داده است.

مدل تشخیص چهره
مدل کاری را از مخزن امتحان کنید

فهرست محتوای این مقاله بدین شکل است:
• معماری مدل
• دیتاست
نسل سه‌گانه Triplet generation

• جزئیات متفرقه
• نتیجه‌گیری

معماری مدل

شبکه عصبی پیچشی Convolutional neural network بدیهی است که آموزش یک (CNN) از نقطه‌ی صفر نیازمند داده‌های فراوان و قدرت محاسباتی بالاست. بنابراین به جای آن از از یادگیری انتقالی Transfer learning استفاده می‌کنیم؛ در این روش مدل را برروی داده‌هایی آموزش می‌دهیم که به دقت مطابق با نیاز ما تنظیم شده‌اند. هندسه‌ی تصویری Visual geometry group گروه (VGG) از دانشگاه آکسفورد سه مدل (VGG-16، ResNet-50 و SeNet-50) برای رده‌بندی و تشخیص چهره ساخته‌اند. من از مدل تشخیص چهره VGG-16 استفاده کرده‌ام زیرا کوچک‌تر است و روی سیستم محلی من که GPU ندارد، پیش‌بینی سریع‌تری انجام می‌دهد.

برای این‌که مدل یادگیری عمیق VGG-16 را با گروه هندسه‌ی تصویری (VGG) اشتباه نگیرید، از این‌جای متن به بعد به این گروه با عنوان گروه آکسفورد اشاره خواهیم کرد.

در این مورد، همه‌ی مدل در Keras با چارچوب TensorFlow v1.14 پیاده‌سازی شده است. من هم قصد داشتم همین مدل را در TensorFlow v2.3 اجرا کنم، به همین دلیل یک ابزار virtualenv در سیستم‌ محلی خود ایجاد کردم و وزن‌های مدل را استخراج نمودم. این وزن‌ها در vgg_face_weights.h5 ذخیره و در گام بعدی روی یک شبکه‌ی آموزش نیافته‌ی VGG-16 (در TensorFlow v2.3) بارگزاری شدند. اگر قصد کار با ResNet-50 یا SeNet-50 را دارید، می‌توانید برای گرفتن مدل و وزن‌ها از Refik Can Malli’s repository استفاده نمایید.

مدل VGG-16 روی دیتاستی آموزش می‌بیند. در مقاله‌ی مذکور مدل رده‌بندی را برروی ۲۶۲۲ چهره آموزش داده‌اند. لایه‌ی یکی مانده به آخر ۴۰۹۶ واحد Dense دارد که به آن‌ها یک لایه‌ی Dense 128 واحدی ضمیمه کرده (بدون شرط سوگیری) و لایه‌ی رده‌بندی/بیشینه‌هموار softmax را که ۲۶۲۲ واحد دارد، حذف می‌نماییم. همه‌ی لایه‌هایی که قبل از لایه‌ی Dense 128 مسدود
frozen
واحدی قرار دارند، (trainable = False) می‌شوند و بدین ترتیب فقط لایه‌ی Dense که تازه اضافه شده نیاز به آموزش خواهد داشت.

vggface = tf.keras.models.Sequential()
vggface.add(tf.keras.layers.Convolution2D(64, (3, 3), activation='relu', padding="SAME", input_shape=(224,224, 3)))
vggface.add(tf.keras.layers.Convolution2D(64, (3, 3), activation='relu', padding="SAME"))
vggface.add(tf.keras.layers.MaxPooling2D((2,2), strides=(2,2)))
 
vggface.add(tf.keras.layers.Convolution2D(128, (3, 3), activation='relu', padding="SAME"))
vggface.add(tf.keras.layers.Convolution2D(128, (3, 3), activation='relu', padding="SAME"))
vggface.add(tf.keras.layers.MaxPooling2D((2,2), strides=(2,2)))
 
vggface.add(tf.keras.layers.Convolution2D(256, (3, 3), activation='relu', padding="SAME"))
vggface.add(tf.keras.layers.Convolution2D(256, (3, 3), activation='relu', padding="SAME"))
vggface.add(tf.keras.layers.Convolution2D(256, (3, 3), activation='relu', padding="SAME"))
vggface.add(tf.keras.layers.MaxPooling2D((2,2), strides=(2,2)))
 
vggface.add(tf.keras.layers.Convolution2D(512, (3, 3), activation='relu', padding="SAME"))
vggface.add(tf.keras.layers.Convolution2D(512, (3, 3), activation='relu', padding="SAME"))
vggface.add(tf.keras.layers.Convolution2D(512, (3, 3), activation='relu', padding="SAME"))
vggface.add(tf.keras.layers.MaxPooling2D((2,2), strides=(2,2)))
 
vggface.add(tf.keras.layers.Convolution2D(512, (3, 3), activation='relu', padding="SAME"))
vggface.add(tf.keras.layers.Convolution2D(512, (3, 3), activation='relu', padding="SAME"))
vggface.add(tf.keras.layers.Convolution2D(512, (3, 3), activation='relu', padding="SAME"))
vggface.add(tf.keras.layers.MaxPooling2D((2,2), strides=(2,2)))

vggface.add(tf.keras.layers.Flatten())

vggface.add(tf.keras.layers.Dense(4096, activation='relu'))
vggface.add(tf.keras.layers.Dropout(0.5))
vggface.add(tf.keras.layers.Dense(4096, activation='relu'))
vggface.add(tf.keras.layers.Dropout(0.5))
vggface.add(tf.keras.layers.Dense(2622, activation='softmax'))

vggface.load_weights(os.path.join(base_dir, 'vgg_face_weights.h5'))

vggface.pop()
vggface.add(tf.keras.layers.Dense(128, use_bias=False))

for layer in vggface.layers[:-2]:
    layer.trainable = False

“بارگزاری وزن‌های از پیش آموزش دیده‌شده‌ی VGG-16 و سپس اختصاصی کردن مدل.”

حال برای آموزش این شبکه از یک تابع زیان سه‌گانه استفاده می‌کنیم. تابع زیان سه‌گانه سه ویژگی ۱۲۸ بُعدی را که از شبکه‌ی بالا تولید شده‌اند، دریافت می‌کند. این سه ویژگی را می‌توانیم با این نام‌ها و تعاریف مشخص کنیم:

لنگر anchor : تصویری از یک فرد که برای مقایسه استفاده می‌شود؛
مثبت positive : تصویر همان فرد حاضر در تصویر لنگر؛
منفی negative : تصویر فردی متفاوت از تصویر لنگر.

مدل تشخیص چهره
تابع زیان سه‌گانه

تابع زیان سه‌گانه تلاش دارد فاصله‌ی بین لنگر و مثبت را کم و فاصله‌ی بین لنگر و منفی را بیشتر کند. یک پارامتر دیگر هم داریم (alpha = 0.2) که یک حاشیه اضافه کرده و بدین ترتیب آموزش را سخت‌تر می‌کند و همگرایی بهتری به دست می‌دهد. این پارامترها (یعنی واحد متراکم ۱۲۸ بُعدی و آلفا که پارامتر تابع زیان است) بر اساس تجزیه‌تحلیلی انتخاب می‌شوند که در این مقاله به نمایش گذاشته شده است.

def loss_function(x, alpha = 0.2):
    # Triplet Loss function.
    anchor,positive,negative = x
    # distance between the anchor and the positive
    pos_dist = K.sum(K.square(anchor-positive),axis=1)
    # distance between the anchor and the negative
    neg_dist = K.sum(K.square(anchor-negative),axis=1)
    # compute loss
    basic_loss = pos_dist-neg_dist+alpha
    loss = K.mean(K.maximum(basic_loss,0.0))
    return loss

# Note K in the above function is defined as follows K = tf.keras.backend

پیاده‌سازی تابع زیان سه‌گانه

اجازه دهید تا این‌جای مقاله را جمع‌بندی کنیم. شبکه‌ی VGG-16 به ما ویژگی‌های ۱۲۸-D (128 بُعدی) با عناوین لنگر، مثبت و منفی می‌دهد که بعداً به تابع زیان خورانده می‌شوند.
حال یک گزینه برای آموزش، فراخوانی سه‌باره‌ی همان مدل روی تصاویر لنگر، مثبت و منفی و سپس ارائه‌ی مقدار به دست آمده به تابع زیان می‌باشد. با این حال اجرای پشت سر هم آن‌ها فکر خوبی نیست؛ به همین دلیل به جای این کار، آن‌ها را در یک رده از شبکه‌ی Siamese قرار می‌دهیم که tf.keras.Model را گسترش داده و موازی‌سازی parallelization را به TensorFlow روش تنظیمی L2 regularization می‌سپارد. L2 هم به مدل اضافه می‌شود که روی خروجی لایه‌ی Dense 128 بُعدی اجرا می‌گردد.

class SiameseNetwork(tf.keras.Model):
    def __init__(self, vgg_face):
        super(SiameseNetwork, self).__init__()
        self.vgg_face = vgg_face
        
    @tf.function
    def call(self, inputs):
        image_1, image_2, image_3 =  inputs
        with tf.name_scope("Anchor") as scope:
            feature_1 = self.vgg_face(image_1)
            feature_1 = tf.math.l2_normalize(feature_1, axis=-1)
        with tf.name_scope("Positive") as scope:
            feature_2 = self.vgg_face(image_2)
            feature_2 = tf.math.l2_normalize(feature_2, axis=-1)
        with tf.name_scope("Negative") as scope:
            feature_3 = self.vgg_face(image_3)
            feature_3 = tf.math.l2_normalize(feature_3, axis=-1)
        return [feature_1, feature_2, feature_3]
    
    @tf.function
    def get_features(self, inputs):
        return tf.math.l2_normalize(self.vgg_face(inputs), axis=-1)

model = SiameseNetwork(vggface)

رده‌ی شبکه‌ی Siamese

من به رده‌ی شبکه‌ی Siamese یک تابع get_features اضافه کردم که طی آزمایش شبکه به عنوان بهینه‌ساز مفید خواهد بود.
حالا که یک مدل ساخته‌ایم، می‌توانیم وارد بحث دیتاست آموزشی بشویم.

دیتاست

دیتاست VGGFace از ۲۶۲۲ تصویر متمایز از شخصیت‌های مشهور تشکیل شده و برای آموزش مدل VGG-16 مورد استفاده قرار می‌گیرد. گروه آکسفورد دیتاست VGGFace2 را نیز ارائه داده که ۸۶۳۱ تصویر را از افراد مشهور در برمی‌گیرد؛ تصاویر این دیتاست برای آموزش و ۵۰۰ تصویر آن برای آزمایش کاربرد دارند. از آن‌جایی که حجم مجموعه‌ی آموزشی ۳۹GB است، من فقط مجموعه‌ی آزمایشی (با حجم ۲GB) را دانلود کردم و آخرین لایه‌ی متراکم را با آن آموزش دادم.

استفاده از مجموعه‌ی آزمایشی برای آموزش شاید اشتباه به نظر برسد، اما باید در نظر داشت که این قانون مربوط به مدلی است که روی همان داده‌های آزمایشی، آموزش دیده است. من در کار خود از این مجموعه برای آموزش و از تصاویر خودم و اعضای خانواده و دوستانم به عنوان داده‌های آزمایشی استفاده کردم.

پیش‌پردازش Pre-processing معمولاٌ متکی بر مدل زیربنایی است. بنابراین برای آموزش و آزمایش، تصاویر ورودی باید همان پیش‌پردازشی را طی کنند که مدل VGG-16 تعریف کرده است. تصاویر ورودی ابتدا از یک مدل تشخیص‌ چهره (که در این مقاله معرفی شده) عبور کرده و سپس به تابع preprocess_input (که این‌جا آورده‌ام) فرستاده می‌شوند. من در کار خودم از مدل تشخیص چهره‌ که کتابخانه‌ی dlib ارائه کرده استفاده نمودم و سپس تصاویر را به تابع preprocess_input فرستادم.

نکته: تابع preprocess_input (توضیح آن‌ را در این قسمت می‌بینید) با تابعی که مدل VGG-16 (که روی ImageNet آموزش دیده) استفاده می‌کند، تفاوت دارد. بنابراین کد مربوط به پیش‌پردازش که در منبع کد پروژه‌ی من ذکر شده ، از کتابخانه‌ی VGGFace گرفته شده است.

حال ساختار دایرکتوری دیتاست‌ها را توضیح خواهم داد که راهی برای بهینه‌سازی حافظه طی آموزش محسوب می‌شوند. اجازه بدهید ابتدا ساختار دایرکتوری دیتاست دانلودشده را بررسی کنیم. در ساختار دایرکتوری که پایین مشاهده می‌نمایید، هر دایرکتوری (n000001, n000009 و غیره) به همه‌ی تصاویر یک شخصیت مشهور اختصاص داده شده است.

.
└── vggface2_test
    └── test
        ├── n000001
        │   ├── ۰۰۰۱_۰۱.jpg
        │   ├── ۰۰۰۲_۰۱.jpg
        │   ├── ۰۰۰۳_۰۱.jpg ...
        ├── n000009
        │   ├── ۰۰۰۱_۰۱.jpg
        │   ├── ۰۰۰۲_۰۱.jpg
        │   ├── ۰۰۰۳_۰۱.jpg ...
(so on and so forth)

همانطور که پیش‌تر اشاره کردیم به منظور تشخیص چهره ها و ذخیره‌سازی آن‌ها در پوشه‌ای متفاوت به نام دیتاست از مدل تشخیص چهره dlib استفاده می‌کنیم. این‌جا درخت دایرکتوری تصاویر شناسایی‌شده را مشاهده می‌کنید. این نوتبوک نیز همین شیوه‌ی پیاده‌سازی را نشان می‌دهد.

.
└── dataset
    └── list.txt
    └── images
        ├── n000001
        │   ├── ۰۰۰۱_۰۱.jpg
        │   ├── ۰۰۰۲_۰۱.jpg
        │   ├── ۰۰۰۳_۰۱.jpg ...
        ├── n000009
        │   ├── ۰۰۰۱_۰۱.jpg
        │   ├── ۰۰۰۲_۰۱.jpg
        │   ├── ۰۰۰۳_۰۱.jpg ...
(so on and so forth)

ساختار دایرکتوری vggface_test و دیتاست تقریباً مشابه بکدیگر هستند. اما دایرکتوری دیتاست ممکن است تصاویر کمتری از برخی چهره‌ها داشته باشد، زیرا توسط مدل تشخیص چهره dlib شناسایی نشده‌اند. تفاوت دیگر این است که در دایرکتوری دیتاست یک فایل list.txt وجود دارد که دربرگیرنده‌ی داده‌های directory-name/image-name برای هر تصویر می‌باشد. از list.txt به منظور بهینه‌سازی حافظه طی آموزش استفاده می‌شود.

نسل سه‌گانه

همانطورکه گفتیم یک مدل برای آموزش به سه تصویر نیاز دارد (لنگر، مثبت و منفی). اولین ایده‌ای که به ذهن می‌رسد تولید همه‌ی جفت‌های ممکن از این سه‌گانه‌ است. شاید به نظر بیاید این روش داده‌های زیادی در اختیار می‌گذارد اما پیشینه‌ی پژوهش حاکی از ناکافی بودن آن است. بنابراین برای انتخاب لنگر، مثبت و منفی از یک مولد اعداد تصادفی Random number generator استفاده کردم. همچنین مولد داده‌ای را به کار بردم که طی چرخه‌ی آموزشی داده تولید می‌کند.

نکته‌ی جانبی: مقدار زمانی که من برای نوشتن رده‌ی DataGenerator لازم داشتم از مدت زمان لازم برای آموزش مدل بیشتر بود.

class DataGenerator(tf.keras.utils.Sequence):
    def __init__(self, dataset_path, batch_size=32, shuffle=True):
        self.dataset = self.curate_dataset(dataset_path)
        self.dataset_path = dataset_path
        self.shuffle = shuffle
        self.batch_size =batch_size
        self.no_of_people = len(list(self.dataset.keys()))
        self.on_epoch_end()
        
    def __getitem__(self, index):
        people = list(self.dataset.keys())[index * self.batch_size: (index + 1) * self.batch_size]
        P = []
        A = []
        N = []
        
        for person in people:
            anchor_index = random.randint(0, len(self.dataset[person])-1)
            a = self.get_image(person, anchor_index)
            
            positive_index = random.randint(0, len(self.dataset[person])-1)
            while positive_index == anchor_index:
                positive_index = random.randint(0, len(self.dataset[person])-1)
            p = self.get_image(person, positive_index)
            
            negative_person_index = random.randint(0, self.no_of_people - 1)
            negative_person = list(self.dataset.keys())[negative_person_index]
            while negative_person == person:
                negative_person_index = random.randint(0, self.no_of_people - 1)
                negative_person = list(self.dataset.keys())[negative_person_index]
            
            negative_index = random.randint(0, len(self.dataset[negative_person])-1)
            n = self.get_image(negative_person, negative_index)
            P.append(p)
            A.append(a)
            N.append(n)
        A = np.asarray(A)
        N = np.asarray(N)
        P = np.asarray(P)
        return [A, P, N]
        
    def __len__(self):
        return self.no_of_people // self.batch_size
        
    def curate_dataset(self, dataset_path):
        with open(os.path.join(dataset_path, 'list.txt'), 'r') as f:
            dataset = {}
            image_list = f.read().split()
            for image in image_list:
                folder_name, file_name = image.split('/')
                if folder_name in dataset.keys():
                    dataset[folder_name].append(file_name)
                else:
                    dataset[folder_name] = [file_name]
        return dataset
    
    def on_epoch_end(self):
        if self.shuffle:
            keys = list(self.dataset.keys())
            random.shuffle(keys)
            dataset_ =  {}
            for key in keys:
                dataset_[key] = self.dataset[key]
            self.dataset = dataset_
            
    def get_image(self, person, index):
        # print(os.path.join(self.dataset_path, os.path.join('images/' + person, self.dataset[person][index])))
        img = cv2.imread(os.path.join(self.dataset_path, os.path.join('images/' + person, self.dataset[person][index])))
        img = cv2.resize(img, (224, 224))
        img = np.asarray(img, dtype=np.float64)
        img = preprocess_input(img)
        return img
    
data_generator = DataGenerator(dataset_path='./dataset/')

مولد داده‌ی سه‌گانه

__getitem__ مهم‌ترین تابع می‌باشد. برای این‌که این نتیجه را به چشم خود ببینیم اجازه بدهید سازنده constructor و سایر مدل‌ها را نیز بررسی کنیم.

• __init__: سازنده‌ مسیر رسیدن به دایرکتوری دیتاستی که در قسمت قبل توضیح دادیم را طی می‌کند. سازنده از تابع list.txt به منظور ساخت یک دیکشنری استفاده می‌کند. این دیکشنری از اسم دایرکتوری به عنوان کلید و از لیست تصاویر آن به عنوان ارزش استفاده می‌کند. تابع list.txt درمرحله‌ی به‌هم زدن راهی آسان برای مرور دیتاست در اختیار ما قرار می‌دهد و بدین ترتیب می‌توانیم از بارگزاری تصاویر برای به‌هم زدن shuffling جلوگیری کنیم.
• __getitem__: نام افراد را از کلیدهای دیکشنری بالا می‌گیریم. برای بسته‌ی داده‌ای اول، ۳۲ تصویر اول از افراد به عنوان لنگر استفاده می‌شود و یک تصویر دیگر از همان افراد به عنوان مثبت در نظر گرفته می‌شود. برای همه‌ای اجزای این سه‌گانه (لنگر، مثبت و منفی) تصاویر به صورت تصادفی انتخاب می‌شوند. ۳۲ تصویر از افراد بعدی، لنگر بسته‌ی دیگری محسوب می‌گردند.
• curate_dataset : دیکشنری توضیح‌داده شده در تابع __init__ را می‌سازد.
• on_epoch_end : در انتهای هر دوره ترتیب افراد به هم‌ می‌ریزد؛ به نحوی که ۳۲ تصویر اول در بسته‌ی بعدی از آن‌چه در بسته‌ی قبلی وجود داشته متفاوت باشد.
• get_image : این تابع بعد از تغییر اندازه‌ی تصاویر به ابعاد (۲۲۴×۲۲۴) از preprocess_input استفاده می‌کند.
• __len__: خروجی این تابع تعداد بسته‌های داده‌ای است که یک دوره را تعریف می‌کنند.

انجام شد!!!

آموزش و آزمایش

من از یک چرخه‌ی آموزشی سفارشی با کتابخانه‌ی tqdm استفاده کردم (you still get Keras to feel) و مدل را برای ۵۰ دوره آموزش داده‌ام. در کو‌لب colab زمان مورد نیاز برای هر دوره‌ی آموزشی ۲۴ ثانیه است (که سرعت بالایی برای آموزش محسوب می‌شود).

برای آزمایش می‌توانید از تصاویر خود، خانواده، دوستانتان و دایرکتری خود استفاده کنید و ویژگی‌های ۱۲۸ بُعدی که برای هر فرد توسط لایه‌ی متراکم تولید شده را ذخیره کنید. می‌توانید از تابع (get_features) استفاده کنید که در رده‌ی شبکه‌ی Siamese توضیح داده شد. همچنین برای صرفه‌جویی در زمان می‌توانید به نوتبوک Real-time-prediction.ipynb که در پروژه‌ی خود درست کرده‌ام مراجعه کنید. در این نوتبوک وزن‌ها checkpoint بارگزاری شده و دستورالعمل‌هایی ارائه می‌گردد که برای جمع‌آوری تصاویر به منظور آزمایش آنی و پیش‌بینی روی تصویر وب‌کم کاربرد خواهند داشت.

جزئیات متفرقه

سرعت آموزش را در کو‌لب افزایش دهید

در مولد داده به جای همه‌ی تصاویر، شاخص‌های آن‌ها برای دستکاری روی حافظه بارگزاری شده‌اند. اگر GPU دارید، شاید جزئیاتی که در این قسمت بیان می‌کنیم برایتان چندان مفید نباشد.
ابتدا فکر می‌کردم خواندن و نوشتن عملیات‌ها از کو‌لب به روی درایو drive باید سریع باشد، اما بعد متوجه شدم سرعت آن‌ها از سرعت سیستم محلی من که GPU ندارد هم کمتر است. به منظور حل این مشکل دیتاست را به dataset.7z فشرده‌سازی و سپس آن‌را روی درایو خودم بارگزاری کردم. در قدم بعدی فایل زیپ‌شده را از google drive برروی فضای کو‌لب که بر اساس هر جلسه مرتب شده کپی و بعد برای آموزش از آن استفاده می‌کنم. استفاده از فضای کو‌لب سرعت فرآیند آموزش را به حد معناداری افزایش داد.
با این‌حال خلاصه‌های من از tensorboard و وزن‌های مدل روی درایو ذخیره شدند، زیرا در هر دوره در دسترس هستند و عملکرد را خیلی کاهش نمی‌دهند.

ابزار مبتنی بر رابط کاربری

قصد داشتم به یادگیری برخی از تکنولوژی‌های شبکه‌ای همچون HTML، CSS و Javascript بپردازم. بهترین راه برای یادگیری، طراحی یک پروژه‌ی کوچک بود. بنابراین سعی کردم یک ابزار مبتنی بر رابط کاربری برای جمع‌آوری داده برای آزمایش و پیش‌بینی بسازم. در این قسمت گام‌هایی که در این مسیر برداشتم را توضیح‌ داده‌ام؛ می‌توانید از آن‌ها برای اجرای کار خود استفاده کنید.

نتیجه‌گیری

در این بلاگ جزئیات کلیدی در مورد تنظیم دقیق یک شبکه‌ی موجود و ساخت یک شبکه‌ی Siamese برروی آن‌ها صحبت کردیم. یافته‌های مدل کنونی از آن‌چه انتظار می‌رفت بسیار بهتر بود اما با ساخت سه‌گانه‌های خوب به صورت دستی، هنوز هم می‌توان آن‌ها را ارتقا بخشید. همچنین می‌توانید همه‌ی دیتاست آموزشی را برای آموزش مدل خود دانلود کنید. پیشینه‌ی پژوهش نشان می‌دهد که انتخاب دستی یک مجموعه از سه‌گانه‌های سخت در نهایت مقدار زمان آموزش را به طرز چشمگیری کاهش و نرخ همگرایی مدل را افزایش خواهد داد.
برای امتحان ابزار جستجو‌محور Browser-based می‌توانید سری به نوت‌بوک‌ها بزنید. این ابزار قادر به تشخیص چهره چندین فرد می‌باشد.

میانگین امتیاز / ۵. تعداد ارا :

مطالب پیشنهادی مرتبط

اشتراک در
اطلاع از
0 نظرات
بازخورد (Feedback) های اینلاین
مشاهده همه دیدگاه ها
[wpforms id="48325"]