---
# System prepended metadata

title: '[GenAI][RAG] Building Multimodal Search and RAG。多模態搜尋與RAG - Overview of Multimodality'
tags: [Retrieval Augmented Generation, GenAI, Generative AI, Multimodal, RAG, Mulimodal]

---


### [AI / ML領域相關學習筆記入口頁面](https://hackmd.io/@YungHuiHsu/BySsb5dfp)
#### [Deeplearning.ai GenAI/LLM系列課程筆記](https://learn.deeplearning.ai/)
##### GenAI
- [Large Language Models with Semantic Search。大型語言模型與語義搜索 ](https://hackmd.io/@YungHuiHsu/rku-vjhZT)
- [LangChain for LLM Application Development。使用LangChain進行LLM應用開發](https://hackmd.io/1r4pzdfFRwOIRrhtF9iFKQ)
- [Finetuning Large Language Models。微調大型語言模型](https://hackmd.io/@YungHuiHsu/HJ6AT8XG6)
##### AI Agents
- [AI Agents in LangGraph](https://hackmd.io/@YungHuiHsu/BJTKpkEHC)
##### RAG
- [Preprocessing Unstructured Data for LLM Applications。大型語言模型(LLM)應用的非結構化資料前處理](https://hackmd.io/@YungHuiHsu/BJDAbgpgR)
- [Building and Evaluating Advanced RAG。建立與評估進階RAG](https://hackmd.io/@YungHuiHsu/rkqGpCDca)
- [[GenAI][RAG] Multi-Modal Retrieval-Augmented Generation and Evaluaion。多模態的RAG與評估
](https://hackmd.io/@YungHuiHsu/B1LJcOlfA)
- [[GenAI][RAG] Building Multimodal Search and RAG。多模態搜尋與RAG 
](https://hackmd.io/8jXegjZgSECNZqcv9UdwM)
 
--- 

# [Building Multimodal Search and RAG。多模態搜尋與RAG](https://learn.deeplearning.ai/courses/building-multimodal-search-and-rag/lesson/1/introduction)![image](https://hackmd.io/_uploads/B1O_TSLdR.png =50x)![image](https://hackmd.io/_uploads/HyOsaB8_0.png =50x)

講得很基礎、 
第二章以後大部分是Weaviate向量資料庫的操作API教學
RAG的部分講的不深、適合想學Weaviate操作的新手
如果對多模態基礎不了解的第一章可以看一下

## [Overview of Multimodality](https://learn.deeplearning.ai/courses/building-multimodal-search-and-rag/lesson/2/overview-of-multimodality)

- Multimodal Embedding Models
![image](https://hackmd.io/_uploads/SkhCAQ8OC.png =400x)

- Training Multimodal Models 
    - Start with specialist models
        - 每種資料類型有其獨特的特徵，因此需要專門的模型來捕捉這些特徵
        - 專家模型是針對特定類型資料（如圖像、文本、音頻等）進行訓練的模型
    - Unify the specialist models
![image](https://hackmd.io/_uploads/rygD1NI_0.png =500x)

- Unify the Models Using Contrastive Learning 
    * Process to train any embedding model 
        * 資料準備：收集多模態資料（如圖片和對應的描述文字）
        * 嵌入生成：使用專家模型生成各自的資料嵌入（向量表示）
        * 對比學習：在共享嵌入空間中，通過對比正樣本（如圖片和描述文字）和負樣本（不樣本的圖片和文字），學習有效的嵌入
    * Unify multiple models
        * 嵌入空間共享：將各專家模型的嵌入映射到同一向量空間
        * 對比損失：使用對比損失函數，最大化正樣本的相似度，最小化負樣本的相似度
    * Create one vector space
        - 一個統一的嵌入空間，使得不同模態的資料能夠在同一向量空間中進行比較和計算
    - Tune models by providing contrastive examples
        - 利用正、負樣本對進行訓練，調整模型參數，使正樣本對的嵌入更接近，負樣本對的嵌入更遠

- Understanding Contrastive Learning for Text。瞭解對比學習的概念，以文字為例
    
    ![image](https://hackmd.io/_uploads/S1YRIVIOC.png =500x)
    > - **學習之前**：
    >   - 錨點（藍色）與正樣本（綠色）和負樣本（紅色）的位置
    >   - 初始狀態下，錨點與正樣本和負樣本之間的距離可能不反映其實際的語義相似度
    > 
    > - **學習過程**：
    >   - **目標**：調整嵌入，使錨點更靠近正樣本，遠離負樣本
    >   - **機制**：通常通過對比損失函數實現，該函數鼓勵減少錨點與正樣本之間的距離，同時增加錨點與負樣本之間的距離
    > 
    > - **學習之後**：
    >   - 錨點（藍色）現在更接近正樣本（綠色），且遠離負樣本（紅色）
    >   - 模型已學會區分語義上相似和不相似的對，使其能更好地辨別相關和不相關的例子
 

- Contrastive Loss Function。對比學習損失函素
![image](https://hackmd.io/_uploads/SksewV8u0.png =500x)
 
 
> 1. **Encoder ($\theta$)**：
>    - 功能：編碼器處理每張圖片 ($I^a$, $I^+$, 和 $I^-$) 生成相應的嵌入 ($f^a$, $f^+$, 和 $f^-$)。
>    - 輸出：
>      - $f^a = \theta(I^a)$
>      - $f^+ = \theta(I^+)$
>      - $f^- = \theta(I^-)$
> 
> 2. **Distance Function ($\delta$)**：
>    - 目的：測量兩個嵌入之間的相似性或不相似性。
>    - 計算的距離類型：
>      - $\delta(f^a, f^+)$：錨點與正樣本之間的距離。
>      - $\delta(f^a, f^-)$：錨點與負樣本之間的距離。
> 
> 3. **學習目標**：
>    - **最小化 $\delta(f^a, f^+)$**：
>      - 目標：減少錨點與正樣本嵌入之間的距離，使它們更相似。
>    - **最大化 $\delta(f^a, f^-)$**：
>      - 目標：增加錨點與負樣本嵌入之間的距離，使它們更不相似。
> 
 
- Understanding Contrastive Learning for Multimodal Data
    類似的概念拓展到多模態資料
    ![image](https://hackmd.io/_uploads/Bk_NoNIO0.png =300x)
    > 圖-文配對。將圖-文配對相近的嵌入空間拉近、反之，則推遠
    - Finding contrastive examples
    ![image](https://hackmd.io/_uploads/S1dkhVLOA.png =400x)
    > - **Text Encoder（文本編碼器）**：
    >    - 輸入：一系列的文本輸入（如 "Pepper the aussie pup"）
    >    - 輸出：編碼後的文本表示 $T_1, T_2, \ldots, T_N$。
    >    - 目的：將文本輸入轉換為數值向量表示，捕捉文本的語義。
    > - **Image Encoder（圖像編碼器）**：
    >    - 輸入：一系列的圖像輸入（如狗的圖片）
    >    - 輸出：編碼後的圖像表示 $I_1, I_2, \ldots, I_N$
    >    - 目的：將圖像輸入轉換為數值向量表示，捕捉圖像的視覺特徵
    > - **矩陣結構**：
    >   - 矩陣顯示每個編碼圖像 $I_i$ 和每個編碼文本 $T_j$ 之間的互動
    >   - 矩陣中的每個單元格 $I_i \cdot T_j$ 代表圖像 $I_i$ 和文本 $T_j$ 之間的相似度或互動度量
    >  
    > - 目標是通過比較嵌入找到圖像和文本描述之間的最佳匹配。
    > - 在訓練過程中，模型被優化以最大化正確圖像-文本對的相似度得分，並最小化錯誤對的得分
    
- Understanding the Contrastive Loss Function
    ![image](https://hackmd.io/_uploads/BkGd0EIuR.png =400x)
 

    > - **嵌入生成**:
    >   - $\mathbf{q}_i = f(\text{圖片})$ 表示通過函數 $f$（例如圖像編碼器）對圖片進行編碼，生成查詢向量 $\mathbf{q}_i$。
    >   - $\mathbf{k}_i = g(\text{圖片})$ 表示通過函數 $g$ 對圖片進行編碼，生成鍵值向量 $\mathbf{k}_i$。
    > 
    > - 損失函數 $L_{\mathcal{I}, \mathcal{M}}$
    >       $$
    >       L_{\mathcal{I}, \mathcal{M}} = -\log \frac{\exp(\mathbf{q}_i^\top \mathbf{k}_i / \tau)}{\exp(\mathbf{q}_i^\top \mathbf{k}_i / \tau) + \sum_{j \ne i} \exp(\mathbf{q}_i^\top \mathbf{k}_j / \tau)}
    >       $$
    >  
    >     - 分子 $\exp(\mathbf{q}_i^\top \mathbf{k}_i / \tau)$: 表示查詢向量 $\mathbf{q}_i$ 與正樣本鍵值向量 $\mathbf{k}_i$ 的相似度，經過溫度參數 $\tau$ 縮放
    >     - 分母 $\exp(\mathbf{q}_i^\top \mathbf{k}_i / \tau) + \sum_{j \ne i} \exp(\mathbf{q}_i^\top \mathbf{k}_j / \tau)$: 包含了查詢向量 $\mathbf{q}_i$ 與所有鍵值向量（包括正樣本 $\mathbf{k}_i$ 和負樣本 $\mathbf{k}_j$）的相似度和
    >         - 分母特別排除了正樣本自己$\sum_{j \ne i}$，更強調負樣本的對比
    >         - 通過將正樣本的距離放在分母中，損失函數實際上是在計算錨點和正樣本之間相似度的相對機率。錨點和正樣本的相似度在所有樣本（包括正樣本和負樣本）中的比例
    >         
    >         包含正樣本在分母中有助於在同一範圍內進行比較，使得優化過程更穩定，損失函數範圍在 (0,1) 之間，有助於梯度穩定。這樣的設計強調了相對相似度，而不是絕對相似度
    >     - $\tau$: 溫度參數，控制相似度分佈的集中程度
    >     
    > 目標是最小化損失函數 $L_{\mathcal{I}, \mathcal{M}}$，即最大化查詢向量與正樣本鍵值向量之間的相似度，同時最小化與負樣本鍵值向量之間的相似度



## Lab 


核心程式碼
- Contrastive Loss Function
```python=
# The ideal distance metric for a positive sample is set to 1, for a negative sample it is set to 0      
class ContrastiveLoss(nn.Module):
    def __init__(self):
        super(ContrastiveLoss, self).__init__()
        self.similarity = nn.CosineSimilarity(dim=-1, eps=1e-7)

    def forward(self, anchor, contrastive, distance):
        # use cosine similarity from torch to get score
        score = self.similarity(anchor, contrastive)
        # after cosine apply MSE between distance and score
        return nn.MSELoss()(score, distance) #Ensures that the calculated score is close to the ideal distance (1 or 0)
```

- Model Training
    ```python=
    def train_model(epoch_count=10):#
        net = Network()
        lrs = []
        losses = []

        for epoch in range(epoch_count):
            epoch_loss = 0
            batches=0
            print('epoch -', epoch)
            lrs.append(optimizer.param_groups[0]['lr'])
            print('learning rate', lrs[-1])

            for anchor, contrastive, distance, label in tqdm(trainLoader):
                batches += 1
                optimizer.zero_grad()
                anchor_out = net(anchor.to(device))
                contrastive_out = net(contrastive.to(device))
                distance = distance.to(torch.float32).to(device)
                loss = loss_function(anchor_out, contrastive_out, distance)
                epoch_loss += loss
                loss.backward()
                optimizer.step()

            losses.append(epoch_loss.cpu().detach().numpy() / batches)
            scheduler.step()
            print('epoch_loss', losses[-1])

            # Save a checkpoint of the model
            checkpoint_path = os.path.join(checkpoint_dir, f'model_epoch_{epoch}.pt')
            torch.save(net.state_dict(), checkpoint_path)

        return {
            "net": net,
            "losses": losses
        }
    ```

#### 視覺化顯示embedding。Visualize the Vector Space!
- Generate 64d Representations of the Training Set


```python=
encoded_data = []
labels = []

with torch.no_grad():
    for anchor, _, _, label in tqdm(trainLoader):
        output = model(anchor.to(device))
        encoded_data.extend(output.cpu().numpy())
        labels.extend(label.cpu().numpy())

encoded_data = np.array(encoded_data)
labels = np.array(labels)
```


- Reduce Dimensionality of Data: 64d -> 3d
    - Apply PCA to reduce dimensionality of data from 64d -> 3d to make it easier to visualize!
    ```python=
    pca = PCA(n_components=3)
    encoded_data_3d = pca.fit_transform(encoded_data)
    ```
- Interactive Scatter Plot in 3d – with PCA
    ```python=
    scatter = go.Scatter3d(
        x=encoded_data_3d[:, 0],
        y=encoded_data_3d[:, 1],
        z=encoded_data_3d[:, 2],
        mode='markers',
        marker=dict(size=4, color=labels, colorscale='Viridis', opacity=0.8),
        text=labels, 
        hoverinfo='text',
    )
    
    # Create layout

    layout = go.Layout(
        title="MNIST Dataset - Encoded and PCA Reduced 3D Scatter Plot",
        scene=dict(
            xaxis=dict(title="PC1"),
            yaxis=dict(title="PC2"),
            zaxis=dict(title="PC3"),
        ),
        width=1000, 
        height=750,
    )
    ```
    ![image](https://hackmd.io/_uploads/BJ1kYBU_R.png =300x)

    - Scatterplot in 2d - with UMAP
    ```python=
    mapper = umap.UMAP(random_state=42, metric='cosine').fit(encoded_data)
    umap.plot.points(mapper, labels=labels);
    ```
    
    ![image](https://hackmd.io/_uploads/BkzGtSLu0.png =300x)
    
    - 觀察隨著訓練的epoch增加，embedding空間分布的變化
        每個資料點間距離越拉越開
        - epoch=0
            ![image](https://hackmd.io/_uploads/H1DKKSU_C.png =300x)
        - epoch=97
            ![image](https://hackmd.io/_uploads/HJHjFSL_0.png =300x)

...
後面章節大部分是Weaviate向量資料庫的操作API教學，揀選一些概念性的投影片放上
...

####  共享多模態向量空間（Shared Multimodal Vector Space）
![image](https://hackmd.io/_uploads/HkFx18I_C.png =500x)

- 將不同模態的數據映射到同一個向量空間，使得不同模態之間可以進行直接比較和運算(檢索)
- 不同模態的數據具有不同的特徵和結構。例如，圖像有像素值，文本有詞向量。共享多模態向量空間將這些異質數據轉換為統一的向量表示，使得不同模態的數據可以在同一平面上進行處理


![image](https://hackmd.io/_uploads/SyX71ULOR.png =500x)
![image](https://hackmd.io/_uploads/HJ-8JIUOC.png =500x)
- vector search
![image](https://hackmd.io/_uploads/rkysJUU_0.png =500x)




- Multivector Recommender Systems
![image](https://hackmd.io/_uploads/SJ46Q8IOR.png =500x)
- Specialized Embedding Models
![image](https://hackmd.io/_uploads/rJjgV8LOC.png  =500x)


---
## 補充
#### 其他對比學習損失函數設計
:::info
對比學習設計
- 公式
$$
L = -\log \frac{\exp(\text{sim}(v_i, v_j)/\tau)}{\sum_{k=1}^{N} \exp(\text{sim}(v_i, v_k)/\tau)}
$$


    - **$\text{sim}(v_i, v_j)$**：
      - 表示樣本 $v_i$ 和 $v_j$ 之間的相似度。
      - 通常使用余弦相似度來計算，公式為：
        $$
        \text{sim}(v_i, v_j) = \frac{v_i \cdot v_j}{\|v_i\| \|v_j\|}
        $$
      - 相似度值越高，表示兩個嵌入的相似度越高。

    - **$\tau$ (溫度參數)**：
      - 這是一個控制分佈集中程度的縮放因子。
      - $\tau$ 值越低，分佈越尖銳，模型更關注最相似的樣本對。
      - $\tau$ 值越高，分佈越平滑。



    1. **分子**(正樣本間的相似度)：
       $$
       \exp(\text{sim}(v_i, v_j)/\tau)
       $$
       - 計算錨點樣本 $v_i$ 和正樣本 $v_j$ 之間相似度的指數，並由溫度參數 $\tau$ 縮放。
       - 這個項強調 $v_i$ 和 $v_j$ 之間的相似度。

    2. **分母**(負樣本間的相似度)：
       $$
       \sum_{k=1}^{N} \exp(\text{sim}(v_i, v_k)/\tau)
       $$
       - 計算錨點樣本 $v_i$ 與批次中所有其他樣本 $v_k$ 之間相似度的指數和，並由 $\tau$ 縮放。
       - 包含正樣本和負樣本。


    4. **對數和負號**：
       $$
       -\log \left(   \right)
       $$
       - 取對數將機率轉換為對數機率，使損失更穩定，適合基於梯度的優化
           ![image](https://hackmd.io/_uploads/rJJR44IOR.png =300x)
           - 非常低機率的小變化（例如從 $0.001$ 到 $0.0001$）在其對數值中會產生顯著差異，例如，$\log(0.001) \approx -6.91$ 對比 $\log(0.0001) \approx -9.21$
            - 穩定性：對數函數的平滑效果防止非常小的機率在計算中引起不穩定。在優化模型時，極小的機率可能導致非常大的梯度，這會使優化過程變得不穩定或發散。對數轉換通過產生較為溫和的梯度值來緩解這一問題
       - 負號確保最大化正樣本對的機率（即提升模型）對應於最小化損失






- 直觀理解
    - 損失函數鼓勵模型使錨點 $v_i$ 和正樣本 $v_j$ 之間的相似度（分子）儘可能高，相較於錨點 $v_i$ 和所有其他樣本 $v_k$ 的相似度（分母）。
    - 通過最小化這個損失，模型學會區分正樣本對（相似項）和負樣本對（不相似項），有效地將相似項聚集在嵌入空間中，將不相似項分開。

:::
     