卷积神经网络提高准确率(shuffle,优化器,batchsize,权重初始化)通过某次实际CNN调参过程

最近做一个CNN,从0开始调节,终于让准确率提高到了95%。

网络结构为,两层卷积,池化,两层卷积,池化,两层全连接:


目录

打乱

优化器

BATCHSIZE(重要!)

权重初始化

其他方法


打乱

1.千万要对数据进行shuffle,不然准确率低的令人发指。发现某一类别正确率极高,但是数据是平均分布的,怀疑shuffle出错,但是没有。。。

优化器

2.由于准确率一直很低,怀疑陷入局部最优,也可能是鞍点,所以采用各种优化器尝试了下,

adam结果:

理解:adam采用自适应优化,所以它的优势是训练快,但是问题在于更容易陷入局部最优、鞍点等!虽然SDG慢了点,但是真好用(所以那么多研究中都采用SDG)

SDG对应tensorflow:tf.train.GradientDescentOptimizer

ADAM对应tensorflow:tf.train.AdamOptimizer

采用SDG方法损失函数突破1.5,(ADAM为1.9)

BATCHSIZE(重要!)

(我这个网络的问题主要与batchsize有关,由于此参数的不合适,学习到内容过于偏离预期!)

3.batchsize,主要三个作用:

  • 内存利用率(只要能跑就行)
  • 跑完一次 epoch(全数据集)所需的迭代次数减少,对于相同数据量的处理速度进一步加快。但是盲目加大导致达到相同的精度,其所花费的时间大大增加了,从而对参数的修正也就显得更加缓慢。
  • 一般来说 Batch_Size 越大,其确定的下降方向越准,引起训练震荡越小。但是Batch_Size 增大到一定程度,其确定的下降方向已经基本不再变化。也就说容易陷入局部最优(也可以理解为如果batch_size很大会导致学习到的特征偏向于整体特征,学习到的内容不够)

忽略异常的波动:发现合理减少batch-size后准确率提升了,损失函数值下降到新高度(batch-size=700时准确率不足40%,损失最低达到1.5)

橙色为训练集,蓝色为验证集

batch-size=128batch-size=32batch-size=8
下图为batch-size=32时每个类别的正确率,发现某几个类别从一开始就学习不到(这里只有两个类别没有学习到,batch-size值更大时更多类别学习不到,尤其700时只能学习到2个类别),所以:Batch_Size 增大到一定程度,其确定的下降方向已经基本不再变化,陷入局部最优

来一个batch-size=8对比:

思考那是不是batch-size越小学习的内容越多,最终准确率越高?(虽然越小训练时间越长,不考虑时间的情况下:)

batch-size=1:只学习到了2个类别,未截图

batch-size=2:

原理:batch-size过大,下降方向为整体方向,学习不到足够的东西,batch-size过小,每次下降方向横冲直撞,其实会偏向每个都有的特征方向,最终导致学习不到东西,无法达到预期准确率。只有合理的batch-size才能快准

方法:观测前几代,看是否学习到足够的内容,及时停止,及时止损(batch-size可以理解成下降方向,而算法结果跟初始化权重是有关系的,所以如果在这种batch-size下,在这种下降方向下,总是落到很差的局部最优解,就及早重新来过)

权重初始化

4.权重初始化影响很大,不同初始化导致不同结果,多试几次。而且An Explanation of Xavier Initialization文章介绍xavier不适用于卷积初始化,适用于全连接初始化(尝试了几次,感觉没啥区别啊,想看看原理,文章怎么都找不到。。。)

其他方法

5.batch normlization:加入BN层,可以让权重初始化更加优秀(没有尝试过,当batch-size调整的比较好,多试几次结果就比较好了)

6.网络调整,将网络扩宽或者加深,可以提高准确率(95%足够了,没将此网络继续进行下去)

以下是一个简单的CNN卷积神经网络的MATLAB代码示例: ```matlab % 加载数据和标签 load mnist_uint8; train_x = double(train_x) / 255; test_x = double(test_x) / 255; train_y = double(train_y); test_y = double(test_y); % 设置网络参数 input_layer_size = 28 * 28; % 输入层大小 hidden_layer_size = 50; % 隐藏层大小 output_layer_size = 10; % 输出层大小 filter_size = 5; % 卷积核大小 num_filters = 20; % 卷积核数量 % 初始化卷积核和偏置项 conv_filter = randn(filter_size, filter_size, num_filters); conv_bias = zeros(num_filters, 1); % 初始化隐藏层权重和偏置项 hidden_weights = randn(hidden_layer_size, num_filters * (input_layer_size - filter_size + 1)^2) / sqrt(num_filters * (input_layer_size - filter_size + 1)^2); hidden_bias = zeros(hidden_layer_size, 1); % 初始化输出层权重和偏置项 output_weights = randn(output_layer_size, hidden_layer_size) / sqrt(hidden_layer_size); output_bias = zeros(output_layer_size, 1); % 训练网络 num_epochs = 10; learning_rate = 0.1; batch_size = 100; for epoch = 1:num_epochs % 随机打乱训练数据顺序 shuffle_index = randperm(size(train_x, 1)); train_x = train_x(shuffle_index, :); train_y = train_y(shuffle_index, :); % 每个batch进行一次前向传播和反向传播 for batch = 1:(size(train_x, 1) / batch_size) % 获取一个batch的数据和标签 batch_start = (batch - 1) * batch_size + 1; batch_end = batch * batch_size; batch_x = train_x(batch_start:batch_end, :); batch_y = train_y(batch_start:batch_end, :); % 前向传播 conv_out = conv_layer(batch_x, conv_filter, conv_bias); conv_out_relu = relu_layer(conv_out); hidden_out = hidden_layer(conv_out_relu, hidden_weights, hidden_bias); hidden_out_relu = relu_layer(hidden_out); output_out = output_layer(hidden_out_relu, output_weights, output_bias); % 计算损失和准确率 loss = cross_entropy_loss(output_out, batch_y); accuracy = accuracy_metric(output_out, batch_y); % 反向传播 output_error = cross_entropy_loss_derivative(output_out, batch_y); hidden_error = hidden_layer_derivative(hidden_out_relu, output_weights, output_error); conv_error = conv_layer_derivative(batch_x, conv_filter, conv_bias, conv_out, hidden_error); % 更新卷积核和偏置项 conv_filter = conv_filter - learning_rate * conv_error.filter_gradient; conv_bias = conv_bias - learning_rate * conv_error.bias_gradient; % 更新隐藏层权重和偏置项 hidden_weights = hidden_weights - learning_rate * hidden_error.weights_gradient; hidden_bias = hidden_bias - learning_rate * hidden_error.bias_gradient; % 更新输出层权重和偏置项 output_weights = output_weights - learning_rate * output_error.weights_gradient; output_bias = output_bias - learning_rate * output_error.bias_gradient; end % 在测试集上测试准确率 conv_out = conv_layer(test_x, conv_filter, conv_bias); conv_out_relu = relu_layer(conv_out); hidden_out = hidden_layer(conv_out_relu, hidden_weights, hidden_bias); hidden_out_relu = relu_layer(hidden_out); output_out = output_layer(hidden_out_relu, output_weights, output_bias); accuracy = accuracy_metric(output_out, test_y); fprintf('Epoch %d: Test accuracy = %f\n', epoch, accuracy); end ``` 其中,`conv_layer`、`relu_layer`、`hidden_layer`、`output_layer`、`cross_entropy_loss`、`accuracy_metric`、`cross_entropy_loss_derivative`、`hidden_layer_derivative`、`conv_layer_derivative` 都是各自层的函数,需要自行实现。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值