# Cross Entropy vs KL divergence ## GAN GAN 是非監督式學習的一種方法,由生成器和判別器組成,生成器會隨機取樣作為輸入,其目標盡可能讓輸出模仿真實樣本,而判別網路的輸入則為真實樣本以及生成器生出來的樣本,兩者相互對抗並輸出 real or fake。 簡單說就是用 G 模擬像是真圖 A 的假圖 B,並且比較 A, B,輸出 true, false ![截圖 2025-03-15 下午6.53.44](https://hackmd.io/_uploads/BkUrhRz2kg.png) 而在這其中判斷 A, B 相似度的損失函式為 Binary Cross Entropy(二分類交叉熵損失): $$ max_{D} V(D,G) = \mathbb{E}_{x \sim p_{\text{data}}(x)}[\log D(x)] + \mathbb{E}_{z \sim p_z(z)}[\log(1 - D(G(z)))] $$ 對於真實資料 $x$,希望 discriminator(x) 越接近 1,而對於生成器生出來的 $z$ 則希望 discriminator(z) 越接近 0,真正的目標是讓下式盡量相等,這樣就可以知道模擬出來的圖片其實跟真的沒兩樣,比如 deepfake 內部訓練的GAN: $discriminator(x)=1-discriminator(z)$ 而 cross entropy 中的 max 是為了找到其中一組對抗結果最接近 1,這樣就代表說他是這一個訓練週期和真實圖片最像的模擬圖片。 ## KL divergence 用來計算機率之間的距離,此處的散度其實指的是兩者的距離有多散,算是最基礎的比較差異工具(計算兩者比例)。而 cross entropy 則是直接地計算兩者差異 **KL:** $$ D_{KL}(P || Q)= \sum_i P(i)log(\frac{P(i)}{Q(i)}) $$ **cross entropy:** $$ H(p,q)=− i ∑ p(i)log(q(i)) $$ **entropy** $$ H(p)=− i ∑ ​ p(i)log(p(i)) $$ ## 三者關係 1. $$ H(p,q) = H(p) + D_{KL}(p||q) $$ $$ H(q,p) = H(q) + D_{KL}(q||p) $$ 2. 展開可得三者其實環環相扣 $$ H(p,q)=−i ∑p(i)log(q(i))=−i∑p(i)log(p(i))+i∑p(i)[(log(p(i))−log(q(i))]=H(p)+D_{KL}(p∥q) $$ [**code**](https://colab.research.google.com/drive/1GHlWB-ac-37dor9FxiwoS1pVwwTBBxJf?usp=sharing) ## Ref [機器學習 ML NOTE Generative Adversarial Network, GAN 生成對抗網路](https://medium.com/%E9%9B%9E%E9%9B%9E%E8%88%87%E5%85%94%E5%85%94%E7%9A%84%E5%B7%A5%E7%A8%8B%E4%B8%96%E7%95%8C/%E6%A9%9F%E5%99%A8%E5%AD%B8%E7%BF%92-ml-note-generative-adversarial-network-gan-%E7%94%9F%E6%88%90%E5%B0%8D%E6%8A%97%E7%B6%B2%E8%B7%AF-c672125af9e6) [KL Divergence vs cross entropy](https://hackmd.io/@kk6333/Byp2LxHes) [KL Divergence intro](https://youtu.be/SxGYPqCgJWM?si=OmWQ4ymddoLC1mw3) #### GPT **prompt:** 請用程式比較 KL divergence, cross entropy, entropy,只給我程式碼 **ans:** ```python= import numpy as np # 定義一個小常數防止 log(0) EPS = 1e-12 def entropy(p): """ 計算分布 p 的熵 (Entropy) H(p) = -Σ p(x) log p(x) """ return -np.sum(p * np.log(p + EPS)) def cross_entropy(p, q): """ 計算分布 p 與 q 之間的交叉熵 (Cross Entropy) H(p, q) = -Σ p(x) log q(x) """ return -np.sum(p * np.log(q + EPS)) def kl_divergence(p, q): """ 計算分布 p 與 q 之間的 KL Divergence D_KL(p || q) = Σ p(x) [log p(x) - log q(x)] """ return np.sum(p * (np.log(p + EPS) - np.log(q + EPS))) # 定義兩個示例機率分布 # p: 真實分布 (例如 one-hot 標籤展開的分布,這裡用較平滑的分布示例) p = np.array([0.7, 0.2, 0.1]) # q: 模型預測的分布 q = np.array([0.6, 0.3, 0.1]) # 計算熵、交叉熵和 KL Divergence H_p = entropy(p) H_pq = cross_entropy(p, q) KL = kl_divergence(p, q) print("Entropy of p: ", H_p) print("Cross Entropy (H(p,q)): ", H_pq) print("KL Divergence (D_KL(p||q)): ", KL) # 根據公式 H(p,q) = H(p) + D_KL(p||q) 檢查兩者是否相等 print("H(p) + D_KL(p||q) = ", H_p + KL) print("Relation holds? ", np.allclose(H_pq, H_p + KL)) # -------------------------------------------------- # 更換 q 的值,觀察變化 q2 = np.array([0.8, 0.1, 0.1]) H_pq2 = cross_entropy(p, q2) KL2 = kl_divergence(p, q2) print("\n-- Changing q to q2 = [0.8, 0.1, 0.1] --") print("Cross Entropy (H(p,q2)): ", H_pq2) print("KL Divergence (D_KL(p||q2)): ", KL2) print("H(p) + D_KL(p||q2) = ", H_p + KL2) print("Relation holds? ", np.allclose(H_pq2, H_p + KL2)) ```