tek4

Vòng Lặp Huấn Luyện 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ề</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>.&nbsp;<span style="font-weight: 400;">Trong b&agrave;i n&agrave;y, ch&uacute;ng ta sẽ t&igrave;m hiểu c&aacute;ch x&acirc;y dựng v&ograve;ng lặp huấn luyện cho một mạng neural t&iacute;ch chập bằng Python. Bắt đầu th&ocirc;i!</span></em></p> <h3 style="text-align: justify;"><img style="width: 100%;" src="http://tek4vn.2soft.top/public_files/vong-lap-huan-luyen-mang-neural-tich-chap-png-1" alt="V&ograve;ng Lặp Huấn Luyện Mạng Neural T&iacute;ch Chập" /></h3> <p style="text-align: center;"><a href="https://tek4.vn/dao-tao-mo-hinh-lap-trinh-neural-network-voi-pytorch-bai-25/" target="_blank" rel="noopener">Xem th&ecirc;m b&agrave;i viết trước:&nbsp;Đ&agrave;o Tạo M&ocirc; H&igrave;nh</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. Hiện tại, ch&uacute;ng ta đang ở giai đoạn 3 đ&oacute; l&agrave; đ&agrave;o tạo m&ocirc; h&igrave;nh. </span><span style="font-weight: 400;">Trong b&agrave;i trước, ch&uacute;ng ta đ&atilde; biết rằng qu&aacute; tr&igrave;nh huấn luyện l&agrave; một qu&aacute; tr&igrave;nh lặp đi lặp lại v&agrave; để huấn luyện một mạng neural, ch&uacute;ng ta cần x&acirc;y dựng c&aacute;i được gọi l&agrave; v&ograve;ng lặp huấn luyện.</span></p> <ol style="text-align: justify;"> <li style="font-weight: 400;"><span style="font-weight: 400;">Chuẩn bị dữ liệu</span></li> <li style="font-weight: 400;"><span style="font-weight: 400;">X&acirc;y dựng m&ocirc; h&igrave;nh</span></li> <li style="font-weight: 400;"><strong>Đ&agrave;o tạo m&ocirc; h&igrave;nh</strong></li> <li style="font-weight: 400;"><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>Huấn luyện với 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 để training với single batch 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 style="text-align: justify;"><strong>Output:</strong></p> <pre class="language-python"><code>loss1: 2.3034827709198 loss2: 2.2825052738189697</code></pre> <p style="text-align: justify;"><span style="font-weight: 400;">Một điều m&agrave; bạn sẽ nhận thấy l&agrave; ch&uacute;ng ta nhận được c&aacute;c kết quả kh&aacute;c nhau mỗi khi ch&uacute;ng ta chạy code n&agrave;y. Như ch&uacute;ng ta đ&atilde; biết từ c&aacute;c b&agrave;i viết trước điều n&agrave;y l&agrave; do trọng số của m&ocirc; h&igrave;nh được khởi tạo ngẫu nhi&ecirc;n.</span></p> <p style="text-align: justify;"><span style="font-weight: 400;">B&acirc;y giờ ch&uacute;ng ta h&atilde;y xem c&aacute;ch ch&uacute;ng ta c&oacute; thể sửa đổi code n&agrave;y để huấn luyện bằng c&aacute;ch sử dụng tất cả c&aacute;c batch v&agrave; cũng c&oacute; nghĩa l&agrave; sử dụng to&agrave;n bộ tập huấn luyện.</span></p> <h3 style="text-align: justify;"><strong>Huấn luyện với tất cả batches (Single Epoch)</strong></h3> <p style="text-align: justify;"><span style="font-weight: 400;">B&acirc;y giờ, để huấn luyện với tất cả c&aacute;c batches c&oacute; sẵn b&ecirc;n trong data loader, ch&uacute;ng ta cần thực hiện một v&agrave;i thay đổi v&agrave; th&ecirc;m một d&ograve;ng code bổ sung:</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) total_loss = 0 total_correct = 0 for batch in train_loader: # Get Batch images, labels = batch preds = network(images) # Pass Batch loss = F.cross_entropy(preds, labels) # Calculate Loss optimizer.zero_grad() loss.backward() # Calculate Gradients optimizer.step() # Update Weights total_loss += loss.item() total_correct += get_num_correct(preds, labels) print( "epoch:", 0, "total_correct:", total_correct, "loss:", total_loss )</code></pre> <p style="text-align: justify;"><span style="font-weight: 400;">Thay v&igrave; nhận một batch duy nhất từ data loader, ch&uacute;ng ta sẽ tạo một v&ograve;ng lặp for để lặp lại tr&ecirc;n tất cả c&aacute;c batches.</span></p> <p style="text-align: justify;"><span style="font-weight: 400;">V&igrave; ch&uacute;ng ta c&oacute; 60.000 mẫu trong tập huấn luyện của m&igrave;nh n&ecirc;n sẽ c&oacute; 60.000 / 100 = 600 lần lặp. V&igrave; l&yacute; do n&agrave;y, ch&uacute;ng ta sẽ x&oacute;a c&acirc;u lệnh in ra khỏi v&ograve;ng lặp v&agrave; theo d&otilde;i tổng số loss v&agrave; tổng số dự đo&aacute;n đ&uacute;ng in ch&uacute;ng ở cuối.</span></p> <p style="text-align: justify;"><span style="font-weight: 400;">Một điều cần lưu &yacute; về 600 lần lặp n&agrave;y l&agrave; trọng số của ch&uacute;ng ta sẽ được cập nhật 600 lần v&agrave;o cuối v&ograve;ng lặp. Nếu ch&uacute;ng ta tăng k&iacute;ch thước </span><em><span style="font-weight: 400;">batch_size</span></em><span style="font-weight: 400;">, con số n&agrave;y sẽ giảm xuống v&agrave; nếu ch&uacute;ng ta giảm k&iacute;ch thước </span><em><span style="font-weight: 400;">batch_size</span></em><span style="font-weight: 400;">, con số n&agrave;y sẽ tăng l&ecirc;n.</span></p> <p style="text-align: justify;"><span style="font-weight: 400;">Cuối c&ugrave;ng, sau khi 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, ch&uacute;ng ta biết c&aacute;c gradient sẽ được t&iacute;nh to&aacute;n v&agrave; th&ecirc;m v&agrave;o thuộc t&iacute;nh grad của c&aacute;c tham số network. V&igrave; l&yacute; do n&agrave;y, ch&uacute;ng ta cần loại bỏ c&aacute;c gradient n&agrave;y. Ch&uacute;ng ta c&oacute; thể l&agrave;m điều n&agrave;y với một phương thức gọi l&agrave;</span><em><span style="font-weight: 400;"> zero_grad()</span></em><span style="font-weight: 400;"> đi k&egrave;m với tr&igrave;nh </span><em><span style="font-weight: 400;">optimzer</span></em><span style="font-weight: 400;">.</span></p> <p style="text-align: justify;"><span style="font-weight: 400;">Ch&uacute;ng ta đ&atilde; sẵn s&agrave;ng để chạy code n&agrave;y. Lần n&agrave;y sẽ l&acirc;u hơn v&igrave; v&ograve;ng lặp đang hoạt động tr&ecirc;n 600 batches.</span></p> <pre class="language-python"><code>epoch: 0 total_correct: 42104 loss: 476.6809593439102</code></pre> <p style="text-align: justify;"><span style="font-weight: 400;">Ch&uacute;ng ta nhận được kết quả v&agrave; c&oacute; thể thấy rằng tổng số đ&uacute;ng trong số 60.000 l&agrave; 42.104.</span></p> <pre class="language-python"><code>&gt; total_correct / len(train_set) 0.7017333333333333</code></pre> <p style="text-align: justify;"><span style="font-weight: 400;">Điều đ&oacute; l&agrave; kh&aacute; tốt chỉ sau một epoch (một lần chuyển to&agrave;n bộ dữ liệu). Mặc d&ugrave; ch&uacute;ng ta đ&atilde; thực hiện một epoch, ch&uacute;ng ta vẫn phải lưu &yacute; rằng trọng số đ&atilde; được cập nhật 600 lần v&agrave; thực tế n&agrave;y phụ thuộc v&agrave;o k&iacute;ch thước batch của ch&uacute;ng ta. Nếu l&agrave;m cho batch_size của ch&uacute;ng ta lớn hơn, chẳng hạn như 10.000, trọng số sẽ chỉ được cập nhật 6 lần v&agrave; kết quả sẽ kh&ocirc;ng ho&agrave;n to&agrave;n tốt. </span></p> <h3 style="text-align: justify;"><strong>Huấn luyện với nhiều epochs</strong></h3> <p style="text-align: justify;"><span style="font-weight: 400;">Để thực hiện nhiều epoch, tất cả những g&igrave; ch&uacute;ng ta phải l&agrave;m l&agrave; đặt code n&agrave;y v&agrave;o một v&ograve;ng lặp for.</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) for epoch in range(10): total_loss = 0 total_correct = 0 for batch in train_loader: # Get Batch images, labels = batch preds = network(images) # Pass Batch loss = F.cross_entropy(preds, labels) # Calculate Loss optimizer.zero_grad() loss.backward() # Calculate Gradients optimizer.step() # Update Weights total_loss += loss.item() total_correct += get_num_correct(preds, labels) print( "epoch", epoch, "total_correct:", total_correct, "loss:", total_loss )</code></pre> <p style="text-align: justify;"><span style="font-weight: 400;">Sau khi chạy code n&agrave;y, ch&uacute;ng ta nhận được kết quả cho mỗi epoch:</span></p> <pre class="language-markup"><code>epoch 0 total_correct: 43301 loss: 447.59147948026657 epoch 1 total_correct: 49565 loss: 284.43429669737816 epoch 2 total_correct: 51063 loss: 244.08825492858887 epoch 3 total_correct: 51955 loss: 220.5841210782528 epoch 4 total_correct: 52551 loss: 204.73878084123135 epoch 5 total_correct: 52914 loss: 193.1240530461073 epoch 6 total_correct: 53195 loss: 184.50964668393135 epoch 7 total_correct: 53445 loss: 177.78808392584324 epoch 8 total_correct: 53629 loss: 171.81662507355213 epoch 9 total_correct: 53819 loss: 166.2412590533495</code></pre> <p style="text-align: justify;"><span style="font-weight: 400;">Ch&uacute;ng ta c&oacute; thể thấy rằng số lượng gi&aacute; trị đ&uacute;ng tăng l&ecirc;n v&agrave; loss giảm xuống.</span></p> <h3 style="text-align: justify;"><strong>Ho&agrave;n th&agrave;nh v&ograve;ng lặp huấn luyện</strong></h3> <p style="text-align: justify;"><span style="font-weight: 400;">Kết hợp tất cả những điều n&agrave;y lại với nhau, ch&uacute;ng ta c&oacute; thể k&eacute;o </span><em><span style="font-weight: 400;">network</span></em><span style="font-weight: 400;">, </span><em><span style="font-weight: 400;">optimizer</span></em> <span style="font-weight: 400;">v&agrave; </span><em><span style="font-weight: 400;">train_loader </span></em><span style="font-weight: 400;">ra khỏi &ocirc; v&ograve;ng lặp huấn luyện.</span></p> <pre class="language-python"><code>network = Network() optimizer = optim.Adam(network.parameters(), lr=0.01) train_loader = torch.utils.data.DataLoader( train_set ,batch_size=100 ,shuffle=True )</code></pre> <p style="text-align: justify;"><span style="font-weight: 400;">Điều n&agrave;y gi&uacute;p cho ch&uacute;ng ta c&oacute; thể chạy v&ograve;ng lặp huấn luyện m&agrave; kh&ocirc;ng cần đặt lại trọng số networks.</span></p> <pre class="language-python"><code>for epoch in range(10): total_loss = 0 total_correct = 0 for batch in train_loader: # Get Batch images, labels = batch preds = network(images) # Pass Batch loss = F.cross_entropy(preds, labels) # Calculate Loss optimizer.zero_grad() loss.backward() # Calculate Gradients optimizer.step() # Update Weights total_loss += loss.item() total_correct += get_num_correct(preds, labels) print( "epoch", epoch, "total_correct:", total_correct, "loss:", total_loss )</code></pre> <h3 style="text-align: justify;"><strong>Kết Luận</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ề c&aacute;c v&ograve;ng lặp huấn luyện v&agrave; c&aacute;ch ch&uacute;ng ta x&acirc;y dựng ch&uacute;ng bằng PyTorch. Điều th&uacute; vị về PyTorch l&agrave; ch&uacute;ng ta c&oacute; thể gỡ lỗi code v&ograve;ng lặp huấn luyện giống như c&aacute;ch ch&uacute;ng ta đ&atilde; l&agrave;m với h&agrave;m </span><em><span style="font-weight: 400;">forward()</span></em><span style="font-weight: 400;">.</span></p> <p style="text-align: justify;"><span style="font-weight: 400;">Trong phần tiếp theo, ch&uacute;ng ta sẽ xem c&aacute;ch lấy c&aacute;c dự đo&aacute;n cho mọi mẫu trong tập huấn luyện v&agrave; sử dụng những dự đo&aacute;n đ&oacute; để tạo ra một </span><span style="font-weight: 400;">confusion matrix. </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: right;"><a href="https://tek4.vn/wp-admin/post.php?post=6955&amp;action=edit" target="_blank" rel="noopener">B&agrave;i viết tiếp theo:&nbsp;Confusion Matrix</a></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>