###### tags: `pytorch入門`
[參考連結 microsoft介紹](https://docs.microsoft.com/zh-tw/learn/modules/intro-machine-learning-pytorch/)
# ch2 What is Tensors?
## 一、Tensors(張量)
> 張量的結構是類似array和matrices(矩陣)
> 我們使用張量去encode(編碼) 模型的輸入輸出和參數
> tensot和numpy會共享記憶體空間,因此較節省記憶體空間。
## 二、need moudles
```python=
import torch
import numpy as np
```
## 三、常用指令整理
```python=
# 1. 宣告tensor
t = torch.tensor(list) # list to tensor
t = torch.from_numpy(np_array) # ndarray to tensor
t = torch.ones_like(x_data)
t = torch.rand_like(x_data, dtype=torch.float)
t = torch.rand(shape)
t = torch.ones(shape)
t = torch.zeros(shape)
# 2. 查詢tensor attributes
print(f"Shape of tensor: {tensor.shape}")
print(f"Datatype of tensor: {tensor.dtype}")
print(f"Device tensor is stored on: {tensor.device}")
# 3. 使用gpu運算(這裡不確定,希望有大神指點)
if torch.cuda.is_available():
tensor = tensor.to('cuda')
# 4. tensor索引概念 = list = np.array
print('First row: ',tensor[0])
print('First column: ', tensor[:, 0])
print('Last column:', tensor[..., -1])
# 5. 矩陣運算
# 乘法
y1 = tensor @ tensor.T
y2 = tensor.matmul(tensor.T)
y3 = torch.rand_like(tensor)
torch.matmul(tensor, tensor.T, out=y3) # y3 = tensor @ tensor
# 矩陣內的值,逐個乘積
z1 = tensor * tensor
z2 = tensor.mul(tensor)
z3 = torch.rand_like(tensor)
torch.mul(tensor, tensor, out=z3)
# 6. Bridge with Numpy (tensor和ndarray會互相影響)
n = tensor.numpy() #tensor to ndarray
t = torch.from_numpy(ndarray) #ndarray to tensor
# 7. 特殊用法
agg = tensor.sum() # 將矩陣內所有值加起來,讓他變成torch.Size([1,1])
agg_item = agg.item() # torch.tensot.item() 取的這個值(純數值) #備註 只能在只有一個值時使用
print(agg_item, type(agg_item))
```
## 四、詳解
### 1. 各種宣告tensor (不論是直接宣告或轉換)
```python=
# 最原始 list to torch.tensor
data = [[1, 2],[3, 4]]
x_data = torch.tensor(data)
# ndarray to torch.tensor
np_array = np.array(data)
x_np = torch.from_numpy(np_array)
# 指定數值或隨機,大小則是指定的另一個torch.tensor
x_ones = torch.ones_like(x_data) # retains the properties of x_data
print(f"Ones Tensor: \n {x_ones} \n")
x_rand = torch.rand_like(x_data, dtype=torch.float) # overrides the datatype of x_data
print(f"Random Tensor: \n {x_rand} \n")
# 指定數值或隨機,大小則是以shape的方式指定
shape = (2,3,)
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)
print(f"Random Tensor: \n {rand_tensor} \n")
print(f"Ones Tensor: \n {ones_tensor} \n")
print(f"Zeros Tensor: \n {zeros_tensor}")
# 查詢tensor各屬性
tensor = torch.rand(3,4)
print(f"Shape of tensor: {tensor.shape}")
print(f"Datatype of tensor: {tensor.dtype}")
print(f"Device tensor is stored on: {tensor.device}")
```
### 2. Operation on Tensor 張量運算
```python=
# 使用gpu進行運算,We move our tensor to the GPU if available
if torch.cuda.is_available():
tensor = tensor.to('cuda')
# 類似numpy的索引功能,這部分概念相當於一般list
# Standard numpy-like indexing and slicing:
tensor = torch.ones(4, 4) # 類似[ [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
print('First row: ',tensor[0])
print('First column: ', tensor[:, 0])
print('Last column:', tensor[..., -1])
tensor[:,1] = 0 # [ [1, 0, 1, 1], [1, 0, 1, 1], [1, 0, 1, 1], [1, 0, 1, 1]]
print(tensor)
# 合併tensor,Joining tensors
#合併矩陣的概念 [1 1 1]和[2 2 2] => [1 1 1 2 2 2]
#[[1 1] [2 2]]和[[3 3] [4 4]] => [[1 1 3 3] [2 2 4 4]]
t1 = torch.cat([tensor, tensor, tensor], dim=1)
print(t1)
# 算術運算Arithmetic operations
# 矩陣乘法, 乘法符號@, 兩個都是乘法
y1 = tensor @ tensor.T
y2 = tensor.matmul(tensor.T)
y3 = torch.rand_like(tensor)
torch.matmul(tensor, tensor.T, out=y3) # y3 = tensor @ tensor.T
# 矩陣內的值 逐個乘積 (a_11 * b_11這樣)
z1 = tensor * tensor
z2 = tensor.mul(tensor)
z3 = torch.rand_like(tensor)
torch.mul(tensor, tensor, out=z3)
# Single-element tensors
agg = tensor.sum() # 將矩陣內所有值加起來,讓他變成torch.Size([1,1])
agg_item = agg.item() # torch.tensot.item() 取的這個值(純數值) #備註 只能在只有一個值時使用
print(agg_item, type(agg_item))
# In-place operations (不鼓勵使用 原因如第二項)
# Operations that store the result into the operand are called in-place.
# In-place operations save some memory, but can be problematic when computing derivatives because of an immediate loss of history. Hence, their use is discouraged.
print(tensor, "\n")
tensor.add_(5) #全部矩陣元素+5
print(tensor)
```
### 3. Bridge with NumPy
```python=
# Tensor to NumPy array
t = torch.ones(5)
n = t.numpy() # tensor to np.array
print(f"t: {t}")
print(f"n: {n}")
# 發生在tensor上的運算,會影響np.array。例如: tensor+5 => np.array通通+5
# A change in the tensor reflects in the NumPy array.
t.add_(1)
print(f"t: {t}")
print(f"n: {n}")
# NumPy array to Tenso
n = np.ones(5)
t = torch.from_numpy(n)
# 同理,np.array也會影響tensor
# Changes in the NumPy array reflects in the tensor.
np.add(n, 1, out=n)
print(f"t: {t}")
print(f"n: {n}")
```