---
# System prepended metadata

title: MCLIP Usage Document
tags: [Tag(change me!)]

---

[TOC]
# Model Architecture
![COPY (2)](https://hackmd.io/_uploads/Sk-CM6Swp.png)

# Project Directory Structure
```python=
📂MCLIP/
    ├── 📂Config/
    │   ├── PreTrain_config.yaml
    │   └── FineTune_config.yaml
    ├── 📂Dataset/
    │   ├── 📂IMDB_dataset/
    │   │   ├── IMDB_ViT-B32_feature_dataset.pkl
    │   │   └── movie1K_list.csv
    │   └── 📂KKstream_dataset/
    │       ├── original_metadata.json
    │       ├── expanded_metadata.json
    │       ├── KKStream_original_ViT-B32_feature_dataset.pkl
    │       └── KKStream_expanded_ViT-B32_feature_dataset.pkl
    ├── 📂Logs/
    │   └── yyyy-MM-dd_HH-mm-ss/
    │       └──events.out   
    ├── 📂Output/
    │   └── yyyy-MM-dd_HH-mm-ss/
    │       ├── config.yaml
    │       ├── trained_genres_model_5.pth
    │       ├── trained_genres_model_10.pth
    │       └── trained_genres_model_15.pth
    ├── 📂ReleaseWeight/
    │   ├── 📂Pretrain/
    │   │   ├── config.yaml
    │   │   └── model_weight.pth
    │   └── 📂Finetune/ 
    │       ├── config.yaml
    │       └── model_weight.pth
    ├── 📂Feature_extractor/
    │   ├── CLIP_feature_extractor.py
    │   ├── create_kk_pklfile.py
    │   └── genres_pool_feature_extractor.py
    ├── 📂GenreClassificationPool/
    │   ├── genres_pool.json
    │   └── genres_pool_feature.pkl
    ├── 📂utils/
    │   ├── config_utils.py
    │   ├── data_utils.py
    │   ├── media_utils.py
    │   └── torch_utils.py
    ├── environment.yml
    ├── requirements.txt
    ├── argument_parser.py
    ├── dataset.py
    ├── dataloder.py
    ├── dcl.py
    ├── end_to_end_inferrance.py
    ├── loss.py
    ├── metric.py
    ├── model.py
    ├── preprocess.py
    ├── test.py
    ├── train.py
    └── train_config.py
```

# 環境配置
**版本:**
>* Linux => Ubuntu 20.04.6 LTS
>* python => 3.7
>* torch => 1.9.0
>* torchvision => 0.10.0
>* cuda => 11.1
>* numpy => 1.21.6


1. **創建虛擬環境:**
    ```bash
    conda create -n mclip python=3.7
    conda activate mclip
    ```

2. **Clone專案:**
    ```bash
    git clone https://github.com/AlanHuang0220/MovieCLIP.git
    ```
    
3. **pytorch安裝:**
    
    ```bash
    pip install torch==1.9.0+cu111 torchvision==0.10.0+cu111 torchaudio==0.9.0 -f https://download.pytorch.org/whl/torch_stable.html
    ```
4. **安裝相依套件:**

    ```bash
    pip install -r requirements.txt
    conda install ffmpeg
    ```
    
    ```txt
    info-nce-pytorch  #https://github.com/RElbers/info-nce-pytorch
    numpy==1.21.6
    matplotlib==3.5.3
    pyyaml==6.0.1
    tensorboardx==2.6.2.2
    ftfy regex tqdm
    git+https://github.com/openai/CLIP.git
    moviepy==1.0.3
    librosa==0.10.1
    ```
或者你也可以使用我們的`environment.yaml`進行環境的快速建立與配置只需兩步驟
1. **Clone專案:**
     ```bash
    git clone https://github.com/AlanHuang0220/MovieCLIP.git
    ```
2. **虛擬環境建置以及相依套件下載**
    ```bash
    conda env create -f environment.yml
    ```
    ```yaml
    name: MovieCLIP
    channels:
      - defaults
    dependencies:
      - python=3.7
      - ffmpeg
      - pip
      - pip:
        - "torch==1.9.0+cu111"
        - "torchvision==0.10.0+cu111"
        - "torchaudio==0.9.0"
        - "-f https://download.pytorch.org/whl/torch_stable.html"
        - info-nce-pytorch
        - numpy==1.21.6
        - matplotlib==3.5.3
        - pyyaml==6.0.1
        - tensorboardx==2.6.2.2
        - ftfy
        - regex
        - tqdm
        - git+https://github.com/openai/CLIP.git
        - moviepy==1.0.3
        - librosa==0.10.1
    ```

# Download Dataset
若有需要使用我們訓練模型時所使用到的資料集，可以使用以下網址進行下載。
資料集網址: https://gofile.me/7jNiV/x6ohxSt6c
Step1: 點擊如下圖所示 **下載資料夾** 
![image](https://hackmd.io/_uploads/HyQQG3Hw6.png)
Step2: 將下載下來的檔案解壓縮後，如下圖資料夾結構擺放
```python=
📂MCLIP/
    ├── 📂Dataset/
    │   ├── 📂IMDB_dataset/
    │   │   ├── IMDB_ViT-B32_feature_dataset.pkl
    │   │   └── movie1K_list.csv
    │   └── 📂KKstream_dataset/
    │       ├── original_metadata.json
    │       ├── expanded_metadata.json
    │       ├── KKStream_original_ViT-B32_feature_dataset.pkl
    │       └── KKStream_expanded_ViT-B32_feature_dataset.pkl
```
有關資料集中更詳細的資訊請查閱 -[Project Details底下的Dataset](##Dataset)

# Download Weight
模型權重網址:https://gofile.me/7jNiV/7codIEyhl

# Quick Start
**For Pre-Training**
```python
python train_config.py -config Config/PreTrain_config.yaml
```
**For Fine-Tuning**
```python
python train_config.py -config Config/FineTune_config_config.yaml
```
**For Inference**
```
#一部影片
python end_to_end_inferrance.py -video_path ID.mp4

#多部影片
python end_to_end_inferrance.py -video_folder folder_path
```
# Project Details
## Config
- **PreTrain_config.yaml**
![image](https://hackmd.io/_uploads/rJw0GvhIa.png)
```yaml=
dataset:
  type: CustomDataset # 目前支援 CustomDataset 和 KKStreamDataset
  args:
    pkl_file: "IMDB_ViT-B32_feature_dataset.pkl" # 對應的資料集特徵檔案路徑
    max_sequence_length: 1000 # 使用 CustomDataset 進行預訓練時，確保 max_sequence_length 大於資料集中最長的視頻長度（單位：秒）

> # KKStreamDataset 使用範例
# dataset:
#   type: KKStreamDataset
#   args:
#     original_pkl_file: "dataset/KKStream_dataset/KKStream_original_ViT-B32_feature_dataset.pkl" # KKstream 資料由兩部分組成：original_pkl_file 和 expanded_pkl_file
#     expanded_pkl_file: "dataset/KKStream_dataset/KKStream_expanded_ViT-B32_feature_dataset.pkl"
#     max_sequence_length: 1000 
#     filter_threshold: 0.93 # filter_threshold 範圍為 0-1，數值越高，向量間需要更相似才會被過濾掉
#     filter_mod: 'none' # 目前支援 none, only, concat, add 

data_loader:
  args:
    batch_size: 32 
    shuffle: false # 是否隨機洗牌資料
    train_ratio: 0.7 # 訓練資料集比例
    val_ratio: 0.1  # 驗證資料集比例
    test_ratio: 0.2 # 測試資料集比例
    split_dataset: # 是否分割資料集，若否，train_ratio, val_ratio, test_ratio 參數將不生效

model:
  type: MCLIP # 我們提出的模型架構
  args:
    embedding_dim: 512 # 嵌入的維度
    num_heads: 4 # Transformer中的注意力頭數量
    ff_hidden_dim: 1024 # Transformer中前饋層的維度
    num_block: 2 # Transformer Block的數量
    dropout: 0.1 # 正則化的丟棄率

optimizer:
  type: Adam # 可以更換成其他不同的優化器
  args:
    lr: 0.001 # 學習率

lr_scheduler:
  type: ExponentialLR # 可以更換成其他不同的學習率調整器
  args:
    gamma: 0.997 # 不同學習率調整器的參數會有所不同

loss:
  type: LossCalculator # 目前支援 LossCalculator 和 DCLLossCalculator
  args:
    temperature: 0.1 # InfoNCE Loss 中的溫度參數
    v_t_weight: 0.5 # 損失函數中不同組件的權重
    a_t_weight: 0.5
    va_t_weight: 1
    av_t_weight: 1

trainer:
  args:
    pretrain: True # 是否加載預訓練參數，若否，pretrain_weight 可為空
    pretrain_weight: "output/2023-10-15_02-26-17/trained_genres_model_30.pth" # 預訓練模型權重路徑
    epochs: 100 # 總訓練週期數
    save_dir: Output # 儲存模型權重的文件夾
    save_period: 5 # 儲存模型權重的頻率（單位：epochs）
```

## Dataset
- IMDB_dataset
    - IMDB_ViT-B32_feature_dataset.pkl
    `id` -> 電影 ID
    `genres_text`-> 電影類型的文字描述
    `visual_feature`-> 通過 CLIP Image Encoder 編碼的視覺特徵（每秒一幀）
    `audio_feature`->  電影聲音的音頻特徵，通過 mel 頻譜轉換後由 CLIP Image Encoder 編碼
    `genres_feature`-> 由 CLIP Text Encoder 編碼的**電影類型**文字特徵
    `description_feature`->  由 CLIP Text Encoder 編碼的**電影描述**文字特徵
    `poster_feature`->  由 CLIP Image Encoder 編碼的電影宣傳海報視覺特徵
    - movie1K_list.csv
    1100 movie IDs from MovieNet
- KKStream_dataset
    - original_metadata.json 
    - expanded_metadata.json
    - KKStream_original_ViT-B32_feature_dataset.pkl 
    - KKStream_expanded_ViT-B32_feature_dataset.pkl
    `id` -> 電影 ID
    `genres_text` -> 電影類型的文字描述
    `visual_feature` -> 通過 CLIP Image Encoder 編碼的視覺特徵（每秒一幀）
    `audio_feature` ->  電影聲音的音頻特徵，通過 mel 頻譜轉換後由 CLIP Image Encoder 編碼
    `genres_feature` -> 由 CLIP Text Encoder 編碼的**電影類型**文字特徵
## Logs

開始一次新的訓練時，會在 Logs 目錄中創建一個新文件夾。所有的訓練數據將被儲存於 **events.out** 文件中。要查看訓練結果，您可以使用以下命令：
```python 
tensorboard --logdir=Logs/yyyy-MM-dd_HH-mm-ss
```
## Output
開始一次新的訓練時，將在 Output 文件夾內創建一個新文件夾。這個文件夾將儲存當前訓練階段的**配置文件**，以及在訓練過程中保存的**模型權重**。
## ReleaseWeight
該文件夾將包含我們發布的兩個權重文件及其訓練配置文件。這些包括僅使用 MovieNet 提供的 1,100 部電影預告片預訓練的權重文件，以及使用 KKStream 提供的數據進行微調的版本。

## GenreClassificationPool
- **KKStream_genres_pool.json**
這個 JSON 文件指定了模型在推理過程中預期要預測的類別。由於這個模型的架構不受分類頭數量的限制，它允許動態地增加或減少希望預測的電影類型。
![image](https://hackmd.io/_uploads/BydeAunLT.png)
- **KKStream_genres_feature.pkl**

## utils
### config_utils.py
| Funtion | 功能描述 | 
| -------- | -------- |
| extract_config_components | 從配置字典中提取指定組件及其參數，返回包含這些組件信息的字典 |
| initialize_component | 根據配置初始化組件，如果組件類型未在模塊中找到或未指定，則拋出錯誤 |
### data_utils.py
| Funtion | 功能描述 | 
| -------- | -------- |
| read_metadata | 從JSON文件中讀取元數據，將每行解析為JSON對象並存儲在列表中 |
| genres_statistics_from_metadata | 從JSON文件讀取元數據，計算並打印每種類型的出現次數及總共有多少不同的類型 |
| check_for_genre | 檢查給定的數據中是否包含特定的目標類型，返回布林值以指示是否存在這些類型 |

### media_utils.py
| Funtion | 功能描述 | 
| -------- | -------- |
| split_movie_into_segments | 將輸入影片按照參數`segment_duration`所設定之秒數進行分割 |
| extract_audio | 這個函數從一個視頻文件中提取出音頻部分，並將其保存為MP3格式的文件 |
| extract_mfcc | 此函數從音頻文件中提取梅爾頻率倒譜係數（MFCC） |
| extract_mel_spectrogram |此函數計算一個音頻文件的梅爾頻譜圖 |
| visualize_mfcc | 這個函數用於視覺化MFCC |
| visualize_mel_spectrogram | 這個函數用於視覺化梅爾頻譜 |

### torch_utils.py
| Funtion                | 功能描述                                            | 
| ---------------------  | ------------------------------------------------- |
| create_new_ordereddict | 使用PyTorch的torch.load函數從文件加載狀態字典，並移除鍵名中的'module.'前綴，返回更新後的狀態字典                |
| set_random_seeds       | 為PyTorch、CUDA和NumPy設置隨機種子，以確保結果的可重現性 |
## Feature_extractor
若需要使用我們提取資料集特徵所使用的Feature Extractor則可以使用`CLIP_feature_extractor.py`裡我們所構建的Class `CLIPFeatureExtractor`

### CLIP_feature_extractor.py
- init：

    `model_scale`   模型大小
    `extract_fps`   每秒提取frame數
- extract_visual_feature：

    **功能:**
         從影片中提取視覺特徵
    
    **Parameters:**
        `video_path`: The path to the video file.

    **Returns:**
        List of visual features extracted from frames in the video.
- extract_image_feature：

    **功能:**
    Extract visual features from an image file or NumPy array.
    
    **Parameters:**
        `image_path_or_array`: The path to the image file or a NumPy array representing the image.

    **Returns:**
        Visual features extracted from the image.
- extrac_text_feture：
    
    **功能:**
     Extract features from text or a list of text.

    **Parameters:**
    `input_text`: Text or a list of texts.

    **Returns:**
    Text features obtained from the CLIP model.

# License
## 使用到的pakage及其對應的license
| Package                                 | License                                     |
|-----------------------------------------|---------------------------------------------|
| `info-nce-pytorch`                      | OSI Approved :: MIT License                 |
| `numpy`                                 | OSI Approved :: BSD License                 |
| `matplotlib`                            | OSI Approved :: Python Software Foundation License |
| `pyyaml`                                | OSI Approved :: MIT License                 |
| `tensorboardx`                          | OSI Approved :: MIT License                 |
| `ftfy`                                  | OSI Approved :: Apache Software License     |
| `regex`                                 | OSI Approved :: Apache Software License     |
| `tqdm`                                  | OSI Approved :: MIT License, OSI Approved :: Mozilla Public License 2.0 (MPL 2.0) |
| `git+https://github.com/openai/CLIP.git` | OSI Approved :: MIT License                |
| `moviepy`                               | OSI Approved :: MIT License                 |
| `librosa`                               | OSI Approved :: ISC License (ISCL)          |
| `ffmpeg`                                | LGPL-2.1-or-later          |

## 各個license的商用限制
| License Name                                  | Commercial Use           | Description |
|:--------------------------------------------- |:------------------------ |:----------- |
| OSI Approved :: MIT License                   | Allowed                  | 非常寬鬆的授權，允許修改、分發、私人使用和商業使用。限制最少。|
| OSI Approved :: BSD License                   | Allowed                  | 與 MIT 授權相似，允許商業使用、分發、修改和私人使用。|
| OSI Approved :: Python Software Foundation License | Allowed             | 寬鬆的授權，與 GPL 兼容。它允許商業使用、分發和修改。|
| OSI Approved :: Apache Software License       | Allowed                  | 寬鬆的授權，允許商業使用、分發和修改。它還為用戶提供了來自貢獻者的專利權利明確授予。|
| OSI Approved :: Mozilla Public License 2.0 (MPL 2.0) | Allowed           | 允許商業使用，但要求對授權代碼的修改在相同授權下共享。比 MIT 或 Apache 有更強的 copyleft。|
| OSI Approved :: ISC License (ISCL)            | Allowed                  | 非常類似於 MIT 授權，但限制更少，允許商業使用、修改和分發。|
| LGPL-2.1-or-later                             | Allowed with conditions  | 允許商業使用，但如果您修改代碼或在您的軟體中使用它，您必須在相同的授權下分發您的應用程式 (copyleft)。如果作為庫使用，庫本身的修改需要開源，但應用程式的其餘部分可以保持專有。|