تنسور در پایتورچ
بهنام خدا، سلام… در جلسه دوم آموزش پایتورچ هوسم ، میخواهیم به نحوه تعریف تنسور در پایتورچ بپردازیم. در این جلسه میآموزید که چطور در پایتورچ بردار ، ماتریس و غیره بسازید. خواص تنسور در پایتورچ هم بخش پایانی این جلسه را تشکیل میدهد. با هوسم همراه باشید…
آشنایی با تنسور در ریاضیات
تنسورها، همان آرایهها یا ماتریسها هستند که در گذشته بارها در زبانهای برنامهنویسی مختلف و ریاضیات دبیرستان با آنها مواجه شدهایم. طبق توضیحات ویکیپدیا، تنسور را میتوان بهصورت یک آرایه چندبُعدی نمایش داد. تنسورها تعمیمیافته ماتریسها هستند که شامل جدولهای اعداد با مقادیر محدود هستند و با اندیسدهی میتوان به درایههای مختلف آنها دسترسی داشت. در گذشته، ما اصولا درباره آرایههای یک بعدی (همان بردارها)، آرایههای دوبعدی (همان ماتریس) بیشتر کار کردهایم. اما آرایهها میتوانند ابعاد بالاتری هم داشته باشند. اتفاقا در بحث شبکههای عصبی و یادگیری عمیق، به وضوح کاربرد تنسورهای با ابعاد بالاتر از 2 را خواهیم دید. قبل از اینکه دستور ساخت تنسور در پایتورچ را به شما معرفی کنیم، بهتر است به شما نشان دهیم که شکل تنسورهای چندبعدی چگونه است.
1- تنسور صفر بعدی
این تنسورها همان اعداد اسکالر هستند. یعنی اعدادی مانند 1 ، 2 ، 10.2- و غیره را میتوانیم تنسورهای صفر بعدی بنامیم.
2- تنسور یک بعدی
این تنسورها همان بردارها هستند. از کنار هم قرار گرفتن مجموعهای از اعداد اسکالر، یک بردار یا تنسور یک بعدی خواهیم داشت. تصویر زیر، نمایشدهنده ساختار یک تنسور یک بعدی است.
3- تنسور دو بعدی
از زیر هم قرار گرفتن تنسورهای یک بعدی ، تنسورهای دو بعدی یا ماتریس به وجود میآید. تنسورهای دو بعدی همانند یک جدول است که در تصویر زیر ساختار کلی آن را میتوانید مشاهده کنید:
4- تنسور سه بعدی
از پشت هم قرار دادن تنسورهای دو بعدی ، یک تنسور سه بعدی بهوجود میآید. تصویر زیر نشاندهنده ساختار یک تنسور سه بعدی است:
به هر یک از تنسورهای دو بعدی یا ماتریس ها در اینجا صفحه یا channel گفته میشود. مثلا صفحه 1 در تصویر پایین زرد رنگ است. پس میگوییم، صفحه 0، صفحه 1، صفحه 2 و …
بیایید تنسور صفر بعدی تا سه بعدی را با دستگاه مختصات مقایسه کنیم. موافقید تنسور صفر بعدی معادل همان نقطه در دستگاه مختصات است؟ از کنار هم قرار دادن همین نقاط است که میتوانیم محور x در دستگاه مختصات را تشکیل دهیم. پس میتوانیم بگوییم که تنسور یک بعدی معادل همان محور x است. حال برویم دستگاه مختصات دو بعدی x-y را ببینیم. موافقید تنسور دو بعدی معادل همان دستگاه مختصات دو بعدی x-y است؟ طبیعتا قابل حدس است که یک تنسور سه بعدی هم معادل یک دستگاه مختصات سه بعدی x-y-z است.
اما سوال این است، بهنظر شما معادل تنسور چهار بعدی را چگونه در دستگاه مختصات پیدا کنیم؟ دستگاه چهار بعدی هم مگر داریم؟ نکته اینجاست که از بعد چهارم به بعد، دوباره همان روال صفر بعدی تا سه بعدی تکرار میشود! چگونه؟ برویم ادامه توضیحات…
5- تنسور چهار بعدی
از کنار هم قرار دادن تنسورهای سه بعدی ، تنسور چهار بعدی تشکیل میشود. در واقع، تنسور چهار بعدی یک بردار است که هریک از درایههای آن یک تنسور سه بعدی است. تصویر زیر یک تنسور چهار بعدی را نشان میدهد.
کافی است یا برویم سراغ تنسور پنج بعدی؟! واقعیت این است که گاهی کارمان به تنسور پنج بعدی هم کشیده میشود. بهنظر شما، تنسور پنج بعدی چگونه است؟
6- تنسور پنج بعدی
از زیر هم قرار گرفتن تنسورهای چهار بعدی یک تنسور پنج بعدی خواهیم داشت. در واقع، تنسور پنج بعدی یک ماتریس است که هریک از درایههای آن تنسور سه بعدی است. تصویرش مشابه تصویر 2 است و هر درایه آن یک تنسور سه بعدی است.
همانطور که گفتیم، تنسور سه بعدی نقش کلیدی در تنسورهای چهار بعدی و پنج بعدی دارد. حال شما به تمرین زیر جواب دهید و سپس با کلیک بر روی سوال، جواب را مشاهده کنید.
در ادامه میخواهیم تمرین با پایتورچ را شروع کنیم. بنابراین، نرمافزار پایچارم یا کولب خود را باز کنید و بنویسید:
>>> import torch
بسیارخب، برویم شروع کنیم…
تنسور در پایتورچ
برای ساختن یک تنسور در پایتورچ ، کافی است از دستور ()tensor استفاده کنید. بهعنوان نمونه، برای ساخت یک تنسور صفر بعدی یا اسکالر کافی است، بنویسید:
>>> tensor0d = torch.tensor(1)
>>> print(tensor0d)
tensor(1)
>>> tensor0d = torch.tensor(-5.2)
>>> print(tensor0d)
tensor(-5.2000)
برای ساخت تنسورهای یک بعدی به بالا، باید از براکت [] همراه با دستور ()tensor استفاده کرد. مثلا برای تعریف یک تنسور یک بعدی یا همان بردار، کافی است بنویسیم:
>>> tensor1d = torch.tensor([1, -1, 15, 1000])
>>> print(tensor1d)
tensor([ 1, -1, 15, 1000])
>>> tensor1d = torch.tensor([10, 5, -9, 1.5])
>>> print(tensor1d)
tensor([10.0000, 5.0000, -9.0000, 1.5000])
خب در تعریف تنسورهای دو بعدی گفتیم که از زیر هم قرار گرفتن تنسورهای یک بعدی ، تنسور دو بعدی ایجاد میشود. در بالا که آموختیم چگونه بردار یا تنسور یک بعدی بسازیم. حالا در کد زیر ببنید، یک مجموعه بردار ساختیم. این بردارها را زیر هم گذاشتیم و درنتیجه یک ماتریس بدست آمده است. دقت کنید، در تنسور زیر، هر بردار معادل با یک سطر از ماتریس یا تنسور دو بعدی است.
>>> tensor2d = torch.tensor([[-10, 11, 1.5],
[ 5.6, 88, 10.0],
[ 2.3, 36, -10.0],
[ 2.0, 12, 0.2]])
>>> print(tensor2d)
tensor([[-10.0000, 11.0000, 1.5000],
[ 5.6000, 88.0000, 10.0000],
[ 2.3000, 36.0000, -10.0000],
[ 2.0000, 12.0000, 0.2000]])
نکته لازم نیست حتما با زدن Enter، بردارها را دقیقا زیر هم بچینید. ما صرفا برای نمایش بهتر اینکار را کردیم. شما میتوانید بهصورت زیر هم بنویسید:
>>> tensor2d = torch.tensor([[-10, 11, 1.5], [5.6, 88, 10.0], [2.3, 36, -10.0], [2.0, 12, 0.2]])
>>> print(tensor2d)
tensor([[-10.0000, 11.0000, 1.5000],
[ 5.6000, 88.0000, 10.0000],
[ 2.3000, 36.0000, -10.0000],
[ 2.0000, 12.0000, 0.2000]])
>>> tensor2d = torch.tensor([[1, 2, 3, 4, 5],
[6, 7, 8, 0, 0]])
>>> print(tensor2d)
tensor([[1, 2, 3, 4, 5],
[6, 7, 8, 0, 0]])
خب تنسور سه بعدی از پشت هم قرار گرفتن تنسورهای دو بعدی بدست میآمد. با افزایش ابعاد تنسورها، وارد کردن اعداد سخت میشود. اما تمرین خوبی است، بیایید یک تنسور سه بعدی بسازیم:
>>> tensor3d = torch.tensor([[[-10, 11, 1.50],
[ 5.6, 88, 10.0],
[ 2.3, 36, -10.0],
[ 2.0, 12, 0.2]],
[[-1.0, 11, 1.50],
[ 0.6, 88, 1.00],
[ 0.3, 3.6, -10.0],
[ 2.1, 1.2, 4.20]]])
>>> print(tensor3d)
tensor([[[-10.0000, 11.0000, 1.5000],
[ 5.6000, 88.0000, 10.0000],
[ 2.3000, 36.0000, -10.0000],
[ 2.0000, 12.0000, 0.2000]],
[[ -1.0000, 11.0000, 1.5000],
[ 0.6000, 88.0000, 1.0000],
[ 0.3000, 3.6000, -10.0000],
[ 2.1000, 1.2000, 4.2000]]])
این مثال به وضوح نشان میدهد که هر براکت [] معادل با یک بُعد است. سه [] داریم، پس تنسور سه بعدی ساختیم.>>> tensor3d = torch.tensor([[[3.8]]])
>>> print(tensor3d)
tensor([[3.8000]])
>>> tensor4d = torch.tensor([[[[1, 5, 8]]], [[[2, 3, 4]]]])
>>> print(tensor4d)
tensor([[[[1, 5, 8]]],
[[[2, 3, 4]]]])
خواص تنسور در پایتورچ
در بخش قبل، با تعریف تنسور در پایتورچ آشنا شدید. امیدواریم خوب تمرین کرده باشید. حالا میخواهیم مجموعهای از خواص تنسور در پایتورچ را به شما معرفی کنیم. مثلا میخواهیم خیلی سریع ابعاد یک تنسور را ببینیم. یا ممکن است بخواهیم نوع داده ( دیتاتایپ datatype ) یک تنسور را بفهمیم. در این جلسه تعدادی از این خواص را به شما معرفی میکنیم. تعدادی را هم در جلسات بعدی به شما معرفی خواهیم کرد.
خواص هر تنسور از طریق نقطه (.) بهراحتی قبل دسترس هست. خصوصا اگر از پایچارم استفاده کنید، بلافاصله پس از گذاشتن نقطه بعد از متغیر (مثلا .tensor1d) مجموعه خواص را برای شما لیست میکند. بسیارخب، برویم سراغ چند خواص کاربردی…
برای مشاهده ابعاد یک تنسور میتوانید از دستور shape یا size استفاده کنید. تفاوت شاخصی بین این دو دستور وجود ندارد. در مثال زیر، نحوه استفاده از shape و size را میتوانید مشاهده کنید:
>>> tensor2d.shape torch.Size([4, 3]) >>> tensor2d.size() torch.Size([4, 3])
توجه دقت کنید، دستور size نیاز به پرانتز () دارد. درهمین لحظه، تنبلها تصمیمشان را گرفتند. از shape استفاده کنیم بهتر است. پرانتز ندارد! D:
هردو دستور، ورودی هم قبول میکنند. فقط یک ورودی میپذیرند. حدس بزنید، ورودی این دو دستور چیست؟ شما میتوانید مشخص کنید که میخواهید مقدار کدام بُعد را بدانید. بُعد اول، دوم یا سوم؟ مثلا در دستور زیر ما از پایتورچ خواستهایم که بُعد دوم تنسور را به ما بدهد:
>>> tensor2d.shape[1] 3 >>> tensor2d.size(1) 3
توجه به دو دستور بالا دقت کنید. دستور size در پایتورچ ورودی را با پرانتز قبول میکند و دستور shape در پایتورچ ورودی را براکت قبول میکند.
>>> tensor3d.shape[2]
2
>>> tensor3d.size(2)
2
در بالا صحبت از نوع داده یا datatype شد. منظورمان همان نوع داده int ، float ، bool و غیره است. هر متغیری که در پایتون تعریف میشود، یک نوع داده مشخص دارد. اتفاقا دیتاتایپ در یادگیری عمیق خیلی مهم هست. برای بررسی اینکه دیتاتایپ یک تنسور در پایتورچ چیست، کافی است از dtype استفاده کنید. مثلا دیتاتایپ tensor3d بهشکل زیر بهدست میآید:
>>> tensor3d.dtype torch.float32
دیتاتایپ متغیر بالا از نوع float32 (فلوت 32 بیتی) است. بیایید برای یک تنسور دیگر هم دیتاتایپ را هم بررسی کنیم:
>>> tensor1d.dtype torch.int64
اینبار از نوع int64 (اینت 64 بیتی) شد. چرا متفاوت با tensor3d شد؟ چون مقادیر متغیر tensor1d همه از نوع صحیح هستند. درحالیکه tensor3d شامل اعداد اعشاری نیز هست. بنابراین، بسته به محتویات هر تنسور، دیتاتایپ آن ممکن است float32 و int64 باشد. البته در پایتورچ دیتاتایپهای دیگر هم داریم. اما لازم نبود در این جلسه معرفی کنیم. بعدا در مورد دیتاتایپها بیشتر صحبت خواهیم کرد.
>>> tensor0d = torch.tensor(-12.5)
>>> tensor0d.dtype
torch.float32
مجموعه خواص تنسورها بیش از اینهاست. اما فعلا نمیخواهیم درمورد سایر خواص صحبت کنیم. اجازه دهید، بهموقع درباره سایر خواص تنسور در پایتورچ صحبت کنیم.
بسیار خب، جلسه دوم آموزش پایتورچ هم به پایان رسید. چند جلسه ابتدایی را میخواهیم به عملیات روی تنسورها اختصاص دهیم (یعنی همان کارهایی که کتابخانه نامپای میتوانیم انجام دهیم). انشالله، جلسه بعدی میخواهیم انواع تنسورهای خاص مانند تنسور صفر ، تنسور واحد ، تصادفی و غیره را به شما آموزش دهیم. پیشنهاد و نظرات خود را درباره آموزش کامنت کنید. شما هم با نظراتتان در تهیه این آموزش سهیم باشید.
مطالب زیر را حتما مطالعه کنید
مدل nanoGPT
شگفتانگیزترین ایده هوش مصنوعی از نظر Andrej Karpathy
شبکه ویژن ترنسفورمر
شبکه اتوانکدر
شبکه عصبی mlp
شبکه ترنسفورمر
12 دیدگاه
به گفتگوی ما بپیوندید و دیدگاه خود را با ما در میان بگذارید.
عالی
سلام تفاوت بین torch.tensor و torch.Tensor چیه؟
خروجی nn.CrossEntropyLoss() میشه یه لیست یا تنسور پس چرا میزنه غیر قابل دسترس هست؟
محیطی که بشه کد را به اشتراک بگذارم ندارید؟
سلام
1- دو دستور tensor و Tensor عملکردی شبیه هم دارن. از هر دو میتونیم استفاده کنیم که تنسور دستی بسازیم. هر دو دستور زیر خروجی یکسانی دارن:
print(torch.tensor([1, 3]))
print(torch.Tensor([1, 3]))
اما اگه بدون براکت به شکل زیر، به اینها ورودی بدید، نتیجه متفاوت میشه:
print(torch.tensor(3))
print(torch.Tensor(3))
2- در مورد کراس آنتروپی، سوالتون واضح نیست.
3- محیطی برای اشتراک کد نداریم.
ممنون
عالی…
سلام
دستور import torch را در پایتورچ نمیشناسه. و به طبع آن tensor . باید پکار کنم؟ لطفا راهنمایی میفرمایید؟
سلام. تشکر فراوان بابت آموزشی که قرار دادید. لطف بزرگی در حق ما دانشجوها کردید. خیلی ساده و جامع توضیح دادید. خداخیرتون بده:)
سلام
سپاس 🌹🙏
سلام. ممنون از آموزش خوبتون. میشه توضیح بدین gradient hook توی پایتورچ به چه معناست؟ و چه موقع نیاز به رجستر اون هست؟
همه چیز عالی ست بدون هیچ گونه اغراقی…با سپاس
سلام
سپاس 🌹🙏
عالی
مخصوصا مفهوم تنسورهای چند بعدی …
سپاس 🌹🙏