[TOC]
# 課程資訊
* [[講義下載]]( https://www.dropbox.com/s/673wyuwqk5a37rx/BDSE_v2023.07.pdf?dl=1)
* [[資料集下載]](
https://www.dropbox.com/s/vn1efjse01qvhrn/BDSE_v2023.03.tar?dl=1)
* [[課程補充筆記本]](https://share.goodnotes.com/s/VmX1d95YwrPNJGffvSeDpZ)
# 作業
1. Q: 在**模型權重數量差不多**時, 我們有兩種建模策略:
**(A) 寬但淺** (淺層網路; 隱藏層很少, 中間只激活少數次; 網路層內有較多神經元)
**(B) 窄但深** (深層網路; 中間會激活很多次; 網路層內有較少神經元)
這兩種建模策略哪一個可能比較好呢?
你可能要建立一個統計表格, 該表格包含: `model_setting`, `num_weights`, `accuracy`等欄位. 這樣會比較好回答此申論問題. 不用太嚴謹或複雜. 簡單實驗, 給出一些說明即可.
2. 使用 [learning rate排程器](https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/LearningRateScheduler) 將MLP模型的訓練, 做學習率排程.
# 7/22
## 課綱
- [x] CNN Continue
- [x] History (LeNet, VGGNet, GoogleNet, ResNet, DenseNet)
- [x] Code Demo
- [x] MNIST
- [ ] ~~(How to build ResNet)~~ (ResNet building block implementation as an exercise)
- [x] More on Optimizers
- [x] Vanilla RNN
- [x] LSTM
# 7/11
## 課綱
- [x] Code Refactoring
- [x] TF Keras Model Construction API: Create a custom layer
- [x] BatchNorm
- [x] Backpropagation
- [x] Activation
- [ ] Convolutional Neural Network
- [x] Basic theories
- [ ] Model overview
- [ ] Know how to build ResNet
## 補充
* Custom Layer
```python=
class MyLayer(tf.keras.layers.Layer):
def __init__(
self,
num_inputs: int = 3,
num_units: int = 5,
num_filters: int = 5,
activation: str = "relu",
**kwargs,
) -> None:
super().__init__(**kwargs)
self.dense1 = tf.keras.layers.Dense(
num_units,
input_shape=(num_inputs,),
activation=activation,
)
self.dense2 = tf.keras.layers.Dense(
num_units,
activation=activation,
)
self.conv1 = tf.keras.layers.Conv1D(
num_filters,
3,
padding='same',
input_shape=(num_inputs, 1),
activation=activation,
)
self.conv2 = tf.keras.layers.Conv1D(
num_filters,
3,
padding='same',
activation=activation,
)
self.flatten = tf.keras.layers.Flatten()
def __call__(self, x):
x1 = self.dense1(x) # [BS, num_inputs] -> [BS, num_units]
x1 = self.dense2(x1) # [BS, num_units] -> [BS, num_units]
x2 = tf.expand_dims(x, axis=-1) # [BS, num_inputs] -> # [BS, num_inputs, 1]
x2 = self.conv1(x2) # [BS, num_inputs, 1] -> [BS, num_inputs, num_filters]
x2 = self.conv2(x2) # [BS, num_inputs, num_filters] -> [BS, num_inputs, num_filters]
x2 = self.flatten(x2) # [BS, num_inputs, num_filters] -> [BS, num_inputs*num_filters]
print(f"x1 shape={x1.shape}")
print(f"x2 shape={x2.shape}")
return tf.concat([x1, x2], -1)
# x1 output: [BS, num_units]
# x2 output: [BS, num_inputs*num_filters]
# (1) use "concat" to combine:
# final output shape: [BS, num_units + num_inputs * num_filters]
# (2) use "+" to combine:
# final output shape: [BS, num_units] = [BS, num_inputs*num_filters]
# (however, the condition `num_units=num_inputs*num_filters` must hold)
```
* Tensor shape變換
```python=
import numpy as np
tmp = np.arange(5)
tmp.reshape((5, 1)).squeeze()
tmp.reshape((5, -1)).shape
tmp[..., np.newaxis].shape
tmp[...].shape
tmp[..., np.newaxis].shape
tmp[np.newaxis, ...].shape
np.expand_dims(tmp, axis=-1).shape
np.expand_dims(tmp, axis=0).shape
[np.expand_dims(tmp, axis=0)]*2
[array([[0, 1, 2, 3, 4]]), array([[0, 1, 2, 3, 4]])]
np.concatenate([np.expand_dims(tmp, axis=0)]*2, axis=0).shape
np.concatenate([np.expand_dims(tmp, axis=0)]*3, axis=0).shape
```
* Some layer's input / output shape
* **Dens**: `[num_samples=batch_size, num_features]` -> `[num_samples, num_dense_units]`
* **Conv2D**: `[num_samples=batch_size, Height, Width, num_channels]=[N, H, W, C]` -> `[num_samples, feature_map_height, feature_map_width, num_filters]`
* **Conv1D**: `[num_samples=batch_size, Width, num_channels]` -> `[num_samples, feature_map_width, num_filters]`
* **RNN / LSTM**: `[num_samples=batch_size, num_time_steps, num_features]`
* Subclassing-API
* 簡單兩層Dense堆疊的網路層
```python=
class MyLayer(tf.keras.layers.Layer):
def __init__(*args, **kwargs):
super().__init__(*args, **kwargs)
self.dense1 = tf.keras.layers.Dense(...)
self.dense2 = tf.keras.layers.Dense(...)
def __call__(x, ):
# 定義 正向傳遞 邏輯
return self.dense2(self.dense1(x))
```
等效於:
```python=
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(...))
model.add(tf.keras.layers.Dense(...))
```
* 兩個Conv, 兩個Dense組成的網路層
* Conv1
* [Pydantic](https://docs.pydantic.dev/latest/)
* [Pydantic-argparse](https://pydantic-argparse.supimdos.com/usage/arguments/)
* turn on inlay type hints in vscode 
# 7/9補充
* 深層網路為何需要activation function?
* $(\Gamma_{-20^\circ})(\Gamma_{+30^\circ})\vec{x} = \Gamma_{+10^\circ} \vec{x}$
* $(\Gamma_{-20^\circ})(K)(\Gamma_{+30^\circ})\vec{x} \neq \Gamma_{+10^\circ} \vec{x}$
* 矩陣K在這裡類比於一種擾動。該擾動使得**兩個**用於旋轉某向量的**旋轉矩陣**,無法**等效於一個旋轉矩陣**。我們用這樣的例子來表示,深層神經網路,激活函數(activation function)存在的必要性。Activation function在上述例子,相當於用做於擾動的矩陣K。
* Model finetuning(調參)時,若不用多折交叉驗證 (太耗時),則可考慮將資料切三份,以驗證模型表現: TRAIN+VAL用做 **模型選擇與訓練** "**Model Training + Model Selection**"; TEST用做 **模型效能驗證**。
* Recall或Precision的理解方式 
* Loss為MSE時, Maximum Likelihood 等同於 Minimize Loss 
* Gradient Descent 公式 
* Stochastic Gradient Descent; 以及何謂Epoch, 何謂Iteration 
* Cross Entropy Loss如何得到 (從統計誤差分佈假設出發)
* Softmax網路層如何運作 
# 7/8 補充
* 補充: Docker image 下載位置
* [DockerHub Official TensorFlow](https://hub.docker.com/r/tensorflow/tensorflow/tags)
* [NGC TensorFlow Image](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/tensorflow)
* [NGC TensorFlow Release Notes]( https://docs.nvidia.com/deeplearning/frameworks/tensorflow-release-notes/)
# 以Poetry 安裝環境
假設已經有:
* Anaconda Python
* NVIDIA GPU Driver
* CUDA
* cuDNN
---
1. 開啟anaconda prompt, 建立conda開發環境`(dlenv)`
```bash
conda create -n dlenv python==3.10.9 ipython==8.10.0
```
上述指令執行後, 按yes確認, 即可完成環境`(dlenv)`的建立.
:::info
:bulb: 你必須在conda `(base)` 的終端機環境執行上述指令. 如果你不是, 請透過`conda deactivate`離開某conda環境, 以回到conda的`(base)`環境.
:::
2. 切換至conda開發環境 `(dlenv)`
```bash
conda activate dlenv
```
3. 安裝Poetry
~~1. 於powershell一鍵安裝 Poetry~~
~~2. 將`C:\Users\student\AppData\Roaming\Python\Scripts`加至PATH~~
:::info
:bulb:之前我們嘗試在系統端安裝poetry.這可能不太好.
因為我們的DL開發環境`(dlenv)`, 是依附在conda內, 所以我們可能必須改在DL開發環境`(dlenv)`內安裝poetry (`pip install poetry`).
在DL開發環境`(dlenv)`內安裝poetry, 我們就可以避免poetry控制其他位置的python. 也就是說, 我們可縮限poetry只能管理DL開發環境`(dlenv)`內的套件.
如果你先前誤執行了:
```bash=
(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -
```
請透過以下指令將系統內的poetry移除:
```bash=
(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py - --uninstall
```
:::
請至`(dlenv)`環境, 執行`pip install poetry`以安裝套件管理工具.
3. 以vscode進入課程資料夾 `C:\Users\student\Desktop\BDSE_v2023.07\BDSE_v2023.03`
1. 開啟課程資料夾內的 `pyproject.toml` 檔案, 並於`[tool.poetry.dependencies]`段落, 編輯TensorFlow相關的套件:
```bash
tensorflow = "2.10.1"
tensorflow-addons = "^0.19.0"
tensorflow-io-gcs-filesystem = "0.31.0"
```
2. 終端機進入DL開發環境`(dlenv)`後, 執行`poetry lock`
(可以確立套件相依關係. 並將環境所有套件版本固定. 這個lock以及`pyproject.toml`文件之後可以給別人, 如此, 別人就會跟你是裝同樣的套件.)
3. 確定終端機在DL開發環境`(dlenv)`後, 執行`poetry install`
4. 安裝一些vscode延伸套件:
* pylance, python
* toml
* reload
* rainbow csv
* Black Formatter (Microsoft)
* 設定 -> 搜尋formatting -> formatting Provider 選 Black

* 搜尋on save -> Editor: Format on save確定打勾
* isort (Microsoft)
* 需要進去settings.json追加一些設定才能format on save.設定如下:
```json
{
"editor.fontSize": 18,
"liveServer.settings.donotVerifyTags": true,
"liveServer.settings.donotShowInfoMsg": true,
"editor.wordWrap": "on",
"editor.formatOnSave": true,
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter",
"editor.formatOnType": true,
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
},
},
"isort.args": [
"--profile",
"black",
],
"terminal.integrated.defaultProfile.windows": "Command Prompt",
"python.formatting.provider": "black",
"python.defaultInterpreterPath": "C:\\Users\\student\\anaconda3\\python.exe",
"window.zoomLevel": -1,
"notebook.formatOnSave.enabled": true,
}
```
* Remote SSH (Microsoft)
* Concept:
* Linting: Pylance
* Formatting: Black
* coding style
* google style: https://google.github.io/styleguide/pyguide.html
* to allow people be happy about your functions, classes:
* type annotation is important
* docstring is also important
---
改用 pip 安裝
https://chat.openai.com/share/cc46158f-4844-4b0a-9dd9-f7b0e6cd2f98
# GPU環境設置
可能的安裝方式:
1. Windows -> NVIDIA GPU Driver -> WSL2(Linux) -> Docker -> 啟動TensorFlow, PyTorch等 官方維護的 Docker image
* Google TensorFlow(+keras) / Facebook PyTorch Docker image 裡面 暗藏了 CUDA (NVIDIA GPU開發框架), cuDNN(Deep Neural Network 函式庫), TensorFlow
2. Linux -> NVIDIA GPU Driver -> Docker -> 啟動TensorFlow, PyTorch等 官方維護的 Docker image
3. Windows -> NVIDIA Driver (NVIDIA顯卡驅動) → CUDA (NVIDIA顯卡軟體開發框架) → cuDNN (用於NVIDIA顯卡運算的神經網路函式庫) → TensorFlow。
## GPU相關套件 - 於 Windows 內直接安裝
安裝順序: NVIDIA Driver (NVIDIA顯卡驅動) → CUDA (NVIDIA顯卡軟體開發框架) → cuDNN (用於NVIDIA顯卡運算的神經網路函式庫) → TensorFlow。
0. 安裝[NVIDIA Driver](https://www.nvidia.com/Download/index.aspx)
(此步驟可略過,因為教室的機器應該已經安裝好NVIDIA驅動程式)
1. 啟動 `NVSMI` (NVIDIA System Management Interface)
開啟終端機 (如GIT BASH或Windows命令提示字元), 輸入`nvidia-smi`後, 按Enter, 即可顯示出GPU使用率等資訊。此步驟若能成功執行,也代表驅動程式應已正常安裝。
2. 安裝[CUDA v11.6.1](https://developer.nvidia.com/cuda-toolkit)。[[下載連結]](https://developer.download.nvidia.com/compute/cuda/11.6.1/local_installers/cuda_11.6.1_511.65_windows.exe)
3. 安裝[cuDNN v 8.4.0 (需與CUDA v11.6.1相容)](https://developer.nvidia.com/cudnn)。[[下載連結]](https://www.dropbox.com/s/vg4yp1cf5hvf2p3/cudnn-windows-x86_64-8.4.0.27_cuda11.6-archive.zip?dl=1)
將解壓縮後的cuDNN資料夾內的檔案, 逐一複製到```C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.6```。
4. 執行以下指令,確定NVIDIA CUDA Compiler (NVCC)有被安裝:
```nvcc -V```
如果有正常執行,表示CUDA應該可以使用。
5. 安裝TensorFlow:
1. 執行 ```pip install tensorflow-gpu``` 即可完成安裝。
2. 檢查TensorFlow是否可把張量丟到GPU
```python
In [1]: import tensorflow as tf
In [2]: tf.__version__
Out[2]: '2.10.1'
In [3]: import numpy as np
In [4]: tmp = np.random.normal(0, 1, (3, 3))
In [5]: tmp
Out[5]:
array([[-0.58497332, 0.91560168, 0.35745953],
[ 0.36502097, 0.81025645, 1.17180727],
[ 0.50818861, -1.05783736, -1.82408266]])
In [6]: tmp = tmp.astype(np.float32)
In [7]: tmp.dtype
Out[7]: dtype('float32')
In [8]: tmp = tf.constant(tmp)
2021-12-28 20:23:09.054421: I tensorflow/core/platform/cpu_feature_guard.cc:151] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX AVX2
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2021-12-28 20:23:09.522473: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 2774 MB memory: -> device: 0, name: NVIDIA GeForce GTX 1050 Ti, pci bus id: 0000:01:00.0, compute capability: 6.1
In [9]: tmp.device
Out[9]: '/job:localhost/replica:0/task:0/device:GPU:0'
```
如有出現`GPU:0`字眼,表示GPU已可正常使用。
6. 修復TensorFlow Bug
很不幸的,目前(2022年12月),發現新版TensorFlow `v2.10.1`在Windows系統上使用卷基層做模型推論的時候會遇到錯誤 (與`zlibwapi.dll`相關)。如果你有遇到這個問題,可將: `C:\Program Files\NVIDIA Corporation\Nsight Systems 2021.5.2\host-windows-x64\zlib.dll` 更名,並且複製到 `C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.6\bin\zlibwapi.dll` 。
複製完後,簡單將一個隨機張量丟進一個卷積層,即可確認問題是否解決。
# 參考連結
* https://www.youtube.com/@ArjanCodes
* Find state-of-art model implementations (if papers are with codes :arrow_right: :100:): https://paperswithcode.com
* Understand CNN basics (:100: you must read this, understand every lines of words): https://cs231n.github.io
* karparthy: https://www.youtube.com/results?search_query=karparthy
* Learn Deep Learning basics (Wow! Learning by doing! :100:): https://zh.d2l.ai
* Machine Learning basic theories (:100: for those who wants to understand every general bits of maths in Machine Learning): https://cs229.stanford.edu/notes2022fall/main_notes.pdf
* Understand Backpropagation: https://www.cs.toronto.edu/~hinton/absps/NatureDeepReview.pdf
* Python Machine Learning (Sebastian Raschka)
* Keras book (API參考用?) https://www.manning.com/books/deep-learning-with-python
---
wengchihung@gmail.com