《Few-Shot Domain Adaptation For End-to-End Communication》
0.摘要
为解决E2E通信中信道环境变化需重新训练编解码器的问题,提出一种小样本域自适应方法(few-shot domain adaptation
)。
与传统的训练阶段无监督或半监督的域自适应方法不同,提出的方法已有一个训练好的基于源域数据
的自动编码器(在测试阶段
用少量贴标签的
样本适应目标域)。此外,一种基于混合高斯密度网络
(Gaussian mixture density network,MDN
)的生成信道模型
和一种利用仿射变换(affine transformations)
的MDN的正则化的参数高效的自适应技术被提出。然后,学习的仿射变换用于在解码器输入处设计最优变换以补偿分布偏移
,并有效地呈现到接近源分布的解码器输入。
实验证明,提出的使用少量目标域样本进行域自适应的有效性(在毫米波FPGA上测试)。
1.Primer(入门) on autoencoder-based end-to-end communication
1.1.Notations(基本定义)
-
Input message: y ∈ Y : = { 1 , ⋯ , m } y \in \mathcal{Y}:=\{1, \cdots, m\} y∈Y:={1,⋯,m}
-
The input message y y y is mapped into a one-hot-coded vector 1 y {1}_{y} 1y,then get z \mathbf{z} z and Z \mathcal{Z} Z ( Z \mathcal{Z} Z is the constellation of the autoencoder):
1 y {1}_{y} 1y
z = E θ e ( 1 y ) \mathbf{z}=\mathbf{E}_{\boldsymbol{\theta}_e}\left(\mathbf{1}_y\right) z=Eθe(1y)
Z = { E θ e ( 1 1 ) , ⋯ , E θ e ( 1 m ) } \mathcal{Z}=\left\{\mathbf{E}_{\boldsymbol{\theta}_e}\left(\mathbf{1}_1\right), \cdots, \mathbf{E}_{\boldsymbol{\theta}_e}\left(\mathbf{1}_m\right)\right\} Z={Eθe(11),⋯,Eθe(1m)}
-
A communication channel, represented by an unknown conditional probability density: p ( x ∣ z ) p(\mathbf{x}|\mathbf{z}) p(x∣z)
-
The decoder is essentially a classifier whose input-output mapping as below and P θ d ( y ∣ x ) P_{\boldsymbol{\theta}_d}(y \mid \mathbf{x}) Pθd(y∣x) is the predicted probability of class y given x.
D θ d ( x ) : = [ P θ d ( 1 ∣ x ) , ⋯ , P θ d ( m ∣ x ) ] \mathbf{D}_{\boldsymbol{\theta}_d}(\mathbf{x}):=\left[P_{\boldsymbol{\theta}_d}(1 \mid \mathbf{x}), \cdots, P_{\boldsymbol{\theta}_d}(m \mid \mathbf{x})\right] Dθd(x):=[Pθd(1∣x),⋯,Pθd(m∣x)]
- The class with the highest predicted probability is the decoded message
y ^ ( x ) = argmax y ∈ Y P θ d ( y ∣ x ) \widehat{y}(\mathbf{x})=\operatorname{argmax}_{y \in \mathcal{Y}} P_{\boldsymbol{\theta}_d}(y \mid \mathbf{x}) y (x)=argmaxy∈YPθd(y∣x)
- As in standard classification, the performance metric of the autoencoder is the symbol error rate (SER)
E ( x , y ) [ 1 ( y ^ ( x ) ≠ y ) ] \mathbb{E}_{(\mathbf{x}, y)}[\mathbb{1}(\widehat{y}(\mathbf{x}) \neq y)] E(x,y)[1(y (x)=y)]
1.2.Generative Channel Model(生成信道模型)
为了使用SGD优化学习编解码网络特征,decoder到encoder需要有一个可微的反向传播路径,尝试用 P θ c ( x ∣ z ) P_{\boldsymbol{\theta}_c}(\mathbf{x} \mid \mathbf{z}) Pθc(x∣z)近似真实信道 p ( x ∣ z ) p(\mathbf{x}|\mathbf{z}) p(x∣z),具体 P θ c ( x ∣ z ) P_{\boldsymbol{\theta}_c}(\mathbf{x} \mid \mathbf{z}) Pθc(x∣z)的建模如下
P θ c ( x ∣ z ) = ∑ i = 1 k π i ( z ) N ( x ∣ μ i ( z ) , Σ i ( z ) ) , z ∈ { E θ e ( 1 1 ) , ⋯ , E θ e ( 1 m ) } P_{\boldsymbol{\theta}_c}(\mathbf{x} \mid \mathbf{z})=\sum_{i=1}^k \pi_i(\mathbf{z}) N\left(\mathbf{x} \mid \boldsymbol{\mu}_i(\mathbf{z}), \boldsymbol{\Sigma}_i(\mathbf{z})\right), \quad \mathbf{z} \in\left\{\mathbf{E}_{\boldsymbol{\theta}_e}\left(\mathbf{1}_1\right), \cdots, \mathbf{E}_{\boldsymbol{\theta}_e}\left(\mathbf{1}_m\right)\right\} Pθc(x∣z)=∑i=1kπi(z)N(x∣μi(z),Σi(z)),z∈{Eθe(11),⋯,Eθe(1m)}
该建模使用混合高斯(Gaussian mixtures),何谓Gaussian mixtures?下面详解
参考[1],
1.2.1.混合高斯模型
- 单高斯模型(Gaussian single model, GSM)
一维高斯分布的概率密度函数如下:
f ( x ) = 1 2 π σ exp ( − ( x − μ ) 2 2 σ 2 ) f(x)=\frac{1}{\sqrt{2 \pi} \sigma} \exp \left(-\frac{(x-\mu)^2}{2 \sigma^2}\right) f(x)=2πσ1exp(−2σ2(x−μ)2) , X ∼ N ( μ , σ 2 ) X \sim N\left(\mu, \sigma^2\right) X∼N(μ,σ2)
多维变量 X = ( x 1 , x 2 , … x n ) X=\left(x_1, x_2, \ldots x_n\right) X=(x1,x2,…xn) 的联合概率密度函数为:
f ( X ) = 1 ( 2 π ) d / 2 ∣ Σ ∣ 1 / 2 exp [ − 1 2 ( X − u ) T Σ − 1 ( X − u ) ] , X = ( x 1 , x 2 … x n ) f(X)=\frac{1}{(2 \pi)^{d / 2}|\Sigma|^{1 / 2}} \exp \left[-\frac{1}{2}(X-u)^T \Sigma^{-1}(X-u)\right], X=\left(x_1, x_2 \ldots x_n\right) f(X)=(2π)d/2∣Σ∣1/21exp[−21(X−u)TΣ−1(X−u)],X=(x1,x2…xn)
其中:
d
d
d :变量维度。对于二维高斯分布,有
d
=
2
\mathrm{d}=2
d=2;
u
=
(
u
1
u
2
⋯
u
n
)
u=\left(\begin{array}{l}u_1 \\ u_2 \\ \cdots \\ u_n\end{array}\right)
u=
u1u2⋯un
, 各维变量的均值;
Σ
\Sigma
Σ : 协方差矩阵,描述各维变量之间的相关度。对于二维高斯分布有:
Σ
=
[
δ
11
δ
12
δ
21
δ
22
]
\Sigma=\left[\begin{array}{ll} \delta_{11} & \delta_{12} \\ \delta_{21} & \delta_{22} \end{array}\right]
Σ=[δ11δ21δ12δ22]
- 混合高斯模型(Gaussian mixture model, GMM)
更一般化的描述为:假设混合高斯模型由K个高斯模型组成(即数据包含K个类),则GMM的概率密度函数如下:
p
(
x
)
=
∑
k
=
1
K
p
(
k
)
p
(
x
∣
k
)
=
∑
k
=
1
K
π
k
N
(
x
∣
u
k
,
Σ
k
)
p(x)=\sum_{k=1}^K p(k) p(x \mid k)=\sum_{k=1}^K \pi_k N\left(x \mid u_k, \Sigma_k\right)
p(x)=k=1∑Kp(k)p(x∣k)=k=1∑KπkN(x∣uk,Σk)
其中,
p
(
x
∣
k
)
=
N
(
x
∣
u
k
,
Σ
k
)
p(x \mid k)=N\left(x \mid u_k, \Sigma_k\right)
p(x∣k)=N(x∣uk,Σk) 是第 个
k
k
k 高斯模型的概率密度函数,可以看成选定第 个模
k
k
k 型后, 该模型产生
x
x
x的概率;
p
(
k
)
=
π
k
p(k)=\pi_k
p(k)=πk 是第
k
k
k 个高斯模型的权重,称作选择第
k
k
k 个模型的先验概率,且满足
∑
k
=
1
K
π
k
=
1
\sum_{k=1}^K \pi_k=1
∑k=1Kπk=1。
所以,混合高斯模型并不是什么新奇的东西,它的本质就是融合几个单高斯模型,来使得模型更加复杂,从而产生更复杂的样本。理论上,如果某个混合高斯模型融合的高斯模型个数足够多,它们之间的权重设定得足够合理,这个混合模型可以拟合任意分布的样本。
1.2.2.混合高斯模型(本文的应用)
本文对于 P θ c ( x ∣ z ) P_{\boldsymbol{\theta}_c}(\mathbf{x} \mid \mathbf{z}) Pθc(x∣z)的建模是混合高斯模型
P θ c ( x ∣ z ) = ∑ i = 1 k π i ( z ) N ( x ∣ μ i ( z ) , Σ i ( z ) ) , z ∈ { E θ e ( 1 1 ) , ⋯ , E θ e ( 1 m ) } P_{\boldsymbol{\theta}_c}(\mathbf{x} \mid \mathbf{z})=\sum_{i=1}^k \pi_i(\mathbf{z}) N\left(\mathbf{x} \mid \boldsymbol{\mu}_i(\mathbf{z}), \boldsymbol{\Sigma}_i(\mathbf{z})\right), \quad \mathbf{z} \in\left\{\mathbf{E}_{\boldsymbol{\theta}_e}\left(\mathbf{1}_1\right), \cdots, \mathbf{E}_{\boldsymbol{\theta}_e}\left(\mathbf{1}_m\right)\right\} Pθc(x∣z)=∑i=1kπi(z)N(x∣μi(z),Σi(z)),z∈{Eθe(11),⋯,Eθe(1m)}
π i ( z ) \pi_i(\mathbf{z}) πi(z)可以用 s o f t m a x softmax softmax函数建模, π i ( z ) = e α i ( z ) / ∑ j = 1 k e α j ( z ) , ∀ i ∈ [ k ] \pi_i(\mathbf{z})=e^{\alpha_i(\mathbf{z})} / \sum_{j=1}^k e^{\alpha_j(\mathbf{z})}, \forall i \in[k] πi(z)=eαi(z)/∑j=1keαj(z),∀i∈[k],其中 α i ( z ) ∈ R \alpha_i(\mathbf{z}) \in \mathbb{R} αi(z)∈R是Prior logits的一部分。
对于包含 i i i的未知变量参数化, ϕ i ( z ) T = [ α i ( z ) , μ i ( z ) T \phi_i(\mathbf{z})^T=\left[\alpha_i(\mathbf{z}), \boldsymbol{\mu}_i(\mathbf{z})^T\right. ϕi(z)T=[αi(z),μi(z)T, vec ( Σ i ( z ) ) T ] \left.\operatorname{vec}\left(\boldsymbol{\Sigma}_i(\mathbf{z})\right)^T\right] vec(Σi(z))T]
结合所有的参数, ϕ ( z ) T = [ ϕ 1 ( z ) T , ⋯ , ϕ k ( z ) T ] \phi(\mathbf{z})^T=\left[\phi_1(\mathbf{z})^T, \cdots, \phi_k(\mathbf{z})^T\right] ϕ(z)T=[ϕ1(z)T,⋯,ϕk(z)T]
备注:Prior logits是指在一个分类模型中,每个类别的先验概率对应的logit值。在softmax回归中,每个类别的概率由其对应的logit值通过softmax函数转换而来。在有些情况下,我们可能需要在训练过程中对先验概率进行调整,这时我们可以通过修改prior logits的值来实现。例如,在样本类别分布不均衡的情况下,我们可以通过增加少数类别的prior logits的值来平衡样本分布,从而提高模型的性能。
1.2.3.预测参数
利用高斯混合密度网络(Gaussian mixture density network,MDN)预测建模 P θ c ( x ∣ z ) P_{\boldsymbol{\theta}_c}(\mathbf{x} \mid \mathbf{z}) Pθc(x∣z)的混合高斯模型的参数 M θ c \mathbf{M}_{\boldsymbol{\theta}_c} Mθc , ϕ ( z ) = M θ c ( z ) \phi(\mathbf{z})=\mathbf{M}_{\boldsymbol{\theta}_c}(\mathbf{z}) ϕ(z)=Mθc(z), θ c {\theta}_c θc即为MDN网络的参数
1.3小结
为什么使用MDN?
- 强大的近似拟合能力
- 便于分析计算,适用于这里域自适应的场景
- 对于无线通信建模是有效的
autoencoder的输入输出函数如下:
f θ ( 1 y ) = D θ d ( h θ c ( E θ e ( 1 y ) , u ) ) \mathbf{f}_{\boldsymbol{\theta}}\left(\mathbf{1}_y\right)=\mathbf{D}_{\boldsymbol{\theta}_d}\left(\mathbf{h}_{\boldsymbol{\theta}_c}\left(\mathbf{E}_{\boldsymbol{\theta}_e}\left(\mathbf{1}_y\right), \mathbf{u}\right)\right) fθ(1y)=Dθd(hθc(Eθe(1y),u))
需要说明的是,信道采样函数 h θ c \mathbf{h}_{\boldsymbol{\theta}_c} hθc不可微,需借助Gumbel-Softmax。
2.提出的方法
2.1.问题描述
x \mathbf{x} x: channel output,
y y y: message (class label),
z \mathbf{z} z: input (symbol)
p ( x , y , z ) p(\mathbf{x}, y, \mathbf{z}) p(x,y,z):joint distribution
2.1.1.建立联合分布
p ( x , y , z ) p(\mathbf{x}, y, \mathbf{z}) p(x,y,z)和 p ( x , y ) p(\mathbf{x}, y) p(x,y)的联合分布如下, δ ( ⋅ ) \delta(\cdot) δ(⋅)是脉冲函数,定义 p ( x ∣ y ) : = p ( x ∣ E θ e ( 1 y ) ) p(\mathbf{x} \mid y):=p\left(\mathbf{x} \mid \mathbf{E}_{\boldsymbol{\theta}_{\boldsymbol{e}}}\left(\mathbf{1}_y\right)\right) p(x∣y):=p(x∣Eθe(1y))是给定类别 y y y后 x \mathbf{x} x的条件分布
p ( x , y , z ) = p ( x ∣ E θ e ( 1 y ) ) p ( y ) δ ( z − E θ e ( 1 y ) ) , ∀ x , z ∈ R d , y ∈ Y p(\mathbf{x}, y, \mathbf{z})=p\left(\mathbf{x} \mid \mathbf{E}_{\boldsymbol{\theta}_e}\left(\mathbf{1}_y\right)\right) p(y) \delta\left(\mathbf{z}-\mathbf{E}_{\boldsymbol{\theta}_e}\left(\mathbf{1}_y\right)\right), \quad \forall \mathbf{x}, \mathbf{z} \in \mathbb{R}^d, y \in \mathcal{Y} p(x,y,z)=p(x∣Eθe(1y))p(y)δ(z−Eθe(1y)),∀x,z∈Rd,y∈Y
p ( x , y ) = p ( x ∣ E θ e ( 1 y ) ) p ( y ) , ∀ x ∈ R d , y ∈ Y p(\mathbf{x}, y)=p\left(\mathbf{x} \mid \mathbf{E}_{\boldsymbol{\theta}_e}\left(\mathbf{1}_y\right)\right) p(y), \forall \mathbf{x} \in \mathbb{R}^d, y \in \mathcal{Y} p(x,y)=p(x∣Eθe(1y))p(y),∀x∈Rd,y∈Y
2.1.2.数据收集
D s = { ( x i s , y i s , z i s ) , i = 1 , ⋯ , N s } \mathcal{D}^s=\left\{\left(\mathbf{x}_i^s, y_i^s, \mathbf{z}_i^s\right), i=1, \cdots, N^s\right\} Ds={(xis,yis,zis),i=1,⋯,Ns}是
来自源分布 p s ( x , y , z ) = p s ( x ∣ y ) p s ( y ) δ ( z − E θ e ( 1 y ) ) p^s(\mathbf{x}, y, \mathbf{z})=p^s(\mathbf{x} \mid y) p^s(y) \delta\left(\mathbf{z}-\mathbf{E}_{\boldsymbol{\theta}_e}\left(\mathbf{1}_y\right)\right) ps(x,y,z)=ps(x∣y)ps(y)δ(z−Eθe(1y))的数据集
MDN和autoencoder也是基于此数据集训练
2.1.3.信道环境变化
变化后的分布为:
p t ( x , y , z ) = p t ( x ∣ y ) p t ( y ) δ ( z − E θ e ( 1 y ) ) p^t(\mathbf{x}, y, \mathbf{z})=p^t(\mathbf{x} \mid y) p^t(y) \delta\left(\mathbf{z}-\mathbf{E}_{\boldsymbol{\theta}_e}\left(\mathbf{1}_y\right)\right) pt(x,y,z)=pt(x∣y)pt(y)δ(z−Eθe(1y))
从目标分布搜集一个小数据集:
D t = { ( x i t , y i t , z i t ) , i = 1 , ⋯ , N t } \mathcal{D}^t=\left\{\left(\mathbf{x}_i^t, y_i^t, \mathbf{z}_i^t\right), i=1, \cdots, N^t\right\} Dt={(xit,yit,zit),i=1,⋯,Nt} , N t < < N s N^t << N^s Nt<<Ns
Our goal is to design a few-shot domain adaptation for the MDN and autoencoder in order to maintain or improve the symbol error rate.
合理假设下,输入信息 y y y的的先验概率不变: p t ( y ) ≈ p s ( y ) , ∀ y ∈ Y p^t(y) \approx p^s(y), \forall y \in \mathcal{Y} pt(y)≈ps(y),∀y∈Y
信道输出的类条件分布变化:
p
(
x
∣
y
)
p(\mathbf{x} \mid y)
p(x∣y)
(备注:信道输出的类条件分布是指通信信道接收到某个特定符号或信息后的输出信号的概率分布。换句话说,它描述了在考虑信道特性的情况下,特定输入符号产生特定输出信号的可能性。
信道输出的类条件分布(class-conditional distribution of channel output)通常使用概率密度函数进行建模,例如高斯或泊松分布,具体取决于信道类型和传输信号的特性。该分布是通信理论中的重要概念,用于设计和分析通信系统,例如数字调制方案和纠错编码。
在实践中,信道输出的类条件分布可能会受到各种因素的影响,包括噪声、干扰、衰减和失真等。因此,设计能够应对这些影响并确保信息可靠传输的通信系统非常重要。)
因此类后验分布也变化:
p
(
y
∣
x
)
p( y\mid \mathbf{x})
p(y∣x)
(备注:类后验分布(class-posterior distribution)是指在给定观测值的情况下,某个样本属于每个类别的概率分布。也就是说,对于一个给定的观测值,类后验分布可以告诉我们这个观测值属于每个类别的概率大小。
在分类问题中,类后验分布是分类器的输出结果之一,它可以用于选择分类器最终输出的类别。例如,如果某个样本的类后验分布表明它属于第一个类别的概率更高,那么分类器就可以将其划分到第一个类别。
类后验分布可以通过贝叶斯定理得到,其中观测值是先验信息,类别是待求解的后验信息。它在许多机器学习算法中都有广泛应用,例如朴素贝叶斯分类器、支持向量机和决策树等。
需要注意的是,类后验分布的准确性取决于训练数据的质量和数量,以及所采用的特征和模型。因此,在实际应用中,需要仔细选择和设计特征和模型,以获得更准确和可靠的类后验分布。)
2.2.提出的方法
- 尝试用 P θ c ( x ∣ z ) P_{\boldsymbol{\theta}_c}(\mathbf{x} \mid \mathbf{z}) Pθc(x∣z)近似真实信道 p ( x ∣ z ) p(\mathbf{x}|\mathbf{z}) p(x∣z),参数由MDN预测, ϕ ( z ) = M θ c ( z ) \phi(\mathbf{z})=\mathbf{M}_{\boldsymbol{\theta}_c}(\mathbf{z}) ϕ(z)=Mθc(z), θ c {\theta}_c θc即为MDN网络的参数。
- p ( x ∣ y ) = p ( x ∣ E θ e ( 1 y ) ) p(\mathbf{x} \mid y)=p\left(\mathbf{x} \mid \mathbf{E}_{\boldsymbol{\theta}_{\boldsymbol{e}}}\left(\mathbf{1}_y\right)\right) p(x∣y)=p(x∣Eθe(1y)),所以类条件分布的自适应等价于m个高斯混合的自适应。
- 高斯混合的自适应可以通过MDN利用少量目标域数据 D t \mathcal{D}^t Dt获得。
- 在解码器的输入处进行有效的特征转换(基于MDN适应),以补偿类条件分布的变化。
- 所有的自适应只在MDN上进行,编解码器网络不变( θ e \boldsymbol{\theta}_{\boldsymbol{e}} θe和 θ d \boldsymbol{\theta}_{\boldsymbol{d}} θd),而且如此频繁的自适应只要少量目标样本。
2.3.MDN信道模型自适应
对于 P θ c ( x ∣ z ) P_{\boldsymbol{\theta}_c}(\mathbf{x} \mid \mathbf{z}) Pθc(x∣z)的建模是混合高斯模型,假设与该高斯模型需要拟合的目标的类条件分布是:
P θ ^ c ( x ∣ z ) = ∑ i = 1 k π ^ i ( z ) N ( x ∣ μ ^ i ( z ) , Σ ^ i ( z ) ) , z ∈ { E θ e ( 1 1 ) , ⋯ , E θ e ( 1 m ) } P_{\widehat{\boldsymbol{\theta}}_c}(\mathbf{x} \mid \mathbf{z})=\sum_{i=1}^k \widehat{\pi}_i(\mathbf{z}) N\left(\mathbf{x} \mid \widehat{\boldsymbol{\mu}}_i(\mathbf{z}), \widehat{\boldsymbol{\Sigma}}_i(\mathbf{z})\right), \quad \mathbf{z} \in\left\{\mathbf{E}_{\boldsymbol{\theta}_e}\left(\mathbf{1}_1\right), \cdots, \mathbf{E}_{\boldsymbol{\theta}_e}\left(\mathbf{1}_m\right)\right\} Pθ c(x∣z)=∑i=1kπ i(z)N(x∣μ i(z),Σ i(z)),z∈{Eθe(11),⋯,Eθe(1m)},
θ ^ c \widehat{\boldsymbol{\theta}}_c θ c:则为适应的MDN的参数
自适应的MDN预测目标混合高斯的参数: ϕ ^ ( z ) = M θ ^ c ( z ) \widehat{\phi}(\mathbf{z})=\mathbf{M}_{\widehat{\boldsymbol{\theta}}_c}(\mathbf{z}) ϕ (z)=Mθ c(z)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i2qoX63h-1678952890076)(null)]
2.2.1.affine-transformation
不同于对MDN所有参数本地fine-tuning,提出了基于高斯分布affine-transformation属性的的参数高效自适应方法,即一种通过affine-transformation可以在任意两个多元高斯间的变化
两个假设:
- 每个类别的源高斯混合模型和目标高斯混合模型具有相同数量的成分 k k k → \rightarrow → 为了避免在适应过程中添加或删除成分时不必更改MDN的架构。
- 每个类别的源高斯混合模型和目标高斯混合模型之间的成分存在一一对应的关系 → \rightarrow → 找到每个类别的源高斯混合模型和目标高斯混合模型之间简化KL散度的闭合形式表达式。
2.2.2.参数转换(Parameter Transformations)
源高斯混合模型和目标高斯混合模型之间的参数变换如下
μ
^
i
(
z
)
=
A
i
μ
i
(
z
)
+
b
i
,
Σ
^
i
(
z
)
=
C
i
Σ
i
(
z
)
C
i
T
,
and
α
^
i
(
z
)
=
β
i
α
i
(
z
)
+
γ
i
\widehat{\boldsymbol{\mu}}_i(\mathbf{z})=\mathbf{A}_i \boldsymbol{\mu}_i(\mathbf{z})+\mathbf{b}_i, \quad \widehat{\boldsymbol{\Sigma}}_i(\mathbf{z})=\mathbf{C}_i \boldsymbol{\Sigma}_i(\mathbf{z}) \mathbf{C}_i^T, \text { and } \widehat{\alpha}_i(\mathbf{z})=\beta_i \alpha_i(\mathbf{z})+\gamma_i
μ
i(z)=Aiμi(z)+bi,Σ
i(z)=CiΣi(z)CiT, and α
i(z)=βiαi(z)+γi
Reference
1.详解EM算法与混合高斯模型(Gaussian mixture model, GMM)
复现
该函数用于模拟生成信道数据。根据所选择的信道类型、信噪比(EbNodB)以及其他配置参数,它生成相应的输入数据和信道输出数据。
函数参数说明:
type_channel:信道类型,可以是’fading_ricean’(瑞利褪色信道)、‘fading_rayleigh’(瑞利信道)或’awgn’(加性高斯白噪声信道)。
EbNodB:信噪比(以分贝为单位)。
n_samp:生成的数据样本数。
config:其他配置参数的字典。
constellation:调制星座点的数组。
函数主要的操作如下:
计算 QAM 符号的平均功率 E_avg_qam。
将信噪比 EbNodB 转换为线性比例 EbNo。
根据信道类型进行不同的操作:
对于瑞利褪色信道和瑞利信道,计算相应的参数(nu、sigma_a、K),并打印相关信息。然后使用这些参数通过调用 simulate_channel_variations_ricean_fading 函数来生成数据。
对于普通的褪色信道,计算褪色因子并打印相关信息。然后使用褪色因子通过调用 simulate_channel_variations_fading 函数来生成数据。
对于加性高斯白噪声信道,计算噪声标准差并打印相关信息。然后使用噪声标准差通过调用 simulate_channel_variations_gaussian 函数来生成数据。
返回生成的输入数据 x_data、信道输出数据 y_data,以及调制星座点数组的 TensorFlow 张量。
总结起来,该函数根据所选择的信道类型和信噪比,使用合适的模型和参数来模拟生成相应的输入数据和信道输出数据。这些数据可用于训练和评估信道相关的模型。
def generate_channel_data_simulated(type_channel, EbNodB, n_samp, config, constellation):
# Generate data from standard channel models.
# Average power of the symbols
E_avg_qam = np.sum(constellation ** 2) / constellation.shape[0]
EbNo = 10. ** (EbNodB / 10.) # Channel SNR in ratio
n_samp_val = int(0.1 * n_samp)
if type_channel in ('fading_ricean', 'fading_rayleigh'):
EbNo_min = EbNo if (type_channel == 'fading_rayleigh') else config['EbNo_min']
nu, sigma_a, K = calculate_ricean_fading_params(
EbNo, EbNo_min, config['sigma_noise_measurement'], config['rate_comm'], E_avg_qam
)
print("Channel SNR = {:g}dB. Ricean fading parameters: nu = {:.6f}, sigma_a = {:.6f}, K = {:.4f}dB".
format(EbNodB, nu, sigma_a, K))
# Generate data
inputs_target_list, x_target_list, y_target_list = simulate_channel_variations_ricean_fading(
constellation, n_samp, n_samp_val, nu, sigma_a, config['sigma_noise_measurement']
)
elif type_channel == 'fading':
scale_fading = calculate_fading_factor(EbNo, config['sigma_noise_measurement'], config['rate_comm'], E_avg_qam)
print("Channel SNR = {:g}dB. Scale-fading = {:.4f}".format(EbNodB, scale_fading))
# Generate data
inputs_target_list, x_target_list, y_target_list = simulate_channel_variations_fading(
constellation, n_samp, n_samp_val, scale_fading, config['sigma_noise_measurement']
)
elif type_channel.lower() == 'awgn':
sigma_noise = get_noise_stddev(EbNodB, rate=config['rate_comm'], E_avg_symbol=E_avg_qam)
print("Channel SNR = {:g}dB. Noise-stddev = {:.6f}".format(EbNodB, sigma_noise))
# Generate data
inputs_target_list, x_target_list, y_target_list = simulate_channel_variations_gaussian(
None, constellation, n_samp, n_samp_val, [sigma_noise] * config['dim_encoding'], use_channel_output=False
)
else:
raise ValueError("Invalid value '{}' for input 'type_channel'".format(type_channel))
x_data = x_target_list[0] # encoded symbols
y_data = y_target_list[0] # channel outputs
return x_data, y_data, tf.convert_to_tensor(constellation, dtype=DTYPE_TF)
函数名:wrapper_train_autoencoder
这是一个包装函数,用于训练自编码器。
参数:
type_autoencoder:自编码器的类型。
x_train:训练数据集。
x_val:验证数据集。
mdn_model:MDN(混合密度网络)模型。
config:配置参数。
config_optimizer:优化器的配置参数。
model_dir:模型保存的目录。
modelfile_init:初始化文件的路径(可选)。
verbose:是否显示详细信息。
函数主体:
首先打印信息,表示开始训练自编码器模型。
确定训练样本数量。
定义保存模型检查点的目录和文件名。
根据自编码器类型,初始化和编译自编码器模型,并根据需要加载初始化文件的权重。
定义回调函数(ModelCheckpoint和EarlyStopping)。
训练自编码器模型,并记录训练和验证的损失。
从保存的检查点加载最佳轮次的权重。
如果自编码器类型是’symbol_estimation_map’,则调用train_map_estimation_autoencoder函数进行训练。
将自编码器的编码器部分应用于输入数据集,将得到的编码结果保存到文件中。
将自编码器的编码结果和对应的标签保存为.mat文件。
将自编码器模型的权重保存到文件中。
最后,函数返回训练好的自编码器模型、训练损失和验证损失的数组。
def wrapper_train_autoencoder(type_autoencoder, x_train, x_val, mdn_model, config, config_optimizer,
model_dir, modelfile_init='', verbose=0):
print("\nTraining the autoencoder model:")
n_train = x_train.shape[0]
# Directory to save the model checkpoints
model_ckpt_path = os.path.join(model_dir, 'model_ckpts')
model_ckpt_filename = os.path.join(model_ckpt_path, 'autoencoder_{}'.format(type_autoencoder))
if not os.path.isdir(model_ckpt_path):
os.makedirs(model_ckpt_path)
if type_autoencoder in ('standard', 'symbol_estimation_mmse', 'adapt_generative'):
# Initialize and compile the autoencoder
autoencoder = initialize_autoencoder(type_autoencoder, mdn_model, config, config_optimizer, n_train)
if modelfile_init:
# Initialize the autoencoder weights from the initialization file
autoencoder.load_weights(modelfile_init).expect_partial()
# Define callbacks
# monitor='val_loss', mode='min'
# monitor='val_categorical_accuracy', mode='max'
mc = ModelCheckpoint(filepath=model_ckpt_filename, save_weights_only=True, monitor='val_loss',
mode='min', verbose=verbose, save_best_only=True)
es = EarlyStopping(monitor='val_loss', mode='min', verbose=verbose, patience=20)
# Train the autoencoder
hist = autoencoder.fit(
x=x_train, y=x_train, epochs=config_optimizer['n_epochs'], batch_size=config_optimizer['batch_size'],
validation_data=(x_val, x_val), callbacks=[mc]
)
train_loss = hist.history['loss']
val_loss = hist.history['val_loss']
# Load the weights corresponding to the best epoch from the saved checkpoint
autoencoder.load_weights(model_ckpt_filename).expect_partial()
elif type_autoencoder == 'symbol_estimation_map':
config_anneal = copy.copy(CONFIG_ANNEAL)
config_anneal['anneal'] = config_optimizer['anneal']
autoencoder, train_loss, val_loss = train_map_estimation_autoencoder(
x_train, x_val, mdn_model, config, config_optimizer, config_anneal, model_ckpt_filename,
modelfile_init=modelfile_init, verbose=verbose
)
else:
raise ValueError("Invalid value '{}' for input 'type_autoencoder'".format(type_autoencoder))
# Save the autoencoder constellation to a file
unique_x = autoencoder.encoder(autoencoder.inputs_unique).numpy()
fname = os.path.join(model_dir, CONSTELLATION_BASENAME)
with open(fname, 'wb') as fp:
np.save(fp, unique_x)
# Save the autoencoder constellation and the corresponding one-hot-coded labels
symbol_dic = {"SYMBOLS": unique_x}
sio.savemat(os.path.join(model_dir, 'symbols.mat'), symbol_dic)
label_dic = {"Labels": autoencoder.inputs_unique.numpy()}
sio.savemat(os.path.join(model_dir, 'labels.mat'), label_dic)
# Save the autoencoder model to a file
fname = os.path.join(model_dir, get_autoencoder_name(autoencoder), 'autoencoder')
autoencoder.save_weights(fname) # save only the model weights
# autoencoder.save(fname, include_optimizer=True) # save the entire model
'''
# Use the autoencoder model from the saved
这是一个辅助函数initialize_autoencoder,用于根据不同类型初始化和编译自编码器模型。
函数的参数如下:
type_autoencoder:自编码器的类型。
mdn_model:MDN(混合密度网络)模型。
config:配置参数。
config_optimizer:优化器的配置参数。
n_train:训练样本数量。
temperature:温度参数(默认为CONFIG_ANNEAL[‘temp_final’])。
freeze_encoder:是否冻结编码器部分的权重。
freeze_decoder:是否冻结解码器部分的权重。
根据传入的type_autoencoder参数,函数将初始化相应类型的自编码器模型,例如标准自编码器(standard)、自适应生成自编码器(adapt_generative)、最小均方误差符号估计自编码器(symbol_estimation_mmse)和MAP符号估计自编码器(symbol_estimation_map)。
在编译模型之前,如果设置了freeze_encoder为True,将冻结编码器部分的权重;如果设置了freeze_decoder为True,将冻结解码器部分的权重。
模型的优化器根据传入的配置参数config_optimizer进行初始化,包括优化方法、学习率调度、训练样本数量、批次大小、最大训练轮数等。
最后,如果需要,可以通过传递metrics=[‘categorical_accuracy’]给compile方法来添加额外的评估指标。
函数返回初始化和编译好的自编码器模型对象。
def initialize_autoencoder(type_autoencoder, mdn_model, config, config_optimizer, n_train,
temperature=CONFIG_ANNEAL['temp_final'], freeze_encoder=False, freeze_decoder=False):
# Helper function to initialize and compile the right type of autoencoder.
n_symbols = config['dim_encoding'] // 2
if type_autoencoder == 'standard':
autoencoder = AutoencoderInverseAffine(
mdn_model, config['n_bits'], n_symbols, n_hidden=config['n_hidden'],
scale_outputs=config.get('scale_outputs', True), l2_reg_strength=config.get('l2_reg_strength', 0.)
)
elif type_autoencoder == 'adapt_generative':
autoencoder = AutoencoderAdaptGenerative(
mdn_model, config['n_bits'], n_symbols, n_hidden=config['n_hidden'],
scale_outputs=config.get('scale_outputs', True), l2_reg_strength=config.get('l2_reg_strength', 0.)
)
elif type_autoencoder == 'symbol_estimation_mmse':
autoencoder = AutoencoderSymbolEstimation(
mdn_model, config['n_bits'], n_symbols, n_hidden=config['n_hidden'],
scale_outputs=config.get('scale_outputs', True), l2_reg_strength=config.get('l2_reg_strength', 0.)
)
elif type_autoencoder == 'symbol_estimation_map':
autoencoder = AutoencoderSymbolEstimation(
mdn_model, config['n_bits'], n_symbols, n_hidden=config['n_hidden'],
scale_outputs=config.get('scale_outputs', True), l2_reg_strength=config.get('l2_reg_strength', 0.),
map_estimation=True, temperature=temperature
)
else:
raise ValueError("Invalid value '{}' for the input 'type_autoencoder'".format(type_autoencoder))
# Has to be done before compiling the model
if freeze_encoder:
autoencoder.encoder.trainable = False
if freeze_decoder:
autoencoder.decoder.trainable = False
# The MAP symbol estimation autoencoder runs only a few epochs per temperature step. However, its learning rate
# schedule is configured using the maximum number of epochs. This is intentional because it ensures that the same
# learning rate schedule is maintained in all cases.
optim_obj = get_optimizer(
config_optimizer['optim_method'], config_optimizer['use_lr_schedule'], n_train,
config_optimizer['batch_size'], config_optimizer['n_epochs'],
lr_init_adam=config_optimizer['learning_rate_adam'], lr_init_sgd=config_optimizer['learning_rate_sgd']
)
# If needed, pass `metrics=['categorical_accuracy']` to the `compile` method
autoencoder.compile(optimizer=optim_obj, loss='categorical_crossentropy')
_ = autoencoder(tf.keras.Input(shape=(config['mod_order'],)))
return autoencoder
这段代码使用csv.writer将训练时间记录写入CSV文件。首先,它打开文件fname以写入模式,并使用逗号作为分隔符和换行符作为行终止符。然后,创建csv.writer对象cw,将它与文件对象关联。接下来,通过cw.writerow()方法写入两行数据。第一行包含列标题channel_train和autoencoder_train,第二行包含对应的训练时间值。在写入之前,训练时间值会通过’{:.4f}‘.format()格式化为保留四位小数的字符串。
with open(fname, ‘w’) as fp:
cw = csv.writer(fp, delimiter=’,‘, lineterminator=’\n’)
cw.writerow([‘channel_train’, ‘autoencoder_train’])
cw.writerow([‘{:.4f}’.format(time_log[‘channel_train’]), ‘{:.4f}’.format(time_log[‘autoencoder_train’])])