يعمل إطار عمل الشبكات العصبية المتكررة (RNN) مع آلية الانتباه الذي تعرفنا عليه في المقال السابق بشكل جيد للموسيقى أحادية اللحن (monophonic) ، ولكن هل يمكن تكييفها مع الموسيقى متعددة الألحان (polyphonic)؟
من المؤكد أن إطار عمل RNN مرن بدرجة كافية لتصور معمارية يتم من خلالها إنشاء خطوط موسيقية متعددة في وقت واحد ، من خلال آلية متكررة.
ولكن في الوضع الحالي ، لم يتم إعداد مجموعة البيانات التي إستخدمناها في المقال السابق لهذا الغرض ، حيث إننا نقوم بتخزين الأوتار ككيانات فردية بدلاً من أجزاء تتكون من عدة ملاحظات فردية.
و لا توجد وسيلة لـ RNN الحاليه لدينا لمعرفة ذلك ، على سبيل المثال ، أن الوتر C الرئيسي (C ، E ، و G) هو في الواقع قريب جدًا من وتر A- ثانوي (A ، C ، و E) – ملاحظة واحدة فقط سيتم تغييرها ، G إلى A. وبدلاً من ذلك ، فإنه يعامل كلاهما على أنهما عنصرين متميزين يمكن توقعهما بشكل مستقل.
من الناحية المثالية ، نود تصميم شبكة يمكنها قبول قنوات متعددة من الموسيقى كتدفقات فردية ومعرفة كيفية تفاعل هذه التدفقات مع بعضها البعض لتوليد موسيقى جميلة ، بدلاً من الضوضاء غير المتناغمة.
و هذا مشايه لإنشاء الصور ، أليس كذلك؟ لتوليد الصور ، لدينا ثلاث قنوات (الأحمر والأخضر والأزرق) ، ونريد أن تتعلم الشبكة كيفية دمج هذه القنوات لإنشاء صور جميلة المظهر ، بدلاً من التشويش العشوائي المنقسم.
في الواقع ، كما سنرى في هذا المقال ، يمكننا التعامل مع إنشاء الموسيقى مباشرةً على أنها مشكلة إنشاء صورة. هذا يعني أنه بدلاً من استخدام الشبكات المتكررة ، يمكننا تطبيق نفس التقنيات القائمة على طبقات اللف الرياضي والتي نجحت بشكل جيد في مشاكل إنشاء الصور للموسيقى – على وجه الخصوص ، شبكات GAN.
قبل أن نستكشف هذه الهندسة المعمارية الجديدة ، هناك ما يكفي من الوقت لزيارة قاعة الحفلات الموسيقية ، حيث سيبدأ العرض …
ألة الأوغن الموسيقية
قائد الأوركسترا يدق عصاه مرتين على المنصة. العرض على وشك أن يبدأ. أمامه تجلس أوركسترا. ومع ذلك ، فإن هذه الأوركسترا ليست على وشك عزف سيمفونية بيتهوفن أو عرض تشايكوفسكي. تؤلف هذه الأوركسترا موسيقى أصلية مباشرة أثناء أدائهم.
ويتم عزفها بالكامل بواسطة مجموعة من العازفين عن طريق إعطاء تعليمات إلى ألة الأورغن الموسيقية الضخمة (Musical Organ) إو بإختصار MuseGAN الموجوده في منتصف المسرح ، و التي تحول هذه التعليمات إلى موسيقى جميلة لإمتاع الجمهور . يمكن تدريب الأوركسترا على تأليف الموسيقى بأسلوب معين ، ولا يوجد عرضان متماثلان على الإطلاق.
ال 128 عازف في الأوركسترا مقسمين إلى 4 أقسام متساوية من 32 عازف. يعطي كل قسم تعليمات إلى MuseGAN ولديه مسؤولية مميزة داخل الأوركسترا.
1- قسم الأسلوب (style) هو المسؤول عن إنتاج الذوق الموسيقي العام للأداء. من نواح كثيرة ، لديه أسهل وظيفة من بين جميع الأقسام حيث يتعين على كل عازف ببساطة إنشاء تعليمات واحدة في بداية الحفلة الموسيقية التي يتم تغذيتها باستمرار إلى MuseGAN طوال الأداء.
2- قسم الأخدود (groove) له وظيفة مماثلة ، لكن كل عازف ينتج عدة تعليمات: واحد لكل من المقطوعات الموسيقية المميزة التي ينتجها MuseGAN. على سبيل المثال ، في حفلة موسيقية واحدة ، أصدر كل عازف في قسم الأخدود خمسة تعليمات ، واحدة لكل من المسارات الصوتية والبيانو والوتر والباس والطبل. وبالتالي ، فإن وظيفتهم هي توفير الأخدود لكل صوت آلي فردي يكون ثابتًا طوال الأداء.
لا تغير أقسام النمط والأخدود تعليماتها في طوال المعزوفة. يتم توفير العنصر الديناميكي للأداء بواسطة القسمين الأخيرين ، مما يضمن أن الموسيقى تتغير باستمرار مع كل شريط يمر.
الميزان أو القياس (bar) هو وحدة صغيرة من الموسيقى تحتوي على عدد ثابت وصغير من الإيقاعات. على سبيل المثال ، إذا كان بإمكانك العد 1 ، 2 ، 1 ، 2 إلى جانب مقطوعة موسيقية ، فهناك دقاتان في كل شريط ومن المحتمل أنك تستمع إلى موسيقى المارش (March). إذا كان بإمكانك العد 1 ، 2 ، 3 ، 1 ، 2 ، 3 ، فهناك ثلاث دقات لكل شريط وقد تستمع إلى موسيقى الفالس(Waltz).
3- يغير العازفون في قسم الأوتار (chords) تعليماتهم في بداية كل ميزان . هذا له تأثير إعطاء كل شريط شخصية موسيقية مميزة ، على سبيل المثال ، من خلال تغيير الوتر. يُصدر العازفون في قسم الأوتار تعليمة واحدة فقط لكل الميزان يتم تطبيقه بعد ذلك على كل مقطوعة موسيقية.
العازفون في قسم اللحن (melody) لديهم أكثر الوظائف إرهاقًا ، لأنهم يقدمون تعليمات مختلفة لمسار كل ألة موسيقية في بداية كل ميزان طوال المعزوفة. يتمتع هؤلاء العازفين بأكبر قدر من التحكم في الموسيقى ، وبالتالي يمكن اعتبار هذا القسم الذي يوفر الاهتمام باللحن.
هذا يكمل وصف الأوركسترا. يمكننا تلخيص مسؤوليات كل قسم كما هو موضح في
الأمر متروك لـ MuseGAN لإنشاء الميزان الموسيقي التالي ، بالنظر إلى المجموعة الحالية المكونة من 128 تعليمة (واحد من كل عازف). تدريب MuseGAN على القيام بذلك ليس بالأمر السهل. في البداية ، لا تصدر الآلة سوى ضوضاء مروعة ، حيث لا توجد طريقة لفهم كيفية تفسير التعليمات لإنتاج موازين لا يمكن تمييزها عن الموسيقى الأصلية.
هنا دور قائد الأوركستر حيث يخبر MuseGAN عندما تكون الموسيقى التي ينتجها قابلة للتمييز بوضوح عن الموسيقى الحقيقية ، ثم يقوم MuseGAN بعد ذلك بتكييف أسلاكه الداخلية ليكون أكثر عرضة لخداع قائد الأوركستر في المرة القادمة. يستخدم قائد الأوركستر و MuseGAN نفس العملية تمامًا كما رأينا في المقالة الخامسة من شبكات الخصومة التوليدية ، عندما عمل وليد و مبز معًا لتحسين صور المخلوقات التي يلتقطها وليد باستمرار.
الأن سنرى كيف يمكننا بناء MuseGAN باستخدام Keras ، لمعرفة كيفية إنشاء موسيقى واقعية متعددة الألحان.
بناء MuseGAN
تم تقديم MuseGAN في بحث عام 2017 بعنوان “MuseGAN: Multi-Track Sequential Generative Adversarial Networks for Symbolic Music Generation and Accompaniment”.
يوضح المؤلفون كيف يمكن تدريب نموذج لتوليد موسيقى متعددة الألحان (polyphonic)، متعددة المسارات (multitrack) ، متعددة الموازين (multibar) من خلال إطار عمل شبكة خصومة توليدية جديدة علاوة على ذلك ، فإنهم يوضحون كيف ، من خلال تقسيم مسؤوليات نواقل الضوضاء التي تغذي المولد ، أنهم قادرون على الحفاظ على التحكم الدقيق في كل من السمات الزمنية عالية المستوى (high-level tempora) و السمات المبنية على المسارات (track-based features ) للموسيقى.
لبدء هذا المشروع ، ستحتاج أولاً إلى تنزيل ملفات MIDI التي سنستخدمها لتدريب MuseGAN. سنستخدم مجموعة بيانات من 229 ج. كورال باخ لأربعة أصوات ، متاح على Github .
تتكون مجموعة البيانات من مصفوفة مكونه من أربعة أرقام لكل خطوة زمنية: نغمات ملاحظة MIDI لكل من الأصوات الأربعة. الخطوة الزمنية في مجموعة البيانات هذه تساوي النغمة السادسة عشرة (نصف التوقف (semiquaver)).
لذلك ، على سبيل المثال ، في ميزان واحد من 4 دقات أرباع (سوداء (crotchet) ) ، سيكون هناك 16 خطوة زمنية. أيضًا ، يتم تقسيم مجموعة البيانات تلقائيًا إلى مجموعات تدريب وتحقق واختبار. سنستخدم مجموعة بيانات القطار لتدريب MuseGAN.
نحتاج أولاً إلى الحصول على البيانات بالشكل الصحيح لتغذية GAN. في هذا المثال ، سننشئ ميزانين من الموسيقى ، لذلك سنستخرج أول ميزانين فقط من كل كورال. توضح الصورة التالية كيفية تحويل ميزانين من البيانات الأولية إلى مجموعة البيانات المحولة التي ستغذي GAN بالتدوين الموسيقي المقابل.
يتكون كل ميزان من 16 خطوة زمنية وهناك 84 نغمة محتملة عبر المسارات الأربعة. لذلك ، الشكل المناسب للبيانات المحولة هو:
[batch_size, n_bars, n_steps_per_bar, n_pitches, n_tracks]بحيث
n_bars = 2
n_steps_per_bar = 16
n_pitches = 84
n_tracks = 4
للحصول على البيانات في هذا الشكل ، نقوم بإستخدام خط الترميز الأحادي (one-hot encode) لتشفير درجات النغمة (pitch) إلى متجه بطول 84 ونقسم كل سلسلة من النوتات إلى مجموعتين من 16 ، لتكرار الميزانين.
الآن بعد أن قمنا بتحويل مجموعة البيانات الخاصة بنا ، دعنا نلقي نظرة على الهيكل العام لـ MuseGAN ، بدءًا من المولد.
مولد MuseGAN
مثل جميع شبكات GAN ، يتكون MuseGAN من مولد (generator) وناقد (critic). يحاول المولد خداع الناقد بإبداعاته الموسيقية ، ويحاول الناقد منع حدوث ذلك من خلال التأكد من قدرته على التمييز بين كورال باخ المزورة و الحقيقي.
ما يجعل MuseGAN مختلف هو حقيقة أن المولد لا يقبل فقط متجه ضوضاء واحده كمدخل ، ولكنه يحتوي بدلاً من ذلك على أربعة مدخلات منفصلة ، والتي تتوافق مع الأقسام الأربعة للأوركسترا في القصة – الأوتار ، والأسلوب ، واللحن ، و أخدود. من خلال معالجة كل من هذه المدخلات بشكل مستقل يمكننا تغيير الخصائص عالية المستوى للموسيقى المولدة.
يوضح الرسم التخطيطي كيف يتم تمرير مدخلات الأوتار واللحن أولاً عبر شبكة زمنية (temporal network) تنتج تنسور بأحد الأبعاد التي تساوي عدد الأشرطة المراد إنشاؤها. لا يتم شد مدخلات النمط والأخدود زمنياً بهذه الطريقة ، حيث تظل ثابتة خلال المعزوفة.
ثم ، لإنشاء ميزان معين لمسار معين ، يتم ربط المتجهات ذات الصلة من الأوتار والأسلوب واللحن وأجزاء الأخدود في الشبكة لتشكيل متجه أطول. ثم يتم تمرير هذا إلى مولد ميزان (bar generator)، والذي ينتج في النهاية الميزان المحدد للمسار المحدد.
من خلال ربط الموازين التي تم إنشاؤها لجميع المسارات ، نقوم بإنشاء معزوفة يمكن مقارنتها بالنتائج الحقيقية بواسطة الناقد.
يتم إعطاء معايير النموذج كما هو موضح أدناه
BATCH_SIZE = 64 n_bars = 2 n_steps_per_bar = 16 n_pitches = 84 n_tracks = 4 z_dim = 32 gan = MuseGAN(input_dim = data_binary.shape[1:] , critic_learning_rate = 0.001 , generator_learning_rate = 0.001 , optimiser = 'adam' , grad_weight = 10 , z_dim = 32 , batch_size = 64 , n_tracks = 4 , n_bars = 2 , n_steps_per_bar = 16 , n_pitches = 84 )
الأوتار والأسلوب واللحن والأخدود
دعنا الآن نلقي نظرة فاحصة على المدخلات الأربعة المختلفة التي تغذي المولد.
الأوتار
مدخل الأوتارهو متجه بطول 32 (z_dim). نحتاج إلى إخراج متجة مختلف لكل ميزان ، حيث تتمثل وظيفته في التحكم في الطبيعة الديناميكية العامة للموسيقى بمرور الوقت.
لاحظ أنه على الرغم من أن هذا يسمى chords_input ، إلا أنه يمكنه التحكم في أي شيء متعلق بالموسيقى يتغير لكل مبزان ، مثل النمط الإيقاعي العام ، دون أن يكون محددًا لأي مسار معين.
الطريقة التي يتم بها تحقيق ذلك هي من خلال شبكة عصبية تتكون من طبقات اللف الرياضية التناقليه (convolutional transpose) نسميها الشبكة الزمنية. لبنائها في keras
def conv_t(self, x, f, k, s, a, p, bn): x = Conv2DTranspose( filters = f , kernel_size = k , padding = p , strides = s , kernel_initializer = self.weight_init )(x) if bn: x = BatchNormalization(momentum = 0.9)(x) if a == 'relu': x = Activation(a)(x) elif a == 'lrelu': x = LeakyReLU()(x) return x def TemporalNetwork(self): input_layer = Input(shape=(self.z_dim,), name='temporal_input') #1 x = Reshape([1,1,self.z_dim])(input_layer) #2 x = self.conv_t(x, f=1024, k=(2,1), s=(1,1), a= 'relu', p = 'valid', bn = True) x = self.conv_t(x, f=self.z_dim, k=(self.n_bars - 1,1) , s=(1,1), a= 'relu', p = 'valid', bn = True) #3 output_layer = Reshape([self.n_bars, self.z_dim])(x) #4 return Model(input_layer, output_layer)
1- المدخل إلى الشبكة الزمنية هو متجه بطول 32 (z_dim).
2- نعيد تشكيل هذا المتجه إلى تنسور 1 × 1 مع 32 قناة ، حتى نتمكن من تطبيق عمليات ا اللف الرياضية التناقليه عليه.
3- نطبق طبقات Conv2DTranspose لتوسيع حجم التنسور على طول محور واحد ، بحيث يكون بنفس طول n_bars.
4- نقوم بإزالة البعد الإضافي غير الضروري بطبقة Reshape.
السبب في استخدامنا للعمليات التلافيفية بدلاً من طلب متجهي وتر مستقلين في الشبكة هو أننا نود أن تتعلم الشبكة كيف يجب أن يتبع ميزان واحد لأخر بطريقة متناسقة. إن استخدام شبكة عصبية لتوسيع متجه الإدخال على طول محور الوقت يعني أن النموذج لديه فرصة لمعرفة كيفية تدفق الموسيقى عبر الموازين ، بدلاً من التعامل مع كل ميزان على أنه مستقل تمامًا عن الأخير.
الأسلوب
إدخال الأسلوب هو أيضًا متجه بطول z_dim. يتم نقلها عبر مولد الميزان دون أي تغيير ، لأنه مستقل عن الميزان والمسار. بمعنى آخر ، يجب أن يستخدم مولد الميزان هذه المتجه لإنشاء التناسق بين الموازين والمسارات.
اللحن
إدخال اللحن عبارة عن مصفوفة ذات شكل [n_tracks، z_dim] – أي أننا نوفر للنموذج متجه ضوضاء عشوائي بطول z_dim لكل مسار.
يتم تمرير كل من هذه المتجهات من خلال نسختها الخاصة من الشبكة الزمنية المحددة مسبقًا. لاحظ أن أوزان هذه النسخ غير مشتركة. وبالتالي ، يكون الناتج متجهًا بطول z_dim لكل مسار من كل ميوات. بهذه الطريقة ، سيكون مولد الميزان قادرًا على استخدام هذا المتجه لضبط محتوى كل ميزان وتتبعه بشكل مستقل.
الأخدود
مدخل الأخدود هو أيضًا مصفوفة ذات الشكل [n_tracks، z_dim] – متجه ضوضاء عشوائي بطول z_dim لكل مسار. على عكس مدخل اللحن ، لا يتم تمريرها عبر الشبكة الزمنية ولكن بدلاً من ذلك يتم تغذيتها مباشرة من خلال مولد الميزان دون تغيير ، تمامًا مثل متجه النمط. ومع ذلك ، على عكس متجه النمط ، يوجد مدخل أخدود مميز لكل مسار ، مما يعني أنه يمكننا استخدام هذه المتجهات لضبط الناتج الإجمالي لكل مسار بشكل مستقل.
مولد الميزان
يقوم مولد الميزان بتحويل متجه بطول 4 * z_dim إلى ميزان واحد لمسار واحد – أي ، تنسور حجمه [1 ، n_steps_per_bar ، n_pitches ، 1]. يتم إنشاء متجه الإدخال من خلال ربط متجهات الوتر والأسلوب واللحن والأخدود كل منها بطول z_dim.
مولد الميزان عبارة عن شبكة عصبية تستخدم طبقات اللف الرياضية التناقليه لتوسيع أبعاد الوقت و درجة النغمة. سننشئ مولد الميزان واحد لكل مسار ، ولن يتم مشاركة الأوزان. طريقة بناء في keras كالأتي :
def BarGenerator(self): input_layer = Input(shape=(self.z_dim * 4,), name='bar_generator_input') #1 x = Dense(1024)(input_layer) x = BatchNormalization(momentum = 0.9)(x) x = Activation('relu')(x) x = Reshape([2,1,512])(x) #2 x = self.conv_t(x, f=512, k=(2,1), s=(2,1), a= 'relu', p = 'same', bn = True) #3 x = self.conv_t(x, f=256, k=(2,1), s=(2,1), a= 'relu', p = 'same', bn = True) x = self.conv_t(x, f=256, k=(2,1), s=(2,1), a= 'relu', p = 'same', bn = True) x = self.conv_t(x, f=256, k=(1,7), s=(1,7), a= 'relu', p = 'same',bn = True) #4 x = self.conv_t(x, f=1, k=(1,12), s=(1,12), a= 'tanh', p = 'same', bn = False) #5 output_layer = Reshape([1, self.n_steps_per_bar , self.n_pitches ,1])(x) #6 return Model(input_layer, output_layer)
1- مدخل مولد الشريط هو متجه بطول 4 * z_dim.
2- بعد المرور عبر طبقة كثيفة ، نعيد تشكيل التنسور لتجهيزه لعمليات اللف الرياضية التناقليه.
3- أولاً نقوم بتوسيع النمسور على طول محور الوقت …
4- … ثم على طول محور درجة النغمة.
5- تم تطبيق تنشيط tanh على الطبقة النهائية ، حيث سنستخدم WGAN-GP (الذي يتطلب tanh كمخرج التنشيط) لتدريب الشبكة.
6- تمت إعادة تشكيل التنسور لإضافة بعدين إضافيين بالحجم 1 ، لإعداده للربط مع الموازين والمسارات الأخرى.
و ضع كل شيء معا
في نهاية المطاف ، يمتلك MuseGAN مولدًا واحدًا يشتمل على جميع الشبكات الزمنية ومولدات الموازين . تأخذ هذه الشبكة لتنسورات المدخلات الأربعة وتحولها إلى نقاط متعددة المسارات متعددة المعزوفات . ننشى المولد في كيراس كالأتي :
chords_input = Input(shape=(self.z_dim,), name='chords_input') #1 style_input = Input(shape=(self.z_dim,), name='style_input') melody_input = Input(shape=(self.n_tracks, self.z_dim), name='melody_input') groove_input = Input(shape=(self.n_tracks, self.z_dim), name='groove_input') # CHORDS -> TEMPORAL NETWORK #2 self.chords_tempNetwork = self.TemporalNetwork() self.chords_tempNetwork.name = 'temporal_network' chords_over_time = self.chords_tempNetwork(chords_input) # [n_bars, z_dim] # MELODY -> TEMPORAL NETWORK #3 melody_over_time = [None] * self.n_tracks # list of n_tracks [n_bars, z_dim] tensors self.melody_tempNetwork = [None] * self.n_tracks for track in range(self.n_tracks): self.melody_tempNetwork[track] = self.TemporalNetwork() melody_track = Lambda(lambda x: x[:,track,:])(melody_input) melody_over_time[track] = self.melody_tempNetwork[track](melody_track) # CREATE BAR GENERATOR FOR EACH TRACK #4 self.barGen = [None] * self.n_tracks for track in range(self.n_tracks): self.barGen[track] = self.BarGenerator() # CREATE OUTPUT FOR EVERY TRACK AND BAR #5 bars_output = [None] * self.n_bars for bar in range(self.n_bars): track_output = [None] * self.n_tracks c = Lambda(lambda x: x[:,bar,:] , name = 'chords_input_bar_' + str(bar))(chords_over_time) s = style_input for track in range(self.n_tracks): m = Lambda(lambda x: x[:,bar,:])(melody_over_time[track]) g = Lambda(lambda x: x[:,track,:])(groove_input) z_input = Concatenate(axis = 1 , name = 'total_input_bar_{}_track_{}'.format(bar, track) )([c,s,m,g]) track_output[track] = self.barGen[track](z_input) bars_output[bar] = Concatenate(axis = -1)(track_output) generator_output = Concatenate(axis = 1, name = 'concat_bars')(bars_output) #6 self.generator = Model([chords_input, style_input, melody_input, groove_input] , generator_output) #7
1-يتم تحديد مدخلات المولد.
2- قم بتمرير إدخال الأوتار عبر الشبكة الزمنية.
3- مرر إدخال اللحن عبر الشبكة الزمنية.
4-قم بإنشاء شبكة مولد الميزان المستقل لكل مسار.
5-قم بالالتفاف على المسارات و الموازين، لإنشاء ميزان تم إنشاؤه لكل مجموعة.
6-اربط كل شيء معًا لتكوين موتر إخراج واحد.
7-يأخذ نموذج MuseGAN أربعة تنسورات ضوضاء مميزة كمدخلات يخرج توليد لمعزوفة متعددة المسارات متعددة الموازين.
الناقد
بالمقارنة مع المولد ، فإن معمارية الناقد أكثر وضوحًا (كما هو الحال غالبًا مع شبكات GAN).
يحاول الناقد التمييز بين المعزوفات للمسارات المتعددة و الموازين متعدد الكاملة التي أنشأها المولد من القطع الحقيقية من كورالي باخ. و الناقد عبارة إنها شبكة لف رياضية عصبية (تلافيفية) ، تتكون في الغالب من طبقات Conv3D التي تحول المعزوفة إلى توقع مخرج واحد.
حتى الآن ، تعاملنا فقط مع طبقات Conv2D ، تنطبق على صور الإدخال ثلاثية الأبعاد (العرض ، الارتفاع ، القنوات). هنا يتعين علينا استخدام طبقات Conv3D ، التي تشبه طبقات Conv2D ولكنها تقبل تنسور إدخال رباعي الأبعاد (n_bars ، n_steps_per_bar ، n_pitches ، n_tracks).
أيضًا ، لا نستخدم طبقات تسوية الحزم في الناقد لأننا سنستخدم إطار عمل WGAN-GP لتدريب GAN ، مما يمنع ذلك.
def conv(self, x, f, k, s, a, p): x = Conv3D( filters = f , kernel_size = k , padding = p , strides = s , kernel_initializer = self.weight_init )(x) if a =='relu': x = Activation(a)(x) elif a== 'lrelu': x = LeakyReLU()(x) return x critic_input = Input(shape=self.input_dim, name='critic_input') #1 x = critic_input x = self.conv(x, f=128, k = (2,1,1), s = (1,1,1), a = 'lrelu', p = 'valid') #2 x = self.conv(x, f=128, k = (self.n_bars - 1,1,1) , s = (1,1,1), a = 'lrelu', p = 'valid') x = self.conv(x, f=128, k = (1,1,12), s = (1,1,12), a = 'lrelu', p = 'same') #3 x = self.conv(x, f=128, k = (1,1,7), s = (1,1,7), a = 'lrelu', p = 'same') x = self.conv(x, f=128, k = (1,2,1), s = (1,2,1), a = 'lrelu', p = 'same') #4 x = self.conv(x, f=128, k = (1,2,1), s = (1,2,1), a = 'lrelu', p = 'same') x = self.conv(x, f=256, k = (1,4,1), s = (1,2,1), a = 'lrelu', p = 'same') x = self.conv(x, f=512, k = (1,3,1), s = (1,2,1), a = 'lrelu', p = 'same') x = Flatten()(x) x = Dense(1024, kernel_initializer = self.weight_init)(x) x = LeakyReLU()(x) critic_output = Dense(1, activation=None , kernel_initializer = self.weight_init)(x) #5 self.critic = Model(critic_input, critic_output)
1- المدخل إلى الناقد عبارة عن مصفوفة من معزوفة متعددة المسارات ، متعددة الموازين ، حجمها [n_bars، n_steps_per_bar، n_pitches، n_tracks].
2- أولاً ، نقوم بطي التنسور على طول محور الميزان . نطبق طبقات Conv3D لكل الناقد لأننا نعمل مع تنسور4D.
3- بعد ذلك ، نقوم بطي الموتر على طول محور درجة النغمة.
4- أخيرًا ، نقوم بطي الموتر على طول محور الخطوات الزمنية.
5-الإخراج عبارة عن طبقة كثيفة مع وحدة واحدة ولا توجد دالة تنشيط ، كما هو مطلوب بواسطة إطار عمل WGAN-GP.
تحليل MuseGAN
يمكننا إجراء بعض التجارب مع MuseGAN الخاص بنا عن طريق إنشاء معزوفة ، ثم تعديل بعض معايير ضوضاء الإدخال لمعرفة التأثير على المخرجات.
الناتج من المولد عبارة عن مجموعة من القيم في النطاق [–1 ، 1] (بسبب دالة تنشيط tanh للطبقة النهائية). لتحويل هذا إلى نوته واحدة لكل مسار ، نختار النوته ذات القيمة القصوى على جميع النغمات الـ 84 لكل خطوة زمنية
. في ورقة MuseGAN الأصلية ، يستخدم المؤلفون عتبة 0 ، حيث يمكن أن يحتوي كل مسار على ملاحظات متعددة ؛ ومع ذلك ، في هذا الإعداد ، يمكننا ببساطة أخذ الحد الأقصى ، لضمان نوته واحدة بالضبط لكل خطوة زمنية لكل مسار ، كما هو الحال بالنسبة لكورال باخ.
توضح الصورة التالية النتيجة التي تم إنشاؤها بواسطة النموذج من متجهات الضوضاء العشوائية الموزعة بشكل طبيعي (أعلى اليسار). يمكننا العثور على أقرب معزوفة في مجموعة البيانات (عن طريق المسافة الإقليدية) والتحقق من أن النتيجة التي تم إنشاؤها ليست نسخة من مقطوعة موسيقية موجودة بالفعل في مجموعة البيانات – تظهر أقرب نتيجة أسفلها مباشرة ، ويمكننا أن نرى أنها لا تشبه معزوفتنا التي تم إنشاؤها.
لنقم الآن بتغيير ضوضاء الإدخال لتعديل النتيجة التي تم إنشاؤها. أولاً ، يمكننا محاولة تغيير متجه التشويش – تُظهر النتيجة في أسفل اليمين في الصورة السابقة .
يمكننا أن نرى أن كل مسار قد تغير ، كما هو متوقع ، وأن الميزانين يظهران خصائص مختلفة. في الميزان الثاني ، يكون الخط الأساسي أكثر ديناميكية ويكون الخط العلوي أعلى في درجة النغمة منه في الميزان الأول.
عندما نغير متجه الأسلوب (أعلى اليسار) ، يتغير كلا الميزانين بطريقة مماثلة. لا يوجد فرق كبير في الأسلوب بين الميزانين ، لكن المقطع بأكمله قد تغير عن المعزوفة الأصلية التي تم إنشاؤها.
يمكننا أيضًا تغيير المسارات بشكل فردي ، من خلال مدخلات اللحن والأخدود.يمكننا أن نرى تأثير تغيير مدخل ضجيج اللحن فقط للخط العلوي للموسيقى. تظل جميع الأجزاء الأخرى غير متأثرة ، ولكن تتغير نوتات السطر العلوي بشكل كبير. أيضًا ، يمكننا أن نرى تغييرًا إيقاعيًا بين الميزان في السطر العلوي: الميزان الثاني أكثر ديناميكية ، ويحتوي على نغمات أسرع من الميزان الأول.
أخيرًا ، تُظهر المعزوفة السفلية اليسرى في الرسم البياني الدرجة المتوقعة عندما نغير معييار إدخال الأخدود للخط الأساسي فقط. مرة أخرى ، تظل جميع الأجزاء الأخرى غير متأثرة ، لكن الخط الأساسي مختلف. علاوة على ذلك ، يظل النمط العام لخط الأساس مشابهًا بين الأعمدة ، كما نتوقع.
يوضح هذا كيف يمكن استخدام كل معييار من معايير الإدخال للتأثير بشكل مباشر على السمات عالية المستوى للتسلسل الموسيقي الذي تم إنشاؤه ، بنفس الطريقة التي تمكنا بها من ضبط المتجاهات الكامنة لـ VAEs و GANs في المقالات السابقة لتغيير مظهر صورة تم إنشاؤها.
عيب واحد للنموذج هو أنه يجب تحديد عدد الموازين المراد إنشاؤها مقدمًا. لمعالجة هذا ، أظهر المؤلفون امتدادًا للنموذج يسمح بتغذية الموازين السابقة كمدخلات ، وبالتالي السماح للنموذج بتوليد معزوفات طويلة من خلال التغذية المستمرة لأحدث الموازين المتوقعة في النموذج كمدخل إضافي.
ختاماً
في هذا المقال ، لقد رأينا أن إنشاء بيانات متسلسلة لا يتطلب دائمًا نموذجًا متكررًا – يستخدم MuseGAN شبكات اللف الرياضي لتوليد معزوفات موسيقية متعددة الألحان بمسارات متعددة ، من خلال التعامل مع المعزوفة كنوع من الصور حيث تكون المسارات قنوات فردية للصورة. تكمن حداثة MuseGAN في الطريقة التي يتم بها تنظيم متجهات ضوضاء المدخلات الأربعة (الأوتار ، والأسلوب ، واللحن ، والأخدود) بحيث يمكن الحفاظ على التحكم الكامل في السمات عالية المستوى للموسيقى.
رابط الدفتر على غيتهاب
إضافة تعليق