動手做科研-day04-pytorch學習

yiranxie233發表於2024-08-20

寫練習時遇到的問題

1. 如何判斷一個張量的分佈服從[0,1)的均勻分佈?

t = torch.rand(5, 4)

怎麼證明這個是服從均勻分佈的?
解決:
均勻分佈的機率密度f(x)為:\(f(x) = \frac{1}{b-a}\), 其中x為[a, b],根據本例子為f(x) = 1, \(x \in [0,1]\)
均值\(\mu\)的計算為:$$\mu = \int_{a}^{b} x f(x) , dx$$, 所以,

\[\mu = \int_{0}^{1} x \cdot 1 \, dx = \int_{0}^{1} x \, dx = \left[\frac{x^2}{2}\right]_{0}^{1} = \frac{1}{2} = 0.5 \]

方差 \(\sigma^2\) 是根據以下公式計算的:

\[\sigma^2 = \int_{a}^{b} (x - \mu)^2 f(x) \, dx \]

對於均勻分佈 \([0, 1)\)

\[\sigma^2 = \int_{0}^{1} (x - 0.5)^2 \cdot 1 \, dx = \int_{0}^{1} (x - 0.5)^2 \, dx \]

分別計算三個部分的積分:

\[\int_{0}^{1} x^2 \, dx = \left[\frac{x^3}{3}\right]_{0}^{1} = \frac{1}{3} \]

\[\int_{0}^{1} x \, dx = \left[\frac{x^2}{2}\right]_{0}^{1} = \frac{1}{2} \]

\[\int_{0}^{1} \frac{1}{4} \, dx = \frac{1}{4} \cdot \left[x\right]_{0}^{1} = \frac{1}{4} \]

因此,方差為:

\[\sigma^2 = \frac{1}{3} - \frac{1}{2} + \frac{1}{4} = \frac{4}{12} - \frac{6}{12} + \frac{3}{12} = \frac{1}{12} \]

標準差 \(\sigma\) 是方差的平方根:

\[\sigma = \sqrt{\frac{1}{12}} \approx 0.2887 \]

寫出對應程式碼:

print(t.mean())
print(t.std())


"""
結果:
tensor(0.5417)
tensor(0.2662)
"""

是符合均勻分佈的, 得到解決

2. cat和stack的區別

GPT回答:

`torch.stack` 和 `torch.cat` 都是 PyTorch 中用於操作張量的函式,但它們的作用和行為有所不同。

### 1. `torch.cat`

- **功能**: `torch.cat` 是沿著已有的維度拼接張量。它不會建立新的維度,而是將多個張量在指定維度上連線起來。

- **引數**:
  - `tensors`:要連線的張量列表。
  - `dim`:沿著哪個維度進行拼接。

- **示例**:

  ```python
  import torch

  # 建立兩個形狀為 (2, 3) 的張量
  t1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
  t2 = torch.tensor([[7, 8, 9], [10, 11, 12]])

  # 沿著第0維拼接
  result = torch.cat((t1, t2), dim=0)
  print(result)
  ```

  輸出:

  ```
  tensor([[ 1,  2,  3],
          [ 4,  5,  6],
          [ 7,  8,  9],
          [10, 11, 12]])
  ```

  這裡 `t1` 和 `t2` 沿著第0維拼接,結果的形狀為 `(4, 3)`。

### 2. `torch.stack`

- **功能**: `torch.stack` 是沿著新維度拼接張量。與 `torch.cat` 不同,`torch.stack` 會建立一個新的維度。它不僅將張量拼接在一起,還會在指定的維度上增加一個新的維度。

- **引數**:
  - `tensors`:要堆疊的張量列表。
  - `dim`:新維度插入的位置。

- **示例**:

  ```python
  import torch

  # 建立兩個形狀為 (2, 3) 的張量
  t1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
  t2 = torch.tensor([[7, 8, 9], [10, 11, 12]])

  # 沿著新維度堆疊
  result = torch.stack((t1, t2), dim=0)
  print(result)
  ```

  輸出:

  ```
  tensor([[[ 1,  2,  3],
           [ 4,  5,  6]],

          [[ 7,  8,  9],
           [10, 11, 12]]])
  ```

  這裡 `t1` 和 `t2` 沿著新維度堆疊,結果的形狀為 `(2, 2, 3)`。

### 總結區別

- **維度變化**:
  - `torch.cat`: 沿著指定的已有維度拼接張量,拼接後張量的維度不會增加。
  - `torch.stack`: 在新維度上堆疊張量,拼接後張量的維度會增加一個。

- **使用場景**:
  - 使用 `torch.cat` 可以在不改變張量的維度數量的情況下拼接張量,常用於資料擴充套件、合併等操作。
  - 使用 `torch.stack` 可以在需要保留各張量獨立性(如生成批次)或需要增加新的維度的情況下堆疊張量。

由於torch.stack會有新的維度產生,需要reshape操作才能和cat的效果保持一致。

3. 記憶體共享

在 PyTorch 中,tensor 和 numpy 陣列之間可以相互轉換。轉換過程中有兩種情況需要注意:

共享記憶體:當你使用 tensor.numpy() 將一個 PyTorch 張量轉換為 NumPy 陣列時,得到的 NumPy 陣列與原始張量共享相同的記憶體。這意味著對其中任何一個的修改都會影響另一個。

不共享記憶體:當你直接使用 torch.tensor() 建立一個新的張量時,它會分配新的記憶體,不再與原來的張量或陣列共享記憶體。因此,此後對張量或陣列的修改不會影響另一個。

在進行梯度回傳時, 定義一個變數對網路權重進行賦值操作,發現更新後用==時權重沒有發生變化,但是實際上權重已經改變,由於記憶體共享的原因,造成更新的同時賦值的變數也被更新
利用。

x = tensor.clone()

建立一個記憶體相互獨立的變數

相關文章