(1)Python所有方向的学习路线(新版)
这是我花了几天的时间去把Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
最近我才对这些路线做了一下新的更新,知识体系更全面了。
(2)Python学习视频
包含了Python入门、爬虫、数据分析和web开发的学习视频,总共100多个,虽然没有那么全面,但是对于入门来说是没问题的,学完这些之后,你可以按照我上面的学习路线去网上找其他的知识资源进行进阶。
(3)100多个练手项目
我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了,只是里面的项目比较多,水平也是参差不齐,大家可以挑自己能做的项目去练练。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
推理模型 Q ϕ ( z ∣ x ) Q_\phi (z|x) Qϕ(z∣x)从输入 x x x生成潜矢量 z z z。 Q ϕ ( z ∣ x ) Q_\phi (z|x) Qϕ(z∣x)类似于自编码器模型中的编码器。另一方面, P θ ( x ∣ z ) P_θ(x|z) Pθ(x∣z)从潜码z重建输入。 P θ ( x ∣ z ) P_θ(x|z) Pθ(x∣z)的作用类似于自编码器模型中的解码器。要估算 P θ ( x ) P_θ(x) Pθ(x),必须确定其与 Q ϕ ( z ∣ x ) Q_\phi (z|x) Qϕ(z∣x)和 P θ ( x ∣ z ) P_θ(x|z) Pθ(x∣z)的关系。
如果 Q ϕ ( z ∣ x ) Q_\phi (z|x) Qϕ(z∣x)是 P θ ( z ∣ x ) P_θ(z|x) Pθ(z∣x)的估计值,则Kullback-Leibler(KL)散度确定这两个条件密度之间的距离:
D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ∣ x ) ) = E z ∼ Q [ l o g Q ϕ ( z ∣ x ) − l o g P θ ( z ∣ x ) ] ( 7 ) D_{KL}(Q_\phi (z|x) \| P_θ(z|x)) = \mathbb E_{z\sim Q}[logQ_\phi (z|x)-logP_θ(z|x)] \qquad (7) DKL(Qϕ(z∣x)∥Pθ(z∣x))=Ez∼Q[logQϕ(z∣x)−logPθ(z∣x)](7)
使用贝叶斯定理:
P θ ( z ∣ x ) = P θ ( x ∣ z ) P θ ( z ) P θ ( x ) ( 8 ) P_θ(z|x)=\frac{P_θ(x|z)P_θ(z)}{P_θ(x)} \qquad(8) Pθ(z∣x)=Pθ(x)Pθ(x∣z)Pθ(z)(8)
通过公式(8)改写公式(7),同时由于 l o g P θ ( x ) logP_θ(x) logPθ(x)不依赖于 z ∼ Q z\sim Q z∼Q:
D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ∣ x ) ) = E z ∼ Q [ l o g Q ϕ ( z ∣ x ) − l o g P θ ( x ∣ z ) − l o g P θ ( z ) ] + l o g P θ ( x ) ( 9 ) D_{KL}(Q_\phi (z|x) \| P_θ(z|x)) = \mathbb E_{z\sim Q}[logQ_\phi (z|x)-logP_θ(x|z)-logP_θ(z)] + logP_θ(x)\qquad (9) DKL(Qϕ(z∣x)∥Pθ(z∣x))=Ez∼Q[logQϕ(z∣x)−logPθ(x∣z)−logPθ(z)]+logPθ(x)(9)
重排上式并由:
E z ∼ Q [ l o g Q ϕ ( z ∣ x ) − l o g P θ ( z ) ] = D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ) ) ( 10 ) \mathbb E_{z\sim Q}[logQ_\phi (z|x)-logP_θ(z)] = D_{KL}(Q_\phi (z|x) \| P_θ(z)) \qquad (10) Ez∼Q[logQϕ(z∣x)−logPθ(z)]=DKL(Qϕ(z∣x)∥Pθ(z))(10)
公式 (10) 的左侧也称为变化下界(evidence lower bound, ELBO),可以变化得到:
l o g P θ ( x ) − D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ∣ x ) ) = E z ∼ Q [ l o g P θ ( x ∣ z ) ] − D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ) ) ( 11 ) logP_θ(x)-D_{KL}(Q_\phi (z|x) \| P_θ(z|x)) = \mathbb E_{z\sim Q}[logP_θ(x|z)] - D_{KL}(Q_\phi (z|x) \| P_θ(z))\qquad (11) logPθ(x)−DKL(Qϕ(z∣x)∥Pθ(z∣x))=Ez∼Q[logPθ(x∣z)]−DKL(Qϕ(z∣x)∥Pθ(z))(11)
上式是VAE的核心。左侧项 P θ ( x ) P_θ(x) Pθ(x),它最大化地减少了 Q ϕ ( z ∣ x ) Q_\phi (z|x) Qϕ(z∣x)与真实 P θ ( z ∣ x ) P_θ(z|x) Pθ(z∣x)之间距离的差距。对数不会改变最大值(或最小值)的位置。给定一个可以很好地估计 P θ ( z ∣ x ) P_θ(z|x) Pθ(z∣x)的推断模型, D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ∣ x ) ) D_{KL}(Q_\phi (z|x) \| P_θ(z|x)) DKL(Qϕ(z∣x)∥Pθ(z∣x))约为零。
右边的第一项 P θ ( z ∣ x ) ) P_θ(z|x)) Pθ(z∣x))类似于解码器,该解码器从推理模型中提取样本以重建输入。
第二项是 Q ϕ ( z ∣ x ) Q_\phi (z|x) Qϕ(z∣x)与 P θ ( z ) P_θ(z) Pθ(z)间的KL距离。由于KL始终为正,因此ELBO是 l o g P θ ( x ) logP_θ(x) logPθ(x)的下限。通过优化神经网络的参数 φ φ φ和 θ θ θ来最大化ELBO意味着:
-
D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ∣ x ) ) → 0 D_{KL}(Q_\phi (z|x) \| P_θ(z|x))\to 0 DKL(Qϕ(z∣x)∥Pθ(z∣x))→0或在 z z z中对属性 x x x进行编码的推理模型得到优化。
-
右侧的 l o g P θ ( x ∣ z ) logP_θ(x|z) logPθ(x∣z)最大化,或者从潜在矢量 z z z重构 x x x时,解码器模型得到优化。
优化方式
公式的右侧具有有关VAE损失函数的两个重要信息。解码器项 E z ∼ Q [ l o g P θ ( x ∣ z ) ] \mathbb E_{z\sim Q}[logP_θ(x|z)] Ez∼Q[logPθ(x∣z)]表示生成器从推理模型的输出中获取 z z z个样本以重构输入。最大化该项意味着将重建损失 L R \mathcal L_R LR最小化。如果图像(数据)分布假定为高斯分布,则可以使用MSE。
如果每个像素(数据)都被认为是伯努利分布,那么损失函数就是一个二元交叉熵。
第二项 − D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ) ) - D_{KL}(Q_\phi (z|x) \| P_θ(z)) −DKL(Qϕ(z∣x)∥Pθ(z)),由于 Q ϕ Q_\phi Qϕ是高斯分布。通常 P θ ( z ) = P ( z ) = N ( 0 , 1 ) P_θ(z)=P(z)=\mathcal N(0,1) Pθ(z)=P(z)=N(0,1),也是均值为0且标准偏差等于1.0的高斯分布。KL项可以简化为:
− D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ) ) = 1 2 ∑ j = 0 J ( 1 + l o g ( σ j ) 2 − ( μ j ) 2 − ( σ j ) 2 ) ( 12 ) - D_{KL}(Q_\phi (z|x) \| P_θ(z))=\frac{1}{2} \sum_{j=0}^J (1+log(\sigma_j)2-(\mu_j)2-(\sigma_j)^2)\qquad(12) −DKL(Qϕ(z∣x)∥Pθ(z))=21j=0∑J(1+log(σj)2−(μj)2−(σj)2)(12)
其中 J J J是 z z z的维数。和都是通过推理模型计算得到的关于 x x x的函数。要最大化 − D K L -D_{KL} −DKL:则 σ j → 1 \sigma_j \to 1 σj→1, μ j → 0 \mu_j \to 0 μj→0。 P ( z ) = N ( 0 , 1 ) P(z)=\mathcal N(0,1) P(z)=N(0,1)的选择是由于各向同性单位高斯分布的性质,可以给定适当的函数将其变形为任意分布。
根据公式(12),KL损失 L K L \mathcal L_{KL} LKL为 D K L D_{KL} DKL。 综上,VAE损失函数定义为:
L V A E = L R + L K L ( 13 ) \mathcal L_{VAE}=\mathcal L_R + \mathcal L_{KL}\qquad (13) LVAE=LR+LKL(13)
给定编码器和解码器模型的情况下,在构建和训练VAE之前,还有一个问题需要解决。
重参数化技巧(Reparameterization trick)
下图左侧显示了VAE网络。编码器获取输入 x x x,并估计潜矢量z的多元高斯分布的均值 μ μ μ和标准差 σ σ σ。 解码器从潜矢量 z z z采样,以将输入重构为 x x x。
但是反向传播梯度不会通过随机采样块。虽然可以为神经网络提供随机输入,但梯度不可能穿过随机层。
解决此问题的方法是将“采样”过程作为输入,如图右侧所示。 采样计算为:
S a m p l e = μ + ε σ ( 14 ) Sample=\mu + εσ\qquad(14) Sample=μ+εσ(14)
如果 ε ε ε和 σ σ σ以矢量形式表示,则 ε σ εσ εσ是逐元素乘法。 使用公式(14),令采样好像直接来自于潜空间。 这项技术被称为重参数化技巧。
之后在输入端进行采样,可以使用熟悉的优化算法(例如SGD,Adam或RMSProp)来训练VAE网络。
为了便于可视化潜在编码,将 z z z的维度设置为2。编码器仅是两层MLP,第二层生成均值和对数方差。对数方差的使用是为了简化KL损失和重参数化技巧的计算。编码器的第三个输出是使用重参数化技巧进行的 z z z采样。在采样函数中, e 0.5 l o g σ 2 = σ 2 = σ e{0.5log\sigma2}=\sqrt{\sigma^2}=\sigma e0.5logσ2=σ2 =σ,因为 σ > 0 σ> 0 σ>0是高斯分布的标准偏差。
解码器也是两层MLP,它对 z z z的样本进行采样以近似输入。
VAE网络只是将编码器和解码器连接在一起。损失函数是重建损失和KL损失之和。使用Adam优化器。
导入库
from tensorflow import keras
import tensorflow as tf
import numpy as np
import os
import argparse
from matplotlib import pyplot as plt
重参数技巧
#reparameterization trick
#z = z_mean + sqrt(var) * eps
def sampling(args):
“”"Reparameterization trick by sampling
Reparameterization trick by sampling fr an isotropic unit Gaussian.
#Arguments:
args (tensor): mean and log of variance of Q(z|x)
#Returns:
z (tensor): sampled latent vector
“”"
z_mean,z_log_var = args
batch = keras.backend.shape(z_mean)[0]
dim = keras.backend.shape(z_mean)[1]
epsilon = keras.backend.random_normal(shape=(batch,dim))
return z_mean + keras.backend.exp(0.5 * z_log_var) * epsilon
绘制测试图片函数
def plot_results(models,
data,
batch_size=128,
model_name=‘vae_mnist’):
“”"Plots labels and MNIST digits as function of 2 dim latent vector
Arguments:
models (tuple): encoder and decoder models
data (tuple): test data and label
batch_size (int): prediction batch size
model_name (string): which model is using this function
“”"
encoder,decoder = models
x_test,y_test = data
xmin = ymin = -4
xmax = ymax = +4
os.makedirs(model_name,exist_ok=True)
filename = os.path.join(model_name,‘vae_mean.png’)
#display a 2D plot of the digit classes in the latent space
z,, = encoder.predict(x_test,batch_size=batch_size)
plt.figure(figsize=(12,10))
#axes x and y ranges
axes = plt.gca()
axes.set_xlim([xmin,xmax])
axes.set_ylim([ymin,ymax])
subsampling to reduce density of points on the plot
z = z[0::2]
y_test = y_test[0::2]
plt.scatter(z[:,0],z[:,1],marker=‘’)
for i,digit in enumerate(y_test):
axes.annotate(digit,(z[i,0],z[i,1]))
plt.xlabel(‘z[0]’)
plt.ylabel(‘z[1]’)
plt.savefig(filename)
plt.show()
filename = os.path.join(model_name,‘digits_over_latent.png’)
#display a 30*30 2D mainfold of digits
n = 30
digit_size = 28
figure = np.zeros((digit_size * n,digit_size * n))
#线性间隔的坐标,对应于潜在空间中数字类的二维图
grid_x = np.linspace(-4,4,n)
grid_y = np.linspace(-4,4,n)[::-1]
for i,yi in enumerate(grid_x):
for j,xi in enumerate(grid_y):
z_sample = np.array([[xi,yi]])
x_decoded = decoder.predict(z_sample)
digit = x_decoded[0].reshape(digit_size,digit_size)
figure[i * digit_size:(i+1)digit_size,jdigit_size:(j+1)*digit_size] = digit
plt.figure(figsize=(10, 10))
start_range = digit_size // 2
end_range = (n-1) * digit_size + start_range + 1
pixel_range = np.arange(start_range, end_range, digit_size)
sample_range_x = np.round(grid_x, 1)
sample_range_y = np.round(grid_y, 1)
plt.xticks(pixel_range, sample_range_x)
plt.yticks(pixel_range, sample_range_y)
plt.xlabel(“z[0]”)
plt.ylabel(“z[1]”)
plt.imshow(figure, cmap=‘Greys_r’)
plt.savefig(filename)
plt.show()
加载数据与超参数
MNIST dataset
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
image_size = x_train.shape[1]
original_dim = image_size * image_size
x_train = np.reshape(x_train, [-1, original_dim])
x_test = np.reshape(x_test, [-1, original_dim])
x_train = x_train.astype(‘float32’) / 255
x_test = x_test.astype(‘float32’) / 255
#超参数
input_shape = (original_dim,)
intermediate_dim = 512
batch_size = 128
latent_dim = 2
epochs = 50
VAE模型
#VAE model
#encoder
inputs = keras.layers.Input(shape=input_shape,name=‘encoder_input’)
x = keras.layers.Dense(intermediate_dim,activation=‘relu’)(inputs)
z_mean = keras.layers.Dense(latent_dim,name=‘z_mean’)(x)
z_log_var = keras.layers.Dense(latent_dim,name=‘z_log_var’)(x)
z = keras.layers.Lambda(sampling,output_shape=(latent_dim,),name=‘z’)([z_mean,z_log_var])
encoder = keras.Model(inputs,[z_mean,z_log_var,z],name=‘encoder’)
encoder.summary()
keras.utils.plot_model(encoder,to_file=‘vae_mlp_encoder.png’,show_shapes=True)
#decoder
latent_inputs = keras.layers.Input(shape=(latent_dim,),name=‘z_sampling’)
做了那么多年开发,自学了很多门编程语言,我很明白学习资源对于学一门新语言的重要性,这些年也收藏了不少的Python干货,对我来说这些东西确实已经用不到了,但对于准备自学Python的人来说,或许它就是一个宝藏,可以给你省去很多的时间和精力。
别在网上瞎学了,我最近也做了一些资源的更新,只要你是我的粉丝,这期福利你都可拿走。
我先来介绍一下这些东西怎么用,文末抱走。
(1)Python所有方向的学习路线(新版)
这是我花了几天的时间去把Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
最近我才对这些路线做了一下新的更新,知识体系更全面了。
(2)Python学习视频
包含了Python入门、爬虫、数据分析和web开发的学习视频,总共100多个,虽然没有那么全面,但是对于入门来说是没问题的,学完这些之后,你可以按照我上面的学习路线去网上找其他的知识资源进行进阶。
(3)100多个练手项目
我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了,只是里面的项目比较多,水平也是参差不齐,大家可以挑自己能做的项目去练练。
(4)200多本电子书
这些年我也收藏了很多电子书,大概200多本,有时候带实体书不方便的话,我就会去打开电子书看看,书籍可不一定比视频教程差,尤其是权威的技术书籍。
基本上主流的和经典的都有,这里我就不放图了,版权问题,个人看看是没有问题的。
(5)Python知识点汇总
知识点汇总有点像学习路线,但与学习路线不同的点就在于,知识点汇总更为细致,里面包含了对具体知识点的简单说明,而我们的学习路线则更为抽象和简单,只是为了方便大家只是某个领域你应该学习哪些技术栈。
(6)其他资料
还有其他的一些东西,比如说我自己出的Python入门图文类教程,没有电脑的时候用手机也可以学习知识,学会了理论之后再去敲代码实践验证,还有Python中文版的库资料、MySQL和HTML标签大全等等,这些都是可以送给粉丝们的东西。
这些都不是什么非常值钱的东西,但对于没有资源或者资源不是很好的学习者来说确实很不错,你要是用得到的话都可以直接抱走,关注过我的人都知道,这些都是可以拿到的。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!