2017-09-12 12:03:10 zhangjiaxuu 阅读数 748
  • 深度学习基础与TensorFlow实践教程

    本课程主要介绍了深度学习的基础原理和TensorFlow系统基本使用方法。TensorFlow是目前机器学习、深度学习领域优秀的计算系统之一,本课程将结合实例介绍使用TensorFlow开发机器学习应用的详细方法和步骤,着重讲解了用于图像识别的卷积神经网络和用于自然语言处理的循环神经网络的理论知识及其TensorFlow实现方法,并结合实际场景和例子描述了深度学习技术的应用范围与效果。 所有案例均来自讲师团队工作中的亲身实践,所选案例均是深度学习的经典应用,非常具有代表性。

    21447 人正在学习 去看看 AI100讲师

问题:1:构成的网络结构?

         2:输入数据大小?



https://yq.aliyun.com/articles/118726?spm=5176.100239.blogcont122848.14.zwhUbk


import tensorflow as tf
import pandas as pd
import numpy as np
import os
import matplotlib
import matplotlib.pyplot as plt
import random
#matplotlib inline
import tensorflow as tf
import shutil
import tensorflow.contrib.learn as tflearn
import tensorflow.contrib.layers as tflayers
from tensorflow.contrib.learn.python.learn import learn_runner
import tensorflow.contrib.metrics as metrics
import tensorflow.contrib.rnn as rnn


random.seed(111)
rng=pd.date_range(start='2000',periods=209,freq='M')
"""pd.date_range 函数:生成日期范围 
   start:开始日期 periods:日期范围内日期的个数,periods*freq 等于日期范围的长度
   freq:每多少天或其他明确时间频率的方式,默认为D,即1天 M为一个月
"""
ts=pd.Series(np.random.uniform(-10,10,size=len(rng)).cumsum())
ts.plot(c='b',title='Example Time Series')     #颜色蓝色
plt.show()
ts.head(10)                 #使用head查看前几行数据(默认是前5行),不过你可以指定前几行


TS=np.array(ts)
num_periods=20              #观测值
f_horizon=1     #forecast horizon 预测一步

x_data=TS[:(len(TS)-len(TS)%num_periods)]          #len(TS)=209
x_batches=x_data.reshape(-1,20,1)

y_data=TS[1:(len(TS)-(len(TS)%num_periods))+f_horizon]
y_batches=y_data.reshape(-1,20,1)

print("x_data shape%s"%len(TS))
print("x_batchesis%s"%len(x_batches))             #10
print(x_batches.shape)                    # (10, 20, 1)
print("x_batches[0:2]is %s"%x_batches[0:2])


print("y_batches[0:1]is%s"%y_batches[0:1])
print(y_batches.shape)                      #(10, 20, 1)

##??不懂 测试数据是怎么取的 为什么
def test_data(series,forecast,num_periods):
    test_x_setup=TS[-(num_periods+forecast):]
    testX=test_x_setup[:num_periods].reshape(-1,20,1)
    testY=TS[-(num_periods):].reshape(-1,20,1)
    return testX,testY

X_test,Y_test=test_data(TS,f_horizon,num_periods)
print(X_test.shape)

print(X_test)


tf.reset_default_graph()              #清除默认图的堆栈,并设置全局图为默认图

num_periods=20
inputs=1
hidden=100
output=1

X=tf.placeholder(tf.float32,[None,num_periods,inputs])
y=tf.placeholder(tf.float32,[None,num_periods,output])

basic_cell=tf.contrib.rnn.BasicRNNCell(num_units=hidden,activation=tf.nn.relu)
rnn_output,states=tf.nn.dynamic_rnn(basic_cell,X,dtype=tf.float32)

learning_rate=0.001


"tf.layers.dense:全连接层 操作 outputs = activation(inputs.kernel + bias) "
stacked_rnn_output=tf.reshape(rnn_output,[-1,hidden])            #转为二维数据
stacked_outputs=tf.layers.dense(stacked_rnn_output,output)
outputs=tf.reshape(stacked_outputs,[-1,num_periods,output])              #?

loss=tf.reduce_sum(tf.square(outputs-y))
optimizer=tf.train.AdamOptimizer(learning_rate=learning_rate)
training_op=optimizer.minimize(loss)

init=tf.global_variables_initializer()

####################################
epochs=1000
with tf.Session() as sess:
    init.run()
    for ep in range(epochs):
        sess.run(training_op,feed_dict={X:x_batches,y:y_batches})
        if ep %100 ==0:
            mse=loss.eval(feed_dict={X:x_batches,y:y_batches})
            print(ep,"\TMSE:",mse)

    y_pred=sess.run(outputs,feed_dict={X:X_test})
    print(y_pred)

plt.title("Forecast vs Actual",fontsize=14)
plt.plot(pd.Series(np.ravel(Y_test)),"bo",markersize=10,label="Actual")
#plt.plot(pd.Series(np.ravel(Y_test)),"w*",markersize=10)
plt.plot(pd.Series(np.ravel(y_pred)),"r.",markersize=10,label="Forecast")
plt.legend(loc="upper left")
plt.xlabel("Time Periods")

plt.show()

2019-03-25 17:15:33 qq_37667364 阅读数 317
  • 深度学习基础与TensorFlow实践教程

    本课程主要介绍了深度学习的基础原理和TensorFlow系统基本使用方法。TensorFlow是目前机器学习、深度学习领域优秀的计算系统之一,本课程将结合实例介绍使用TensorFlow开发机器学习应用的详细方法和步骤,着重讲解了用于图像识别的卷积神经网络和用于自然语言处理的循环神经网络的理论知识及其TensorFlow实现方法,并结合实际场景和例子描述了深度学习技术的应用范围与效果。 所有案例均来自讲师团队工作中的亲身实践,所选案例均是深度学习的经典应用,非常具有代表性。

    21447 人正在学习 去看看 AI100讲师

原理部分完全参照另外2篇:

深度学习初步,全连接神经网络,MLP从原理到实现(一)原理部分,反向传播详细解释和实际计算例子

深度学习初步,全连接神经网络,MLP从原理到实现(二)原理部分,过拟合,激活函数,batchsize和epochs,训练DL模型的建议

说明:这个实现全部用java实现,依赖矩阵运算库jblas和画图的一个库jfree(不需要画学习率衰减曲线的可以不用这个库),无论是预测还是反向传播求梯度都是基于矩阵/向量运算的,这样更简洁明了。使用了多线程来并行的预测和训练,但是速度仍然比GPU跑的慢好多,项目 用eclipse构建,导入到eclipse可直接使用。完整源码见我的GitHub:https://github.com/colin0000007/MLP4j,如果觉得可以,点个star啊!!

这篇文章我会挑一些重要部分的源码说明,主要是反向传播,参数更新等。整体的源码设计参照了keras。使用new Sequential,然后添加layer,最后train,完整的例子参照源码中的MinistExample(测试Minist数据集)。

 

	public static void main(String[] args) {
		loadData();
		Sequential model = new Sequential();
		//必须首先设置Input
		model.setInput(new Input(x[0].length));
		model.addLayer(new Dense(400,ActivationFunction.RELU));
		model.addLayer(new Dense(400,ActivationFunction.RELU));
		model.addLayer(new Dense(10,SoftMax.SOFTMAX));
		System.out.println("x_train:("+x.length+","+x[0].length+")");
		//衰减可以使用默认的ExponentialLearningRateDecay.defaultDecay,默认lr初始0.2可以修改
		//model.trainParallel(x, y, 400, 20, ExponentialLearningRateDecay.defaultDecay);
		//衰减使用ExponentialLearningRateDecay.noDecay可以不进行lr的衰减,lr默认0.2可以修改
		//model.trainParallel(x, y, 400, 20, ExponentialLearningRateDecay.noDecay);
		ExponentialLearningRateDecay decay = 
				new ExponentialLearningRateDecay(2, 0.2, 0.8, false);
		model.trainParallel(x, y, 400, 20, decay);
		//以上参数迭代20个epoch后训练集acc=0.9860282
	}

好了,下面直接说说源码中比较重要的部分:

前向传播的源码:

	/**
	 * 前向传播计算a和z这两个list
	 * 每个list保存了每一层的a或者z
	 * 只计算单个样本
	 * 每个样本的forwardPropagation可以并行,单个样本的forwardPropagation矩阵运算可以并行
	 * @return
	 */
	public ArrayList<double[]>[] forwardPropagation(double[] x) {
		ArrayList<double[]>[] za = new ArrayList[2];
		za[0] = new ArrayList<>(layers.size());
		za[1] = new ArrayList<>(layers.size());
		double[] input = x;
		for(int i = 0; i < layers.size(); i++) {
			double[][] weights = layers.get(i).getWeights();
			double[] biases = layers.get(i).getBiases();
			DoubleMatrix w = new DoubleMatrix(weights);
			DoubleMatrix a = new DoubleMatrix(input);
			DoubleMatrix b = new DoubleMatrix(biases);
			// z = w*input + b
			DoubleMatrix zMatrix = w.mmul(a).addi(b);
			double[] zs = zMatrix.toArray();
			//计算这一层的输出
			ActivationFunction sigma = layers.get(i).getActivationFunction();
			double[] as = sigma.functionValue(zs);
			za[0].add(zs);
			za[1].add(as);
			input = as;
		}
		return za;
	}

这里的forwardPropagation是针对单个样本计算的,前向传播就是要计算一个样本输入经过每一层的z值和a值,所以这里就是遍历所有layer,计算z和a,z和计算直接对应原理部分的矩阵运算,w*input+b,w就是一个权重矩阵,b是偏置向量,参照Dense(全连接层)的设计:

/**
 * 全连接层
 * @author outsider
 *
 */
public class Dense extends Layer{
	//wij 指的时当前层第i个单元到上一层的j个单元连接的权重。
	//所以weights的行数是本层的单元个数,列数是上一层单元的个数
	private double[][] weights;
	//偏置
	private double[] biases;
	//当前层的单元个数
	private int units;
	//激活函数
	private ActivationFunction activationFunction;
	public Dense(int units, ActivationFunction activationFunction) {
		this.units = units;
		this.activationFunction  = activationFunction;
	}
	/**
	 * 初始化权重参数
	 * @param lastUnits
	 */
	public void init(int lastUnits) {
		this.biases = new double[units];
		//权重随机初始化
		this.weights = DoubleMatrix.randn(units, lastUnits).divi(10).toArray2();
		DoubleMatrix doubleMatrix = new DoubleMatrix();
	}
	
}

a的计算是把计算后的z送到对应层的激活函数中一个个计算a值。这里所有layer的a和z都要保存。保存z是因为\frac{\partial l}{\partial z}中计算\sigma (z)'需要用到,保存a在计算\frac{\partial l}{\partial w}会用到,和原理部分对应的。

反向传播计算\frac{\partial l}{\partial z}部分源码:

	/**
	 * 
	 * @param x 单个样本的x
	 * @param y 单个样本的y
	 * @return 每一层的梯度矩阵,注意是一个3维数组,每一个矩阵的尺寸不一样
	 */
	public Gradient backPropagation(double[] x, double[] y) {
		//(1) 前向传播
		ArrayList<double[]>[] za = forwardPropagation(x);
		ArrayList<double[]> z = za[0];
		ArrayList<double[]> a = za[1];
		//(2) 反向传播计算 partial L / partial Z,这直接是偏置的梯度
		double[][] LZ = new double[layers.size()][];
		//计算最后一层的 partial L / partial z
		LZ[LZ.length - 1] = layers.get(layers.size() - 1).getActivationFunction()
				.partialLoss2PartialZ(null, a.get(a.size() - 1), y);
		//计算其他层的 partial L / partial z 
		for(int i = LZ.length -2; i >=0; i--) {
			Dense layer = layers.get(i);
			//1.求激活函数的一阶导数
			double[] sigmaP = layer.getActivationFunction().firstDerivativeValue(z.get(i));
			//2.后一层的权重矩阵的转置乘以 partial L / partial z 向量
			DoubleMatrix m1 = new DoubleMatrix(layers.get(i + 1).getWeights()).
					transpose().mmul(new DoubleMatrix(LZ[i+1]));
			// 1和2得到的向量对应元素相乘即为结果
			LZ[i] = new DoubleMatrix(sigmaP).muli(m1).toArray();
		}
		//(3).计算梯度
		//partial L / partial Z的 列向量乘以上一层的输入a行向量
		double[] input = x;
		double[][][] gradients = new double[layers.size()][][];
		for(int i = 0; i < gradients.length; i++) {
			DoubleMatrix aVec = new DoubleMatrix(input);
			DoubleMatrix lzVec = new DoubleMatrix(LZ[i]);
			aVec = aVec.reshape(aVec.columns, aVec.rows);
			gradients[i] = lzVec.mmul(aVec).toArray2();
			input = a.get(i);
		}
		Gradient gradient = new Gradient(gradients, LZ);
		return gradient;
	}

计算\frac{\partial l}{\partial z}需要倒着来,最后一层的\frac{\partial l}{\partial z}在激活函数中被计算,也就是partialLoss2PartialZ,然后从倒数第二层开始计算,先求这一层的激活函数的一阶导数,这时候需要用到forwardPropagation中对应层的z值,计算后是一个double[] sigmaP向量,然后计算一个中间结果,后一层权重矩阵的转置和后一层\frac{\partial l}{\partial z}向量的乘积得到一个向量,最后将这2个向量对应元素相乘得到该层的\frac{\partial l}{\partial z},对应原理部分的公式:

迭代完所有的layer即可求得全部层的\frac{\partial l}{\partial z}

求梯度源码:(求梯度实在train中实现的所以直接看train,为了便于理解这里不看并行训练的方法)

/**
	 * 训练
	 * @param x 
	 * @param y 每一个标签必须one-hot编码,所以是二维数组
	 * @param lr 学习率
	 * @param batchSize 每次梯度下降的更新参数用到的样本个数
	 * @param epochs 在整个样本集上做多少次的训练
	 * @param lrDecay 学习率指数衰减
	 */
	public void train(double[][] x, double[][] y, 
			int batchSize, int epochs, ExponentialLearningRateDecay lrDecay) {
		//一个epoch中的各个batch可以并行,一个batch之间各单个样本之间可以并行
		double lr = lrDecay.lr;
		DoubleMatrix yM = new DoubleMatrix(y);
		int[] yTrue = yM.rowArgmaxs();
		this.classNum = layers.get(layers.size() - 1).getUnits();
		//1.划分样本
		int sampleNum = x.length;
		//分多少批
		int batchNum = sampleNum / batchSize;
		System.out.println("batchNum:"+batchNum);
		int left = sampleNum % batchSize;//样本余数
		//保存样本的索引位置
		List<Integer> sampleIndices = new ArrayList<>(x.length);
		for(int i = 0; i < sampleNum; i++) {
			sampleIndices.add(i);
		}
		// epoch循环
		for(int i = 0; i < epochs; i++) {
			//对学习率衰减
			lr = lrDecay.decayLR(i);
			System.out.println("epoch "+(i+1)+"/"+epochs+",lr="+lr);
			//batch循环
			for(int j = 0; j < batchNum; j++) {
				int c = left *((j+1)/batchNum);
				double[][] batchX = new double[batchSize + c][];
				double[][] bathcY = new double[batchSize + c][];
				System.out.println("epoch..."+(i+1)+"/"+epochs+",batch..."+(j+1)+"/"+batchNum+","+"batchSize="+batchX.length);
				int offset = j * batchSize;
				for(int k = j * batchSize; k < (j+1)*batchSize + c; k++) {
					batchX[k-offset] = x[sampleIndices.get(k)];
					bathcY[k-offset] = y[sampleIndices.get(k)];
				}
				//训练,一个一个样本计算梯度,这个过程可以同时进行。
				//将每个样本的梯度累加
				Gradient gradient = backPropagation(batchX[0], bathcY[0]);
				double[][][] totalWeightsGradient = gradient.weightsGradient;
				double[][] totalBiasesGradient = gradient.biasesGradient;
				for(int m = 1; m < batchX.length; m++) {
					Gradient gradient2 = backPropagation(batchX[m], bathcY[m]);
					double[][][] weightsGradient = gradient2.weightsGradient;
					double[][] biasesGradient = gradient2.biasesGradient;
					for(int f = 0; f < weightsGradient.length; f++) {
						totalWeightsGradient[f] = new DoubleMatrix(totalWeightsGradient[f]).
								addi(new DoubleMatrix(weightsGradient[f])).toArray2();
						totalBiasesGradient[f] = new DoubleMatrix(totalBiasesGradient[f]).
								addi(new DoubleMatrix(biasesGradient[f])).toArray();
					}
				}
				//梯度除以N
				for(int k = 0; k < layers.size(); k++) {
					totalBiasesGradient[k] = new DoubleMatrix(totalBiasesGradient[k])
							.divi(batchX.length).toArray();
					totalWeightsGradient[k] = new DoubleMatrix(totalWeightsGradient[k]).
							divi(batchX.length).toArray2();
				}
				//更新参数
				for(int f = 0; f < layers.size(); f++) {
					Dense dense = layers.get(f);
					double[][] oldW = dense.getWeights();
					double[] oldBia = dense.getBiases();
					// w = w - lr * gradient
					double[][] newW = new DoubleMatrix(oldW).
							subi(new DoubleMatrix(totalWeightsGradient[f]).mul(lr)).toArray2();
					double[] newBia = new DoubleMatrix(oldBia).
							subi(new DoubleMatrix(totalBiasesGradient[f]).mul(lr)).toArray();
					dense.setWeights(newW);
					dense.setBiases(newBia);
				}
				//每20倍批次输出一次训练信息
				/*if((j+1) % 20 == 0) {
					int[] yPredicted = predictAndReturnClassIndex(x);
					//训练集上的准确率
					float acc = accuracy(yPredicted, yTrue);
					System.out.println("\n"+(j+1)*batchSize + "/" + x.length+"........acc:"+acc+"\n");
				}*/
			}
			double[][] yPre = predictParallel(x);
			int[] yPredicted = new DoubleMatrix(yPre).rowArgmaxs();
			double loss = loss(yPre, y);
			float acc = accuracy(yPredicted, yTrue);
			String print = "epoch " +(i+1)+ " done"+"........acc:"+acc+",total loss:"+loss;
			System.out.println(print);
			//打乱数据位置
			//acc会有一些不稳定,估计也和这个操作有关系。
			//测试后发现,shuffle有利用梯度下降
			Collections.shuffle(sampleIndices);
		}
	}

重点看//batch循环中的代码,再说说epoch和batchsize,指定了epoch和batchsize和,需要对训练样本划分成多少个batch对应源码中的batchNum,然后每一个batch计算梯度,更新一次参数。训练过程中每次batch的划分后每个batch里的样本是随机的,sampleIndices保存了最初的样本索引位置,每一轮epoch这些位置被打乱,我已经验证过,打乱后的效果更好。接下来有了一个batch的数据,batchX和batchY就需要计算分别计算里面样本的梯度,先进行一次forwardPropagation然后backPropagation就有了a,z和\frac{\partial l}{\partial z},然后梯度的公式是:

\frac{\partial l}{\partial z}列向量乘以a向量的转置就可以得到梯度,最后将所有样本的梯度累加起来,最后更新梯度w=w-lr*gradient

这些过程只要理解了理论部分就能实现。注意这里梯度总和一定要除以样本的个数。我之前没有除出现了准确率一直维持再0.1左右。至于原因我大概猜测了下,如果不除以N,那么优化的总的loss,如果除以N那么优化平均loss,想象loss的是一个曲面,这时候从较高部分到较低部分地势相差很高,梯度下降学习率足够大才可能会有效果,如果优化平均loss,那么最大的loss值也不过是单个样本的最大的loss,远远小于多个样本的loss总和,这时候较高部分与低洼部分距离不会相差很大,所以优化时学习效率小一点依然效果显著。

预测过程和forwardPropagation一样,只是我们不需要保存中间层的a和z,只需要最后一层softmax的a向量作为结果。

感受:实际上我觉得只要理解了反向传播和梯度计算,就很简单,我觉得写起来比CRF那种模型还简单些。

下面是实现过程中的一些问题记录:

1.遇到的问题:nn参数初始化
如果参数初始太大,而且没有负数,会造成溢出的情况,
因为softmax作为输出层,里面存在着指数,输入太大则
会溢出。建议初始化较小的参数,并且必须有正负,比如
-0.25到0.25之间,关于参数初始化也有很大的学问,好的
参数初始化可以使收敛更快。

2.遇到的问题
//之前不work主要有两个原因:
//(1)梯度最后一步计算的矩阵化公式有错
//(2)损失函数没有除以N(我不知道为什么这个影响这么大,这直接导致了效果完全不行)
//目前存在的问题
//(1)效率不够高
//(2)收敛不够快,前面设置的参数情况下,epoch 2才达到0.82左右的acc
//3.23更新:
//使用了学习率指数衰减,效果好多了
//参数建议,如果epochs比较小,那么lr也要小一点
3.关于并行
之前使用call(),或者线程的join()来实现主线程等待子线程完成后继续
发现效果都不好,比串行都慢,但使用countDownLatch这个对象后发现
竟然速度快了2倍左右
3.线程级别的计算基于单个样本还是多个样本?
在我自己的实现中,单个线程就是单个样本的计算,因为线程池最大也就处理器个数+1,
所以如果直接将样本划分为处理器个数份,来并行,可能效果会好一些,不用涉及到大量
线程的管理。
实验了下:差不多能快个1000毫秒
4.并行对比
//train_parallel:4m22s one epoch
//train:7m07s
//train_parallel 比 train快1.63倍
使用并行预测大约快出2倍

5.关于并行训练的实现
将每个batch拆分成处理器个数这么多份,然后并行,每个线程保存了该线程计算的所有样本的梯度和
最后将这些线程中的梯度加起来就可以求得这个batch的梯度
不能单个样本作为一个线程,这样保存梯度会占用很大的内存
不能并行去修改总的梯度变量,这样互斥使得并行效果不那么有效了

6.使用方法
借鉴了keras的设计,
model = new Sequential()
model.add(layer)
.....
model.train()


       

2019-03-25 16:30:54 qq_37667364 阅读数 391
  • 深度学习基础与TensorFlow实践教程

    本课程主要介绍了深度学习的基础原理和TensorFlow系统基本使用方法。TensorFlow是目前机器学习、深度学习领域优秀的计算系统之一,本课程将结合实例介绍使用TensorFlow开发机器学习应用的详细方法和步骤,着重讲解了用于图像识别的卷积神经网络和用于自然语言处理的循环神经网络的理论知识及其TensorFlow实现方法,并结合实际场景和例子描述了深度学习技术的应用范围与效果。 所有案例均来自讲师团队工作中的亲身实践,所选案例均是深度学习的经典应用,非常具有代表性。

    21447 人正在学习 去看看 AI100讲师

其他两篇:

深度学习初步,全连接神经网络,MLP从原理到实现(一)原理部分,反向传播详细解释和实际计算例子

深度学习初步,全连接神经网络,MLP从原理到实现(三)实现部分,用java实现MLP

1.激活函数

(1)Sigmoid

Sigmoid将所有输入压缩到0到1之间,这样造成的问题是,当随着神经网络的层次加深时,特征的变化由于sigmoid而慢慢衰减。这样会造成靠近输入层的梯度很小。

(2)ReLU

普通类型的ReLU

 

ReLU是现在DL流行使用的激活函数,有一些变种。

ReLU实际上是一种线性的函数,

在z<0,σ(z) = 0

在z>0,σ(z) = z

 

(3)MaxOut

MaxOut可以自适应的训练出激活函数。

将每层的神经元分组,在组内选择最大的z值作为下一层的输入,例如:

这样可以产生不同的激活函数:

组内神经元数不同的效果:

怎么计算梯度呢?

因为取max操作是针对特定样本,比如:

被选中为最大,那么其对应的激活函数就是线性的 ,会更新 对应的权重,输入不同的样本,可能选中不同的z, 也可能会被选中更新参数。

还有其他类型的激活函数,可以自己查询。

2.batch size 和 epochs

batch size的来源:将样本分批,每一批样本用来优化损失函数,这其实就是批量梯度下降,分批最好随机。。比如样本有10000个,batch size = 100,那么分批为100批,优化时需要做100次参数更新。

epochs:将样本分批后,一次epoch就是用完所有批次的样本用来梯度下降。例如:样本10000,batch size = 100,epochs = 10,每一个epoch参数更新100次,共10个epoch。

考虑下面的情况:

样本10000:

  1. batch size = 1,每一个epoch梯度下降10000次,更新10000次参数
  2. batch  size = 10,每一个epoch梯度下降1000次,更新1000次参数

因为单次更新参数,计算梯度时可以并行(大量的矩阵运算可以用gpu并行)的,(2)的bach size更大更利于并行,单次epoch快于(1),但是batch size有限制,太大会占用很多内存。另外如果batch size调的太大,那么此时就直接优化比较多样本的损失(越大越接近总损失),这样容易陷入局部最小值,而batch size小一些就成了批量梯度下降,这样下降时会具有一定的随机性,有利于跳出局部最小。

3.过拟合处理(正则和dropout)

(1)正则

和线性回归和逻辑回归中的正则类似,L1和L2正则项

(2)dropout(提升模型泛化能力)

   1)什么是dropout

在训练时,设定概率p,添加dropout的层中的每个神经元有p的概率被丢掉和之相连的所有权重不被更新,注意训练时才会这样操作,预测时不需要。

 

在预测时需要,如果概率设置p,预测时所有权重需要乘以(1-p),为什么?

如果神经元被扔掉的概率时0.5,训练时可能出现下面的情况:

在预测时,由于多了2个权重,所以计算出的z可能是训练的2倍,为了降低z,每个权重乘以1-p=0.5

2)为什么dropout有效

dropout可以被认为是一种集成学习,这里的集成概念类似于随机森林,adaboost中的集成概念。

因为每次丢掉了一些神经元,每次minibatch训练时神经网络的结构不一样。

预测时,使用了完整的神经网络结构,权重乘以1-p,它的结果会和不同结构的神经网络预测出的平均结果接近。

 

举个例子:设p=0.5

(1)(2)(3)(4)出现的可能都是1/4。例如(1)x1不被丢掉的概率是0.5,x2不被丢掉的概率是0.5,所以情况(1)出现的可能是0.5*0.5=0.25=1/4。总和计算4中情况的z结果,就是算一个z的期望,

0.25*z(1)+ 0.25*z(2)+ 0.25*z(3)+ 0.25*z(4) = 1/2w1x1+1/2w2x2

这样的结果和图中右下角直接对权重乘以1-p的结果相等。

上述这种情况只有当激活函数是线性时成立,若非线性不成立。

但是非线性激活函数使用dropout任然有效,只是可能没有线性的有效。(关于理论解释暂时不知道)

3.训练DL模型的建议

 

 

 Keras注意事项:

  1. 做分类时,label必须要one-hot编码
  2. 首先关注在训练集上的效果,如果训练集上的效果都不好,那么一定有问题,如果训练集上拟合得比较好,但测试集不太好,这时可以考虑是不是过拟合了
  3. 损失函数的选择
  4. 激活函数的选择(见激活函数小节)
  5. 优化算法的选择(adam是比较好的优化算法)
2019-03-24 21:53:55 qq_40522828 阅读数 90
  • 深度学习基础与TensorFlow实践教程

    本课程主要介绍了深度学习的基础原理和TensorFlow系统基本使用方法。TensorFlow是目前机器学习、深度学习领域优秀的计算系统之一,本课程将结合实例介绍使用TensorFlow开发机器学习应用的详细方法和步骤,着重讲解了用于图像识别的卷积神经网络和用于自然语言处理的循环神经网络的理论知识及其TensorFlow实现方法,并结合实际场景和例子描述了深度学习技术的应用范围与效果。 所有案例均来自讲师团队工作中的亲身实践,所选案例均是深度学习的经典应用,非常具有代表性。

    21447 人正在学习 去看看 AI100讲师

深度学习的应用

语音识别
图像应用
大规模图片识别(分类/聚类)
基于图片的搜索服务
图片内容识别(具体图片内容信息)
NP(自然语言)处理
游戏 机器人等
常见的机器学习领域应用(聚类 分类 回归问题)

神经网络之深度神经网络
增多中间层(隐层)的神经网络就叫做深度神经网络(DNN),可以认为深度学习是神经网络的一个发展

解决神经网络过拟合的方法
1.交叉验证
训练集(子集)
验证集(评估模型的性能和指标)
测试集(预测)
2.剪枝
每次训练的epoch结束时,将计算的accuracy跟上一次进行比较,如果连续几次accuracy都不再变化,则停止训练
3.正则化
就是在目标函数上加上一个参数,用来惩罚那些权重很大的向量,称之为一个正则化处理
两种正则化规则:L1(想知道哪一个特征对于最后结果产生较大影响)
L2(如果不在意对于特征分析)

神经网络之激活函数
S函数:
双SS函数:

神经网络之BP算法
神经网络的一种求解w的算法,分为信号“正向传播(FP)”求损失,“反向传播(BP)”回传误差;根据误差值修改每层的权重,继续迭代,使用梯度下降法来优化参数

神经网络之SGD
误差E有了,那么为了使误差越来越小,可以采用随机梯度下降的方式进行w和u的求解,即求得w和u使误差E最小

使用jupyter notebook来一步一步执行,观察结果

用深度学习来做线性回归问题

In[1]:	import numpy as np
		import tensorflow as tf
		import matplotlib.pyplot as plt
In[2]:	# 随机生成一千个点,围绕在y=0.1x+0.3的直线范围内
		num_points = 1000
		vectors_set = []
		for i in range(num_points):
			# 生成一个均值为0.0,方差为0.55的高斯分布
			x1 = np.random.normal(0.0, 0.55)
			# 声明一个y=0.1x+0.3的函数,增加一些抖动(wx+b)
			y1 = x1*0.1 + 0.3 + np.random.normal(0.0, 0.03)
			# 放入vectors_set中
			vectors_set.append([x1,y1])
In[3]:	# 生成一些样本
		x_data = [v[0] for v in vectors_set]
		y_data = [v[1] for v in vectors_set]
		plt.scatter(x_data, y_data)
		plt.show()
In[4]:	# 模拟训练
		# 生成一个一维的w矩阵,取值范围在[-1,1]之间
		W = tf.Variable(tf.random_uniform([1], -1, 1), name='W')
		print(W)
In[5]:	# 生成一个一维的矩阵b,初始值为0
		b = tf.Variable(tf.zeros([1]), name='b')
In[6]:	# 经过计算得出预估值y
		y = W * x_data + b
In[7]:	# 以预估值y和实际值y_data之间的协方差作为损失
		loss = tf.reduce_mean(tf.square(y-y_data), name='loss')
		# 使用梯度下降法来优化参数
		op = tf.train.GradientDescentOptimizer(0.5) # 每次更新的幅度为0.5
		# 训练的过程就是最小化这个误差值
		train = op.minimize(loss, name='train')
		# 建立会话
		sess = tf.Session()
		# 全局变量的初始化
		init = tf.global_variables_initializer()
		# 初始化训练变量
		sess.run(init)
		# 查看初始化的W和b的值
		print('W=', sess.run(W), 'b=', sess.run(b), 'loss=', sess.run(loss))
In[8]:	# 进行训练,训练30次
		for step in range(30):
			sess.run(train)
		# 输出训练完的W和b的值,看一下能否接近0.1和0.3
		print('W=', sess.run(W), 'b=', sess.run(b), 'loss=', sess.run(loss))
In[9]:	# 完成线性回归
		plt.scatter(x_data, y_data)
		plt.plot(x_data, sess.run(W)*x_data + sess.run(b), c='r')
		plt.show()

深度学习实现逻辑回归

In[1]:	import numpy as np
		import tensorflow as tf
		import matplotlib.pyplot as plt
		import tensorflow.examples.tutorials.mnist.input_dataput_data as input_data
In[2]:	mnist = input_data.read_data_sets('data/', one_hot=True)
		print(mnist)
In[3]:	# 下载下来的数据集被分为三个子集
		# 5.5W行的训练数据集(mnist.train)
		# 五千行的验证数据集(mnist.validation)
		# 一万行的测试数据集(mnist.test)
		# 因为每张图片为28X28的黑白照片,所以每行为784维的向量
		trainimg = mnist.train.images
		trainlabel = mnist.train.labels
		testimg = mnist.test.images
		testlabel = mnist.test.labels
		print(mnist.validation.labels.shape)
In[4]:	print(trainimg.shape)
		print(trainlabel.shape)
		print(testimg.shape)
		print(testlabel.shape)
		print(trainlabel[0])	
In[5]:	x = tf.placeholder('float', [None, 784]) # 784是维度,None表示无限多
		y = tf.placeholder('float', [None, 10])
		W = tf.Variable(tf.zeros([784, 10])) # 每个数字是784个像素点的,所以w和x相乘的话也要有784个,b=10表示这个是十分类的
		b = tf.Variable(tf.zeros([10]))
		# 回归模型
		actv = tf.nn.softmax(tf.matmul(x, W) + b) # 将逻辑回归升级为softmax,x*W+b相当于得到y,每次x*W+b之后都要经过激活函数
		# cost function 总和 均值
		cost = tf.reduce_mean(-tf.reduce_sum(y*tf.log(actv), reduction_indices=1))
		# 优化
		learning_rate = 0.1
		optm = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
In[6]:	pred = tf.equal(tf.argmax(actv, 1), tf.argmax(y, 1)) # 看一下预测值与真实值是否一样
		# 正确率
		accr = tf.reduce_mean(tf.cast(pred, 'float')) # tf.cast将True变为1,False变为0
		# 初始化
		init = tf.global_variables_initializer()
In[7]:	sess = tf.InteractiveSession()
		arr = np.array([[31, 23, 4, 24, 27, 34],
                		[18, 3, 25, 0, 6, 35],
                		[28, 14, 33, 22, 20, 8],
                		[13, 30, 21, 19, 7, 9],
                		[16, 1, 26, 32, 2, 29],
                		[17, 12, 5, 11, 10, 15]])
        tf.rank(arr).eval() # 返回矩阵的维度,在tensorflow中打印要加.eval()
        tf.shape(arr).eval()
        tf.argmax(arr,0).eval() # 返回最大值的索引,0表示axis=0,按列求解 
In[8]:	# 每多少次迭代显示一次损失
		training_epochs = 50
		# 批尺寸
		batch_size = 100
		# 训练迭代次数
		display_step = 5
		# session
		sess = tf.Session()
		sess.run(init)

		for epoch in range(training_epochs):
			avg_cost = 0
			# 55000/100
			num_batch = int(mnist.train.num_examples/batch_size)
			for i in range(num_batch):
				# 获取数据集  next_batch:获取下一批数据
				batch_xs, batch_ys = mnist.train.next_batch(batch_size)
				# 模型训练
				sess.run(optm, feed_dict={x:batch_xs, y:batch_ys})
				feeds = {x:batch_xs, y:batch_ys}
				avg_cost += sess.run(cost, feed_dict=feeds) / num_batch
			# 满足5次的一个迭代
			if epoch % display_step == 0:
				feed_train = {x:batch_xs, y:batch_ys}
				feed_test = {x:mnist.test.images, y:mnist.test.labels}
				train_acc = sess.run(accr, feed_dict=feed_train)
				test_acc = sess.run(accr, feed_dict=feed_test)
				print('Epoch:%03d/%03d cost: %.9f train_acc:%.3f test_acc: %.3f' % (epoch, training_epochs, avg_cost, train_acc, test_acc))	
		print('Done')	

深度学习手写数字

In[1]:	import numpy as np
		import matplotlib.pyplot as plt
		import tensorflow as tf
		import tensorflow.examples.tutorials.mnist.input_data as input_data
In[2]:	mnist = input_data('data1/', one_hot=True) # 从网上下载数据,放在data1中
		print('type of mnist is %s' % type(mnist))	
		print('number of train data is %d' % (mnist.train.num_examples)) # input_data里自带统计数据集数量的函数
		print('number of test data is %d' % (mnist.test.num_examples))
In[3]:	# 显示mnist数据集的内容
		trainimg = mnist.train.images
		trainlabel = mnist.train.labels
		testimg = mnist.test.images
		testlabel = mnist.test.labels

		print('type of mnist.train.images is %s' % type(trainimg))
		print('type of mnist.train.labels is %s' % type(trainlabel))
		print('type of mnist.test.images is %s' % type(testimg))
		print('type of mnist.test.labels is %s' % type(testlabel))

		print('type of mnist.train.images is %s' % (trainimg.shape,)) # 将28*28像素的图片 变成784*1   将28行变成1行
		print('type of mnist.train.labels is %s' % (trainlabel.shape,))
		print('type of mnist.test.images is %s' % (testimg.shape,))
		print('type of mnist.test.labels is %s' % (testlabel.shape,))
		# 要加,号 不然会报错	
In[4]:	# 操作数据集
		# 数据图像化
		nsample = 5
		randix = np.random.randint(trainimg.shape[0], size=nsample) # 在55000中随机选出5个数
		for i in randix:
			curr_img = np.reshape(trainimg[i, :], (28,28)) # 28*28的矩阵
			curr_label = np.argmax(trainlabel[i, :]) # label 		
			plt.matshow(curr_img, cmap=plt.get_cmap('gray')) # cmap=plt.get_cmap('gray')指定画出的图是灰色的
			plt.title(str(i) + 'th Training Data,Label is ' + str(curr_label))
			plt.show()
In[5]:	# batch学习
		batch_size = 100
		batch_xs, batch_ys = mnist.train.next_batch(batch_size)
		print(type(batch_xs))
		print(type(batch_ys))

		print(batch_xs.shape)
		print(batch_ys.shape) # 有十个类属于这一类的数字为1,其余为0	

SimpleNeuralNetwork

In[1]:	import numpy as np
		import tensorflow as tf
		import matplotlib.pyplot as plt
		import tensorflow.examples.tutorials.mnist.input_data as input_data
In[2]:	mnist = input_data.read_data_sets('data/', one_hot=True)
In[3]:	# network topologies
		n_hidden_1 = 256 # 第一个隐藏层的神经元数
		n_hidden_2 = 128 # 第二个隐藏层的神经元数
		n_input = 784 # 输入的像素
		n_classes = 10 # 输出的label
		# input and output
		x = tf.placeholder('float', [None, n_input]) # 入口数据
		y = td.placeholder('float', [None, n_classes])

		# 神经网络
		stddev=0.1
		weights = {
			'w1':tf.Variable(tf.random_normal([n_input, n_hidden_1], stddev=stddev)),
			'w2':tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2], stddev=stddev)),
			'out':tf.Variable(tf.random_normal([n_hidden_2, n_classes], stddev=stddev))
		}			
		biases = {
			'b1':tf.Variable(tf.random_normal([n_hidden_1])),
			'b2':tf.Variable(tf.random_normal([n_hidden_2])),
			'out':tf.Variable(tf.random_normal([n_classes]))
		}
		print('network hard')
		print(weights['w1'])
In[4]:	# s激活函数,进行数据的操作(BP算法)
		def multilayer_perceotron(_X, _weights, _biases):
			layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(_X, _weights['w1']), _biases['b1'])) # 每次wx+b之后经过sigmoid函数激活
			layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['w2']), _biases['b2']))
			return (tf.matmul(layer_2, _weights['out']) + _biases['out']) # 返回的是10个输出
In[5]:	pred = multilayer_perceotron(x, weights, biases)
		# 损失函数 softmax_cross_entropy_with_logits中0.x版本和1.x版本的不同的是1.x版本要加上logits和labels
		cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y))
		# 执行GradientDescentOptimizer梯度下降minimize优化
		optm = tr.train.GradientDescentOptimizer(learning_rate=0.001).minimize(cost)
		# 如果相等返回true,不等返回false
		corr = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1)) # argmax是返回每行最大的数的列名,1的意思是axis=1
		# 把true转换为1,false为0,再相加,计算总的(正确率)
		accr = tf.reduce_mean(tf.cast(corr, 'float'))
		# 初始化
		init = tf.global_variables_initializer()
		print('function ready')
In[6]:	# 执行模型的训练
		training_epochs = 20 # 迭代的次数
		batch_size = 100 # 每次处理的图片数
		display_step = 4 # 每四次打印一次
		# launch the graph
		sess = tf.Session()
		sess.run(init)
		# optimize
		for epoch in range(training_epochs):
			avg_cost = 0. # 平均误差
			total_batch = int(mnist.train.num_examples / batch_size)
			# iteration 训练集循环次数的确定
			for i in range(total_batch):
				# 取出x和y的值
				batch_xs, batch_ys = mnist.train.next_batch(batch_size)
				feeds = {x:batch_xs, y:batch_ys}
				sess.run(optm, feed_dict=feeds)
				avg_cost += sess.run(cost, feed_dict=feeds)
			avg_cost = avg_cost / total_batch # 更新平均误差
			# display 显示误差率和训练集正确率以及测试集的正确率
			if (epoch+1) % display_step == 0:
				print('Epoch:%03d/%03d cost:%.9f' % (epoch, training_epochs, avg_cost))
				feeds = {x:batch_xs, y:batch_ys}
				train_acc = sess.run(accr, feed_dict=feeds)
				print('TRAIN ACCURACY:%.3f' % (train_acc))
				feeds = {x:mnist.test.images, y:mnist.test.labels}	
				test_acc = sess.run(accr, feed_dict=feeds)
				print('TEST ACCURACY:%.3f' % (test_acc))
		print('optimization finished')
		# 最后的损失函数下降得不是很多,正确率也不高,需要加大迭代次数 
2019-12-08 16:13:29 weixin_43838785 阅读数 11
  • 深度学习基础与TensorFlow实践教程

    本课程主要介绍了深度学习的基础原理和TensorFlow系统基本使用方法。TensorFlow是目前机器学习、深度学习领域优秀的计算系统之一,本课程将结合实例介绍使用TensorFlow开发机器学习应用的详细方法和步骤,着重讲解了用于图像识别的卷积神经网络和用于自然语言处理的循环神经网络的理论知识及其TensorFlow实现方法,并结合实际场景和例子描述了深度学习技术的应用范围与效果。 所有案例均来自讲师团队工作中的亲身实践,所选案例均是深度学习的经典应用,非常具有代表性。

    21447 人正在学习 去看看 AI100讲师

什么是深度学习?

深度学习可以理解为“深度”和“学习”这两个名词的组合。“深度”体现在神经网络的层数上,一般来说,神经网络的层数越多,也就是越深,则学习效果越好;“学习”体现为神经网络可以通过不断地灌溉数据来自动校正权重偏置等参数,以拟合更好的学习效果。

一个2层的神经网络的例子

在这里插入图片描述
深度学习可以应用于什么?

深度学习最典型最广泛的应用就是图像识别。此外,深度学习还可以应用于语音、自然语言等领域。

现在有哪些深度学习框架?

目前主流的深度学习框架有:TensorFlow、Keras、Caffe、PyTorch等。

深度学习和神经网络是什么关系?

深度学习就是加深了层的深度神经网络,在深度学习领域中,有各式各样的神经网络,其中最出名的即是卷积神经网络(CNN)。

神经网络和感知机是什么关系?

感知机是神经网络的起源,神经网络是使用了非线性的激活函数(如sigmoid函数)的感知机。

神经网络中有哪些激活函数?

激活函数分为两类:

隐藏层的激活函数:sigmoid函数、ReLU函数等

输出层的激活函数:softmax函数、恒等函数等

神经网络中有哪些参数?

神经网络中的参数主要分为两类:

普通参数(自动更新):权重、偏置

超参数(人为设定):学习率、batch大小、各层神经元数量、权值衰减系数等

什么是泛化能力?

泛化能力指神经网络处理未被观察过的数据(不包含在训练集中的数据)的能力,获得泛化能力是深度学习的最终目的。

什么是过拟合?

与泛化能力相对的是过拟合,即仅对训练数据集表现出良好的学习效果,而无法处理其他类似的数据集,我们需要避免过拟合。

过拟合的典型表现如下:

在这里插入图片描述
如上图所示,训练集的识别率达到100%(正常情况下,识别率是无法达到100%的),而测试集的识别率仅有70%左右,这就是发生了过拟合。
如何抑制过拟合?

过拟合是需要避免的,一般抑制过拟合有两种方法:

权值衰减

Dropout优化

什么是损失函数?

神经网路的学习是指从训练数据中自动获取最优权重偏置参数的过程,而如何评价这个最优参数呢?这里就引入了损失函数。将损失函数作为神经网络学习的指标,损失函数的值越小,表示神经网络的学习效果越好,也就是说此刻的参数相对是最优参数。

损失函数主要有哪些?

常用的损失函数有两种:

均方误差

交叉熵误差

一般而言,使用交叉熵误差作为softmax函数的损失函数;使用均方误差作为恒等函数的损失函数。

寻找最优参数的方法有哪些?

神经网络学习的目的是寻找使损失函数尽可能小的权重偏置参数,也即是寻找最优参数,目前主要有四种寻找最优参数的方法:

随机梯度下降法(SGD):使用最广泛

Momentum

AdaGrad

Adam:综合性能最好

这四种方法的参数更新路径的对比如下图:

在这里插入图片描述
随机梯度下降法(SGD)的主要思路是什么?

将损失函数关于权重偏置参数的梯度作为线索,沿梯度方向更新参数,并重复步骤多次,逐渐靠近最优参数。

随机梯度下降法中有哪些求梯度的方法?

这里的梯度特指的是损失函数关于权重偏置参数的梯度。主要有两种求梯度的方法:

数值微分

误差反向传播法:速度更快

神经网络学习的整体过程是怎样的?

神经网络的学习主要是以下四大步骤:

步骤1(mini-batch):从训练数据中随机选择一部分数据

步骤2(计算梯度):使用误差反向传播法计算损失函数关于各个权重参数的梯度

步骤3(更新参数):将权重参数沿梯度方向进行微小的更新

步骤4(重复):重复步骤1、2、3。

权重初始值如何设定?

虽然权重参数是自动更新的,但其初始值仍是非常重要,一个好的初始值能够加快学习进度。

主要有三种权重初始值:

标准差为0.01的高斯分布

Xavier初始值:适用于激活函数是sigmoid函数

He初始值:适用于激活函数是ReLU函数

用Adam更新参数的条件下,基于MNIST数据集的三种权重初始值的比较如下图:

在这里插入图片描述
可以看出,He初始值的综合性能最好

视频解析

没有更多推荐了,返回首页