tek4

Element-Wise Trong Pytorch

by - September. 21, 2021
Kiến thức
Machine Learning
Python
<h3 class="sub-section-heading" style="text-align: justify;">Element-Wise l&agrave; g&igrave;?</h3> <p><img style="width: 602px; display: block; margin-left: auto; margin-right: auto;" src="http://tek4vn.2soft.top/public_files/capture-190-png-1" alt="Capture-190" height="314" /></p> <p style="text-align: justify;"><em>Element-wise</em>&nbsp;l&agrave; c&aacute;c ph&eacute;p to&aacute;n cực kỳ phổ biến với tensor trong lập tr&igrave;nh mạng neural.&nbsp;H&atilde;y bắt đầu b&agrave;i viết n&agrave;y với định nghĩa về một&nbsp;element-wise operation.</p> <pre><code>An element-wise operation operates on corresponding elements between tensors.</code></pre> <p style="text-align: justify;">Hiểu đơn giản th&igrave;&nbsp;<em>Element-wise</em>&nbsp;l&agrave; ph&eacute;p to&aacute;n tr&ecirc;n c&aacute;c phần tử tương ứng giữa c&aacute;c tensor.&nbsp;Hai phần tử được cho l&agrave; tương ứng nếu hai phần tử chiếm c&ugrave;ng một vị tr&iacute; trong tensor.&nbsp;Vị tr&iacute; được x&aacute;c định bởi c&aacute;c index được sử dụng để định vị từng phần tử.</p> <p style="text-align: justify;">Giả sử ch&uacute;ng ta c&oacute; hai tensor sau:</p> <pre class="language-python"><code>&gt; t1 = torch.tensor([ [1,2], [3,4] ], dtype=torch.float32) &gt; t2 = torch.tensor([ [9,8], [7,6] ], dtype=torch.float32)</code></pre> <p style="text-align: justify;">Cả hai tensor n&agrave;y đều l&agrave; tensor rank 2 c&oacute; shape l&agrave; 2 x 2.</p> <p style="text-align: justify;">Điều n&agrave;y c&oacute; nghĩa l&agrave; ch&uacute;ng ta c&oacute; 2 axes m&agrave; cả hai đều c&oacute; độ d&agrave;i l&agrave; 2 ở mỗi axis.&nbsp;C&aacute;c phần tử của axis thứ nhất l&agrave; mảng v&agrave; c&aacute;c phần tử của axis thứ hai l&agrave; số.</p> <pre class="language-python"><code># V&iacute; dụ về axis đầu ti&ecirc;n &gt; print(t1[0]) tensor([1., 2.]) # V&iacute; dụ về axis thứ 2 &gt; print(t1[0][0]) tensor(1.)</code></pre> <p style="text-align: justify;">Ch&uacute;ng ta biết rằng hai phần tử được cho l&agrave; tương ứng nếu hai phần tử chiếm c&ugrave;ng một vị tr&iacute; trong tensor v&agrave; vị tr&iacute; được x&aacute;c định bởi c&aacute;c index được sử dụng để định vị mỗi phần tử.&nbsp;H&atilde;y xem v&iacute; dụ về c&aacute;c phần tử tương ứng:</p> <pre class="language-python"><code>&gt; t1[0][0] tensor(1.) &gt; t2[0][0] tensor(9.)</code></pre> <p style="text-align: justify;">Điều n&agrave;y cho ph&eacute;p ch&uacute;ng ta thấy rằng phần tử tương ứng với 1 trong <em>t1</em> l&agrave; 9 trong <em>t2.&nbsp;</em></p> <p style="text-align: justify;">Sự tương ứng được x&aacute;c định bởi c&aacute;c index, điều n&agrave;y rất quan trọng v&igrave; n&oacute; tiết lộ một t&iacute;nh năng quan trọng của&nbsp;element-wise operations, đ&oacute; l&agrave;&nbsp;c&aacute;c tensor phải c&oacute; c&ugrave;ng số phần tử để thực hiện một ph&eacute;p to&aacute;n&nbsp;element-wise. Từ đ&oacute; suy ra được l&agrave; c&aacute;c tensor phải c&oacute; shape giống nhau.</p> <h3 class="sub-section-heading" style="text-align: justify;">Ph&eacute;p cộng l&agrave; một Element wise</h3> <p style="text-align: justify;">H&atilde;y xem v&iacute; dụ dưới đ&acirc;y:</p> <pre class="language-python"><code>&gt; t1 + t2 tensor([[10., 10.], [10., 10.]])</code></pre> <p style="text-align: justify;">Điều n&agrave;y cho ch&uacute;ng ta thấy rằng ph&eacute;p cộng giữa c&aacute;c tensor l&agrave; một ph&eacute;p to&aacute;n&nbsp;element-wise.&nbsp;Mỗi cặp phần tử ở c&aacute;c vị tr&iacute; tương ứng được cộng v&agrave;o với nhau để tạo ra một tensor mới c&oacute; c&ugrave;ng shape.</p> <p style="text-align: justify;">V&igrave; vậy, ph&eacute;p cộng l&agrave; một ph&eacute;p to&aacute;n element-wise v&agrave; tr&ecirc;n thực tế, tất cả c&aacute;c ph&eacute;p to&aacute;n số học, cộng, trừ, nh&acirc;n v&agrave; chia đều l&agrave; ph&eacute;p to&aacute;n element-wise.</p> <h4 style="text-align: justify;">C&aacute;c ph&eacute;p to&aacute;n số học l&agrave; c&aacute;c&nbsp;element-wise</h4> <p style="text-align: justify;">Một ph&eacute;p to&aacute;n ch&uacute;ng ta thường thấy với tensor l&agrave; ph&eacute;p to&aacute;n số học sử dụng c&aacute;c gi&aacute; trị v&ocirc; hướng.&nbsp;C&oacute; hai c&aacute;ch ch&uacute;ng ta c&oacute; thể l&agrave;m điều n&agrave;y:</p> <p style="text-align: justify;"><strong>C&aacute;ch 1:</strong></p> <pre class="language-python"><code>&gt; print(t + 2) tensor([[3., 4.], [5., 6.]]) &gt; print(t - 2) tensor([[-1., 0.], [ 1., 2.]]) &gt; print(t * 2) tensor([[2., 4.], [6., 8.]]) &gt; print(t / 2) tensor([[0.5000, 1.0000], [1.5000, 2.0000]])</code></pre> <p style="text-align: justify;"><strong>C&aacute;ch 2:</strong></p> <pre class="language-python"><code>&gt; print(t1.add(2)) tensor([[3., 4.], [5., 6.]]) &gt; print(t1.sub(2)) tensor([[-1., 0.], [ 1., 2.]]) &gt; print(t1.mul(2)) tensor([[2., 4.], [6., 8.]]) &gt; print(t1.div(2)) tensor([[0.5000, 1.0000], [1.5000, 2.0000]])</code></pre> <p style="text-align: justify;">Cả hai c&aacute;ch n&agrave;y đều hoạt động như nhau.&nbsp;Ch&uacute;ng ta c&oacute; thể thấy rằng trong cả hai trường hợp, gi&aacute; trị v&ocirc; hướng, số 2, được &aacute;p dụng cho mỗi phần tử bằng ph&eacute;p to&aacute;n số học tương ứng.</p> <p style="text-align: justify;">C&aacute;c bạn c&oacute; thấy điều g&igrave; kh&ocirc;ng ổn trong những v&iacute; dụ n&agrave;y kh&ocirc;ng?&nbsp;Những v&iacute; dụ n&agrave;y đang ph&aacute; vỡ quy tắc m&agrave; ch&uacute;ng ta đ&atilde; thiết lập ban đầu rằng c&aacute;c ph&eacute;p to&aacute;n <em>element-wise</em> n&oacute;i tr&ecirc;n hoạt động tr&ecirc;n c&aacute;c tensors c&oacute; c&ugrave;ng shape.</p> <p style="text-align: justify;">Gi&aacute; trị v&ocirc; hướng l&agrave; tensor rank 0, c&oacute; nghĩa l&agrave; ch&uacute;ng kh&ocirc;ng c&oacute; shape v&agrave; tensor <em>t1</em> của ch&uacute;ng ta l&agrave; tensor rank 2 c&oacute; shape l&agrave; 2 x 2.</p> <p style="text-align: justify;">Vậy l&agrave;m thế n&agrave;o để điều n&agrave;y trở th&agrave;nh ph&ugrave; hợp? H&atilde;y c&ugrave;ng nhau đến với kh&aacute;i niệm mới l&agrave;&nbsp;<em>tensor broadcasting</em>&nbsp;hoặc<em> broadcasting</em>&nbsp;để giải th&iacute;ch được vấn đề n&agrave;y.</p> <h4 class="sub-section-heading" style="text-align: justify;">Broadcasting Tensors</h4> <p style="text-align: justify;">Broadcasting&nbsp;m&ocirc; tả c&aacute;ch xử l&yacute; c&aacute;c tensors với c&aacute;c shape kh&aacute;c nhau trong ph&eacute;p to&aacute;n&nbsp;element-wise.</p> <p style="text-align: justify;">H&atilde;y nghĩ về ph&eacute;p to&aacute;n <em>t1 + 2</em>. Ở đ&acirc;y, tensor của gi&aacute; trị v&ocirc; hướng (2) đ&atilde; được&nbsp;broadcasted trở th&agrave;nh shape giống với shape của <em>t1.&nbsp;</em>Sau đ&oacute;, ph&eacute;p to&aacute;n&nbsp;element-wise đ&atilde; được thực hiện.</p> <p style="text-align: justify;">Ch&uacute;ng ta c&oacute; thể thấy gi&aacute; trị v&ocirc; hướng được broadcasted tr&ocirc;ng như thế n&agrave;o bằng c&aacute;ch sử dụng h&agrave;m <em>broadcast_to()</em>&nbsp;trong numpy:</p> <pre class="language-python"><code>&gt; np.broadcast_to(2, t1.shape) array([[2, 2], [2, 2]])</code></pre> <p style="text-align: justify;">Điều n&agrave;y c&oacute; nghĩa l&agrave; gi&aacute; trị v&ocirc; hướng được chuyển đổi th&agrave;nh tensor rank 2 giống như <em>t1,</em> v&agrave; như vậy c&aacute;c quy tắc về phần tử của <em>element-wise</em> sẽ hoạt động b&igrave;nh thường.</p> <p style="text-align: justify;">Đoạn code dưới đ&acirc;y sẽ chỉ ra r&otilde; hơn về điều n&agrave;y.</p> <p style="text-align: justify;">Ch&uacute;ng ta thấy:</p> <pre class="language-python"><code>&gt; t1 + 2 tensor([[3., 4.], [5., 6.]])</code></pre> <p style="text-align: justify;">Thực tế l&agrave;:</p> <pre class="language-python"><code>&gt; t1 + torch.tensor( np.broadcast_to(2, t1.shape) ,dtype=torch.float32 ) tensor([[3., 4.], [5., 6.]])</code></pre> <p style="text-align: justify;">Tại thời điểm n&agrave;y, ch&uacute;ng ta c&oacute; thể nghĩ rằng điều n&agrave;y c&oacute; vẻ phức tạp, v&igrave; vậy h&atilde;y xem một v&iacute; dụ sau đ&acirc;y.</p> <h4 class="sub-section-heading" style="text-align: justify;">V&iacute; dụ Trickier về&nbsp;Broadcasting</h4> <p style="text-align: justify;">Giả sử ch&uacute;ng ta c&oacute; 2 tensor sau:</p> <pre class="language-python"><code>t1 = torch.tensor([ [1,1], [1,1] ], dtype=torch.float32) t2 = torch.tensor([2,4], dtype=torch.float32)</code></pre> <p style="text-align: justify;">Kết quả của thao t&aacute;c cộng&nbsp;element-wise n&agrave;y l&agrave; g&igrave;:</p> <pre class="language-python"><code># t1 + t2 ??????? &gt; t1.shape torch.Size([2, 2]) &gt; t2.shape torch.Size([2])</code></pre> <p style="text-align: justify;">Mặc d&ugrave; hai tensors n&agrave;y c&oacute; shape kh&aacute;c nhau, tuy nhi&ecirc;n ph&eacute;p to&aacute;n&nbsp;element-wise vẫn c&oacute; thể thực hiện nhờ v&agrave;o&nbsp;broadcasting.</p> <p style="text-align: justify;">Tensor t2 c&oacute; rank thấp hơn n&ecirc;n sẽ được&nbsp;broadcasting để ph&ugrave; hợp với shape của tensor t1 c&oacute; rank cao hơn v&agrave; ph&eacute;p to&aacute;n&nbsp;element-wise giữa c&aacute;c phần tử tương ứng sẽ được thực hiện như b&igrave;nh thường.</p> <p style="text-align: justify;">Kh&aacute;i niệm về broadcasting l&agrave; ch&igrave;a kh&oacute;a để hiểu hoạt động n&agrave;y sẽ được thực hiện như thế n&agrave;o.&nbsp;Như trước đ&acirc;y, ch&uacute;ng ta c&oacute; thể kiểm tra sự chuyển đổi broadcast bằng c&aacute;ch sử dụng h&agrave;m <em>broadcast_to()</em>&nbsp;của numpy.</p> <pre class="language-python"><code>&gt; np.broadcast_to(t2.numpy(), t1.shape) array([[2., 4.], [2., 4.]], dtype=float32) &gt; t1 + t2 tensor([[3., 5.], [3., 5.]])</code></pre> <p style="text-align: justify;">Sau khi broadcast, ph&eacute;p to&aacute;n cộng giữa hai tensors n&agrave;y l&agrave; một ph&eacute;p to&aacute;n element-wise giữa c&aacute;c tensors c&oacute; c&ugrave;ng shape.</p> <p style="text-align: justify;">Khi n&agrave;o ch&uacute;ng ta cần sử dụng broadcast?&nbsp;Ch&uacute;ng ta cần sử dụng broadcast khi ch&uacute;ng ta tiền xử l&yacute; dữ liệu của m&igrave;nh v&agrave; đặc biệt l&agrave; trong c&aacute;c quy tr&igrave;nh chuẩn h&oacute;a.</p> <h3 class="section-heading" style="text-align: justify;">C&aacute;c ph&eacute;p to&aacute;n so s&aacute;nh l&agrave; Element-Wise</h3> <p style="text-align: justify;">C&aacute;c ph&eacute;p to&aacute;n so s&aacute;nh cũng l&agrave; c&aacute;c ph&eacute;p to&aacute;n&nbsp;element-wise.</p> <p style="text-align: justify;">Đối với ph&eacute;p to&aacute;n so s&aacute;nh nhất định giữa hai tensor, một tensor mới c&oacute; c&ugrave;ng shape được trả về với mỗi phần tử chứa gi&aacute; trị <em>torch.bool</em> l&agrave; <em>True</em> hoặc <em>False.</em></p> <p style="text-align: justify;">V&iacute; dụ, giả sử ch&uacute;ng ta c&oacute; tensor sau:</p> <pre class="language-python"><code>&gt; t = torch.tensor([ [0,5,0], [6,0,7], [0,8,0] ], dtype=torch.float32)</code></pre> <p style="text-align: justify;">H&atilde;y kiểm tra một số thao t&aacute;c so s&aacute;nh n&agrave;y.</p> <pre class="language-python"><code>&gt; t.eq(0) tensor([[True, False, True], [False, True, False], [True, False, True]]) &gt; t.ge(0) tensor([[True, True, True], [True, True, True], [True, True, True]]) &gt; t.gt(0) tensor([[False, True, False], [True, False, True], [False, True, False]]) &gt; t.lt(0) tensor([[False, False, False], [False, False, False], [False, False, False]]) &gt; t.le(7) tensor([[True, True, True], [True, True, True], [True, False, True]])</code></pre> <p style="text-align: justify;">Suy nghĩ về c&aacute;c hoạt động n&agrave;y từ g&oacute;c độ broadcasting, ch&uacute;ng ta c&oacute; thể thấy rằng hoạt động cuối c&ugrave;ng, <em>t.le(7),</em> thực sự l&agrave;:</p> <pre class="language-python"><code>&gt; t &lt;= torch.tensor( np.broadcast_to(7, t.shape) ,dtype=torch.float32 ) tensor([[True, True, True], [True, True, True], [True, False, True]])</code></pre> <p style="text-align: justify;">V&agrave; tương đương như sau:</p> <pre class="language-python"><code>&gt; t &lt;= torch.tensor([ [7,7,7], [7,7,7], [7,7,7] ], dtype=torch.float32) tensor([[True, True, True], [True, True, True], [True, False, True]])</code></pre> <h3 class="section-heading" style="text-align: justify;">Element-Wise sử dụng c&aacute;c h&agrave;m</h3> <p style="text-align: justify;">Với c&aacute;c ph&eacute;p to&aacute;n element-wise của phần tử l&agrave; c&aacute;c h&agrave;m, c&oacute; thể giả sử rằng h&agrave;m được &aacute;p dụng cho từng phần tử của tensor.</p> <p style="text-align: justify;">Dưới đ&acirc;y l&agrave; một số v&iacute; dụ:</p> <pre class="language-python"><code>&gt; t.abs() tensor([[0., 5., 0.], [6., 0., 7.], [0., 8., 0.]]) &gt; t.sqrt() tensor([[0.0000, 2.2361, 0.0000], [2.4495, 0.0000, 2.6458], [0.0000, 2.8284, 0.0000]]) &gt; t.neg() tensor([[-0., -5., -0.], [-6., -0., -7.], [-0., -8., -0.]]) &gt; t.neg().abs() tensor([[0., 5., 0.], [6., 0., 7.], [0., 8., 0.]])</code></pre> <h4 style="text-align: justify;">Một số thuật ngữ</h4> <p style="text-align: justify;">C&oacute; một số c&aacute;ch kh&aacute;c để đề cập đến c&aacute;c ph&eacute;p to&aacute;n&nbsp;element-wise như sau:</p> <ul style="text-align: justify;"> <li>Element-wise</li> <li>Component-wise</li> <li>Point-wise</li> </ul> <p style="text-align: justify;">Nếu bạn gặp bất kỳ thuật ngữ n&agrave;o trong 3 thuật ngữ tr&ecirc;n đ&acirc;y, ch&uacute;ng đều c&oacute; nghĩa như nhau.</p> <h3 style="text-align: justify;">Kết Luận</h3> <p style="text-align: justify;">B&agrave;i n&agrave;y đ&atilde; gi&uacute;p ch&uacute;ng ta hiểu r&otilde; về c&aacute;c ph&eacute;p to&aacute;n element-wise v&agrave; c&aacute;ch ch&uacute;ng được &aacute;p dụng cho c&aacute;c ph&eacute;p to&aacute;n của tensor trong mạng neural v&agrave; Deep learning. Hi vọng bạn th&iacute;ch b&agrave;i viết n&agrave;y.</p> <p style="text-align: justify;">Hẹn gặp lại bạn trong c&aacute;c 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>