# Cross Entropy vs KL divergence
## GAN
GAN 是非監督式學習的一種方法,由生成器和判別器組成,生成器會隨機取樣作為輸入,其目標盡可能讓輸出模仿真實樣本,而判別網路的輸入則為真實樣本以及生成器生出來的樣本,兩者相互對抗並輸出 real or fake。
簡單說就是用 G 模擬像是真圖 A 的假圖 B,並且比較 A, B,輸出 true, false

而在這其中判斷 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))
```