高数 相关知识

矩阵乘法


exp()、log()、log2()、log10()、ln、lg

1.exp函数即指数函数:e的x次方的函数
	exp:高等数学里以自然常数e为底的指数函数,等于2.718281828459045
	numpy.exp():返回e的幂次方,e是一个常数为2.718281828459045
	exp(0) = e的0次方 = 1
	exp(1) = e的1次方 = e = 2.718281828459045
 	exp(2) = e的2次方 = 7.38905609893065
 
	>>> import numpy as np
	>>> np.exp(1)
	2.718281828459045
	>>> np.exp(2)
	7.38905609893065

2.log10()、log2()
	#log10:以10为底数的对数,对数是对求幂的逆运算
	#log2:以2为底数的对数,对数是对求幂的逆运算

	>>> import numpy as np
	#log10:以10为底,求10的多少次方为1,即10的0次方为1
	>>> np.log10(1)
	0.0
	#log10:以10为底,求10的多少次方为10,即10的1次方为10
	>>> np.log10(10)
	1.0
	#log10:以10为底,求10的多少次方为100,即10的2次方为100
	>>> np.log10(100)
	2.0
	>>> np.log10(1000)
	3.0

	#log2:以2为底,求2的多少次方为1,即2的0次方为1
	>>> np.log2(1)
	0.0
	#log2:以2为底,求2的多少次方为2,即2的1次方为2
	>>> np.log2(2)
	1.0
	#log2:以2为底,求2的多少次方为4,即2的2次方为4
	>>> np.log2(4)
	2.0
	>>> np.log2(8)
	3.0
	>>> np.log2(16)
	4.0

3.log()
	#log默认以e为底,求e(2.718281828459045)的多少次方为1,即e(2.718281828459045)的0次方为1
	>>> np.log(1)
	0.0
	#log默认以e为底,求e(2.718281828459045)的多少次方为e,即e(2.718281828459045)的1次方为e
	>>> np.log(np.e)
	1.0
	#log默认以e为底,求e(2.718281828459045)的多少次方为10,即e(2.718281828459045)的2.302585092994046次方为10
	>>> np.log(10)
	2.302585092994046
	#log默认以e为底,求e(2.718281828459045)的多少次方为100,即e(2.718281828459045)的4.605170185988092次方为100
	>>> np.log(100)
	4.605170185988092

4.math.log()、math.log2()、math.log10()
	#math.log()、math.log2()、math.log10() 等同于 numpy的log()、log2()、log10()
	>>> import math
	#log默认以e为底,求e(2.718281828459045)的多少次方为1,即e(2.718281828459045)的0次方为1
	>>> math.log(1)
	0.0
	>>> math.log(math.e)
	1.0
	>>> math.log(10)
	2.302585092994046
	>>> math.log(100)
	4.605170185988092

	#log2:以2为底,求2的多少次方为1,即2的0次方为1
	>>> math.log2(1)
	0.0
	>>> math.log2(2)
	1.0
	>>> math.log2(4)
	2.0
	 
	#log10:以10为底,求10的多少次方为1,即10的0次方为1
	>>> math.log10(1)
	0.0
	>>> math.log10(10)
	1.0
	>>> math.log10(100)
	2.0

5.math.log(m,n)	和对应的numpy写法(np.log(m) / np.log(n))
	#math.log(m,n) 表示n为底数,m为真数,即以n为底m的对数

	#4的1次方为4
	>>> math.log(4,4)
	1.0
	#3的1.2618595071429148次方约为4
	>>> math.log(4,3)
	1.2618595071429148
	#2的2次方约为4
	>>> math.log(4,2)
	2.0

	#等同于 math.log(4,4)
	>>> np.log(4) / np.log(4)
	1.0
	#等同于 math.log(4,3)
	>>> np.log(4) / np.log(3)
	1.2618595071429148
	#等同于 math.log(4,2)
	>>> np.log(4) / np.log(2)
	2.0


向上取整⌈⌉和向下取整⌊⌋符号

1.向下取整的运算称为Floor,用数学符号⌊⌋表示;向上取整的运算称为Ceiling,用数学符号⌈⌉表示。
	向上取整:比自己大的最小整数;
	向下取整:比自己小的最大整数;
	四舍五入:更接近自己的整数;
2.例子1:
 	⌊59/60⌋=0
	⌈59/60⌉=1
	⌊-59/60⌋=-1
	⌈-59/60⌉=0
	⌊1/2⌋⇒ 0    
	⌊-1/2⌋ ⇒ -1

3.例子2:给定 4.9
	调用用向下取整函数“⌊⌋”得到的是 4
	调用用向上取整函数“⌈⌉”得到的是 5

指数加权移动平均(EWMA)(动手学 深度学习 MXNet 优化算法 动量法一节中)

1.将yt看作是对最近1/(1-γ)个时间步的xt值的加权平均。
2.例如,当γ=0.95时,yt可以被看作对最近20个时间步的xt值的加权平均:1/(1-γ)=1/(1-0.95)=20。
3.当γ=0.9时,yt可以看作是对最近10个时间步的xt值的加权平均:1/(1-γ)=1/(1-0.9)=10。
4.而且,离当前时间步t越近的xt值获得的权重越⼤(越接近1)。
5.将动量超参数momentum设0.5(当γ=0.5时),这时可以看成是特殊的小批量随机梯度下降,
  其小批量随机梯度为最近2个时间步的2倍小批量梯度的加权平均:1/(1-γ)=1/(1-0.5)=2。
6.将动量超参数momentum增⼤到0.9(当γ=0.9时),这时依然可以看成是特殊的小批量随机梯度下降,
  其小批量随机梯度为最近10个时间步的10倍小批量梯度的加权平均:1/(1-γ)=1/(1-0.9)=10。

将动量超参数momentum设0.5(当γ=0.5时),这时可以看成是特殊的小批量随机梯度下降,
其小批量随机梯度为最近2个时间步的2倍小批量梯度的加权平均:1/(1-γ)=1/(1-0.5)=2。

将动量超参数momentum增⼤到0.9(当γ=0.9时),这时依然可以看成是特殊的小批量随机梯度下降,
其小批量随机梯度为最近10个时间步的10倍小批量梯度的加权平均:1/(1-γ)=1/(1-0.9)=10。


指数加权移动平均(EWMA)的偏差修正

指数加权移动平均、指数加权移动平均的偏差修正 的其他博客:
	http://www.pianshen.com/article/6077318422/
	https://baijiahao.baidu.com/s?id=1621017294033469594&wfr=spider&for=pc
	https://www.jianshu.com/p/b0d89353a541
	https://www.cnblogs.com/cloud-ken/p/7723755.html
	https://www.cnblogs.com/guoyaohua/p/8544835.html

1.当t较小时,过去各时间步t的小批量随机梯度权值之和会较小。
2.例如,当β1 = 0.9时,v1 = 0.9*v0 + (1-0.9)*g1,由于v0一开始初始化为0,因此v1 = 0.9*0 + 0.1*g1,即 v1 = 0.1*g1。
3.v2 = 0.9*v1 + (1-0.9)*g2,由于v1为0.1*g1,因此v2 = 0.9*0.1*g1 + 0.1*g2,即v2 = 0.09*g1 + 0.1*g2。
4.假设g1和g2为正数,计算出v2的结果数要远小于g1或g2,那么造成在t较小时,过去各时间步t的小批量随机梯度权值之和会较小。
5.因此在预测初期,为了在初期预测得更好更准确,也就不直接使用vt,而是使用偏差修正的vt/(1-β**t),β**t和vt中的t是指时间步。
6.当t=2时,v2/(1-β**2) = (0.09*g1 + 0.1*g2) / (1-0.9**2),在做指数加权移动平均的基础上再做预测初期时间步t较少时的偏差修正。
7.会发现随着时间步t的增加,βt越接近于0,所以当时间步t很大的时候,偏差修正几乎不起作用,偏差修正vt/(1-βt)只在时间步较少的预测初期起作用。


移动平均(MA)、加权移动平均(WMA)、指数移动平均(EMA或EXMA)、指数加权移动平均(EWMA)

维基百科 介绍:https://zh.wikipedia.org/wiki/%E7%A7%BB%E5%8B%95%E5%B9%B3%E5%9D%87

1.将yt看作是对最近1/(1-γ)个时间步的xt值的加权平均。
2.例如,当γ=0.95时,yt可以被看作对最近20个时间步的xt值的加权平均:1/(1-γ)=1/(1-0.95)=20。
3.当γ=0.9时,yt可以看作是对最近10个时间步的xt值的加权平均:1/(1-γ)=1/(1-0.9)=10。
4.而且,离当前时间步t越近的xt值获得的权重越⼤(越接近1)。
5.将动量超参数momentum设0.5(当γ=0.5时),这时可以看成是特殊的小批量随机梯度下降,
  其小批量随机梯度为最近2个时间步的2倍小批量梯度的加权平均:1/(1-γ)=1/(1-0.5)=2。
6.将动量超参数momentum增⼤到0.9(当γ=0.9时),这时依然可以看成是特殊的小批量随机梯度下降,
  其小批量随机梯度为最近10个时间步的10倍小批量梯度的加权平均:1/(1-γ)=1/(1-0.9)=10。

指数移动平均值在批标准化(BatchNormalization)中的应用


加权平均

1.加权平均:反映了一组数据的一般水平。
2.“统计初步”这部分内容中,平均数是一个非常重要而又有广泛用途的概念,在日常生活中,我们经常会听到这样一些名词:平均气温、平均降雨量、平均产量、人均年收入等;
  而平均分数、平均年龄、平均身高等名词更熟悉。
3.一般来说,平均数反映了一组数据的一般水平,利用平均数,可以从横向和纵向两个方面对事物进行分析比较,从而得出结论。
  例如,要想比较同一年级的两个班同学学习成绩,如果用每个班的总成绩进行比较,会由于班级人数不同,而使比较失去真正意义。
  但是如果用平均分数去比较,就可以把各班的平均水平呈现出来。
  从纵向的角度来看,可以对同一个事物在不同的时间内的情况利用平均数反映出来,例如,通过两个不同时间人均年收入来比较人们生活水平、经济发展等状况。
4.加权公式 例子讲解
	1.在日常生活中,我们常用平均数表示一组数据的‘平均水平’。在一组数据里,一个数据出现的次数称为权。
	2.例子:学校学期末成绩,期中考试占30%,期末考试占50%,作业占20%,假如某人期中考试得了84,期末92,作业分91,如果是算数平均,那么就是 (84+92+91)/3 = 89。
	  那么通过加权处理后就是 84×30% + 92×50% + 91×20% = 89.4,这是在已知权重的情况下;
           未知权重的情况下,想知道两个班的化学加权平均值,一班50人,平均80,二班60人,平均82,算数平均是 (80+82)/2 = 81,加权后是 (50×80 + 60×82)/(50+60) = 81.09。
	3.还有一种情况 类似第一种情况 也是人为规定,比如说 你觉得专家的分量比较大,老师的分量其次,学生的分量最低,就某观点,满分10分的情况下,
	  专家打8分,老师打7分,学生打6分,但你认为专家权重和老师及学生权重应为0.5:0.3:0.2,那么加权后就是8×0.5 + 7×0.3 + 6×0.2 = 7.3,
	  而算数平均的话就是 (8+6+7)/3 = 7。
	4.小测成绩是80分,期末考成绩是90分,计算总的平均成绩,按小测40%、期末成绩60%的比例来算,平均成绩是:80×40% + 90×60% = 86。
	5.学校食堂吃饭,吃三碗的有x人,吃两碗的有y人,吃一碗的z人。平均每人吃 (3x+2y+z)/(x+y+z)。
	  这里x、y、z分别就是权数值,“加权”就是考虑到不同变量在总体中的比例份额。
	6.加权平均数 = (x1*f1 + x2*f2 + ... + xn*fn) / n,其中f1+f2+...+fn = n,那么f1、f2、...、fn叫做权,加权平均数通过数和权的乘积来计算。
	  需要注意的是:算术平均实际上是一种特殊的加权平均,即权重相同的加权平均。
	  比如f1 = f2 =...= fn的话,那么加权平均数 = (x1*f1 + x2*f2 + ... + xn*fn) / n 实际上确切的说就是一种算术平均。
	7.当一组数据中的某些数重复出现几次时,那么它们的平均数的表示形式发生了一定的变化。
	  例如,某人射击十次,其中二次射中10环,三次射中8环,四次射中7环,一次射中9环,那么他平均射中的环数为:(10×2 + 8×3 + 7×4 + 9×1)/10 = 8.1.
	  这里的7、8、9、10这四个数是射击者射中的几个不同环数,但它们出现的频数不同,分别为4,3,1,2,数据的频数越大,表明它对整组数据的平均数影响越大,
	  实际上,频数起着权衡数据的作用,称之为权数或权重,上面的平均数称为加权平均数,不难看出,各个数据的权重之和恰为10。
	8.在加权平均数中,除了一组数据中某一个数的频数称为权重外,权重还有更广泛的含义。
	  其实,在每一个数的权数相同的情况下,加权平均值就等于算数平均值。
	  此外在一些体育比赛项目中,也要用到权重的思想。
	  比如在跳水比赛中,每个运动员除完成规定动作外,还要完成一定数量的自选动作,而自选动作的难度是不同的,两位选手由于所选动作的难度系数不同,
	  尽管完成各自动作的质量相同,但得分也是不相同的,难度系数大的运动员得分应该高些,难度系数实际上起着权重的作用。
	9.在评估某个同学一学期的学生成绩时,一般不只看他期末的一次成绩,而是将平时测验、期中考试等成绩综合起来考虑。
	  比如说,一同学两次单元测验的成绩分别为88、90,期中的考试成绩为92,而期末的考试成绩为85,如果简单地计算这四个成绩的平均数,
	  即将平时测验与期中、期末考试成绩同等看待,就忽视了期末考试的重要性。鉴于这种考虑,我们往往将这四个成绩分配以不同的权重。
	  由于10%+10%+30%+50%=1,即各个权重之和为1,所以求加权平均数的式子中分母为1。88×10% + 90×10% + 92×30% + 85×50% = 87.9。
	10.下面的例子是未知权重的情况:
		股票A,1000股,价格10;股票B,2000股,价格15。
		算数平均 = (10+15) / 2 = 12.5
		加权平均 = (10×1000 + 15×2000) / (1000+2000) = 13.33
		而普通的算术平均数的权重相等,都是1。比如 3和5的平均数为4,也就是说它们的重要性相同,所以平均数是特殊的加权平均数。

加权平均在模型集成中的应用


Jaccard系数/交并比


均方误差(MSE)、平均绝对误差(MAE)

1.平均绝对误差(MAE):mae = np.mean(np.abs(preds - targets))
2.model.compile(optimizer='rmsprop', loss='mse', metrics=['mae'])
  model.compile(optimizer=RMSprop(), loss='mae')
	编译网络时用的mse 损失函数,即均方误差(MSE,mean squared error),预测值与目标值之差的平方。这是回归问题常用的损失函数。
  	在训练过程中还监控一个新指标:平均绝对误差(MAE,mean absolute error)。它是预测值与目标值之差的绝对值。
  	比如,如果这个问题的 MAE 等于 0.5,真实目标是房屋价格的中位数,单位是千美元,那么就表示你预测的房价与实际价格平均相差 500 美元。
3.比如现在计算得出的 MAE值 为 0.29。因为输入数据已经被标准化成了均值为 0、标准差为 1的数据,
  所以无法直接对这个MAE值进行解释,因此它需要把MAE值转化成“和输入数据同样标准的”值,即MAE值 0.29 乘以 源数据的std值,
  这个过程叫做反标准化,便能转换得出真正的平均绝对误差值。
  注意:此处的MAE值之所以能乘以源数据的std值便能得出真正的平均绝对误差值是有要求的,首先要求 preds - targets都是同种类型的值。
        比如preds是预测的温度值,targets是真实的温度值,而“MAE值所乘以的”std标准值也同样为根据温度值所求出来的std标准值。
        数据标椎化:
        		mean = train_data.mean(axis=0)
        		train_data -= mean
        		std = train_data.std(axis=0)
        		train_data /= std
        比如上述的数据标椎化中的求std标准值,std(axis=0)代表求一行中每列特征值的对应的std标准值,比如第i列的为温度值,
        那么“MAE值所乘以的”std标准值也必须为std[i]才能得出真正的平均绝对误差值。

概率分布之二项分布与多项分布、采样策略之softmax温度

>>> import numpy
>>> numpy.random.binomial(n=10, p=0.7, size = 1)
array([7])
 
>>> a = numpy.random.binomial(n=10, p=0.7, size = 10)
>>> a
array([8, 7, 5, 7, 6, 7, 5, 7, 5, 8])
>>> b = numpy.mean(a)
>>> b
6.5
>>> a = numpy.random.binomial(n=10, p=0.7, size = 10)
>>> b = numpy.mean(a)
>>> b
7.4
 
>>> a = numpy.random.binomial(n=10, p=0.1, size = 20)
>>> a
array([1, 1, 0, 2, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 2, 0, 1])
>>> b = numpy.mean(a)
>>> b
0.55
>>> a = numpy.random.binomial(n=10, p=0.1, size = 20)
>>> b = numpy.mean(a)
>>> b
1.35
结果生成一个一维数组,数组中每个元素值均位于均为 0到n,n由参数n指定,此处每个元素值均为 0到10 之间的整数,
如果令参数 size=100,则生成数量大小为100的一维数组。设置 p=0.1时,数组的均值会在1上下,其均值的分布趋近于p所设置的概率0.1。
设置 p=0.7时,数组的均值会在7上下,其均值的分布趋近于p所设置的概率0.7。下图中根据p=0.7得出的结果所示,可见正例出现 7 的样本数最多,并以 7 为中心向两侧递减。

>>> import numpy
>>> numpy.random.multinomial(n=10, pvals=[0.2,0.4,0.4], size = 1)
array([[1, 4, 5]])
>>> numpy.random.multinomial(n=20, pvals=[0.3,0.3,0.4], size = 2)
array([[9, 4, 7],
       [6, 6, 8]])
>>> np.random.multinomial(n=20, pvals=[1/6.]*6, size=1)
array([[3, 3, 3, 4, 1, 6]])
#[1/6.]*6 为 [0.16666666666666666, 0.16666666666666666, 0.16666666666666666, 0.16666666666666666, 0.16666666666666666, 0.16666666666666666]
 
>>> a = numpy.random.multinomial(n=10.0, pvals=[0.2,0.4,0.4], size = 1000)
>>> a
array([[1, 7, 2],
       [1, 3, 6],
       [2, 5, 3],
       ...,
       [0, 4, 6],
       [3, 4, 3],
       [2, 3, 5]])
>>> a.shape
(1000, 3)
>>> b = numpy.mean(a,axis=0)
>>> b
array([1.927, 3.985, 4.088])
>>> a = numpy.random.multinomial(n=10.0, pvals=[0.2,0.4,0.4], size = 1000)
>>> b = numpy.mean(a,axis=0)
>>> b
array([2.027, 4.015, 3.958])
结果为一个二维数组,二维数组中元素数量由 size值指定,而二维数组中每个元素均为 一维数组(N维向量),一维数组的大小 即 N维向量的 N 等于 pvals参数数组的长度大小,
一维数组(N维向量)中每个元素值位于 0到n值 之间,n值 由参数n指定,一维数组(N维向量)中所有元素值之和也同样为n值,也同样由参数n指定。比如此时设置size = 1000,
那么二维数组中就会有1000个一维数组(N维向量),此时1000个向量的均值基本是在[2.xxx, 4.xxx, 4.xxx] 附近,
从上述计算结果 array([2.027, 4.015, 3.958]) 和 array([1.927, 3.985, 4.088]) 可以得出这个结论,也即可见其均值的分布趋近于pvals所设置的概率[0.2, 0.4, 0.4]。


std标准差(均方差)、平均方差、方差、mean均值

1.data.std(axis=0)
	std 标准差(均方差):https://ww2.mathworks.cn/help/matlab/ref/std.html?searchHighlight=std&s_tid=doc_srchtitle
		1.标准差(Standard Deviation) ,中文环境中又常称均方差,是离均差平方的算术平均数的平方根,用σ表示。
		  算术平均数的重要特性之一是离均差平方和为最小,样本各观测值与平均数之差的平方和为最小,即离均差平方和为最小。
		  在概率统计中最常使用作为统计分布程度上的测量。
		  标准差(Standard Deviation),在概率统计中最常使用作为统计分布程度(statistical dispersion)上的测量。
		  测量到分布程度的结果,原则上具有两种性质:一个总量的标准差或一个随机变量的标准差,及一个子集合样品数的标准差之间,有所差别。
		2.方差与标准差的区别:
			标准差是方差的算术平方根(平方根)。标准差能反映一个数据集的离散程度。
		  	标准差定义为方差的算术平方根,反映组内个体间的离散程度。
			方差是在概率论和统计方差衡量随机变量或一组数据时离散程度的度量。
			概率论中方差用来度量随机变量和其数学期望(即均值)之间的偏离程度。
			统计中的方差(样本方差)是每个样本值与全体样本值的平均数之差的平方值的平均数。
			在许多实际问题中,研究方差即偏离程度有着重要意义。
			标准差能反映一个数据集的离散程度。平均数相同的两组数据,标准差未必相同。
			方差是衡量源数据和期望值相差的度量值。
		3.平均方差
			样本中各数据与样本平均数的差的平方和的平均数叫做样本方差;样本方差的算术平方根叫做样本标准差。
			样本方差和样本标准差都是衡量一个样本波动大小的量,样本方差或样本标准差越大,样本数据的波动就越大。

2.data.mean(axis=0)
	mean 数组的均值:https://ww2.mathworks.cn/help/matlab/ref/mean.html?searchHighlight=mean&s_tid=doc_srchtitle


平均值mean 和 方差variance 在变分自编码器(VAE)中的应用

1.构建Model模型的实例对象model
	from keras.models import Model
	model = Model(input,output) 
		1.将xx模型实例化出一个model对象,它将一个模型输入input映射为一个模型输出output,
		  或者说可以理解为把一个模型输入input映射为一个包含多层的整体的模型。
		2.模型输入input可以是 keras.Input(shape)、layers.Input(shape)。
		3.模型输出output:
			可以是一个自定义类的实例对象:class 自定义类名(keras.layers.Layer)的实例对象。
		  	也可以是一个包含多层layers的模型输出:output=layers.xxx(参数)(上一层layers)。
	 	  	也可以是一个模型实例对象:output=keras.models.Model(input,output)。比如构建GAN模型的例子。
 
2.model实例对象的多种使用形式
	1.output = model(input) 
		给model实例对象传入真实的模型输入数据,输出对应的目标数据
		input为真实的模型输入,output为模型输出
	2.model.fit(x=x_train, y=y_train, shuffle=True, epochs=10, batch_size=batch_size, validation_data=(x_test, y_test))
		对model实例对象直接进行fit训练,传入用于训练/验证的模型输入和模型输出,可以同时指定shuffle/epochs/batch_size等
	3.output = Model实例对象2(Model模型实例对象1(input))
 		多个Model实例对象进行嵌套连接在一起构建为一个新的网络模型,即Model模型1的输出作为Model模型2的输入。
		比如GAN模型中,便把生成器网络模型的实例对象和判别器网络模型的实例对象连接在一起构建为一个新的模型,最终返回判别器网络的模型输出。

3.keras.layers.Layer层:output = layers.Conv2D()/layers.Dense()/layers.Conv2DTranspose()/...
  自定义keras.layers.Layer层的形式:
	1.class 自定义类名(keras.layers.Layer):
		def call(self, inputs):
			#可以不使用这个返回输出值,但层必须要有返回值
			return x 
	2.创建自定义Layer层的实例对象:output = 自定义类名(inputs)

4.GAN 生成器网络 和 GAN 判别器网络 的组合
	1.GAN 生成器网络
		#设置模型输入是一个形状为 (latent_dim,)的随机向量(潜在空间中的一个随机点)
		generator_input = keras.Input(shape=(latent_dim,))
		x = layers.Dense(128 * 16 * 16)(generator_input)
		#构建连续多层layers.Dense/layers.LeakyReLU/layers.Conv2D/layers.Reshape等
		......
		#构建生成器模型实例对象:把形状为 (latent_dim,)的随机向量(潜在空间中的一个随机点)作为模型输入,
		#映射到一个包含多层layers的模型输出网络,最终解码为一张形状为 (32, 32, 3) 的合成图像
		generator = keras.models.Model(generator_input, x) 
		generator.summary()

 	2.GAN 判别器网络
		discriminator_input = layers.Input(shape=(height, width, channels))
		x = layers.Conv2D(128, 3)(discriminator_input)
		#构建连续多层layers.Dense/layers.LeakyReLU/layers.Conv2D/layers.Flatten/layers.Dropout等
		......
		#构建判别器模型实例对象:把形状为(32, 32, 3)的图像作为模型输入,映射到一个包含多层layers的模型输出网络,
		#最终转换为一个二进制分类决策(即分类为真/假)
		discriminator = keras.models.Model(discriminator_input, x)
		discriminator.summary()
		#clipvalue在优化器中使用梯度裁剪(限制梯度值的范围),decay为了稳定训练过程,使用学习率衰减
		discriminator_optimizer = keras.optimizers.RMSprop( lr=0.0008, clipvalue=1.0, decay=1e-8) 
		discriminator.compile(optimizer=discriminator_optimizer, loss='binary_crossentropy')

	3.把生成器网络和判别器网络连接在一起构建一个完整的GAN
		#将判别器网络的权重设置为不可训练(仅应用于GAN模型),这样在训练时判别器网络的权重便不会更新,
		#否则在训练时可以对判别器的权重进行更新的话,则会导致训练判别器始终预测“真”,但这并不是想要的效果
		discriminator.trainable = False 
		#把形状为 (latent_dim,)的随机向量(潜在空间中的一个随机点)作为模型输入
		gan_input = keras.Input(shape=(latent_dim,)) 
		#把生成器网络模型的实例对象 和 判别器网络模型的实例对象 连接在一起构建为一个新的模型,最终返回判别器网络的模型输出
		gan_output = discriminator(generator(gan_input)) 
		#构建完整的GAN模型:将形状为 (latent_dim,)的随机向量(潜在空间中的一个随机点)作为模型输入,
		#最终模型输出转换为一个分类决策(即分类为真/假),训练时的标签都是“真实图像”,那么将会更新生成器网络的权重,
		#使得判别器网络在观察假图像时更有可能预测为“真”,这个模型将让生成器向某个方向移动,从而提高它欺骗判别器的能力
		gan = keras.models.Model(gan_input, gan_output)
		#clipvalue在优化器中使用梯度裁剪(限制梯度值的范围),decay为了稳定训练过程,使用学习率衰减
		gan_optimizer = keras.optimizers.RMSprop(lr=0.0004, clipvalue=1.0, decay=1e-8)
		gan.compile(optimizer=gan_optimizer, loss='binary_crossentropy')

1.转置卷积 Conv2DTranspose 可被称为 反卷积、后卷积、分数步⻓卷积(fractionally-strided convolution)。
2.在模型设计中,转置卷积层常⽤于将较小的特征图变换为更⼤的特征图。在全卷积⽹络中,
  当输⼊是⾼和宽较小的特征图时,转置卷积层可以⽤来将⾼和宽放⼤到输⼊图像的尺⼨。
3.转置卷积层可以放⼤特征图。在图像处理中,我们有时需要将图像放⼤,即上采样(upsample)。上采样的⽅法有很多,常⽤的有双线性插值。
  在全卷积⽹络中,我们将转置卷积层初始化为双线性插值的上采样。

1.padding='same':填充后输出的宽度和高度与输入的宽度和高度相同
2.Conv2DTranspose 例子1:
	下面转置卷积的输入形状为(None, 14, 14, 64),输出形状为(None, 28, 28, 32),上采样为28×28,转置卷积把输入的宽和高都分别放大了2倍
	x = layers.Conv2DTranspose(32, 3, padding='same', activation='relu', strides=(2, 2))
3.Conv2DTranspose 例子2:
	下面转置卷积的输入形状为(None, 16, 16, 256),输出形状为(None, 32, 32, 256),上采样为32×32,转置卷积把输入的宽和高都分别放大了2倍
	x = layers.Conv2DTranspose(256, 4, strides=2, padding='same')(x)
VAE 的参数通过两个损失函数来进行训练:
1.一个是重构损失(reconstruction loss):
	xent_loss = keras.metrics.binary_crossentropy(x, z_decoded) 
	为原始输入和编码-解码后的输出比较,它迫使解码后的样本匹配初始输入。
2.一个是正则化损失(regularization loss):
	kl_loss = -5e-4 * K.mean(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1)
	它有助于学习具有良好结构的潜在空间,并可以降低在训练数据上的过拟合 
3.最后合并重构损失和正则化损失
	K.mean(xent_loss + kl_loss)

1.构建Model模型的实例对象model
	from keras.models import Model
	model = Model(input,output) 
		1.将xx模型实例化出一个model对象,它将一个模型输入input映射为一个模型输出output,
		  或者说可以理解为把一个模型输入input映射为一个包含多层的整体的模型。
		2.模型输入input可以是 keras.Input(shape)、layers.Input(shape)。
		3.模型输出output:
			可以是一个自定义类的实例对象:class 自定义类名(keras.layers.Layer)的实例对象。
		  	也可以是一个包含多层layers的模型输出:output=layers.xxx(参数)(上一层layers)。
	 	  	也可以是一个模型实例对象:output=keras.models.Model(input,output)。比如构建GAN模型的例子。
 
2.model实例对象的多种使用形式
	1.output = model(input) 
		给model实例对象传入真实的模型输入数据,输出对应的目标数据
		input为真实的模型输入,output为模型输出
	2.model.fit(x=x_train, y=y_train, shuffle=True, epochs=10, batch_size=batch_size, validation_data=(x_test, y_test))
		对model实例对象直接进行fit训练,传入用于训练/验证的模型输入和模型输出,可以同时指定shuffle/epochs/batch_size等
	3.output = Model实例对象2(Model模型实例对象1(input))
 		多个Model实例对象进行嵌套连接在一起构建为一个新的网络模型,即Model模型1的输出作为Model模型2的输入。
		比如GAN模型中,便把生成器网络模型的实例对象和判别器网络模型的实例对象连接在一起构建为一个新的模型,最终返回判别器网络的模型输出。

3.keras.layers.Layer层:output = layers.Conv2D()/layers.Dense()/layers.Conv2DTranspose()/...
  自定义keras.layers.Layer层的形式:
	1.class 自定义类名(keras.layers.Layer):
		def call(self, inputs):
			#可以不使用这个返回输出值,但层必须要有返回值
			return x 
	2.创建自定义Layer层的实例对象:output = 自定义类名(inputs)

4.GAN 生成器网络 和 GAN 判别器网络 的组合
	1.GAN 生成器网络
		#设置模型输入是一个形状为 (latent_dim,)的随机向量(潜在空间中的一个随机点)
		generator_input = keras.Input(shape=(latent_dim,))
		x = layers.Dense(128 * 16 * 16)(generator_input)
		#构建连续多层layers.Dense/layers.LeakyReLU/layers.Conv2D/layers.Reshape等
		......
		#构建生成器模型实例对象:把形状为 (latent_dim,)的随机向量(潜在空间中的一个随机点)作为模型输入,
		#映射到一个包含多层layers的模型输出网络,最终解码为一张形状为 (32, 32, 3) 的合成图像
		generator = keras.models.Model(generator_input, x) 
		generator.summary()

 	2.GAN 判别器网络
		discriminator_input = layers.Input(shape=(height, width, channels))
		x = layers.Conv2D(128, 3)(discriminator_input)
		#构建连续多层layers.Dense/layers.LeakyReLU/layers.Conv2D/layers.Flatten/layers.Dropout等
		......
		#构建判别器模型实例对象:把形状为(32, 32, 3)的图像作为模型输入,映射到一个包含多层layers的模型输出网络,
		#最终转换为一个二进制分类决策(即分类为真/假)
		discriminator = keras.models.Model(discriminator_input, x)
		discriminator.summary()
		#clipvalue在优化器中使用梯度裁剪(限制梯度值的范围),decay为了稳定训练过程,使用学习率衰减
		discriminator_optimizer = keras.optimizers.RMSprop( lr=0.0008, clipvalue=1.0, decay=1e-8) 
		discriminator.compile(optimizer=discriminator_optimizer, loss='binary_crossentropy')

	3.把生成器网络和判别器网络连接在一起构建一个完整的GAN
		#将判别器网络的权重设置为不可训练(仅应用于GAN模型),这样在训练时判别器网络的权重便不会更新,
		#否则在训练时可以对判别器的权重进行更新的话,则会导致训练判别器始终预测“真”,但这并不是想要的效果
		discriminator.trainable = False 
		#把形状为 (latent_dim,)的随机向量(潜在空间中的一个随机点)作为模型输入
		gan_input = keras.Input(shape=(latent_dim,)) 
		#把生成器网络模型的实例对象 和 判别器网络模型的实例对象 连接在一起构建为一个新的模型,最终返回判别器网络的模型输出
		gan_output = discriminator(generator(gan_input)) 
		#构建完整的GAN模型:将形状为 (latent_dim,)的随机向量(潜在空间中的一个随机点)作为模型输入,
		#最终模型输出转换为一个分类决策(即分类为真/假),训练时的标签都是“真实图像”,那么将会更新生成器网络的权重,
		#使得判别器网络在观察假图像时更有可能预测为“真”,这个模型将让生成器向某个方向移动,从而提高它欺骗判别器的能力
		gan = keras.models.Model(gan_input, gan_output)
		#clipvalue在优化器中使用梯度裁剪(限制梯度值的范围),decay为了稳定训练过程,使用学习率衰减
		gan_optimizer = keras.optimizers.RMSprop(lr=0.0004, clipvalue=1.0, decay=1e-8)
		gan.compile(optimizer=gan_optimizer, loss='binary_crossentropy')

1.一旦训练好了这样的模型(本例中是在 MNIST 上训练),我们就可以使用 decoder解码网络将任意潜在空间向量转换为图像。
2.此处直接使用 解码器模型Model(decoder_input, x)的实例对象decoder,它可以将 decoder_input转换为解码后的图像。
	#1.编码器输入和输出:
	#	一个编码器模块将输入样本 input_img 转换为表示潜在空间中的两个向量 z_mean 和 z_log_variance,
	#	因此即输入图像最终被编码为这两个向量 z_mean 和 z_log_variance。
	#	而 z_mean = layers.Dense(latent_dim)(x) 和 z_log_var = layers.Dense(latent_dim)(x) 两个Dense层输出的向量的形状都均为 (None, 2),
	# 	(None, 2) 即(批量大小/样本数, 2),指的是(batch_size,latent_dim),采样的实际为形状(latent_dim,)的随机向量(潜在空间中的一个随机点)。
	#2.解码器输入和输出:
	#	假定潜在正态分布能够生成输入图像,并从这个分布中随机采样一个点z,	
	#  	z = z_mean + exp(z_log_variance) * epsilon,其中 epsilon 是取值很小的随机张量,
	#	z、z_mean、z_log_var、epsilon.shape 这四个向量的形状都均是 (None, 2),(None, 2) 即(批量大小/样本数, 2),
	#	指的是(batch_size,latent_dim),采样的实际为形状(latent_dim,)的随机向量(潜在空间中的一个随机点)。
	#  	采样一个潜在点向量z 并对其进行解码,需要两个向量 z_mean 和 z_log_var 二者定义了潜在空间中的一个概率分布。
	#	解码器模块就负责将潜在空间的这个潜在点向量z映射回原始输入图像。
	#3.编码器和解码器的输入和输出流程:
	#  输入图像-->编码器-->向量形状是(None,2)的z_mean和z_log_variance --> z_mean和z_log_variance组装为形状是(None,2)的潜在点向量z --> 解码器 --> 原始输入图像  
  	z = layers.Lambda(sampling)([z_mean, z_log_var])
  	print("z.shape:",K.int_shape(z)) # (None, 2) 即(批量大小/样本数, 2),指的是(batch_size,latent_dim)
  	decoder_input = layers.Input(K.int_shape(z)[1:])
  	print("decoder_input.shape:",K.int_shape(decoder_input)) # (None, 2) 即(批量大小/样本数, 2),指的是(batch_size,latent_dim)
  	decoder = Model(decoder_input, x)
  	z_decoded = decoder(z)
  	print("z_decoded.shape:",K.int_shape(z_decoded)) # (None, 28, 28, 1) 即(批量大小/样本数, 28, 28, 1)

3.因此此处使用解码器模型Model(decoder_input, x)的实例对象decoder 进行predict预测:	
	#将批量解码为数字图像。z_sample的形状为(16, 2),batch_size为16,z_sample代表(批量大小, 2),指的是(batch_size,latent_dim)
	x_decoded = decoder.predict(z_sample, batch_size=batch_size)
	#将批量第一个数字的形状从 28×28×1 转变为 28×28
	digit = x_decoded[0].reshape(digit_size, digit_size)

>>> np.linspace(0.05, 0.95, n)
array([0.05      , 0.11428571, 0.17857143, 0.24285714, 0.30714286,
       0.37142857, 0.43571429, 0.5       , 0.56428571, 0.62857143,
       0.69285714, 0.75714286, 0.82142857, 0.88571429, 0.95      ])
>>> np.linspace(0.05, 0.95, n).shape
(15,)
>>> figure.shape
(420, 420)
>>> grid_x.shape
(15,)
>>> grid_y.shape
(15,)

>>> figure
array([[0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.]])
# grid_x 和 grid_y 值都相同
>>> grid_x
array([-1.64485363e+00, -1.20404696e+00, -9.20822976e-01, -6.97141435e-01,
       -5.03965367e-01, -3.28072108e-01, -1.61844167e-01, -1.39145821e-16,
        1.61844167e-01,  3.28072108e-01,  5.03965367e-01,  6.97141435e-01,
        9.20822976e-01,  1.20404696e+00,  1.64485363e+00])
>>> grid_y
array([-1.64485363e+00, -1.20404696e+00, -9.20822976e-01, -6.97141435e-01,
       -5.03965367e-01, -3.28072108e-01, -1.61844167e-01, -1.39145821e-16,
        1.61844167e-01,  3.28072108e-01,  5.03965367e-01,  6.97141435e-01,
        9.20822976e-01,  1.20404696e+00,  1.64485363e+00])

#负责生成输出每行图像
for i, yi in enumerate(grid_x):
	#负责生成输出每列图像
	for j, xi in enumerate(grid_y):
		z_sample = np.array([[xi, yi]])
		z_sample.shape # (1, 2)
		z_sample = np.tile(z_sample, batch_size).reshape(batch_size, 2)
		z_sample.shape # (16, 2)
z_sample的值为:
array([[grid_x[i], grid_y[j]],
       .......
       [grid_x[i], grid_y[j]]])


正态分布

发布了224 篇原创文章 · 获赞 111 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/zimiao552147572/article/details/104084870