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

یادگیری نیمه نظارتی و شبکه‌های مولد تخاصمی (GAN)

وینسنت ونگوگ Vincent Van Gogh در سال ۱۸۸۹ نقاشی زیبایی به نام «شب پرستاره» را کشید. مدل شبکه‌های مولد تخاصمی من (که نام آن را گَن گوگ گذاشته‌ام) نیز توانست به کمک داده‌های دیتاست MNIST که تنها ۲۰% آن‌ها برچسب داشتند، یک نقاشی بکشد. اما این مدل چگونه توانست به چنین موفقیتی دست یابد؟ در ادامه مقاله با من همراه باشید تا عامل این موفقیت را به شما بگویم.

یادگیری نیمه نظارتی Semi-supervised learning چیست؟

اغلب طبقه­‌بندهای مبتنی بر یادگیری عمیق برای تعمیم نتایج خود به حجم زیادی از نمونه‌های برچسب‌دار نیاز دارند. اما فرآیند به دست آوردن چنین داده‌های بسیار دشوار و هزینه‌بر است. یادگیری نیمه نظارتی با هدف فائق آمدن بر این محدودیت‌ها به وجود آمد. این الگوریتم مجموعه‌ای از تکنیک‌هاست که برای یادگیری نیاز به حجم زیادی داده بدون برچسب و مقدار کمی داده برچسب‌دار دارد. براساس مطالعات انجام گرفته در حوزه یادگیری ماشین، زمانی که در کنار مقدار کمی داده‌های برچسب‌دار از داده‌های بدون برچسب نیز استفاده کنیم، شاهد افزایش چشم‌گیر دقت فرآیند یادگیری خواهیم بود. شبکه‌های مولد تخاصمی (GAN) در حوزه یادگیری نیمه نظارتی پتانسیل و قابلیت‌های زیادی دارند، زیرا این شبکه‌ها، تنها با داشتن مقداری داده برچسب‌دار می‌توانند عملکرد خوبی از خود ارائه دهند.

پیشینه شبکه‌های مولد تخاصمی (GAN)

شبکه‌های GAN یکی از انواع مدل‌های عمیق مولد هستند. دلیل اصلی جذابیت این شبکه این است که توزیع احتمال در فضای داده‌ای را به‌طور واضح نشان نمی‌دهد. بلکه، با تهیه چند نمونه از این توزیع احتمال، به صورت غیرمستقیم با آن تعامل می‌کند.

پیشینه شبکه‌های مولد تخاصمی

ایده اصلی شبکه مولد تخاصمی فراهم آوردن مقدمات بازی بین دو بازیکن است:

  • مولد Generator  G: مولد با دریافت یک نویز تصادفی به نام z به عنوان ورودی، یک تصویر x به عنوان خروجی تحویل می‌دهد. پارامترهای این مولد به نحوی با تنظیم میشوند که بتوانند برای تصویر جعلی که تولید کرده‌اند، امتیاز بالایی از الگوریتم تفکیک‌کننده دریافت کنند.
  • تفکیک کننده Discriminator  D: تفکیک‌کننده یا ابزار تفکیک تصویر x را به عنوان ورودی دریافت می‌کند و خروجی آن امتیازی است که میزان شباهت تصویر جعلی با تصویر واقعی را نشان می‌دهد. پارامترهای ابزار تفکیک به نحوی تنظیم شده‌اند که وقتی مولد یک تصویر واقعی را به آن‌ها می‌دهد، امتیاز بالایی دریافت کند و زمانی که تصویر داده شده جعلی باشد، امتیاز مولد پایین بیاید.

پیشنهاد می‌کنم برای جزئیات بیشتر در این خصوص به مقالات «An introduction to Generative Adversarial Networks (with code in TensorFlow)» و «Overview of GANs (Generative Adversarial Networks) – Part I» مراجعه نمایید. درادامه به بررسی یکی از مهم‌ترین کاربردهای شبکه مولد تخاصمی یعنی یادگیری نیمه نظارتی خواهیم پرداخت.

[irp posts=”۱۶۲۱۰″]

مبانی یادگیری نیمه نظارتی

تفکیک کننده با معماری وانیلا برای جداسازی و طبقه‌بندی احتمالات R/F تنها یک نرون خروج دارد. ما هر دو شبکه (مولد و تفکیک ­کننده) را به‌طور هم‌زمان آموزش می‌دهیم، اما تفکیک­کننده را پس از آموزش دادن کنار می‌گذاریم، زیرا تنها کاربرد آن بهبود عملکرد مولد است.

تفکیک ­کننده در یادگیری نیمه نظارتی، علاوه بر نورون R/F، ۱۰ نورون دیگر نیز برای طبقه‌بندی ارقام MNIST دارد. به علاوه، در این مرحله نقش تفکیک­ کننده و مولد تغییر می‌کند و ما می‌توانیم مولد را پس از آموزش کنار بگذاریم، زیرا تنها هدف آن تولید تفکیک ­کننده در یادگیری نیمه نظارتی، علاوه بر نورون R/F، ۱۰ نورون دیگر نیز برای طبقه‌بندی ارقام MNIST دارد. به علاوه، در این مرحله نقش تفکیک ­کننده و مولد تغییر می‌کند و ما می‌توانیم مولد را پس از آموزش کنار بگذاریم، زیرا تنها هدف آن تولید داده‌های بدون برچسب برای بهبود عملکرد تفکیک ­کننده است.

مبانی یادگیری نیمه نظارتی

تفکیک­ کننده در این مرحله به یک جداساز با ۱۱ کلاس تبدیل می‌شود که یکی از این نورون‌ها (نورون R/F) نشان‌دهنده خروجی داده‌های جعلی است. ۱۰ کلاس دیگر نیز بیان‌گر داده‌های واقعی هستند. موارد زیر را باید به‌خاطر بسپارید:

  • زمانی که دیتاست داده واقعی و نظارت نشده به مدل بدهد، برچسب نورون خروجی R/F «صفر» است.
  • زمانی که مولد داده جعلی و نظارت‌نشده به مدل بدهد، برچسب نورون خروجی R/F عدد «۱» خواهد بود.
  • زمانی که داده واقعی و نظارت‌شده به مدل داده شود، برچسب خروجی R/F «صفر» و خروجی برچسب متناظر با آن «۱» خواهد بود.

اگر به ‌جای دادن مقدار کمی داده برچسب‌دار، منابع مختلف داده‌ای را با یک‌دیگر ترکیب کنیم، تفکیک­کننده می‌تواند طبقه‌بندی و جداسازی را با دقت بیشتری انجام دهد.

معماری

حال زمان آن است به بحث کدنویسی بپردازیم.

تفکیک ­کننده

معماری که در این‌جا شرح دادیم، شباهت زیادی به معماری تعریف‌شده در مقاله «UNSUPERVISED REPRESENTATION LEARNING WITH DEEP CONVOLUTIONAL GENERATIVE ADVERSARIAL NETWORKS» دارد. در این‌جا برای کاهش ابعاد بردارهای ویژگی به جای استفاده از لایه‌های ادغام، از پیچش‌های قدم برداشته strided convolutions استفاده می‌کنیم و توابع leaky_relu ،dropout و BN را برای همه لایه‌ها اجرا می‌کنیم تا فرآیند یادگیری تثبیت شود. باید توجه کنید که تابع BN برای لایه ورودی و آخرین لایه اعمال نمی‌شود (هدف از این کار منطبق کردن ویژگی‌ها با یک‌دیگر است). در آخر نیز از روش Global Average Pooling، میانگین تمامی ابعاد فضایی بردارهای ویژگی را به دست می‌آوریم. با اینکر ابعاد تنسور را در یک مقدار واحد خلاصه میکنیم. پس از مسطح کردن ویژگی‌ها، از یک لایه متراکم متشکل از ۱۱ کلاس و یک تابع فعال‌سازی بیشینه نرم softmax activation  استفاده می‌کنیم تا یک خروجی چند کلاسی به دست بیاوریم.

def discriminator(x, dropout_rate = 0., is_training = True, reuse = False):

# input x -> n+1 classes

with tf.variable_scope('Discriminator', reuse = reuse): 

# x = ?*64*64*1



#Layer 1

conv1 = tf.layers.conv2d(x, 128, kernel_size = [4,4], strides = [2,2],

padding = 'same', activation = tf.nn.leaky_relu, name = 'conv1') # ?*32*32*128

#No batch-norm for input layer

dropout1 = tf.nn.dropout(conv1, dropout_rate)



#Layer2

conv2 = tf.layers.conv2d(dropout1, 256, kernel_size = [4,4], strides = [2,2],

padding = 'same', activation = tf.nn.leaky_relu, name = 'conv2') # ?*16*16*256

batch2 = tf.layers.batch_normalization(conv2, training = is_training)

dropout2 = tf.nn.dropout(batch2, dropout_rate)



#Layer3

conv3 = tf.layers.conv2d(dropout2, 512, kernel_size = [4,4], strides = [4,4],

padding = 'same', activation = tf.nn.leaky_relu, name = 'conv3') # ?*4*4*512

batch3 = tf.layers.batch_normalization(conv3, training = is_training)

dropout3 = tf.nn.dropout(batch3, dropout_rate)



# Layer 4

conv4 = tf.layers.conv2d(dropout3, 1024, kernel_size=[3,3], strides=[1,1],

padding='valid',activation = tf.nn.leaky_relu, name='conv4') # ?*2*2*1024

# No batch-norm as this layer's op will be used in feature matching loss

# No dropout as feature matching needs to be definite on logits



# Layer 5

# Note: Applying Global average pooling 

flatten = tf.reduce_mean(conv4, axis = [1,2])

logits_D = tf.layers.dense(flatten, (1 + num_classes))

out_D = tf.nn.softmax(logits_D) 

return flatten,logits_D,out_D
[irp posts=”۶۳۸۷″]

مولد

معماری مولد به نحوی طراحی شده که خروجی‌های فضایی تفکیک­ کننده را بازنمایی کند. ما از لایه‌های پیچشی قدم برداشته
Fractional strided convolutions
استفاده می‌کنیم تا بعد فضایی ارائه را افزایش دهیم. ورودی که به مولد داده می‌شود یک تنسور ۴-D از نویز z است که H پیچش‌های ترانهاده transposed convolutions و توابع relu ،BN (غیر از لایه خروجی) و dropout روی آن اعمال می‌شوند. درنهایت، تصویر خروجی توسط تابع فعال‌سازی tanh در بازه (-۱,۱) نگاشته می‌شود.

def generator(z, dropout_rate = 0., is_training = True, reuse = False):
    # input latent z -> image x
    with tf.variable_scope('Generator', reuse = reuse):
      #Layer 1
      deconv1 = tf.layers.conv2d_transpose(z, 512, kernel_size = [4,4],
                                         strides = [1,1], padding = 'valid',
                                        activation = tf.nn.relu, name = 'deconv1') # ?*4*4*512
      batch1 = tf.layers.batch_normalization(deconv1, training = is_training)
      dropout1 = tf.nn.dropout(batch1, dropout_rate)
      
      #Layer 2
      deconv2 = tf.layers.conv2d_transpose(dropout1, 256, kernel_size = [4,4],
                                         strides = [4,4], padding = 'same',
                                        activation = tf.nn.relu, name = 'deconv2')# ?*16*16*256
      batch2 = tf.layers.batch_normalization(deconv2, training = is_training)
      dropout2 = tf.nn.dropout(batch2, dropout_rate)
        
      #Layer 3
      deconv3 = tf.layers.conv2d_transpose(dropout2, 128, kernel_size = [4,4],
                                         strides = [2,2], padding = 'same',
                                        activation = tf.nn.relu, name = 'deconv3')# ?*32*32*256
      batch3 = tf.layers.batch_normalization(deconv3, training = is_training)
      dropout3 = tf.nn.dropout(batch3, dropout_rate)
      
      #Output layer

زیان مدل

ما در ابتدا با دادن مقدار صفر به برچسب‌های واقعی یک برچسب را به تمام دسته تعمیم دادیم. هدف این بود که پس از دادن داده‌ها به مدل، خروجی نورون R/F صفر شود. تابع زیان تفکیک­­ کننده برای داده‌های بدون برچسب را می‌توان یک تابع زیان سیگموئید دودویی binary sigmoid loss درنظر گرفت که در آن خروجی نورون R/F برای تصاویر جعلی ۱ و برای تصاویر واقعی صفر است.

### Discriminator loss ###

# Supervised loss -> which class the real data belongs to 

temp = tf.nn.softmax_cross_entropy_with_logits_v2(logits = D_real_logit,

labels = extended_label) 

# Labeled_mask and temp are of same size = batch_size where temp is softmax cross_entropy calculated over whole batch



D_L_Supervised = tf.reduce_sum(tf.multiply(temp,labeled_mask)) / tf.reduce_sum(labeled_mask)



# Multiplying temp with labeled_mask gives supervised loss on labeled_mask

# data only, calculating mean by dividing by no of labeled samples



# Unsupervised loss -> R/F 

D_L_RealUnsupervised = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(

logits = D_real_logit[:, 0], labels = tf.zeros_like(D_real_logit[:, 0], dtype=tf.float32)))



D_L_FakeUnsupervised = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(

logits = D_fake_logit[:, 0], labels = tf.ones_like(D_fake_logit[:, 0], dtype=tf.float32)))



D_L = D_L_Supervised + D_L_RealUnsupervised + D_L_FakeUnsupervised

تابع زیان مولد ترکیبی است از تابع زیان تصویر جعلی و تابع زیان تطبیق ویژگی. هدف تابع زیان تصویر جعلی fake_image loss
گرفتن یک خروجی جعلی با مقدار صفر از نورون R/F است. تابع زیان تطبیق ویژگی feature matching loss نیز میانگین قدرمطلق خطای بین مقدار متوسط مجموعه‌ای از ویژگی‌های داده‌های آموزشی و مقدار متوسط همان ویژگی‌ها در داده‌های تولید شده را کاهش می‌دهد.

آموزش

          ### Generator loss ###                
    # G_L_1 -> Fake data wanna be real 
    
    G_L_1 = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(
            logits = D_fake_logit[:, 0],labels = tf.zeros_like(D_fake_logit[:, 0], dtype=tf.float32)))

ما در این‌جا سایز تصاویر آموزشی را از [batch_size, 28 ,28 , 1] به [batch_size, 64, 64, 1] تغییر دادیم تا مناسب معماری مولد و ابزار تفکیک شوند. سپس توابع زیان، دقت الگوریتم‌ها و نمونه‌های تولید شده برآورد می‌شوند و به منظور بهبود و پیشرفت طی هر دوره تحت بررسی قرار می‌گیرند.

for epoch in range(epochs):
  train_accuracies, train_D_losses, train_G_losses = [], [], []
  for it in range(no_of_batches):
  
  batch = mnist_data.train.next_batch(batch_size, shuffle = False)
  # batch[0] has shape: batch_size*28*28*1         
  batch_reshaped = tf.image.resize_images(batch[0], [64, 64]).eval()
  # Reshaping the whole batch into batch_size*64*64*1 for disc/gen architecture
  batch_z = np.random.normal(0, 1, (batch_size, 1, 1, latent))
  mask = get_labeled_mask(labeled_rate, batch_size)
                
  train_feed_dict = {x : scale(batch_reshaped), z : batch_z,
                              label : batch[1], labeled_mask : mask,
                               dropout_rate : 0.7, is_training : True}
  #The label provided in dict are one hot encoded in 10 classes
                
  D_optimizer.run(feed_dict = train_feed_dict)
  G_optimizer.run(feed_dict = train_feed_dict)
                
  train_D_loss = D_L.eval(feed_dict = train_feed_dict)
  train_G_loss = G_L.eval(feed_dict = train_feed_dict)
  train_accuracy = accuracy.eval(feed_dict = train_feed_dict)
          
  train_D_losses.append(train_D_loss)
  train_G_losses.append(train_G_loss)
  train_accuracies.append(train_accuracy)
          
  tr_GL = np.mean(train_G_losses)
  tr_DL = np.mean(train_D_losses)
  tr_acc = np.mean(train_accuracies)       
  
  print ('After epoch: '+ str(epoch+1) + ' Generator loss: '
                       + str(tr_GL) + ' Discriminator loss: ' + str(tr_DL) + ' Accuracy: ' + str(tr_acc))
        
  gen_samples = fake_data.eval(feed_dict = {z : np.random.normal(0, 1, (25, 1, 1, latent)), dropout_rate : 0.7, is_training : False})
  # Dont train batch-norm while plotting => is_training = False

 

نتیجه‌گیری

باتوجه به محدودیت GPU، آموزش ۵ دوره‌ای این مدل با استفاده از داده‌هایی انجام گرفت که تنها ۲۰% آن‌ها برچسب داشتند. برای کسب نتایج بهتر و دقیق‌تر پیشنهاد می‌کنم که دوره‌های آموزشی را افزایش داده و نرخ برچسب‌دار بودن داده‌ها را پایین بیاورید. برای تکمیل کدهای مربوطه می‌توانید به این لینک مراجعه نمایید.

یادگیری نیمه نظارتی

در حوزه هوش مصنوعی عمومی (AGI) یادگیری بدون نظارت یک نقطه مبهم است. شبکه‌های مولد تخاصمی برای رفع این ابهامات آمده‌اند. این شبکه‌های مولد تخاصمی راه‌حل مناسبی برای مسائل پیچیده یادگیری با داده‌های بدون برچسب هستند. با توجه به ارائه روش‌های جدید در حوزه یادگیری نیمه نظارتی و بدون نظارت، انتظار می‌رود که این ابهامات روزبه‌روز برای ما روشن‌تر شوند. باید خاطرنشان کنم که ایده این مدل را از مقاله زیبای « Semi-supervised learning with Generative Adversarial Networks (GANs) » و دستیار یکی از همکارانم الهام گرفته‌ام.

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

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

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