本证主要相对深度学习的一些学习技巧做一些概括。
对图像数据进行扩展的常用方法包括:对图像进行角度偏移,左右偏移,上下偏移,随机放大或则缩小,水平翻转。 keras 数据预处理:
# -*- coding: utf-8 -*- from keras.preprocessing.image import ImageDataGenerator, img_to_array, load_img,array_to_img import matplotlib.pyplot as plt import numpy as np data_generate = ImageDataGenerator( rotation_range=20, #控制旋转角度 width_shift_range=0.2, #左右偏移度 height_shift_range=0.2, #上下偏移度 shear_range=0.2, #剪切变换程度 zoom_range=0.2, #放大缩小倍数 horizontal_flip=True, fill_mode='nearest' ) img = load_img(r'C:\Users\lenovo\Desktop\cat.1500.jpg') x = img_to_array(img) # x = x.reshape((1,)+x.shape) i = 0 fig, axes = plt.subplots(4, 5,sharex=True, sharey=True) for batch in data_generate.flow(x, batch_size=1, save_prefix='cat', save_format='jpeg'): img = batch.reshape(500, 490, 3).astype(np.int) axes[i//5, i%5].imshow(img) i+=1 if i >= 20: break plt.subplots_adjust(wspace=0,hspace=0) plt.show()原始图像:
输出图像结果:
这里我们直接使用变换函数,置于是怎么实现的这种变化我们暂且不谈(埋下疑惑的种子)。 分析:通过这种变换之后使得神经网路对于多种形态的同一物体也能够很好的识别出来。
0均值实现:
X = np.random.rand(2, 5) X -= np.mean(X, axis=0)每个样本值减去样本的平局值。 图像0均值操作:
import numpy as np from keras.preprocessing.image import load_img,img_to_array,array_to_img import matplotlib.pyplot as plt X = load_img(r'C:\Users\lenovo\Desktop\cat.1500.jpg') X = img_to_array(X) #shape(500, 490, 3) X[:, :, 0] -= np.mean(X[:, :, 0]) #第一个通道 X[:, :, 1] -= np.mean(X[:, :, 1]) #第二个通道 X[:, :, 2] -= np.mean(X[:, :, 2]) #第三个通道 X = X.astype(np.int) #修改数据类型 plt.imshow(X) plt.show()新图片:
两种方法:
将0均值化后的数据的每一维除以每一维的标准差另一种方法是将数据中的每一维归一化到区间[a,b]。第二种归一化方法只适用于数据的不同维度应该具有相同的重要性时,也就是每一维度数据的权重一样时。方法一:
X = np.random.rand(2, 5) X -= np.mean(X, axis=0) X /= np.std(X, axis=0) print(X) [ 1. -1. -1. 1. -1.] [-1. 1. 1. -1. 1.]]方法二:
X_normed = X/=X.max(axis=0)#归一化为(0,1)之间主成分分析之前了解的比较多这里不加赘述。
import numpy as np X = np.random.rand(2, 5) X -= np.mean(X, axis=0) Cov = np.dot(X.T, X) / X.shape[0] U, S, V = np.linalg.svd(Cov) Xrot = np.dot(X, U) #数据取相关性 PCA = np.dot(X, U[:, :100]) #获取前100列数据 print(X, Xrot)(Whitening)的目的是降低数据的冗余性,数据经过白化以后应该具有以下性质
特征之间相关性较低所有特征之间具有相同的方差。在主成分分析算法中我们已经消除了数据之间的相关性,白化还需要使得数据具有相同的方差。 数据白化实现:
XWhiten = PCA/np.sqrt(S + 1e-6) #除以特征值,也就是奇异值的平方根使用随机高斯分布产生初始化网络参数
import numpy as np import matplotlib.pyplot as plt def neurous(sqrt=False, num=1000, b=0): '''神经元模型''' x = np.ones(num) if not sqrt: w = np.random.rand(num) else: w = np.random.rand(num)/np.sqrt(num) return np.dot(w, x) + b #迭代100000次获得不同随机生成的权重参数得到的加权输出 z1 = [] #迭代100000次获得不同的随机生成的权重参数得到的加权输出 for i in range(100000): z1.append(neurous()) #显示100000次加权输出的直方图 n, bins, patches = plt.hist(z1, 100) plt.title('Histigram of z = wx + b') plt.show()效果图如下:
计算激活值:
sigmoid = lambda x:1./(1.+np.exp(-x)) a1 = sigmoid(np.array(z1))输出结果图像:
当使用sigmoid函数作为我们的激活函数时,激活值集中在0,1的附近使得神经元基本处于饱和状态。为什么会出现这种情况呢。下面我们来分析: sigmoid函数曲线:
由图中观察0,1附近的曲线趋于平缓,可想而知经过一次迭代之后该值的改变时十分微小的,输出神经元接近于饱和,也就是下一层的神经元输入饱和,后面通过反向传播BP算法对权重进行微调所带来的变化也不会太明显,这就形成了一个“恶性循环” 最终网络训练速度变得非常的慢,而且更容易过拟合。 如下我选择了一个input,h_layer,output,[1,1,1]的网络。
L层损失为: δ L = ( y − a 3 ) ⊙ f ‘ ( z 3 ) \delta_L = (y-a_3)\odot f^`(z_3) δL=(y−a3)⊙f‘(z3) 对w_2求偏导数: ∂ L ∂ w 2 = δ L . a 2 \frac{\partial L}{\partial w_2} = \delta_L . a_2 ∂w2∂L=δL.a2 w 2 = w 2 − d w 2 w_2 = w_2 - dw_2 w2=w2−dw2 a 2 在 0 附 近 时 , w 2 的 导 数 是 十 分 为 微 小 的 , 所 以 L 层 的 误 差 基 本 上 是 不 变 的 , 所 以 反 过 来 在 求 w 2 时 , 这 种 变 化 还 是 小 的 a_2在0附近时,w_2的导数是十分为微小的,所以L层的误差基本上是不变的,所以反过来在求w_2时,这种变化还是小的 a2在0附近时,w2的导数是十分为微小的,所以L层的误差基本上是不变的,所以反过来在求w2时,这种变化还是小的
产生上面结果的原因是随机产生权重参数的标准差太大,下面该进方法是使用均值为0,标准差为 1 / n 1 / \sqrt{n} 1/n 高斯分布的效果。 该方法有效的解决了神经元的过饱和问题,即保证了网络模型参数在初始化阶段都符合高斯分布的输入,也提高了算法的收敛速度
z1 = [] for i in range(100000): # w= np.random.rand(num)/sqrt(num) z1.append(neurous(sqrt=True))加权值输出为:
激活值输出为:
当然在参数初始化这一块我门可以使用已经训练好的参数,这些参数是经过一定训练的所以他的均值和方差都是我们想要的,而且能够加快我们学习速度,这种方式在深度学习中被称为‘迁移学习’。 如果我们在训练过程中需要将程序停止,这时候我们就可以将采纳数保存,等到下一次我们再次训练的时候再将这些参数拿出来,继续训练。
关于正则方法我在这篇博客中介绍了L2正则化,并且是在实例应用中,比较详细了解具体的实现细节,并且我在后面给出了具体的求导公式的过程。博客