tek4

Giải Thích Về Forward Propagation

by - September. 21, 2021
Kiến thức
Machine Learning
Python
<p style="text-align: justify;"><em>Ch&agrave;o mừng c&aacute;c bạn đến với b&agrave;i viết thứ 22 trong loạt b&agrave;i về&nbsp;<strong><a href="https://tek4.vn/lap-trinh-neural-network-voi-pytorch-deep-learning-voi-pytorch/" target="_blank" rel="noopener">Lập Tr&igrave;nh Neural Network Với Pytorch</a>.&nbsp;</strong>Trong b&agrave;i viết n&agrave;y, ch&uacute;ng ta sẽ xem c&aacute;ch ch&uacute;ng ta c&oacute; thể sử dụng mạng neural t&iacute;ch chập của m&igrave;nh để tạo ra một tensor dự đo&aacute;n đầu ra từ một h&igrave;nh ảnh mẫu của tập dữ liệu fashion mnist. Bắt đầu th&ocirc;i!</em></p> <p style="text-align: justify;">&nbsp;</p> <p style="text-align: justify;">Tại thời điểm n&agrave;y của loạt b&agrave;i, ch&uacute;ng ta đ&atilde; ho&agrave;n th&agrave;nh việc x&acirc;y dựng m&ocirc; h&igrave;nh của m&igrave;nh v&agrave; về mặt kỹ thuật ch&uacute;ng ta c&oacute; thể bắt đầu ngay qu&aacute; tr&igrave;nh đ&agrave;o tạo từ đ&acirc;y.&nbsp;Tuy nhi&ecirc;n, ch&uacute;ng ta cần hiểu r&otilde; hơn về c&aacute;ch mạng của ch&uacute;ng ta hoạt động v&agrave; sau đ&oacute;, khi ch&uacute;ng ta hiểu s&acirc;u hơn về mạng của m&igrave;nh ch&uacute;ng ta sẽ chuẩn bị tốt hơn cho giai đoạn đ&agrave;o tạo m&ocirc; h&igrave;nh.</p> <p style="text-align: justify;">Bước đầu ti&ecirc;n l&agrave; hiểu về sự lan truyền xu&ocirc;i (forward propagation).</p> <h3 class="section-heading" style="text-align: justify;">Forward propagation l&agrave; g&igrave;?</h3> <p style="text-align: justify;"><em>Forward propagation (lan truyền xu&ocirc;i)&nbsp;</em>l&agrave; qu&aacute; tr&igrave;nh biến đổi m&ocirc;t tensor đầu v&agrave;o th&agrave;nh một tensor đầu ra. Về cốt l&otilde;i của n&oacute;, mạng neural l&agrave; một h&agrave;m &aacute;nh xạ một tensor đầu v&agrave;o với một tensor đầu ra v&agrave; lan truyền xu&ocirc;i chỉ l&agrave; một t&ecirc;n gọi đặc biệt cho qu&aacute; tr&igrave;nh truyền đầu v&agrave;o đến mạng v&agrave; nhận đầu ra từ mạng.&nbsp;</p> <p style="text-align: justify;"><img style="width: 100%;" src="http://tek4vn.2soft.top/public_files/tensor-cube-forward-pass-jpg" alt="tensor-cube-forward-pass" /></p> <p style="text-align: justify;">Như ch&uacute;ng ta đ&atilde; thấy, mạng neural hoạt động dựa tr&ecirc;n dữ liệu ở dạng tensor.&nbsp;Kh&aacute;i niệm truyền xu&ocirc;i được sử dụng để chỉ ra rằng dữ liệu tensor đầu v&agrave;o được truyền qua mạng theo hướng thuận.</p> <p style="text-align: justify;">Đối với mạng của ch&uacute;ng ta, điều n&agrave;y đơn giản chỉ l&agrave; chuyển tensor đầu v&agrave;o qua mạng v&agrave; nhận tensor đầu ra.&nbsp;Để thực hiện việc n&agrave;y, ch&uacute;ng ta truyền dữ liệu mẫu của m&igrave;nh sang phương thức <em>forward()</em> của mạng.</p> <p style="text-align: justify;">Đ&acirc;y l&agrave; l&yacute; do tại sao, phương thức <em>forward()</em> c&oacute; t&ecirc;n l&agrave; forward, việc thực thi <em>forward()</em> l&agrave; qu&aacute; tr&igrave;nh truyền xu&ocirc;i.</p> <p style="text-align: justify;">Trong trường hợp của ch&uacute;ng ta v&agrave; từ quan điểm thực tế, truyền xu&ocirc;i l&agrave; qu&aacute; tr&igrave;nh chuyển một tensor h&igrave;nh ảnh đầu v&agrave;o đến phương thức <em>forward()</em> m&agrave; ch&uacute;ng ta đ&atilde; thực hiện trong b&agrave;i trước. Đầu ra n&agrave;y l&agrave; dự đo&aacute;n của mạng.</p> <p style="text-align: justify;">B&acirc;y giờ ch&uacute;ng ta đ&atilde; x&aacute;c định mạng của m&igrave;nh v&agrave; phương thức <em>forward()</em>&nbsp;đ&atilde; được triển khai, h&atilde;y chuyển một h&igrave;nh ảnh v&agrave;o mạng để nhận dự đo&aacute;n đầu ra.</p> <h3 class="section-heading" style="text-align: justify;">Dự Đo&aacute;n Với Mạng: Forward Pass</h3> <p style="text-align: justify;">Trước khi thực hiện, ch&uacute;ng ta sẽ tắt t&iacute;nh năng t&iacute;nh to&aacute;n gradient của PyTorch.&nbsp;Điều n&agrave;y sẽ ngăn PyTorch tự động x&acirc;y dựng đồ thị t&iacute;nh to&aacute;n khi tensor của ch&uacute;ng ta chạy qua mạng.</p> <p><img style="width: 746px; display: block; margin-left: auto; margin-right: auto;" src="http://tek4vn.2soft.top/public_files/neural-network-2-3-2-png-1" alt="neural-network-2-3-2" height="314" /></p> <p style="text-align: justify;">Biểu đồ t&iacute;nh to&aacute;n theo d&otilde;i &aacute;nh xạ của mạng bằng c&aacute;ch theo d&otilde;i từng t&iacute;nh to&aacute;n xảy ra.&nbsp;Biểu đồ được sử dụng trong qu&aacute; tr&igrave;nh đ&agrave;o tạo để t&iacute;nh đạo h&agrave;m (gradient) của h&agrave;m loss li&ecirc;n quan đến trọng số của mạng.</p> <p style="text-align: justify;">V&igrave; ch&uacute;ng ta chưa đ&agrave;o tạo mạng n&ecirc;n kh&ocirc;ng c&oacute; kế hoạch cập nhật trọng số v&agrave; v&igrave; vậy kh&ocirc;ng y&ecirc;u cầu t&iacute;nh to&aacute;n gradient.&nbsp;Ch&uacute;ng ta sẽ bật lại t&iacute;nh năng n&agrave;y khi bắt đầu đ&agrave;o tạo.</p> <p style="text-align: justify;">Qu&aacute; tr&igrave;nh theo d&otilde;i c&aacute;c t&iacute;nh to&aacute;n n&agrave;y diễn ra trong thời gian thực, khi c&aacute;c ph&eacute;p t&iacute;nh xảy ra.&nbsp;H&atilde;y nhớ lại ở <a href="https://tek4.vn/gioi-thieu-pytorch-lap-trinh-neural-network-voi-pytorch-bai-1/" target="_blank" rel="noopener">phần đầu của loạt b&agrave;i</a>, ch&uacute;ng ta đ&atilde; n&oacute;i rằng PyTorch sử dụng một đồ thị t&iacute;nh to&aacute;n động (dynamic computational graph).&nbsp;B&acirc;y giờ ch&uacute;ng ta sẽ tắt n&oacute; đi.</p> <p style="text-align: justify;">Việc tắt t&iacute;nh năng n&agrave;y kh&ocirc;ng ho&agrave;n to&agrave;n cần thiết nhưng việc tắt t&iacute;nh năng n&agrave;y sẽ l&agrave;m giảm mức ti&ecirc;u thụ bộ nhớ v&igrave; biểu đồ kh&ocirc;ng được lưu trữ trong bộ nhớ. code&nbsp;n&agrave;y sẽ tắt t&iacute;nh năng:</p> <pre class="language-python"><code>&gt; torch.set_grad_enabled(False)</code></pre> <h4 class="sub-section-heading" style="text-align: justify;">Truyền một h&igrave;nh anh v&agrave;o mạng</h4> <p style="text-align: justify;">H&atilde;y tiếp tục bằng c&aacute;ch tạo một &nbsp;instance của lớp Network:</p> <pre class="language-python"><code>&gt; network = Network()</code></pre> <p style="text-align: justify;">Tiếp theo, ch&uacute;ng ta sẽ lấy một mẫu duy nhất từ ​​bộ đ&agrave;o tạo của m&igrave;nh, giải n&eacute;n h&igrave;nh ảnh v&agrave; nh&atilde;n, đồng thời x&aacute;c minh shape của h&igrave;nh ảnh:</p> <pre class="language-python"><code>&gt; sample = next(iter(train_set)) &gt; image, label = sample &gt; image.shape torch.Size([1, 28, 28])</code></pre> <p style="text-align: justify;">Shape của tensor&nbsp;h&igrave;nh ảnh cho biết rằng ch&uacute;ng ta c&oacute; h&igrave;nh ảnh với một k&ecirc;nh m&agrave;u duy nhất c&oacute; chiều cao l&agrave; 28 v&agrave; chiều rộng l&agrave; 28.</p> <p style="text-align: justify;"><img style="width: 286px; display: block; margin-left: auto; margin-right: auto;" src="http://tek4vn.2soft.top/public_files/fashion-mnist-ankle-boot-png-2" alt="fashion-mnist-ankle-boot" height="284" /></p> <p style="text-align: justify;">Khi ch&uacute;ng ta truyền một tensor v&agrave;o mạng của m&igrave;nh, mạng đang mong đợi một batch, v&igrave; vậy ngay cả khi ch&uacute;ng ta chỉ muốn truyền v&agrave;o một h&igrave;nh ảnh duy nhất, ch&uacute;ng ta vẫn cần một batch.</p> <p style="text-align: justify;">Ch&uacute;ng ta c&oacute; thể tạo một batch chứa một h&igrave;nh ảnh duy nhất.&nbsp;Tất cả những thứ n&agrave;y sẽ được đ&oacute;ng g&oacute;i th&agrave;nh một tensor bốn chiều duy nhất phản &aacute;nh c&aacute;c k&iacute;ch thước sau:</p> <pre><code>(batch_size, in_channels, height, width)</code></pre> <p style="text-align: justify;">Y&ecirc;u cầu n&agrave;y của mạng ph&aacute;t sinh từ thực tế l&agrave; phương thức <em>forward()</em> của c&aacute;c layers chập <em>nn.Conv2d</em> mong đợi c&aacute;c tensors của ch&uacute;ng c&oacute; 4 chiều.&nbsp;Đ&acirc;y l&agrave; một ti&ecirc;u chuẩn v&igrave; hầu hết c&aacute;c triển khai mạng neural đều xử l&yacute; theo c&aacute;c batch mẫu đầu v&agrave;o thay v&igrave; c&aacute;c mẫu đơn lẻ.</p> <p style="text-align: justify;">Để đặt 1 tensor h&igrave;nh ảnh th&agrave;nh một batch c&oacute; k&iacute;ch thước l&agrave; 1, ch&uacute;ng ta chỉ cần <em>unsqueeze()</em> tensor để th&ecirc;m một k&iacute;ch thước bổ sung.&nbsp;Ch&uacute;ng ta đ&atilde; thấy c&aacute;ch thực hiện điều n&agrave;y trong c&aacute;c <a href="https://tek4.vn/gioi-thieu-reshape-lap-trinh-neural-network-bai-9/" target="_blank" rel="noopener">b&agrave;i trước</a>.</p> <pre class="language-python"><code># Inserts an additional dimension that represents a batch of size 1 image.unsqueeze(0).shape torch.Size([1, 1, 28, 28])</code></pre> <p style="text-align: justify;">B&acirc;y giờ ch&uacute;ng ta c&oacute; thể chuyển h&igrave;nh ảnh unsqueezed v&agrave;o mạng v&agrave; nhận dự đo&aacute;n của mạng.</p> <pre class="language-python"><code>&gt; pred = network(image.unsqueeze(0)) # image shape needs to be (batch_size &times; in_channels &times; H &times; W) &gt; pred tensor([[0.0991, 0.0916, 0.0907, 0.0949, 0.1013, 0.0922, 0.0990, 0.1130, 0.1107, 0.1074]]) &gt; pred.shape torch.Size([1, 10]) &gt; label 9 &gt; pred.argmax(dim=1) tensor([7])</code></pre> <p style="text-align: justify;">Ch&uacute;ng ta đ&atilde; sử dụng phương thức forward của m&igrave;nh để nhận dự đo&aacute;n từ mạng.&nbsp;Mạng đ&atilde; trả về một tensor dự đo&aacute;n chứa gi&aacute; trị dự đo&aacute;n cho từng loại trong số mười loại quần &aacute;o.</p> <p style="text-align: justify;">Shape&nbsp;của tensor dự đo&aacute;n l&agrave; 1 x 10.&nbsp;Điều n&agrave;y cho ch&uacute;ng ta biết rằng axis thứ nhất c&oacute; độ d&agrave;i l&agrave; một trong khi axis thứ hai c&oacute; độ d&agrave;i l&agrave; mười.&nbsp;Việc giải th&iacute;ch điều n&agrave;y cho ch&uacute;ng ta biết c&oacute; một h&igrave;nh ảnh trong batch của m&igrave;nh với mười lớp dự đo&aacute;n.</p> <pre>(batch size, number of prediction classes)</pre> <p style="text-align: justify;">Đối với mỗi đầu v&agrave;o trong batch v&agrave; cho mỗi lớp dự đo&aacute;n, ch&uacute;ng ta c&oacute; một gi&aacute; trị dự đo&aacute;n. Nếu ch&uacute;ng ta muốn c&aacute;c gi&aacute; trị n&agrave;y l&agrave; x&aacute;c suất, ch&uacute;ng ta chỉ c&oacute; thể d&ugrave;ng h&agrave;m <em>softmax()</em> từ g&oacute;i <em>nn.functional.</em></p> <pre class="language-python"><code>&gt; F.softmax(pred, dim=1) tensor([[0.1096, 0.1018, 0.0867, 0.0936, 0.1102, 0.0929, 0.1083, 0.0998, 0.0943, 0.1030]]) &gt; F.softmax(pred, dim=1).sum() tensor(1.)</code></pre> <p style="text-align: justify;">Nh&atilde;n cho h&igrave;nh ảnh đầu ti&ecirc;n trong tập huấn luyện của ch&uacute;ng ta l&agrave; 9 v&agrave; sử dụng h&agrave;m <em>argmax()</em>&nbsp;ch&uacute;ng ta c&oacute; thể thấy rằng gi&aacute; trị cao nhất trong tensor dự đo&aacute;n của ch&uacute;ng ta xảy ra ở lớp được đại diện bởi chỉ số 7.</p> <ul style="text-align: justify;"> <li>Dự đo&aacute;n: Sneaker (7)</li> <li>Thực tế:&nbsp;Ankle boot (9)</li> </ul> <p style="text-align: justify;">H&atilde;y nhớ rằng, mỗi lớp dự đo&aacute;n được đại diện bởi một index tương ứng.</p> <p><img style="width: 443px; display: block; margin-left: auto; margin-right: auto;" src="http://tek4vn.2soft.top/public_files/1-1-png" alt="1-1" height="452" /></p> <p style="text-align: justify;">Dự đo&aacute;n trong trường hợp n&agrave;y l&agrave; kh&ocirc;ng ch&iacute;nh x&aacute;c, đ&oacute; l&agrave; điều ch&uacute;ng ta mong đợi v&igrave; c&aacute;c trọng số trong mạng được tạo ngẫu nhi&ecirc;n.</p> <h4 class="sub-section-heading" style="text-align: justify;">Trọng số mạng được tạo ngẫu nhi&ecirc;n</h4> <p style="text-align: justify;">C&oacute; một số điều quan trọng m&agrave; ch&uacute;ng ta cần chỉ ra về những kết quả n&agrave;y.&nbsp;Hầu hết c&aacute;c x&aacute;c suất đều đạt gần 10% v&agrave; điều n&agrave;y l&agrave; c&oacute; &yacute; nghĩa v&igrave; mạng của ch&uacute;ng ta đang dự đo&aacute;n v&agrave; ch&uacute;ng ta c&oacute; mười lớp dự đo&aacute;n đến từ một tập <a href="https://tek4.vn/dataset-va-dataloader-lap-trinh-neural-network-voi-pytorch-bai-15/" target="_blank" rel="noopener">dữ liệu c&acirc;n bằng</a>.</p> <p style="text-align: justify;">Một h&agrave;m &yacute; kh&aacute;c của c&aacute;c trọng số được tạo ngẫu nhi&ecirc;n l&agrave; mỗi khi ch&uacute;ng ta tạo một phi&ecirc;n bản mới của mạng c&aacute;c trọng số trong mạng sẽ kh&aacute;c nhau.&nbsp;Điều n&agrave;y c&oacute; nghĩa l&agrave; c&aacute;c dự đo&aacute;n ch&uacute;ng ta nhận được sẽ kh&aacute;c nhau nếu ch&uacute;ng ta tạo c&aacute;c mạng kh&aacute;c nhau.&nbsp;Dự đo&aacute;n của bạn sẽ kh&aacute;c với những g&igrave; ch&uacute;ng ta thấy ở đ&acirc;y.</p> <pre class="language-python"><code>&gt; net1 = Network() &gt; net2 = Network() &gt; net1(image.unsqueeze(0)) tensor([[ 0.0855, 0.1123, -0.0290, -0.1411, -0.1293, -0.0688, 0.0149, 0.1410, -0.0936, -0.1157]]) &gt; net2(image.unsqueeze(0)) tensor([[-0.0408, -0.0696, -0.1022, -0.0316, -0.0986, -0.0123, 0.0463, 0.0248, 0.0157, -0.1251]])</code></pre> <h3 style="text-align: justify;">Kết Luận</h3> <p style="text-align: justify;">Giờ đ&acirc;y, ch&uacute;ng ta đ&atilde; sẵn s&agrave;ng chuyển một loạt dữ liệu v&agrave;o mạng của m&igrave;nh v&agrave; diễn giải kết quả.&nbsp;B&acirc;y giờ, ch&uacute;ng ta đ&atilde; hiểu r&otilde; về sự lan truyền xu&ocirc;i l&agrave; g&igrave; v&agrave; l&agrave;m thế n&agrave;o ch&uacute;ng ta c&oacute; thể truyền một tensor với 1 h&igrave;nh ảnh duy nhất đến một mạng neural t&iacute;ch chập trong PyTorch. Trong b&agrave;i tiếp theo, ch&uacute;ng ta sẽ xem c&aacute;ch sử dụng data loader để chuyển một batch v&agrave;o mạng của ch&uacute;ng ta. Hẹn gặp lại bạn trong b&agrave;i viết tiếp theo!</p> <p style="text-align: justify;">&nbsp;</p> <hr /> <p style="text-align: center;"><em><strong>Fanpage Facebook:</strong>&nbsp;<a href="https://www.facebook.com/tek4.vn/">TEK4.VN</a></em>&nbsp;</p> <p style="text-align: center;"><em><strong>Tham gia cộng đồng để chia sẻ, trao đổi v&agrave; thảo luận:</strong>&nbsp;<a href="https://www.facebook.com/groups/tek4.vn/">TEK4.VN - Học Lập Tr&igrave;nh Miễn Ph&iacute;</a></em></p>