tek4

Huấn Luyện Mô Hình Mạng Neural Tích Chập

by - September. 21, 2021
Kiến thức
Machine Learning
Python
<p style="text-align: justify;"><em><span style="font-weight: 400;">Ch&agrave;o mừng c&aacute;c bạn quay trở lại với loạt b&agrave;i về&nbsp; </span><a href="https://tek4.vn/lap-trinh-neural-network-voi-pytorch-deep-learning-voi-pytorch/"><strong>Lập Tr&igrave;nh Neural Network Với Pytorch</strong></a><span style="font-weight: 400;">. Trong b&agrave;i viết n&agrave;y, ch&uacute;ng ta sẽ t&igrave;m hiểu c&aacute;c bước cần thiết để đ&agrave;o tạo một m&ocirc; h&igrave;nh mạng neural t&iacute;ch chập. Bắt đầu th&ocirc;i!</span></em></p> <p style="text-align: justify;"><img style="width: 100%;" src="http://tek4vn.2soft.top/public_files/huan-luyen-mo-hinh-mang-neural-tich-chap-png-1" alt="Huấn Luyện M&ocirc; H&igrave;nh Mạng Neural T&iacute;ch Chập" /></p> <p style="text-align: justify;"><a href="https://tek4.vn/bien-doi-tensor-lap-trinh-neural-network-voi-pytorch-bai-24/" target="_blank" rel="noopener">Xem th&ecirc;m b&agrave;i viết trước:&nbsp;Biến Đổi Tensor</a></p> <h3 style="text-align: justify;"><strong>Tiến độ của dự &aacute;n</strong></h3> <p style="text-align: justify;"><span style="font-weight: 400;">Cho đến nay trong loạt b&agrave;i n&agrave;y, ch&uacute;ng ta đ&atilde; thực hiện xong giai đoạn 1 l&agrave; chuẩn bị dữ liệu v&agrave; giai đoạn 2 l&agrave; x&acirc;y dựng m&ocirc; h&igrave;nh. B&acirc;y giờ, ch&uacute;ng ta đ&atilde; sẵn s&agrave;ng để chuyển sang giai đoạn 3 đ&oacute; l&agrave; đ&agrave;o tạo m&ocirc; h&igrave;nh</span></p> <ol style="text-align: justify;"> <li><span style="font-weight: 400;">Chuẩn bị dữ liệu</span></li> <li><span style="font-weight: 400;">X&acirc;y dựng m&ocirc; h&igrave;nh</span></li> <li><strong>Đ&agrave;o tạo m&ocirc; h&igrave;nh</strong></li> <li><span style="font-weight: 400;">Ph&acirc;n t&iacute;ch kết quả của m&ocirc; h&igrave;nh</span></li> </ol> <h3 style="text-align: justify;"><strong>Qu&aacute; tr&igrave;nh đ&agrave;o tạo m&ocirc; h&igrave;nh</strong></h3> <p style="text-align: justify;"><span style="font-weight: 400;">V&igrave; ch&uacute;ng ta đ&atilde; tắt t&iacute;nh năng </span><span style="font-weight: 400;">gradient tracking</span><span style="font-weight: 400;"> của PyTorch trong b&agrave;i trước n&ecirc;n ta cần đảm bảo bật lại t&iacute;nh năng n&agrave;y (t&iacute;nh năng n&agrave;y được bật theo mặc định).</span></p> <pre class="language-python"><code>&gt; torch.set_grad_enabled(True) </code></pre> <h4 style="text-align: justify;"><strong>Preparing for the forward pass</strong></h4> <p style="text-align: justify;"><span style="font-weight: 400;">Ch&uacute;ng ta đ&atilde; biết c&aacute;ch lấy một batch v&agrave; chuyển tiếp qua mạng. H&atilde;y xem ch&uacute;ng ta l&agrave;m g&igrave; tiếp theo sau khi chuyển tiếp ho&agrave;n tất.</span></p> <p style="text-align: justify;"><span style="font-weight: 400;">Ch&uacute;ng ta sẽ bắt đầu bằng:</span></p> <ol style="text-align: justify;"> <li style="font-weight: 400;"><span style="font-weight: 400;">Tạo một instance của lớp Network</span></li> <li style="font-weight: 400;"><span style="font-weight: 400;">Tạo data loader cung cấp c&aacute;c batch c&oacute; k&iacute;ch thước 100 từ bộ đ&agrave;o tạo của ch&uacute;ng ta.</span></li> <li style="font-weight: 400;"><span style="font-weight: 400;">Giải n&eacute;n c&aacute;c h&igrave;nh ảnh v&agrave; nh&atilde;n từ một trong c&aacute;c batch n&agrave;y.</span></li> </ol> <pre class="language-python"><code>&gt; network = Network() &gt; train_loader = torch.utils.data.DataLoader(train_set, batch_size=100) &gt; batch = next(iter(train_loader)) # Getting a batch &gt; images, labels = batch</code></pre> <p style="text-align: justify;"><span style="font-weight: 400;">Tiếp theo, ch&uacute;ng ta đ&atilde; sẵn s&agrave;ng chuyển c&aacute;c batch h&igrave;nh ảnh của m&igrave;nh qua mạng v&agrave; nhận c&aacute;c dự đo&aacute;n đầu ra. </span><span style="font-weight: 400;">Khi ch&uacute;ng ta c&oacute; tensor dự đo&aacute;n, ch&uacute;ng ta c&oacute; thể sử dụng c&aacute;c dự đo&aacute;n v&agrave; nh&atilde;n thực để t&iacute;nh to&aacute;n h&agrave;m loss.</span></p> <h4 style="text-align: justify;"><strong>T&iacute;nh to&aacute;n h&agrave;m loss</strong></h4> <p style="text-align: justify;"><span style="font-weight: 400;">Để thực hiện việc n&agrave;y, ch&uacute;ng ta sẽ sử dụng h&agrave;m mất m&aacute;t </span><em><span style="font-weight: 400;">cross_entropy()</span></em><span style="font-weight: 400;"> c&oacute; sẵn trong API </span><em><span style="font-weight: 400;">nn.functional</span></em><span style="font-weight: 400;"> của PyTorch. Khi ch&uacute;ng ta c&oacute; loss, ch&uacute;ng ta c&oacute; thể in n&oacute; ra v&agrave; cũng c&oacute; thể kiểm tra số lượng dự đo&aacute;n đ&uacute;ng bằng c&aacute;ch sử dụng h&agrave;m m&agrave; ch&uacute;ng ta đ&atilde; tạo trong b&agrave;i viết trước đ&oacute;.&nbsp;</span></p> <pre class="language-python"><code>&gt; preds = network(images) &gt; loss = F.cross_entropy(preds, labels) # Calculating the loss &gt; loss.item() 2.307542085647583 &gt; get_num_correct(preds, labels) 9</code></pre> <p style="text-align: justify;"><span style="font-weight: 400;">H&agrave;m </span><em><span style="font-weight: 400;">cross_entropy()</span></em><span style="font-weight: 400;"> trả về một kỳ hạn c&oacute; gi&aacute; trị v&ocirc; hướng v&agrave; v&igrave; vậy ch&uacute;ng ta đ&atilde; sử dụng phương thức </span><em><span style="font-weight: 400;">item()</span></em><span style="font-weight: 400;"> để in loss dưới dạng một số Python. Ch&uacute;ng ta c&oacute; 9 trong số 100 c&acirc;u trả lời đ&uacute;ng v&igrave; ch&uacute;ng ta c&oacute; 10 lớp dự đo&aacute;n, đ&acirc;y l&agrave; những g&igrave; ch&uacute;ng ta mong đợi bằng c&aacute;ch đo&aacute;n ngẫu nhi&ecirc;n.</span></p> <h4 style="text-align: justify;"><strong>T&iacute;nh to&aacute;n c&aacute;c gradients</strong></h4> <p style="text-align: justify;"><span style="font-weight: 400;">T&iacute;nh to&aacute;n </span><span style="font-weight: 400;">gradients</span><span style="font-weight: 400;"> rất dễ d&agrave;ng bằng c&aacute;ch sử dụng PyTorch. V&igrave; mạng của ch&uacute;ng ta l&agrave; một </span><em><span style="font-weight: 400;">nn.Module </span></em><span style="font-weight: 400;">của PyTorch, n&ecirc;n PyTorch đ&atilde; tạo một biểu đồ t&iacute;nh to&aacute;n (</span><span style="font-weight: 400;">computation graph</span><span style="font-weight: 400;">) b&ecirc;n dưới. Khi tensor của ch&uacute;ng ta truyền xu&ocirc;i qua mạng, tất cả c&aacute;c t&iacute;nh to&aacute;n được th&ecirc;m v&agrave;o biểu đồ. Đồ thị t&iacute;nh to&aacute;n sau đ&oacute; được PyTorch sử dụng để t&iacute;nh to&aacute;n </span><span style="font-weight: 400;">gradients</span><span style="font-weight: 400;"> của h&agrave;m mất m&aacute;t li&ecirc;n quan đến trọng số của mạng.&nbsp;</span></p> <p style="text-align: justify;"><span style="font-weight: 400;">Trước khi ch&uacute;ng ta t&iacute;nh to&aacute;n c&aacute;c gradient, h&atilde;y x&aacute;c minh rằng ch&uacute;ng ta hiện kh&ocirc;ng c&oacute; gradient n&agrave;o b&ecirc;n trong layer </span><em><span style="font-weight: 400;">conv1</span></em><span style="font-weight: 400;">. Gradient l&agrave; tensor c&oacute; thể truy cập v&agrave;o thuộc t&iacute;nh </span><em><span style="font-weight: 400;">grad</span></em><span style="font-weight: 400;"> (viết tắt của gradient) của tensor trọng số của mỗi layer.&nbsp;</span></p> <pre class="language-python"><code>&gt; network.conv1.weight.grad None</code></pre> <p style="text-align: justify;"><span style="font-weight: 400;">Để t&iacute;nh to&aacute;n gradient, ch&uacute;ng ta gọi phương thức </span><em><span style="font-weight: 400;">backward()</span></em><span style="font-weight: 400;"> tr&ecirc;n loss tensor, như sau:</span></p> <pre class="language-python"><code>loss.backward() # Calculating the gradients</code></pre> <p style="text-align: justify;"><span style="font-weight: 400;">B&acirc;y giờ, c&aacute;c gradient của h&agrave;m loss đ&atilde; được lưu trữ b&ecirc;n trong c&aacute;c tensor trọng số. </span></p> <pre class="language-python"><code>&gt; network.conv1.weight.grad.shape torch.Size([6, 1, 5, 5])</code></pre> <p style="text-align: justify;"><span style="font-weight: 400;">C&aacute;c gradient n&agrave;y được sử dụng bởi tr&igrave;nh tối ưu h&oacute;a (</span><span style="font-weight: 400;">optimizer</span><span style="font-weight: 400;">) để cập nhật c&aacute;c trọng số tương ứng. Để tạo tr&igrave;nh tối ưu h&oacute;a, ch&uacute;ng ta sử dụng g&oacute;i </span><em><span style="font-weight: 400;">torch.optim</span></em><span style="font-weight: 400;"> c&oacute; nhiều triển khai thuật to&aacute;n tối ưu h&oacute;a m&agrave; ch&uacute;ng ta c&oacute; thể sử dụng. Ch&uacute;ng ta sẽ sử dụng </span><em><span style="font-weight: 400;">Adam</span></em><span style="font-weight: 400;"> cho v&iacute; dụ.</span></p> <h4 style="text-align: justify;"><strong>Cập nhật trọng số</strong></h4> <p style="text-align: justify;"><span style="font-weight: 400;">Đối với phương thức khởi tạo lớp </span><em><span style="font-weight: 400;">Adam</span></em><span style="font-weight: 400;">, ch&uacute;ng ta truyền c&aacute;c tham số mạng (đ&acirc;y l&agrave; c&aacute;ch tr&igrave;nh tối ưu h&oacute;a c&oacute; thể truy cập c&aacute;c gradient) v&agrave; ch&uacute;ng ta truyền tốc độ học (<a href="https://tek4.vn/learning-rate-trong-neural-network/" target="_blank" rel="noopener">learning rate</a>).</span></p> <p style="text-align: justify;"><span style="font-weight: 400;">Cuối c&ugrave;ng, tất cả những g&igrave; ch&uacute;ng ta phải l&agrave;m để cập nhật c&aacute;c trọng số l&agrave; y&ecirc;u cầu tr&igrave;nh tối ưu h&oacute;a sử dụng h&agrave;m </span><em><span style="font-weight: 400;">step() </span></em><span style="font-weight: 400;">để tối thiểu h&oacute;a h&agrave;m mất m&aacute;t.</span></p> <pre class="language-python"><code>optimizer = optim.Adam(network.parameters(), lr=0.01) optimizer.step() # Updating the weights</code></pre> <p style="text-align: justify;"><span style="font-weight: 400;">Khi h&agrave;m <em>step()</em> được gọi, tr&igrave;nh tối ưu h&oacute;a sẽ cập nhật c&aacute;c trọng số bằng c&aacute;ch sử dụng c&aacute;c gradient được lưu trữ trong c&aacute;c tham số của mạng. Điều n&agrave;y c&oacute; nghĩa l&agrave; ch&uacute;ng ta n&ecirc;n hy vọng loss của m&igrave;nh sẽ được giảm bớt nếu ch&uacute;ng ta truyền lại c&ugrave;ng một batch qua mạng. Kiểm tra điều n&agrave;y:</span></p> <pre class="language-python"><code>&gt; preds = network(images) &gt; loss.item() &gt; loss = F.cross_entropy(preds, labels) 2.262690782546997 &gt; get_num_correct(preds, labels) 15</code></pre> <h3 style="text-align: justify;"><strong>Huấn luyện sử dụng single batch</strong></h3> <p style="text-align: justify;"><span style="font-weight: 400;">Ch&uacute;ng ta c&oacute; thể t&oacute;m tắt code train với một </span><span style="font-weight: 400;">single batch </span><span style="font-weight: 400;">theo c&aacute;ch sau:</span></p> <pre class="language-python"><code>network = Network() train_loader = torch.utils.data.DataLoader(train_set, batch_size=100) optimizer = optim.Adam(network.parameters(), lr=0.01) batch = next(iter(train_loader)) # Get Batch images, labels = batch preds = network(images) # Pass Batch loss = F.cross_entropy(preds, labels) # Calculate Loss loss.backward() # Calculate Gradients optimizer.step() # Update Weights print('loss1:', loss.item()) preds = network(images) loss = F.cross_entropy(preds, labels) print('loss2:', loss.item())</code></pre> <p class="sub-section-heading" style="text-align: justify;"><strong>Output:</strong></p> <pre class="language-python"><code>loss1: 2.3034827709198 loss2: 2.2825052738189697</code></pre> <h3 style="text-align: justify;"><strong>Tiếp Theo L&agrave; X&acirc;y Dựng Training Loop</strong></h3> <p style="text-align: justify;"><span style="font-weight: 400;">B&acirc;y giờ ch&uacute;ng ta đ&atilde; hiểu r&otilde; về qu&aacute; tr&igrave;nh đ&agrave;o tạo. Trong b&agrave;i tiếp theo, ch&uacute;ng ta sẽ xem c&aacute;ch những &yacute; tưởng n&agrave;y được mở rộng bằng c&aacute;ch ho&agrave;n th&agrave;nh quy tr&igrave;nh x&acirc;y dựng </span><span style="font-weight: 400;">training loop.</span><span style="font-weight: 400;"> Hẹn gặp lại c&aacute;c bạn trong những b&agrave;i tiếp theo!</span></p> <p style="text-align: justify;"><a href="https://tek4.vn/vong-lap-huan-luyen-lap-trinh-neural-network-voi-pytorch/" target="_blank" rel="noopener">B&agrave;i viết tiếp theo: V&ograve;ng Lặp Huấn Luyện</a></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>