شرح ال GANS خطوة بخطوة من البداية باستخدام PyTorch and TensorFlow

798

“الفكرة الأكثر روعة في التعلم العميق في العشرين عاماَ الأخيرة.”

Yann LeCun متحدثا عن الGANS

سنقوم في هذا المقال باستعراض ما يسمى بال GANS وهي اختصار ل Generative Adversarial Networks، إذا لم تكن قد سمعت بهم من قبل فهذه فرصتك لمعرفة ما فاتك من التطورات حتى الآن. على الرغم من أن ضجة الGANS حدثت فقط في الفترة الأخيرة؛ إلا أنها في الحقيقة ظهرت عام 2014. وقد أصبحت الآن معروفة بالفعل باستخداماتها الواسعة ونتائجها المتميزة في توليد البيانات.

وقد تم استخدامهم في الحياة العملية لإنتاج أو توليد نصوص، صور، بل وحتى فيديوهات، كما تم استخدامهم في اكتشاف المخدرات، وتأليف النصوص من الصور. وهنا معنا بعض الصور المنشأة بواسطة الGANS ربما تود إلقاء نظرة عليها.

ويسمى هذا النوع بنقل صورة لصورة، أي التعديل على صورة موجودة بالفعل، أما الأكثر غرابة وربما مخيف قليلا فلو كنت قد سمعت تلك الأخبار المنتشرة منذ فترة عن الموقع الذي يولد صورا لأشخاص غير موجودين ففي الحقيقة الGANS تقف بقلبها وراء هذا الإنجاز الغريب.

بإمكانك تفحص الموقع هنا  ، لاحظ أن كل الصور التي ستظهر لك هي لأشخاص غير حقيقيين لكنها متقنة للغاية بطريقة خادعة!

في هذا المقال سنقوم بشرح الGANS وشرح الأسباب التي جعلتها تنتشر بهذه السرعة، وفي النهاية سنقوم معا ببرمجة Vanilla GAN، وهي أول نموذج قدم للGANS في بداية صنعها على الإطلاق.

أثناء التنفيذ سنقوم باستخدام PyTorch، مع ذلك بإمكانك إيجاد Implementation لها بواسطة الTensorFlow هنا .

 

GANS تتعلم توليد صور لأرقام مكتوبة بخط اليد.

1- مقدمة :

الGANS هي واحدة من أكثر الخوارزميات المشهورة في الMachine learning، والتي تم تطويرها حديثا.

لأولئك الذين لم يبدأوا بالذكاء الاصطناعي سوى مؤخرا، فبإمكاننا وصف تعلم الآلة ML على أنه فرع من فروع الذكاء الاصطناعي الذي يستخدم البيانات ليعلم الآلة أو البرنامج كيفية القيام بعمل مهمة لم يقم بها من قبل. مثال : إعطاء صورة لشخص ما كمدخل حتى يتعلم البرنامج كيفية التعرف على ملامح هذا الشخص في صور أخرى وتحديدها(غالبا سيحتاج صورة negative أيضا).

وبأخذ هذا بعين الاعتبار فبإمكاننا وصف الML بأنه تطبيق التحسين الرياضي أو mathematical optimization، حيث تستطيع الخوارزمية تمثيل البيانات في فضاء متعدد الأبعاد، وتعلم تحديد ما إذا كانت متجهات متعددة البعد جديدة تنتمي للهدف المراد تمييزه أو لا. 

إذا أردت تخيل الأمر بشكل أكثر وضوحا فبإمكانك مشاهدة هذا الفيديو 

اهتمام العالم بتعبير “Generative Adversarial Network”

ما الشيء المميز جدا في ال GANS؟

باختصار الGANS تنتمي إلى مجموعة من الخوارزميات تسمى نماذج التوليد أو Generative models، وهذه الخوارزميات تنتمي لمجال الUnSupervised learning أو التعلم الغير مشرف عليه وهو فرع من فروع الML يهدف لدراسة خوارزميات تتعلم الهيكل الضمني للبيانات المقدمة، بدون تحديد هدف مسبق. تتعلم نماذج التوليد Generative models دالة التوزيع الجوهرية للبيانات المدخلة (P(x أو (P(x,y _إذا كان هناك أكثر من هدف أو تصنيف داخل البيانات_ سامحة لهم بتوليد كلا من مدخلات مصنوعة x’ ومخرجات أو أهداف y’، وعادة تعطى بعض الparameters المخفية.

في المقابل تتعلم خوارزميات ال Supervised learning تكوين دالة (y’=f(x باستخدام بيانات معطاة y، مثال على ذلك سيكون التصنيف classification، حيث يستطيع الشخص استخدام بيانات العميل التي تصف تاريخ مشترياته (X) وعمر العميل (Y) ليصنف عملاء جدد. معظم خوارزميات الsupervised learning تمييزية بطبيعتها ما يعني أنهم يتعلمون كيفية عمل نموذج دالة توزيع الاحتمالات الشرطية(p.d.f) p(y|x)، وهو احتمال حدوث الهدف (age =35) مع العلم أن السلعة المشتراة كمدخل كانت (purchase= Milk)، على الرغم من حقيقة أنه يمكن للشخص عمل تنبؤات بواسطة هذا الp.d.f؛ ففي الحقيقة لا يمكن للشخص تجربة instances جديدة (كمحاكاة الزبائن مع الأعمار) من توزيع الدخل مباشرة.

ملحوظة : من الممكن استخدام خوارزميات تمييزية ليست احتمالية ، وتسمى الدوال التمييزية.

أثبتت GANS كفاءتها في نمذجة وتوليد البيانات في أبعاد أعلى، وهو السبب الذي جعلها أكثر شهرة. ومع ذلك، فهي ليست النوع الوحيد لل Generative model، فهناك أنواع أخرى ومنها : Variational Autoencoders (VAEs) ، pixelCNN/pixelRNN ،real NVP كل نوع منهم لديه مميزاته ومساوئه.

فيم يلي بعض إيجابيات وسلبيات الGANS الأكثر تأثيرا:

  • في الوقت الحالي تقوم بإنشاء Sharpest images.
  • سهلة التدريب _بما أن الأمر لا يتطلب استدلال احصائي statistical inference_ وفقط باستخدام الback propogation يمكننا الحصول على ال gradients أو الميل لكل معامل.
  • من الصعب عمل تحسين أو optimize لها بسبب ديناميكيات التدريب الغير مستقرة.
  • لا يمكن عمل استدلال إحصائي لهم فيم عدا هنا : تنتمي الGANS لتصنيف يدعى direct implicit density models ويعني أنه يقوم بنمذجة ال(P(X بدون وضع تعريف صريح لل p.d.f .

– إذا، لماذا ال GANS ؟

طبقا لشركة openAI  _إحدى شركات الذكاء الاصطناعي المعروفة _ فإن الخوارزميات التي لديها القدرة على صنع وتوليد بيانات بنفسها تستطيع التعامل مع مشاكلنا الواقعية بشكل أكثر كفاءة.

نستعين هنا باقتباس من الفيزيائي الشهير ريتشارد فاينمان 

” ما لا أستطيع صنعه، لا أفهمه”

يمكن لنماذج التوليد استخدامها في عمليات التمييز وإن كانت تعطي نتائج أفضل بكثير من نظيرتها التمييزية.حيث تستخدم أيضا في Classification،Regression. حيث يكون للهدف قيمة مستمرة ك R “مجموعة الأعداد الحقيقية”، يمكن حساب(conditional p.d.f p(y|x اللازمة لمثل هذه المهام. باستخدام (statistical inference on the joint p.d.f. p(x,y إذا كان متوفرا في الGenerative model.

– حالات الاستخدام 

  • صنع عينات فنية واقعية (صوت،صورة،فيديو)
  • المحاكاة والتخطيط باستخدام بيانات متسلسلة زمنيا.
  • الاستدلال الإحصائي.
  • إنشاء مدخلات أخرى للتدريب لتوسيع نموذج التدريب.

 نظرة عامة على الGANS

 

تتكون من نموذجين : 

Generator أو المولد 

ويهدف لتوليد بيانات جديدة مشابهة للبيانات المستهدفة، مثلا صنع أعمال فنية مزيفة أو صنع وجوه بشر غير حقيقية كما رأينا في بداية المقال.

Discriminator أو المميز

ويهدف هذا النموذج لتمييز البيانات وتحديد إذا كانت حقيقية _ بمعنى أنها تنتمي للdata set الأصلية_  أو مزيفة _بمعني أنها مولدة بواسطة الgenerator_

يعمل هذين النموذجين بطريقة الندية، حيث يستمر المولد بتوليد بيانات غير حقيقية، والمميز في التعرف عليها حتى يحسن المولد من بياناته المولدة بحيث تبدو كالحقيقية تماما وبالتالي لا يتعرفها المميز.

-نمذجة الGAN بالرياضيات

على الرغم من أنه يمكن تطبيق الGAN بأي نموذجين يقومان بالموضح أعلاه إلا أنه من الأسهل استخدام الشبكات العصبية Neural Networks لفهمها.

يتم استخدام الشبكة العصبية (G(z, θ₁ لنمذجة المولد المذكور سابقا، فدوره هو تعيين الnoise الداخلة في متغير دخل z إلى الفضاء المطلوب للبيانات X ولنقل صورة مثلا، على العكس من ذلك تقوم الشبكة العصبية الثانية(D(xθ₂ بنمذجة المميز ويكون خرجها هو احتمالية أن المدخل إليها ينتمي إلى البيانات الأصلية وليس المزورة بمدى من 0 ل 1، وفي كلتا الحالتين تمثل ال θᵢ  الأوزان أو المعاملات التي تعرف كل شبكة عصبية.

نتيجة لذلك ، يتم تدريب Discriminator على تصنيف بيانات الإدخال بشكل صحيح إما حقيقية أو مزيفة. هذا يعني تعديل الأوزان بحيث تزيد احتمالية أن تكون البيانات حقيقية إذا كانت بالفعل قادمة من الdata set وتقليل احتمالية أن تكون البيانات حقيقية إذا كانت مزيفة وبطريقة تقنية أكثر بإمكاننا القول أننا نحاول تكبير دالة (D(x، وتقليل دالة((D(G(z.

ما يعني أن المولد يتم تدريبه لخداع المميز ووضع الأوزان بحيث تصبح الصورة المزيفة المولدة أكثر ترجيحا لأن تصنف كصورة حقيقية وبطريقة تقنية أكثر فإننا هنا نحاول تكبير دالة ( ( maximize D( G( Z.

أثناء التطبيق يستخدم لوغاريتم الاحتمال (..)log D في دالة الLoss function بدلا من الاحتمالات العادية، لأن اللوغاريتم يؤثر بشدة بنتائج الclassifiers التي تثق في صور مزيفة.

بعد ما يكفي من التدريب إذا كانت الشبكة قادرة على التوصل لتقريب للدالة الموضوعية الصحيحة فسيصل كلاهما لنقطة لا يمكن تحسين أداء أحدهما أكثر من ذلك، في تلك النقطة يكون المولد قادر على توليد صور حقيقية جدا للدرجة التي لا يتمكن فيها المميز من تمييز زيفها.

بما أن كلا من المميز والمولد يحاولان أثناء التدريب تحسين loss function كل منهما تعاكس الأخرى؛ فبإمكانك التفكير بهما على أنهما agents عميلان يلعبان minimax game مع دالة قيمة هي (V(G,D فما يحاول أن يزيده المولد وهو احتمالية أن يولد صورة مزيفة بقدر كبير من الواقعية يحاول أن يقلله المميز وهو احتمالية أن تمر صورة مزيفة على أنها واقعية.

-تدريب الGAN

بما أن المميز والمولد كلاهما تم نمذجته بواسطة الNeural Networks، فيمكن استخدام خوارزمية تسمىagradient-based optimization في عملية تدريب الGAN، خلال الكود سنقوم باستخدامstochastic gradient descent؛ حيث أثبت كفاءته في عدة مجالات.

خطوات تدريب الGAN

1- قم بوضع عينة noise وعينة data set كلا منهما طوله m.

2- درب المميز على هاتين العينتين.

3- ضع عينة أخرى من الnoise بطول m أيضا.

4- درب المولد على هذه البيانات.

5- كرر من الخطوة رقم 1.

3. Coding a GAN

لبداية تكويد الGAN علينا أولا تنزيل بعض المكتبات

pip install torchvision tensorboardx jupyter matplotlib numpy

وبإمكانك رؤية كيفية تنزيل الpytorch هنا، بإمكانك أيضا رؤية مثال على الTensor flow هنا 

سنبدأ أولا بعمل ملف جديد أو notebook ونقوم بعمل import للملفات الآتية

import torch
from torch import nn, optim
from torch.autograd.variable import Variable
from torchvision import transforms, datasets

 

لتسجيل التقدم الذي أحرزناه، سنقوم بعمل import لملف آخر سيسمح لنا بعمل visualize لعملية التدريب على شاشة الconsole أو Jupyter، وفي نفس الوقت تخزينه في الTensorBoard لأولئك الذين يعرفون بالفعل كيفية استخدامه.

from utils import Logger

ما تحتاجه الآن هو تحميل الملف ووضعه في نفس المجلد الذي ستضع فيه ملفات الGAN، ليس مهما أن تفهم الكود المكتوب به حيث يستخدم فقط لتمثيل البيانات Visualization.

يمكنك تحميل الملف من هنا أو هنا

Dataset

الData set التي سنستخدمها ستكون LeCunn’s MNIST dataset وهي تتكون من 60.000 صورة بيضاء وسوداء لأرقام مكتوبة بخط اليد، كل واحدة حجمها 28*28 pixels ، وسيتم عمل لها pre-processing  طبقا لبعض القواعد التي ثبت أنها تجدي نفعا مع الGAN هنا ، خاصة قيم المدخلات التي تكون عادة بين 0 و255 سيتم عمل Normalization لها لتصبح بين -1 و 1 
def mnist_data():
    compose = transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize((.5, .5, .5), (.5, .5, .5))
        ])
    out_dir = './dataset'
    return datasets.MNIST(root=out_dir, train=True, transform=compose, download=True)
# Load data
data = mnist_data()
# Create loader with data, so that we can iterate over it
data_loader = torch.utils.data.DataLoader(data, batch_size=100, shuffle=True)
# Num batches
num_batches = len(data_loader)

 

الآن سنقوم بتعريف Neural Network، وسنبدأ بالDiscriminator  وهي ستأخذ صورة كمدخل، وت return  احتمالية أن تكون الصورة تنتمي للdata set الأصلية أو لا، حجم المدخلات لكل صورة سيكون 28*28 = 784، وبالنسبة لهيكل هذه الشبكة فسوق يكون لها ثلاث طبقات مخفية hidden layers ، كل واحدة منهم متبوعة ب  Leaky-ReLU nonlinearity و Dropout layer لمنع الoverfitting تحدثنا عنه في مقال سابق، وتطبق دالة سيجمويد على الخرج لجعله بين ال0و1 

class DiscriminatorNet(torch.nn.Module):
    """
    A three hidden-layer discriminative neural network
    """
    def __init__(self):
        super(DiscriminatorNet, self).__init__()
        n_features = 784
        n_out = 1
        
        self.hidden0 = nn.Sequential( 
            nn.Linear(n_features, 1024),
            nn.LeakyReLU(0.2),
            nn.Dropout(0.3)
        )
        self.hidden1 = nn.Sequential(
            nn.Linear(1024, 512),
            nn.LeakyReLU(0.2),
            nn.Dropout(0.3)
        )
        self.hidden2 = nn.Sequential(
            nn.Linear(512, 256),
            nn.LeakyReLU(0.2),
            nn.Dropout(0.3)
        )
        self.out = nn.Sequential(
            torch.nn.Linear(256, n_out),
            torch.nn.Sigmoid()
        )

    def forward(self, x):
        x = self.hidden0(x)
        x = self.hidden1(x)
        x = self.hidden2(x)
        x = self.out(x)
        return x
discriminator = DiscriminatorNet()

وأيضا نحتاج لتمثيل الصورة في بعدين، ثم إعادتها من بعدين لبعد واحد.

def images_to_vectors(images):
    return images.view(images.size(0), 784)

def vectors_to_images(vectors):
    return vectors.view(vectors.size(0), 1, 28, 28)

على الناحية الأخرى تأخذ شبكة التوليد متجهات متغيرة كامنة latent variable vector كمدخل، ويعيد 784 قيمة متجهية وهي قيم 28*28 pixel في الصورة. تذكر أن الغرض من هذه الشبكة هو صنع صور مزيفة لذلك يكون خرجها صورة.

وسيكون لها أيضا ثلاث طبقا مخفية كل واحدة متبوعة ب Leaky-ReLUnonlinearity. والطبقة الأخيرة أو كما نسميها طبقة الخرج سيكون لديها TanH activation function ، وهي تعين قيم النتائج لتكون بين  (-1, 1)، وهو نفس المدى الذي قمنا بتعيينه في الpre-processing.

class GeneratorNet(torch.nn.Module):
    """
    A three hidden-layer generative neural network
    """
    def __init__(self):
        super(GeneratorNet, self).__init__()
        n_features = 100
        n_out = 784
        
        self.hidden0 = nn.Sequential(
            nn.Linear(n_features, 256),
            nn.LeakyReLU(0.2)
        )
        self.hidden1 = nn.Sequential(            
            nn.Linear(256, 512),
            nn.LeakyReLU(0.2)
        )
        self.hidden2 = nn.Sequential(
            nn.Linear(512, 1024),
            nn.LeakyReLU(0.2)
        )
        
        self.out = nn.Sequential(
            nn.Linear(1024, n_out),
            nn.Tanh()
        )

    def forward(self, x):
        x = self.hidden0(x)
        x = self.hidden1(x)
        x = self.hidden2(x)
        x = self.out(x)
        return x
generator = GeneratorNet()

نحتاج أيضا لميزة أخرى تسمح لنا بصناعة بعض الnoise العشوائية، وسيتم تجميع عينات الnoise من توزيع طبيعي ب mean = 0 

variance = 1 كما هو موضح بهذا اللينك 

def noise(size):
    '''
    Generates a 1-d vector of gaussian sampled random values
    '''
    n = Variable(torch.randn(size, 100))
    return n

Optimization

سنقوم باستخدام خوارزمية Adam للتحسين لكلا الشبكتين، بمعدل تعلم 0.0002. وهو مقدم بعدما تم الاختبار بالفعل بأكثر من قيمة، لذا فليس من الضروري أن يكون هو الأنسب لهذه المهمة.

d_optimizer = optim.Adam(discriminator.parameters(), lr=0.0002)
g_optimizer = optim.Adam(generator.parameters(), lr=0.0002)

أما دالة loss function التي سنستخدمها هنا فتسمى (Binary Cross Entopy Loss (BCE Loss، وسيتم استخدامها هنا لتمثيل الloss function لكلا الشبكتين. وسنقوم بأخذ المتوسط المحسوب لكل دفعة صغيرة.

loss = nn.BCELoss()

حيث 

Y: هي الأهداف

v : هي المدخلات

w : هي الأوزان

وبما أننا لا نحتاج الأوزان مطلقا فسيتم اعتبارها بواحد لكل i.

Discriminator Loss :

إذا استبدلنا (vᵢ = D(xᵢ و yᵢ=1  لكل i) i ∀) في تعريف BCE Loss، ونحصل على الloss المتعلقة بالصورة الحقيقية، وبالعكس من ذلك إذا وضعنا

((vᵢ = D(G(zᵢ و yᵢ=0 ∀ i نحصل على الخسارة المتعلقة بالصورة المزورة، وفي النموذج الرياضي الذي يصف الGAN والمذكور سابقا فميل هذا يجب أن يكون تصاعديا، ولكن pytorch ومعظم الmachine learning framework الأخرى عادة ما تصغر الدالة بدلا من ذلك. وبما أن تكبير الدالة يساوي تصغير الجزء السالب منها و عنصر الBCE loss لديه إشارة سالبة،فبإمكاننا استخدام شيء كهذا لتكبير الدالة عوضا عن تصغيرها، وليس هناك حاجة للقلق بشأن الإشارة.

بالإضافة إلى ذلك، بإمكاننا ملاحظة أن أهداف الصور الحقيقة دائما ما تكون 1، في حين تكون أهداف الصور المزيفة 0، لذا سيكون من المفيد تعريف الدوال الآتية :

def ones_target(size):
    '''
    Tensor containing ones, with shape = size
    '''
    data = Variable(torch.ones(size, 1))
    return data

def zeros_target(size):
    '''
    Tensor containing zeros, with shape = size
    '''
    data = Variable(torch.zeros(size, 1))
    return data
وبجمع الloss للمميزين نحصل على الloss الكلية للمميز، وبالتطبيق سنقوم بحساب الميل بشكل منفصل، وثم تحديثهم معا.
def train_discriminator(optimizer, real_data, fake_data):
    N = real_data.size(0)
    # Reset gradients
    optimizer.zero_grad()
    
    # 1.1 Train on Real Data
    prediction_real = discriminator(real_data)
    # Calculate error and backpropagate
    error_real = loss(prediction_real, ones_target(N) )
    error_real.backward()

    # 1.2 Train on Fake Data
    prediction_fake = discriminator(fake_data)
    # Calculate error and backpropagate
    error_fake = loss(prediction_fake, zeros_target(N))
    error_fake.backward()
    
    # 1.3 Update weights with gradients
    optimizer.step()
    
    # Return error and predictions for real and fake inputs
    return error_real + error_fake, prediction_real, prediction_fake

Generator Loss:

بدلا من تقليل (((log(1- D(G(z، تدريب المولد على تكبير (((log(1- D(G(z سيقوم بتوفير gradients أكثر قوة في التدريب.  قد يتم تبديل إحدي الLoss بمأ أنهما في النهاية ينتجان نفس الديناميكيات للمميز والمولد.

تكبير ((log D(G(z مساوي لتصغير القيمة السالبة له، وبما أن الBCE loss له إشارة سالبة فنحن لا نحتاج للانتباه للإشارة. وبالمثل للمميز إذا وضعنا ((vᵢ = D(G(zᵢ و yᵢ=1 ∀ i، فسنحصل على الخسارة المطلوبة وهي في قيمتها الأصغر.

def train_generator(optimizer, fake_data):
    N = fake_data.size(0)
    # Reset gradients
    optimizer.zero_grad()
    # Sample noise and generate fake data
    prediction = discriminator(fake_data)
    # Calculate error and backpropagate
    error = loss(prediction, ones_target(N))
    error.backward()
    # Update weights with gradients
    optimizer.step()
    # Return error
    return error

Testing

في النهاية وقبل أن نقوم بتشغيل البرنامج، نحتاج إلى تمثيل تطور الGAN أثناء تدريبها بصريا، ولفعل ذلك سنقوم بخلق دفعة ثابتة من الnoise، وكل بضع خطوات سنقوم بتمثيل الصور التي يخرجها المولد عند استخدام هذه الnoise  كمدخلات.

num_test_samples = 16
test_noise = noise(num_test_samples)

Training

الآن بما أننا قمنا بالفعل بتعريف الdataset و Network و optimization و خوارزمية التعلم بإمكاننا تدريب GAN،  هذا الجزء بسيط جدا حيث أن كل ما نحتاج إلى عمله هو تكويد بالبايثون ما هو مكتوب بالفعل كpseudocode، انظر  Training a GAN.

سنقوم باستخدام كل ما كتبناه حتى الآن، بالإضافة للملفات التي طلبنا منك تحميلها من قبل 

# Create logger instance
logger = Logger(model_name='VGAN', data_name='MNIST')
# Total number of epochs to train
num_epochs = 200
for epoch in range(num_epochs):
    for n_batch, (real_batch,_) in enumerate(data_loader):
        N = real_batch.size(0)
        # 1. Train Discriminator
        real_data = Variable(images_to_vectors(real_batch))
        # Generate fake data and detach 
        # (so gradients are not calculated for generator)
        fake_data = generator(noise(N)).detach()
        # Train D
        d_error, d_pred_real, d_pred_fake = \
              train_discriminator(d_optimizer, real_data, fake_data)

        # 2. Train Generator
        # Generate fake data
        fake_data = generator(noise(N))
        # Train G
        g_error = train_generator(g_optimizer, fake_data)
        # Log batch error
        logger.log(d_error, g_error, epoch, n_batch, num_batches)
        # Display Progress every few batches
        if (n_batch) % 100 == 0: 
            test_images = vectors_to_images(generator(test_noise))
            test_images = test_images.data
            logger.log_images(
                test_images, num_test_samples, 
                epoch, n_batch, num_batches
            );
            # Display status Logs
            logger.display_status(
                epoch, num_epochs, n_batch, num_batches,
                d_error, g_error, d_pred_real, d_pred_fake
            )

تهانينا، لقد قمت الآن بإنجاز أول GAN لك.

النتائج 

في البداية تكون الصور المكونة pure noise لا معنى لها.

وبعد ذلك تتحسن قليلا :

حتى تصل لنتيجة جيدة

من الممكن أيضا تمثيل عملية التعلم ، فكما ترى في الشكل المقابل كانت أخطاء المميز كبيرة جدا في البداية، ولكن مع الوقت بدأت أخطاؤه تقل وبدأ في التعرف بشكل أفضل على الصور الحقيقية والمزيفة.

عندما يصبح المُميّز أفضل وينخفض خطأه إلى حوالي 0.5 في الخطوة 5k ، يزداد خطأ المولد ، مما يثبت أن المميّز يتفوق على المولد ويمكنه تصنيف العينات المزيفة بشكل صحيح.

مع مرور الوقت واستمرار التدريب ، يقلل خطأ المولد ، مما يعني أن الصور التي يولدها تصبح أفضل وأفضل. وبينما يتحسن المولد ، يزداد خطأ المميّز ، لأن الصور المزيفة تصبح أكثر واقعية في كل مرة.

خطأ المولد بالنسبة للزمن 

خطأ المميز بالنسبة للزمن 

بإمكانك أيضا إلقاء نظرة على notebook تدعى Vanilla Gan PyTorch هنا ، وتشغيلها أونلاين. بإمكانك أيضا تحميل البيانات الخارجة.

الاستنتاج

في هذا المقال قمنا بتقديم الGAN، حيث بدأن بتعلم نوع الخوارزميات الموجودة ولماذا هي مهمة، بعد ذلك استكشفنا أجزاء الGAN وكيفية وضعها معا، ثم ربطنا النظرية بالتطبيق من خلال كتابة كود كامل للشبكة.

الآن بعد أن تعلمت كل هذا ، ستكون الخطوات التالية هي مواصلة القراءة والتعرف على أساليب GAN الأكثر تقدمًا التي أدرجناها في قسم القراءة الإضافية.

القراءة الإضافية

 

تعليقات