مقدمه : برای پروژه ی احراز هویت کاربر توسط کارت ملی هوشمند , تعدادی داده (تصویر کارت ملی) جمع آوری شد که پردازش برخی از این داده ها بخاطر زاویه و مقیاسی که داشتند امکان پذیر نبود به این خاطر تصاویر به صورت دستی توسط برنامه ی Camscanner تراز و سپس برش داده شدند.برنامه ی تراز کردن کارت ملی برای انجام خودکار این فرایند نوشته شده است.
…دسته: دستهبندی نشده
چکیده:
در این پروژه، دو هدف دنبال شدهاست. یکی تشخیص تکبهتک نتهای موسیقی (نام نت و ارزش زمانی نت) از روی یکnote sheet(Note Reader)، و دیگری تشخیص سبک موسیقی(music genre recognition) از روی فایل صوتی (پاپ، راک،…) . و در هر بخش شبکههای متفاوتی آموزش دادهشده است.که یک به یک هر دو هدف توضیح داده خواهد شد.
مقدمه
نوشتن مجدد نوشته های موجود در یک تصویر عملی زمان بر است اما در بسیاری از مواقع این کار لازم است. از این رو بازشناسی دست نوشته یکی از موضوعات پرطرفدار در حوزه تشخیص الگو است. این کار در زبان انگلیسی با استفاده از قطعه بندی پیشرفت کرده است اما با توجه به این که کاراکترهای فارسی به یکدیگر متصل می شوند و هم چنین با توجه به پیچیدگی های دست خط فارسی استفاده از این روش در زبان فارسی توصیه نمی شود. در این پروژه تلاش شده است تا با بررسی رویکردهای مختلف برای انجام این کار بهترین رویکرد مشخص شود.
چکیده
تشخیص خودکار احساس از روی گفتار مساله بسیار مهم، در عرصه تعامل انسان و ماشین است.
قابلیت تشخیص احساس توسط کامپیوتر با دقتی همانند انسان، به منظور ایجاد رابطه طبیعی و دوستانه
بین انسان و کامپیوتر، بسیار حائز اهمیت است. با وجود پیشرفت های گسترده در حوزه ی پردازش گفتار، استخراج و درک احساس پنهان در گفتار انسان، همچون خشم، شادی و جز این از یک ها، سو و تولید گفتار احساسی مناسب از سوی دیگر، یکی از چالش های مهم برای ساخت ماشین های هوشمند محسوب می شود.
اعضای گروه : محسن مدنی – یاسین اسفندیاری – سهیل اشعاری
چکیده
ما در این پروژه قصد داریم صوتی را از شخصی به عنوان ورودی بگیریم و با اعمال تغییرات توسط شبکه ی آموزش داده شده، صوت خروجی را به نحوی بسازیم که حاوی همان بیانات نفر اول به گونه ای که استایل صحبت نفر دوم در آن حفظ شده است، باشد. …
اعضای گروه : عاطفه ولی پور – المیرا قربانی
مقدمه
برای اکثر افراد پیش آمده است که خواستار ترجمه ی یک متن باشند یا معنی یک کلمه را بخواهند . ساده ترین راه برای آن ها استفاده از گوگل ترنسلیت می باشد. اما تا چه اندازه میتوانیم مطمئن باشیم که گوگل ترنسلیت ، ترجمه ی صحیحی به ما ارائه میکند؟ گوگل ترنسلیت یک ماشین هوشمند است که برای ترجمه ی کلمات عمومی در زبان ها ی مختلف دنیا مورد استفاده قرار میگیرد. …
PixToPix
در این بخش قصد داریم مدلی را پیاده سازی کنیم که با دادن یک تصویر به شبکه ، تصویری مشابه الگوهای زیر از شبکه بگیریم . برای مثال بتوانیم عکسی در فضای آفتابی از یک منظره به شبکه بدهیم و تصویر همان منظره را در فضای ابری بخواهیم ، و یا اینکه عکس سیاه سفید از یک شی را به شبکه داده و عکس رنگی آن را از شبکه بگیریم ، و مثال هایی از این قبیل …
در شکل زیر میتوانید نمونه هایی از این دسته را مشاهده نمایید :
همانطور که در تصویر بالا مشاهده میکنید میتوانیم با داشتن لبه های یک کیف به تصویر اصلی کیف ، با داشتن منظره ای در هوای افتابی به آن منظره در هوای ابری و با داشتن segment های یک ساختمان به تصویری مشابه از یک ساختمان واقعی و با داشتن عکس سیاه سفید به عکس رنگی تصویرمان برسیم .
در اینجا می توانید نمونه های از این عملیات را به طور آنلاین مشاهده نمایید .
شبکه GAN
همانطور که می دانید در ساختار یک شبکه ی GAN دو واحد اصلی Genarator و Discriminator داریم ، که در واقع کار اصلی واحد Generator تولید عکس های جعلی و به مرور یادگیری تولید عکس های واقعی تر و شبیه تر به نمونه ی عکس های اصلی ، و وظیفه ی واحد Discriminator یادگیری فرایند تشخیص عکس جعلی از عکس واقعی می باشد .
به مرور هر دو شبکه ی Generator و Discriminator به ترتیب یاد میگیرند عکس های واقعی تر تولید و عکس های تقلبی را تشخیص دهند ( واحد Generator سعی در فریب دادن واحد Descriminator دارد ) . پس بدین ترتیب ( همانظور که در بخش های قبلی دیدیم ) generator یک نویز را به عنوان ورودی میگیرد و تصویری تولید میکند و Discriminator عکس تولیدی واحد Generator را گرفته و سعی در تشخیص جعلی بودن یا نبودن آن دارد .
Conditional GAN :
conditional generative adverserial nets ها در واقع شبکه ها ی GAN ای هستند که می توان با اضافه کردن یک ترم به Generator و Discriminator از شبکه بخواهیم آن چه مورد نظر ماست را تولید کند . برای مثال میتوانیم نویزی که قرار است به جنریتور بدهیم با یک one hot که عدد 3 را نشان می دهد concat کرده و به generator بدهیم تا برای مثال شبکه ای که دیتا ی Mnist را آموزش دیده بتواند عدد 3 را تولید کند یا برای مثال به طور پیشرفته تر از شبکه بخواهیم یک انسان که تصویرش را دریافت می کند ، بتواند پیرتر کند .
بدین ترتیب اگر فرایند Train را بدین گونه تغییر دهیم ( یک ترم اضافه به Discriminator و Generator بدهیم ) میتوانیم آنچه گفته شد را پیاده سازی کنیم .
شبکه ی Generator :
در این بخش از یک auto encoder برای پیاده سازی این شبکه استفاده میکنیم.
همانطور که میدانید auto encoder دارای یک سری لایه ی convlution در لایه های اول ( کوچک کردن طول و عرض و بزرگ کردن عمق ) تا رسیدن به یک bottle neck ، و یک سری لایه ی TransposeConvolution ( بزرگ کردن طول و عرض و کوچک کردن عمق ) تا رسیدن به سایز اولیه می باشد ، بدین صورت عکس ورودی را تا یک جایی کوچک کرده و سپس به ابعاد اولیه می رساند .
در شکل زیر نمونه ی این شبکه را مشاهده می نمایید :
همانطو که در تصویر بالا مشاهده می کنید ، ورودی شبکه ی Generator یک عکس سیاه سفید بوده که این شبکه سعی در تولید عکس رنگی ( در مشابه ترین حالت ممکن به عکس رنگی اصلی در دیتاست) دارد .
ایده ای که در قسمت مطرح شد استفاده از skip connection های مشابه در شبکه ی Resnet بود ، به عبارتی از لایه ی n ام encoding به لایه n ام decoding یک skip connection با این هدف که ممکن است نیازی به طی کردن همه ی لایه های کانولوشن و به طبع تمام لایه های دی کانولوشن ( Transpose Convolution ) نباشد ، و با طی کردن تعداد کمتری از این لایه ها به هدف مربوطه برسیم ، بدین منظور ایده ای مطابق شکل زیر بیان گردید که به آن اصطلاحا U–Net می گویند.
شبکه ی Discriminator :
این شبکه که وظیفه ی تشخیص دیتای واقعی ( دیتای موجود در دیتاست ) از دیتای غیر اصلی و جعلی ( تصویر تولید شده ی Generator ) را دارد ، ساختاری کانولوشنی مطابق شکل زیر داراست .
همانطور که مشاهده می کنید ورودی این واحد ، ورودی شبکه ( مثلا عکس سیاه سفید ) به علاوه عکس Unknown ( دلیل Unknown نامیدن این تصویر این است که نمیدانیم این عکس توسظ Generator تولید شده و یا تصویر اصلی رنگی ) می باشد .
پس بدین ترتیب شبکه ی Discriminator سعی دارد با دریافت یک عکس سیاه سفید و یک عکس رنگی ( تولید شده ی Generator و یا عکس رنگی اصلی ) عکس های جعلی را از اصلی تشخیص دهد .
از آنجایی که این شبکه در خروجی یک تابع Sigmoid دارد و مقادیر بین 0 تا 1 برمیگرداند ، در واقع قضاوت سخت گیرانه ای دارد یعنی حتی اگر تنها یک پیکسل تفاوت مشاهده کند خروجی را نزدیک به 0 نشان می دهد ،از این رو میتوانیم در خروجی به جای داشتن یک سیگموید از یک ماتریس 30 در 30 در 1 استفاده کنیم ، که هر عدد در این ماتریس میتواند بین اعداد 0 و 1 باشد ( یعنی در واقع به جای یک سیگموید 30 در 30 عدد سیگموید داریم ) که هرعدد نزدیک به 1 و یا نزدیک به 0 در این ماتریس به ترتیب بیانگر مساوی بودن یا نبودن 70 پیکسل در تصویر مورد مقایسه است . به عبارت ساده تر اگر اولین عدد این ماتریس ( خانه ی سطر 1 و ستون 1 ) 0.9 باشد ، بیانگر یکسان بودن 70 پیکسل اول تصویر است. ( از آنجایی که 70 * 30 یعنی 2100 عددی بزرگتر از 256 که سایز تصویر ماست ، می باشد ، overlap نیز وجود خواهد داشت)
تعریف خطای شبکه ی Discriminator :
از آنجایی که این شبکه وظیفه دارد عکس تولید شده ی Generator بگیرد و واقعی یا جعلی بودن آن را تشخیص دهد ، پس این مدل باید در راستای تشخیصِ درست دیتای اصلی از دیتای تولید شده ی Generator آموزش ببیند . پس بدین ترتیب 2 خطا برای این شبکه قابل تعریف و اعمال برای به روز رسانی وزن های آن می باشد :
1) خطای ناشی از تشخیص نادرست دیتای اصلی به عنوان دیتای جعلی .
2) خطای ناشی از تشخیص نادرست دیتای جعلی ( تولید شده ی Generator ) به عنوان دیتای اصلی .
اعمال این دو خطا را در شکل زیر میتوانید مشاهده نمایید .
تعریف خطای شبکه ی Generator
1) خطای ناشی از شکست در فریب دادن Discriminator :
با توجه به آنچه که گفته شد شبکه ی Generator باید بتواند عکس هایی تولید کند که شبکه ی Discriminator را فریب دهد ، به ظوری که شبکه ی Discriminator با گرفتن عکسی که Generator تولید می کند ، لیبل True به معنای اصلی بودن عکس برگرداند ، پس برگرداندن هر چیزی جز 1 برای Generator ، یک خطا محسوب می شود (چون در فریب دادن Discriminator موفق نبوده ) و قابل انتشار در شبکه ی Generator برای به روز رسانی وزن های آن است .
2) خطای ناشی از تفاوت عکس تولید شده با عکس واقعی :
علاوه بر این شبکه ی Generator باید بتواند تا حد امکان عکس های نزدیک به عکس واقعی تولید کند و فقط فریب دادن Discriminator نتیجه ی مطلوب نیست ، پس بدین ترتیب تفاوت عکسی که تولید می کند با عکس واقعی نیز خطایی قابل انتشار برای آموزش و بهتر شدن شبکه ی Generator می باشد .
در شکل زیر فرایند اعمال دو خطای تعریف شده مشاهده میگردد :
به نام خدا
کلاس نوت – محمد حسین نیکی ملکی
مقدمه ای بر cyclegan & pix2pix
ساختار شبکه ای pix2pix از ساختار شبکه های شرطی GAN برای ساخت دیتا ها و تبدیل و generate کردن آن هااستفاده میکند .
فرض کنید تصاویری ورودی شبکه ما باینری شده و انتظار خروجی شبکه امان هم از همان جنس دیتا رنگی rgb باشد .طبیعتا انتظار داریم که generator در اینجا یاد بگیرد که چطور رمگ امیزی کند .و همچنین discriminator هم تلاش میکند تا تفاوت بین رنگی که generator تولید کرده و رنگ اصلی به نظر صحیح که در بین دیتاست ها بوده را محاسبه کند .
ساختار generator بصورت “encoder-decoder” است و pix2pix هم تقریبا مانند همین (در شکل پایین هم میبینید ) است .
مقادیر دایمنشن های هر لایه در کنار آن نوشته شده است .در اینجا ورودی شبکه ما یک 256*256*3 است و پس از اعمال تغییرات دوباره به همان شیپ ابتدایی در خروجی باز میگردد .
در اینجا generator ورودی هارا میگیرد وبا انکودر ها مقادیرش را کم میکند ( لازم به یاداوری است که انکودر محصولی از کانولوشن و اکتیویشن فانکشن مربوطه است .) همچنین در ادامه ی مسیر هم از دیکودر برای بازگشت ز مسیر استفاده میکنیم .
نکته : برای بهبود \رفورمنس شبکه و سرعت پردازش میتونیم از شبکه unet هم به جای encoder-decoder استفاده کنیم . شبکه unet در واقع همون encoder-decoder است اما بصورت موازی هر لایه encoder را به لایه decoder مربوطه اش متصل میکند و سودش در این است که ممکن است به برخی از لایه ها احتیاجی نداشته باشیم و از آنها ب\ریم و گذر نکنیم .
Descriminator :
کار descriminator این است که دو عکس یکی از ورودی و یکی از خروجی یا عکس هدف میگیرد و تصمیم میگیرد که ایا عکس دوم توسط generator ساخته شده است یا خیر .
ساختار DISCRIMINATOR شبیه به ENCODER-DECODER به نظر میرسد اما فرق دارد .
خروجی اش یک عکس ۳۰ در ۳۰ باینری است که مشخص میکند چقدر قسمت های مختلف عکس دوم به اول شبیه هستند . در پیاده سازی PIX2PIX هر پیکسل ۳۰ در ۳۰ به یک قسمت ۷۰ در ۷۰ عکس ورودی مپ میشود .
How to train :
برای ترین این شبکه باید هم discriminator و هم generator را اموزش بدهیم .
برای اموزس دیسکریمینیتور ابتدا جنریتور خروجی را تولید میکند و دیسکریمینیتور هر دفه خروجی هارا با ورودی ها مقایسه میکند و یاد میگیرد و میتواند حدس بزند که چقدر آنها طبیعی هستند . پس وزن های دیسکریمینیتور براسا ورودی و خروجی های شبکه ی جنریتور ما تعیین میگردد .
همینطور وزن های جنریتور هم براساس خروجی های دیسکریمینیتور اپدیت میشود هر دفعه .
cyclegans :
pipx2pix میتواند خروجی های بینظیری را تولید کند . چالش اصلی در قسمت ترین است . قسمت لیبل زدن و دو عکسی برای عملیات ترینینگ باید به ورودی شبکه بدهیم به عنوان x و y .
که ممکن است کار را برا ی ما بسیار سخت و گاها غیر ممکن کند.
به خاطر همین از سایکل گن ها استفاده میکنیم .
نکته اصلی انها این است که میتوانند بر اساس معماری pix2pix هم پیاده سازی بشوند اما به شما اجازه دهند که به دو مجموعه از تصاویر اشاره کنید و فراخوانی کنید .
در اینجا بعنوان مثال فرض کنید دو دسته عکس از ساحل دارید یکی در زمان صبح و دیگری در عصر هنگام غروب . سایکل گن میتواند یادبگیرد که چگونه عکس های مربوط به صبح را به عصر تبدیل کند و برعکس بدون آنکه نیاز باشد تا بصورت یک در یک مقابل هم قرارشان دهیم . دلیل اصلی که سایکل را تا این حد قدرتمند کرده پیاده سازی این فرضیه است که بطور کامل تبدیل رفت و برگشتی صورت میپذیرد که باعث میشود هردو جنریتور هم بطور همزمان تقویت شوند .
Loss function :
قدرت سایکل گن در این است که loss function ای برای هر سایکل رفت و برگشت ست میکند و آن را به عنوان یک optimizer اضافی در مسله قرار میدهد .
در این قسمت نحوه ی محاسبه ی loss function برای generator را میبینیم :
g_loss_G_disc = tf.reduce_mean((discY_fake — tf.ones_like(discY_fake)) ** 2)
g_loss_F_dicr = tf.reduce_mean((discX_fake — tf.ones_like(discX_fake)) ** 2)
g_loss_G_cycle = tf.reduce_mean(tf.abs(real_X — genF_back)) + tf.reduce_mean(tf.abs(real_Y — genG_back))
g_loss_F_cycle = tf.reduce_mean(tf.abs(real_X — genF_back)) + tf.reduce_mean(tf.abs(real_Y — genG_back))
در این قسمت نحوه ی محاسبه ی loss function برای discriminator را بررسی میکنیم :
DY_loss_real = tf.reduce_mean((DY — tf.ones_like(DY))** 2)
DY_loss_fake = tf.reduce_mean((DY_fake_sample — tf.zeros_like(DY_fake_sample)) ** 2)
DY_loss = (DY_loss_real + DY_loss_fake) / 2
DX_loss_real = tf.reduce_mean((DX — tf.ones_like(DX)) ** 2)
DX_loss_fake = tf.reduce_mean((DX_fake_sample — tf.zeros_like(DX_fake_sample)) ** 2)
DX_loss = (DX_loss_real + DX_loss_fake) / 2
trigger word detection چیست؟
Trigger word کلمه ای است که با گفتن آن شروع به صحبت با voice assistant می کنیم. در حقیقت voice assistant ها در حال شنیدن صدا هستند و زمانی که ما یک trigger word خاص را می گوییم فعال می شوند.
به عنوان مثال با گفتن “?Hey Siri, what’s the weather like today”، ابزار siri متعلق به شرکت apple سعی در پیدا کردن وضعیت هوای امروز را می کند. در حقیقت ما در اینجا به نحوه ی trigger شدن اینگونه assistant ها می پردازیم.
برخی از voice assistant ها و trigger word های مربوط به آن ها را در زیر می بینیم:
اطلاعات کلی درباره موسیقی:
موسیقی چیست؟ به طور خلاصه موسیقی چیزی جز یک دنباله از نت های موسیقی نیست. ورودی ما به مدل، مجموعه ای از رویدادهای موسیقی / نت ها است.
تصویر بالا نمایشی از موسیقی است که به عنوان sheet شناخته می شود. در اینجا، موسیقی توسط یک دنباله از نت های موسیقی نشان داده شده است. هر نتموسیقی با یک spaceجدا شده است.
ABC Notation
نوع دیگر نت، با استفاده از abc است.که درواقع این نوع نت گذاری شامل دو بخش است:
بخش اول:
نشان دهنده meta data است.شامل:
x: نشان دهنده تعداد بخش های مختلف از لحاظ صدا در موسیقی است
T: عنوان آهنگ
M: علامت سری زمانی نواختن(time signiture)
L: طول زمانی پیش فرض نت ها
R: ژانر موسیقی
K: سر کلید
بخش دوم:
شامل نت ها به صورت abc است.
برای مثال در کلید sol:
a=la
b=si
c=do
d=re
e=mi
f=fa
g=sol
MIDI (Musical Instrument Digital Interface)
midi درواقع خودش صدا تولید نمیکند بلکه شامل یک سری از پیام ها مانند“note on,” “note off,” “note/pitch,” “pitch-bend,… است. این پیام ها توسط ابزار midi که ممکن است سخت افزاری و یا نرم افزاری باشد تفسیر می شوند.
تصویر بالا یک موسیقی تولید شده با استفاده از Music21 که یک کتابخانه پایتون است که موسیقی فرمت MIDI تولید می کند را نشان می دهد.(درباره کتابخانه جلوتر توضیح داده شده است)
Event1: نت B را نشان میدهد.
Event2: آکورد E,A
Music generation
از آنجایی که Rnn خالی نمی تواند موسیقی قشنگی بنوازد ، ما نیاز به کلی preprocessing و postprocessing داریم.
Preprocessing: برای آنکه نت ها را دربیاورد
Postprocessing: شامل یک سری قوانین در علم موسیقی است مثل اینکه دو تا نت ممکن است پشت هم نتوانند بیایند،اما مدل rnn این دو نت را پشت هم قرار داده است.
از کتابخانه پایتونی music21 استفاده میکنیم که یک رابط ساده برای به دست آوردن نت های موسیقی فایل های MIDI را فراهم می کند. علاوه بر این، مابه اجازه می دهد که Note و Chord را ایجاد کنیم تا بتوانیم فایل های MIDI خودمان را به راحتی ایجاد کنیم. درواقع میتوان گفت یک language model است که به جای متن، نت های موسیقی را میگیرد و آن طرف هم به جای نت موسیقی تبدیل میکند به موسیقی. و درواقع یک مدل many to many است.
1 2 3 4 5 6 |
X, Y, n_values, indices_values = load_music_utils() print('shape of X:', X.shape) print('number of training examples:', X.shape[0]) print('Tx (length of sequence):', X.shape[1]) print('total # of unique values:', n_values) print('Shape of Y:', Y.shape) |
shape of x بیانگر آن است که 60 تا sample داریم و 30 تا time step و 78 تا نت موسیقیایی مختلف توانسته استخراج کند.
مقدار y درواقع برعکس مقدار x می باشد که این به این دلیل است که ضرب و تقسیم های lstm به این صورت راحت تر بوده است. حالا درواقع مقدار 30 در y بیانگر time step و 60 نمایانگر mini batch می باشد.
N_values بیانگر تعداد نت های منحصر به فرد و indices_values درواقع شامل تبدیل آن 78 نت منحصر به فرد به زبان خاص خود کتابخانه است.
77: ‘S,0.250,<dd5,d1>’
شبکه:
یک one-hot 78 تایی می دهد که این one – hot در هر time step به یک lstm می رود که این lstm درواقع یک softmax است. و یک a هم داریم که به hidden state ها وارد می شود و در هر time step مقدار خروجی a(مقدار آپدیت شده)را به lstm بعدی می دهد.
ساختن model:
در این قسمت یک مدل می سازیم و train می کنیم که درواقع pattern های موسیقی را یاد میگیرد. برای انجام این کار، نیاز به ساخت یک مدل داریم که شامل X (𝑚,𝑇𝑥,78) و Y (𝑇𝑦، 𝑚، 78) است.
از LSTM با 64 تا hidden stateاستفاده میکنیم.
1 |
n_a = 64 |
حال سه object می سازیم:
1 |
reshapor = Reshape((1, 78)) # Used in Step 2.B of djmodel(), below |
reshapor ، ابعاد را 1*78 میکند.یعنی درواقع یک بعد می خواد اضافه کند.
1 |
densor = Dense(n_values, activation='softmax') # Used in Step 2.D |
Densor، که در واقع همان activation های softmax ای است که در شکل مدل دیده میشود.
1 |
LSTM_cell = LSTM(n_a, return_state = True) # Used in Step 2.C |
چون در کراس نمی توانیم به روش many to many ، ترین(train) کنیم که بعد یک کاراکتر یک کاراکتر از آن سمپل گیری کنیم.درواقع در زمان تست چون many اش رو نداریم خودمون توی زمان بازش میکنیم و train میکنیم. بنابراین آبجکت lstm رو برای یک time step می سازیم و برای تایم استپ مثلا 30 تایی یه فور روی آن میزنیم. در واقع به این صورت که در تایم استپ اول activation یا hidden_layer لایه های قبل را برابرصفر قرار میدهیم و ورودی آن را میدهیم که activation یا hidden layer برای استپ بعد رو میدهد و ورودی بعدی یا hidden state قبلیا رو بهش میدیم و وردی یا hidden state بعدی رو میده.
1 |
x = Lambda(lambda x: X[:,t,:])(X) |
یک تابع lambda تعریف کرده که در کل lambda یک تابع بی نام است .که درواقع در این مثال یک mini batch ای است در تعداد time step در feature vector هایی که دارد است. که درواقع وقتی مثلا t برابر 7 است ،n*78 برگردانده می شود.و وقتی n*30*78 است یعنی تمام mini batch در تایم استپ 7 را برمیگرداند.
مدل:
1 |
def djmodel(Tx, n_a, n_values): |
آرگومان ها شامل:
Tx : تعداد time step های ورودی
n_a : تعداد hidden state های lstm
n_values: تعداد نت های منحصر به فرد
X را با ابعاد Tx در n_values تعریف میکنیم. برای آنکه ورودی many بسازیم.
1 |
X = Input(shape=(Tx, n_values)) |
Hidden state های LSTM را می سازیم.a0,c0
1 2 |
a0 = Input(shape=(n_a,), name='a0') c0 = Input(shape=(n_a,), name='c0') |
به اندازه time step های ورودی (Tx) فور میزنیم.
1 |
for t in range(Tx): |
lambda ای که توضیح دادیم را تعریف میکنیم در زمان t که در واقع زمان t آن زمانی هست که الان هستیم.
1 |
x = Lambda(lambda x: X[:,t,:])(X) |
x مربوط به همان time step را برداشته و reshape میکنیم کهdimention هایی برابر با mimibatch*1*78 داشته باشیم.
1 |
x = reshapor(x) |
در مرحله بعد LSTM_cell را با مقادیر x,a,c فراخوانی میکنیم.به این صورت که a و c در مرحله اول مقداری برابر با 0 دارند و در دفعه های بعد خروجی این قسمت است.
1 |
a, _, c = LSTM_cell(x, initial_state=[a, c]) |
حال مقدار a خروجی را به densor که شامل activation function است میدهیم. و خروجی آن را در outputs،append میکنیم.
1 2 |
out = densor(a) outputs.append(out) |
حال تابع model را با a0,c0,X و خروجی outputs فراخوانی میکنیم:
1 |
model = Model([X, a0, c0], outputs) |
حال مدل را با ویژگی های زیر می سازیم و train میکنیم:
1 2 3 4 5 6 7 |
model = djmodel(Tx = 30 , n_a = 64, n_values = 78) opt = Adam(lr=0.01, beta_1=0.9, beta_2=0.999, decay=0.01) model.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy']) m = 60 a0 = np.zeros((m, n_a)) c0 = np.zeros((m, n_a)) model.fit([X, a0, c0], list(Y), epochs=100) |
m برابر با تعداد time step است.
Generating music
در generation، شبکه Lstm داریم که در واقع یک hidden state به آن پاس داده و یک رندم و یا صفر هم به عنوان ورودی به آن میدهیم، که در نتیجه آن یک softmax هفتاد هشت تایی داریم که index ماکسیمم را برداشته و یک one-hot هفتاد و هشت تایی دیگر درست کرده و آن را به عنوان ورودی به lstm بعدی می دهیم. مانند language model
در هر مرحله از sampeling، به عنوان ورودی activation a و cell state c را از LSTM حالت قبلی ، به صورت مرحله به مرحله ارسال می شود و یک activation خروجی جدید و همچنین cell state جدید دریافت می شود.
1 |
def music_inference_model(LSTM_cell, densor, n_values = 78, n_a = 64, Ty = 100): |
LSTM_cell,densor,n_values,n_a را که قبلا تعریف کردیم که هرکدام چه هستند اما Ty بیانگر time step موزیک خروجی می باشد.
1 2 3 |
x0 = Input(shape=(1, n_values)) a0 = Input(shape=(n_a,), name='a0') c0 = Input(shape=(n_a,), name='c0') |
x0,a0,c0 را مانند قبل تعریف میکنیم و مقدار اولیه آنها را میتوان یا صفر گذاشت یا چند تا نت به عنوان ورودی به ان پاس داد.
به اندازه ty، فور میزنیم.که این ty درواقع می تواند مقدارهای بالاتر از مقداری که برای train داده ایم هم باشد.
1 |
for t in range(Ty): |
در این قسمت x,a,c را به LSTM_cell میدهیم و مانند قبل a تولید شده را به densor میدهیم و خروجی آن را به outputs،append میکنیم و همچنین خروجی را به تابع one_hot میدهیم و خروجی را در x میریزیم.
1 2 3 4 |
a, _, c = LSTM_cell(x, initial_state=[a, c]) out = densor(a) outputs.append(out) x = Lambda(one_hot)(out) |
تابع one_hot در music_utils تعریف شده است.
1 2 3 4 5 |
def one_hot(x): x = K.argmax(x) x = tf.one_hot(x, 78) x = RepeatVector(1)(x) return x |
که درواقع 78 تا prediction میگیرد و argmax میزند و ایندکس بزرگترین prediction را میگیرد و دوباره one_hot 78 تایی از آن می سازد و برای آن که dimention آن به dimention مدل جور در بیاد RepeatVector روی آن میزنیم.
سپس inference_model را با ورودی ها و خروجی ها میسازیم:
1 |
inference_model = Model(inputs=[x0, a0, c0], outputs=outputs) |
در مرحله بعد سه تا بردار صفر ساخته:
1 2 3 |
x_initializer = np.zeros((1, 1, 78)) a_initializer = np.zeros((1, n_a)) c_initializer = np.zeros((1, n_a)) |
تابع زیر را صدا میزنیم که سه بردار بالا و inference_model را به عنوان آرگومان به آن پاس میدهیم.
1 2 3 4 5 |
def predict_and_sample(inference_model, x_initializer = x_initializer, a_initializer = a_initializer, c_initializer = c_initializer): pred = inference_model.predict([x_initializer, a_initializer, c_initializer]) indices = np.argmax(pred, axis=-1) results = to_categorical(indices, num_classes=78) return results, indices |
تابع generate_music را بر روی inference_model صدا میزنیم.
Corpus: مجموعه 193 تا صدا به صورت
‘C,0.333,<P1,d-5>’
abstract_grammars: لیست از grammer ها مانند:
‘S,0.250,<m2,P-4> C,0.250,<P4,m-2> A,0.250,<P4,m-2>’
Tones:مجموعه ای صداهای منحصر به فرد:
‘A,0.250,<M2,d-4>’
tones_indices: دیکشنری بین تن های منحصر به فرد از 0 تا 77
indices_tones: برعکس tones_indices
1 2 3 |
def generate_music(inference_model, corpus = corpus, abstract_grammars = abstract_grammars, tones = tones, tones_indices = tones_indices, indices_tones = indices_tones, T_y = 10, max_tries = 1000, diversity = 0.5): # set up audio stream out_stream = stream.Stream() |
chord:درواقع مجموعه ای از نت ها می باشد. که برای پیانو 18 تا chord مختلف داریم.
1 2 3 4 5 |
# Initialize chord variables curr_offset = 0.0 # variable used to write sounds to the Stream. num_chords = int(len(chords) / 3) # number of different set of chords print("Predicting new values for different set of chords.") |
یک حلقه روی 18تا که در هر بار یک sequence صدا تولید میکند.
یک curr_chords می سازیم تا روی آن تغییرات ایجاد کرده و آن را به موزیک تبدیل میکنیم.
1 2 3 4 |
for i in range(1, num_chords): # Retrieve current chord from stream curr_chords = stream.Voice() |
اضافه کردن آکورد به آکورد فعلی با آفست مناسب
1 2 3 4 |
# Loop over the chords of the current set of chords for j in chords[i]: # Add chord to the current chords with the adequate offset, no need to understand this curr_chords.insert((j.offset % 4), j) |
حال تابع predict_and_sample را روی inference_model صدا میزنیم تا یک sequence از صداهای مختلف ایجاد کنیم.
1 2 3 4 5 6 7 8 9 10 |
# Generate a sequence of tones using the model _, indices = predict_and_sample(inference_model) indices = list(indices.squeeze()) pred = [indices_tones[p] for p in indices] predicted_tones = 'C,0.25 ' for k in range(len(pred) - 1): predicted_tones += pred[k] + ' ' predicted_tones += pred[-1] |
حال به جای A و X ، نت C را جایگذاری میکنیم.
1 2 3 |
#### POST PROCESSING OF THE PREDICTED TONES #### # We will consider "A" and "X" as "C" tones. It is a common choice. predicted_tones = predicted_tones.replace(' A',' C').replace(' X',' C') |
ساده سازی و سلیس کردن
1 2 |
# Pruning #1: smoothing measure predicted_tones = prune_grammar(predicted_tones) |
با استفاده از predicted_tones, curr_chords صدا تولید میکنیم و صداهای یکسان و نزدیک به هم را حذف میکنیم و out_stream را ساخته و روی my_music.midi صدا را ذخیره میکنیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# Use predicted tones and current chords to generate sounds sounds = unparse_grammar(predicted_tones, curr_chords) # Pruning #2: removing repeated and too close together sounds sounds = prune_notes(sounds) # Quality assurance: clean up sounds sounds = clean_up_notes(sounds) # Print number of tones/notes in sounds print('Generated %s sounds using the predicted values for the set of chords ("%s") and after pruning' % (len([k for k in sounds if isinstance(k, note.Note)]), i)) # Insert sounds into the output stream for m in sounds: out_stream.insert(curr_offset + m.offset, m) for mc in curr_chords: out_stream.insert(curr_offset + mc.offset, mc) curr_offset += 4.0 # Initialize tempo of the output stream with 130 bit per minute out_stream.insert(0.0, tempo.MetronomeMark(number=130)) # Save audio stream to fine mf = midi.translate.streamToMidiFile(out_stream) mf.open("output/my_music.midi", 'wb') mf.write() print("Your generated music is saved in output/my_music.midi") mf.close() # Play the final stream through output (see 'play' lambda function above) # play = lambda x: midi.realtime.StreamPlayer(x).play() # play(out_stream) return out_stream |
شبکه های اجتماعی