کانولوشن بسازید و ادغام را انجام دهید

1. قبل از شروع

در این کد لبه، شما در مورد کانولوشن ها و دلیل قدرتمند بودن آنها در سناریوهای بینایی کامپیوتری خواهید آموخت.

در آزمایشگاه کد قبلی، یک شبکه عصبی عمیق (DNN) ساده برای دید کامپیوتری اقلام مد ایجاد کردید. این محدود بود زیرا نیاز داشت که لباس تنها چیزی در تصویر باشد و باید در مرکز قرار می گرفت.

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

پیش نیازها

این آزمایشگاه کد مبتنی بر کارهای تکمیل شده در دو قسمت قبلی است، به «سلام، جهان» یادگیری ماشین سلام کنید و یک مدل بینایی رایانه بسازید . لطفاً قبل از ادامه آن کدها را تکمیل کنید.

چیزی که یاد خواهید گرفت

  • پیچیدگی ها چیست؟
  • نحوه ایجاد نقشه ویژگی
  • استخراج چیست

چیزی که خواهی ساخت

  • نقشه ویژگی یک تصویر

آنچه شما نیاز دارید

می‌توانید کد بقیه کدهای در حال اجرا در Colab را پیدا کنید.

همچنین به نصب TensorFlow و کتابخانه هایی که در codelab قبلی نصب کرده اید نیاز دارید.

2. کانولوشن چیست؟

کانولوشن فیلتری است که از روی یک تصویر عبور می کند، آن را پردازش می کند و ویژگی های مهم را استخراج می کند.

فرض کنید تصویری از شخصی دارید که کفش کتانی پوشیده است. چگونه تشخیص می دهید که یک کفش ورزشی در تصویر وجود دارد؟ برای اینکه برنامه شما تصویر را به‌عنوان یک کفش ورزشی ببیند، باید ویژگی‌های مهم را استخراج کنید و ویژگی‌های غیرضروری را محو کنید. به این نگاشت ویژگی می گویند.

فرآیند نگاشت ویژگی از نظر تئوری ساده است. شما هر پیکسل در تصویر را اسکن می کنید و سپس به پیکسل های مجاور آن نگاه می کنید. شما مقادیر آن پیکسل ها را در وزن های معادل در یک فیلتر ضرب می کنید.

مثلا:

پیچیدگی روی تصویر

در این مورد، یک ماتریس کانولوشن 3x3 یا هسته تصویر مشخص می شود.

مقدار پیکسل فعلی 192 است. شما می توانید مقدار پیکسل جدید را با مشاهده مقادیر همسایه، ضرب آنها در مقادیر مشخص شده در فیلتر، محاسبه کنید و مقدار پیکسل جدید را به مقدار نهایی تبدیل کنید.

اکنون زمان آن رسیده است که با ایجاد یک پیچیدگی اساسی روی یک تصویر دوبعدی در مقیاس خاکستری، نحوه کار کانولوشن ها را بررسی کنیم.

شما این را با تصویر صعود از SciPy نشان خواهید داد. این یک تصویر داخلی زیبا با زوایای و خطوط زیاد است.

3. شروع به کدنویسی کنید

با وارد کردن چند کتابخانه پایتون و تصویر صعود شروع کنید:

import cv2
import numpy as np
from scipy import misc
i = misc.ascent()

در مرحله بعد، از matplotlib کتابخانه Pyplot برای ترسیم تصویر استفاده کنید تا بدانید که چگونه به نظر می رسد:

import matplotlib.pyplot as plt
plt.grid(False)
plt.gray()
plt.axis('off')
plt.imshow(i)
plt.show()

edb460dd5397f7f4.png

می توانید ببینید که تصویری از یک راه پله است. ویژگی های زیادی وجود دارد که می توانید امتحان کنید و جدا کنید. به عنوان مثال، خطوط عمودی قوی وجود دارد.

تصویر به عنوان یک آرایه NumPy ذخیره می شود، بنابراین ما می توانیم تصویر تبدیل شده را فقط با کپی کردن آن آرایه ایجاد کنیم. متغیرهای size_x و size_y ابعاد تصویر را نگه می‌دارند تا بتوانید بعداً روی آن حلقه بزنید.

i_transformed = np.copy(i)
size_x = i_transformed.shape[0]
size_y = i_transformed.shape[1]

4. ماتریس کانولوشن را ایجاد کنید

ابتدا یک ماتریس کانولوشن (یا کرنل) به صورت یک آرایه 3x3 بسازید:

# This filter detects edges nicely
# It creates a filter that only passes through sharp edges and straight lines. 
# Experiment with different values for fun effects.
#filter = [ [0, 1, 0], [1, -4, 1], [0, 1, 0]] 
# A couple more filters to try for fun!
filter = [ [-1, -2, -1], [0, 0, 0], [1, 2, 1]]
#filter = [ [-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]
 # If all the digits in the filter don't add up to 0 or 1, you 
# should probably do a weight to get it to do so
# so, for example, if your weights are 1,1,1 1,2,1 1,1,1
# They add up to 10, so you would set a weight of .1 if you want to normalize them
weight  = 1

حالا پیکسل های خروجی را محاسبه کنید. روی تصویر تکرار کنید، یک حاشیه 1 پیکسلی باقی بگذارید، و هر یک از همسایگان پیکسل فعلی را در مقدار تعریف شده در فیلتر ضرب کنید.

این بدان معناست که همسایه پیکسل فعلی در بالای آن و سمت چپ آن در مورد بالا سمت چپ در فیلتر ضرب می شود. سپس، نتیجه را در وزن ضرب کنید و مطمئن شوید که نتیجه در محدوده 0 تا 255 است.

در نهایت، مقدار جدید را در تصویر تبدیل شده بارگذاری کنید:

for x in range(1,size_x-1):
  for y in range(1,size_y-1):
      output_pixel = 0.0
      output_pixel = output_pixel + (i[x - 1, y-1] * filter[0][0])
      output_pixel = output_pixel + (i[x, y-1] * filter[0][1])
      output_pixel = output_pixel + (i[x + 1, y-1] * filter[0][2])
      output_pixel = output_pixel + (i[x-1, y] * filter[1][0])
      output_pixel = output_pixel + (i[x, y] * filter[1][1])
      output_pixel = output_pixel + (i[x+1, y] * filter[1][2])
      output_pixel = output_pixel + (i[x-1, y+1] * filter[2][0])
      output_pixel = output_pixel + (i[x, y+1] * filter[2][1])
      output_pixel = output_pixel + (i[x+1, y+1] * filter[2][2])
      output_pixel = output_pixel * weight
      if(output_pixel<0):
        output_pixel=0
      if(output_pixel>255):
        output_pixel=255
      i_transformed[x, y] = output_pixel

5. نتایج را بررسی کنید

حالا تصویر را رسم کنید تا اثر عبور فیلتر از روی آن را ببینید:

# Plot the image. Note the size of the axes -- they are 512 by 512
plt.gray()
plt.grid(False)
plt.imshow(i_transformed)
#plt.axis('off')
plt.show()   

48ff667b2df812ad.png

مقادیر فیلتر زیر و تاثیر آنها بر تصویر را در نظر بگیرید.

استفاده از [-1,0,1,-2,0,2,-1,0,1] مجموعه بسیار قوی از خطوط عمودی را به شما می دهد:

تشخیص فیلتر خطوط عمودی

استفاده از [-1,-2,-1,0,0,0,1,2,1] خطوط افقی را به شما می دهد:

تشخیص خطوط افقی

ارزش های مختلف را کاوش کنید! همچنین، فیلترهای با اندازه های مختلف مانند 5x5 یا 7x7 را امتحان کنید.

6. درک Pooling

اکنون که ویژگی های اساسی تصویر را شناسایی کرده اید، چه کار می کنید؟ چگونه از نقشه ویژگی به دست آمده برای طبقه بندی تصاویر استفاده می کنید؟

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

انواع مختلفی از ادغام وجود دارد، اما شما از یکی به نام حداکثر (حداکثر) ادغام استفاده خواهید کرد.

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

7. برای ادغام کد بنویسید

کد زیر یک ترکیب (2، 2) را نشان می دهد. آن را اجرا کنید تا خروجی را ببینید.

خواهید دید که در حالی که اندازه تصویر یک چهارم اندازه اصلی است، اما تمام ویژگی ها را حفظ کرده است.

new_x = int(size_x/2)
new_y = int(size_y/2)
newImage = np.zeros((new_x, new_y))
for x in range(0, size_x, 2):
  for y in range(0, size_y, 2):
    pixels = []
    pixels.append(i_transformed[x, y])
    pixels.append(i_transformed[x+1, y])
    pixels.append(i_transformed[x, y+1])
    pixels.append(i_transformed[x+1, y+1])
    pixels.sort(reverse=True)
    newImage[int(x/2),int(y/2)] = pixels[0]
 
# Plot the image. Note the size of the axes -- now 256 pixels instead of 512
plt.gray()
plt.grid(False)
plt.imshow(newImage)
#plt.axis('off')
plt.show()

1f5ebdafd1db2595.png

به محورهای آن طرح توجه کنید. اکنون تصویر 256x256، یک چهارم اندازه اصلی آن است، و علیرغم وجود داده های کمتر در تصویر، ویژگی های شناسایی شده بهبود یافته اند.

8. تبریک می گویم

شما اولین مدل بینایی کامپیوتری خود را ساخته اید! برای یادگیری نحوه تقویت بیشتر مدل‌های بینایی رایانه خود، به ساخت شبکه‌های عصبی کانولوشنال (CNN) برای تقویت بینایی رایانه بروید.