G1源码之fullGC算法详解

一次服务器上g1回收器发生fullgc的粗浅理解与记录 1.现场监控截图 由上面两张图可以看出, 1. old区内存使用并不多,为何会fullgc。 2.年轻代确实没有进行gc,所以可以确定当时确实进行了fullgc。 2.gc log 我们服务器使用的是g1回收器,找到当时时间节点的gc log,截图如下: 3.分析log,提出问题 我们从监控中可以看到,fullgc时: 总计堆内存2051m -> 142m, 总共回收了 1927m 在年轻代,eden回收了 1532m, survivor44m,总计 1576m 说明老年代总共只回收了 1 阅读详情

一.full gc触发的时机

国际惯例,我们先从full gc的触发时机开始看起,读过笔者之前博客的朋友应该都熟悉这个套路,学习源码都需要先找到入口,而gc算法的入口其实就是其触发的时机。

关于full gc触发的时机其实是 内存申请失败,晋升失败,疏散失败,元空间gc,调用system.gc时会触发full gc ,相关调用关系如下:

//(大对象或内存)申请失败
//年轻代对象晋升老年代的疏散(即回收)失败
//其他原因的疏散(即回收)失败
G1CollectedHeap::mem_allocate
--VM_G1CollectForAllocation::doit()  
----G1CollectedHeap::satisfy_failed_allocation()
------G1CollectedHeap::do_collection()

//入参是GC触发原因:
//other = system.gc
//collect_as_vm_thread = metadata_gc
G1CollectedHeap::collect(GCCause::Cause cause)
--VM_G1CollectFull::doit()
----G1CollectedHeap::do_full_collection()
------ G1CollectedHeap::do_collection()

//看过笔者之前的文章的朋友可以看到VM_G1CollectForAllocation和VM_G1CollectFull是gc时候的任务类
//方法调用到这层时已经进入stw了,有兴趣的朋友可以翻一翻笔者往期博客,有关于stw的实现讲解,这里就先不论述

我们可以看到,最终调用的都是
G1CollectedHeap::do_collection()这个方法去执行full gc的逻辑,下面我们来逐步拆解full gc的过程。

二.full gc前准备


G1CollectedHeap::do_collection()从方法名我们就可以看出这是关于gc的方法,但是这个方法再gc前还会做一些准备工作,我们直接来看下:

//参数分别是:
//1.是否是明确的gc即为false则表示gc应最少满足回收word_size的大小,为true则表示system.gc或整个堆回收
//2.是否清除所有软引用
//3.要申请的空间大小
bool G1CollectedHeap::do_collection(bool explicit_gc,
                                    bool clear_all_soft_refs,
                                    size_t word_size) {
  //检查是否正在执行
  if (GC_locker::check_active_before_gc()) {
    return false;
  }
  //声明一些gc计时器
  STWGCTimer* gc_timer = G1MarkSweep::gc_timer();
  gc_timer->register_gc_start();
  SerialOldTracer* gc_tracer = G1MarkSweep::gc_tracer();
  gc_tracer->report_gc_start(gc_cause(), gc_timer->gc_start());

  SvcGCMarker sgcm(SvcGCMarker::FULL);
  ResourceMark rm;
  //gc前打印相关日志
  print_heap_before_gc();
  trace_heap_before_gc(gc_tracer);
  //元空间之前的使用量
  size_t metadata_prev_used = MetaspaceAux::allocated_used_bytes();

  HRSPhaseSetter x(HRSPhaseFullGC);
  verify_region_sets_optional();

  const bool do_clear_all_soft_refs = clear_all_soft_refs ||
                           collector_policy()->should_clear_all_soft_refs();
  //声明清理所有软引用闭包
  ClearedAllSoftRefs casr(do_clear_all_soft_refs, collector_policy());

  {
    IsGCActiveMark x;

    // 一些时间计算
    assert(gc_cause() != GCCause::_java_lang_system_gc || explicit_gc, "invariant");
    gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);
    //追踪cpu时间
    TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);

    {
      //gc时间追踪器
      GCTraceTime t(GCCauseString("Full GC", gc_cause()), G1Log::fine(), true, NULL);
      TraceCollectorStats tcs(g1mm()->full_collection_counters());
      TraceMemoryManagerStats tms(true /* fullGC */, gc_cause());

      double start = os::elapsedTime();
      //记录full gc开始
      g1_policy()->record_full_collection_start();

      //这里是为了以后更换新的日志框架时留的口子
      wait_while_free_regions_coming();
      //这里是终止并发标记的根区域扫描
      _cm->root_regions()->abort();
      _cm->root_regions()->wait_until_scan_finished();
      //将second_free_list(不为空的话)加入到free_list中
      append_secondary_free_list_if_not_empty_with_lock();
      //这个方法是gc前的准备工作,主要是用虚拟数组填充tlab中,方便退回tlab
      gc_prologue(true);
      //增加统计
      increment_total_collections(true /* full gc */);
      increment_old_marking_cycles_started();

      //gc前验证
      verify_before_gc();
      //在full gc前生成一些dump信息
      pre_full_gc_dump(gc_timer);

      //禁用并发标记引用发现器(用于并发处理非强引用)并清空相关发现列表
      ref_processor_cm()->disable_discovery();
      ref_processor_cm()->abandon_partial_discovery();
      ref_processor_cm()->verify_no_references_recorded();
      //终止并发标记
      concurrent_mark()->abort();

      //释放young region正在使用的region
      release_mutator_alloc_region();
      //取消正在使用的老年代region
      abandon_gc_alloc_regions();
      //清理记忆集合
      g1_rem_set()->cleanupHRRS();

      _hr_printer.start_gc(true /* full */, (size_t) total_collections());

      //清除回收集合,和incremental回收集合,再gc结束后重建
      abandon_collection_set(g1_policy()->inc_cset_head());
      g1_policy()->clear_incremental_cset();
      g1_policy()->stop_incremental_cset_building();
      //清空region sets 包括old_sets, young_list和free_list
      tear_down_region_sets(false /* free_list_only */);
      //修改gcs_are_young标记
      g1_policy()->set_gcs_are_young(true);

      ReferenceProcessorMTDiscoveryMutator stw_rp_disc_ser(ref_processor_stw(), false);
      ReferenceProcessorIsAliveMutator stw_rp_is_alive_null(ref_processor_stw(), NULL);
      //开启stw引用发现器,用于处理非强引用
      ref_processor_stw()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/);
      ref_processor_stw()->setup_policy(do_clear_all_soft_refs);

      // 开始回收工作
      {
        HandleMark hm;
        G1MarkSweep::invoke_at_safepoint(ref_processor_stw(), do_clear_all_soft_refs);
      }
      //gc 结束收尾工作,先忽略一会我们在分析
      .....
}

我们看到在真正的gc开始之前是做了很多准备工作的,包括创建gc时间统计器,开启stw引用发现器,关闭cm引用发现器,填充并退回tlab,终止并发标记,取消正在使用的old region和年轻代region,清理记忆集合,清理回收集合等等,这里笔者就不一一展开分析,其主要逻辑也比较简单,有兴趣的读者可以自行查找阅读。而真正包含full gc算法逻辑的方法是:
G1MarkSweep::invoke_at_safepoint() .

三.full gc算法详解

再看full gc主要算法源码之前,我们要明确一点,full gc使用的是 标记压缩清除算法 ,关于这点有很多同学只了解这个概念,并不清除具体是如何实现的,比如压缩后指针怎么调整,如何进行压缩,标记前锁状态怎么处理等等,接下来笔者会将其慢慢拆解分析,我们先看刚刚提到
G1MarkSweep::invoke_at_safepoint()方法:

void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
                                      bool clear_all_softrefs) {

  SharedHeap* sh = SharedHeap::heap();
  //安装软引用处理策略,rp即前面提到的stw引用发现器,用于处理非强引用
  GenMarkSweep::_ref_processor = rp;
  rp->setup_policy(clear_all_softrefs);

  //当gc时,java方法的字节码地址可能会移动,
  //我们必须刷新所有的bcp,或者将其转换为bic,防止其gc结束后指向错误的位置
  //这里关于bcp和bic(感兴趣的朋友可以自行查看,本文我们不继续深究,先略过):
  //当执行 Java 方法时,程序计数器存放 Java 字节码的地址。
  //实现上可能有两种形式,一种是相对该方法字节码开始处的偏移量,叫做 bytecode index(简称 bci)。
  //另一种是该 Java 字节码指令在内存的地址,叫做 bytecode pointer(简称 bcp)。
  CodeCache::gc_prologue();
  Threads::gc_prologue();

  bool marked_for_unloading = false;
  //申请保存markword(对象头中的markword)的栈,用于保存非偏向锁的锁的markword的栈之后会用到
  allocate_stacks();

  //保存偏向锁的markword
  BiasedLocking::preserve_marks();
  //第一步:标记标记对象
  mark_sweep_phase1(marked_for_unloading, clear_all_softrefs);
  //第二步:准备压缩,即计算压缩后的地址
  mark_sweep_phase2();
  //第三步:调整指针
  mark_sweep_phase3();
  //第四步:复制对象
  mark_sweep_phase4();
  //恢复之前_preserved_marks里保存的markword
  GenMarkSweep::restore_marks();
  //恢复偏向锁
  BiasedLocking::restore_marks();
  //释放之前申请的用于保存markword的栈
  GenMarkSweep::deallocate_stacks();

  Threads::gc_epilogue();
  CodeCache::gc_epilogue();
  JvmtiExport::gc_epilogue();

  // 清空引用扫描器
  GenMarkSweep::_ref_processor = NULL;
}

就像笔者之前说到的,这里的代码逻辑是比较明显的,相对好阅读一些,在进行gc算法之前调用了
BiasedLocking::preserve_marks() 方法保存偏向锁,笔者在这里解释下为什么要先保存偏向锁:

如上图在g1中对象的锁标记位都在markword(对象头中的markword)中,而gc标记也在markword(对象头中的markword)中,并且两者在相同的位置,所以要想标记对象,我们就需要保存锁标记,等gc结束后再进行恢复。

其实不止是偏向锁,其他锁也会被保存,之后我们就可以看到,我们先看下保存偏向锁的方法:

void BiasedLocking::preserve_marks() {
  //判断偏向锁jvm参数
  if (!UseBiasedLocking)
    return;
   //创建保存偏向锁的mark 和oop的栈
   //注:和之前非偏向锁的栈不是一个栈,两者是分开保存的
  _preserved_mark_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<markOop>(10, true);
  _preserved_oop_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<Handle>(10, true);

  //遍历所有线程
  ResourceMark rm;
  Thread* cur = Thread::current();
  for (JavaThread* thread = Threads::first(); thread != NULL; th
什么时候触发full GC(发生场景) 在Java中,Full GC(全局垃圾回收)会回收整个堆内存(包括年轻代、老年代)以及元空间(或永久代)。以下是触发Full GC的主要场景 阅读详情

相关推荐

JVM性能调优实践——G1 垃圾收集器介绍篇

前言 前面两篇主要整理了性能测试的主要观察指标信息:性能测试篇,以及JVM性能调优的工具:JVM篇。这一篇先简单总结一下GC的种类,然后侧重总结下G1(Garbage-First)垃圾收集器的分代,结合open-jdk源码分析下重要算法如SATP,重要存储结构如CSet、RSet、TLAB、PLAB、Card Table等。最后会再梳理下G1 GC的YoungGC,MixedGC收集过程。 ...

马猴烧酒└(┐卍^o^)卍ドゥルルル~楪詩月「YUZURIHA SHIZUKI」 2万+

从电商平台到微信私域:构建合规跳转链路的技术实现

在互联网营销与用户增长领域,链接跳转是连接不同平台、引导用户流量的基础技术。其核心原理是通过服务器端路由与参数解析,实现用户请求的接收、处理与重定向。这项技术的价值在于能够突破平台间的生态壁垒,实现流量的合规、可控迁移,尤其适用于跨平台营销、私域沉淀等场景。在实际应用中,常需处理微信环境限制、参数传递与动态内容生成等挑战。本文聚焦于电商平台(如淘宝)到微信生态的跳转需求,详细阐述了如何利用Node.js、Express框架及二维码生成技术,构建一个包含环境检测、参数传递与动态落地页的完整跳转系统,以解决微信

weixin_33889665的博客 324

保姆级教程:用Qlib和LightGBM从零搭建你的第一个AI量化选股策略(附完整代码)

本文提供了一份详细的教程,教你如何使用Qlib和LightGBM从零搭建AI量化选股策略。教程涵盖了环境配置、数据获取、特征工程、模型训练和策略回测等关键步骤,并附有完整代码和常见问题解决方案,适合量化投资初学者快速上手。

weixin_29191081的博客 446

Halcon dyn_threshold详解

dyn_threshold 原型 dyn_threshold(OrigImage, ThresholdImage : RegionDynThresh : Offset, LightDark : ) 功能 利用局部阈值分割图像 参数列表 OrigImage (input_object):原始图像 ThresholdImage (input_object):处理后图像(一般采用滤波处理) RegionDynThresh (output_object):分割后区域 Offset (input_control):灰

ZiLiangQin的博客 1万+

ANSYS Fluent热边界条件避坑指南:为什么你的自然对流计算结果总出错?

本文深入剖析了在ANSYS Fluent中进行自然对流仿真时,导致计算结果出错或发散的核心原因与解决方案。重点解析了重力项与操作密度设置、Boussinesq与不可压缩理想气体模型的抉择、以及压力离散格式(推荐Body Force Weighted)这三大关键雷区,并结合电子机箱散热等实战案例,提供了一套稳定可靠的仿真设置流程与调试技巧。

weixin_28396629的博客 741

手把手教你用Switched-Capacitor Converter实现高效DC-DC转换(附常见拓扑对比)

本文详细介绍了开关电容转换器(SC)在高效DC-DC电源设计中的应用,对比了四种常见拓扑结构的优缺点,并提供了损耗分析与效率优化的实战技巧。通过无电感设计,SC转换器在5G模块和可穿戴设备中展现出超高功率密度和微小体积的优势,是电源管理领域的革命性技术。

weixin_30790841的博客 273

Android Profiler实战:如何用CPU分析工具揪出卡顿元凶(附线程状态解读)

本文深入解析Android Profiler中的CPU分析工具,重点聚焦线程活动监控。通过解读线程状态时间轴上的绿、黄、灰三色含义,并结合实战案例,指导开发者精准定位导致界面卡顿的CPU密集型或I/O阻塞代码,有效提升应用性能与用户体验。

weixin_29197699的博客 374

直方图均衡化原理及matlab和opencv实现代码

详细分析了直方图均衡化的数学原理,配有matlab和opencv实现代码

qq_21603315的博客 4779

手把手教你学Simulink——基于Simulink的无位置传感器PMSM滑模观测器(SMO)控制

本文基于Simulink平台实现无位置传感器PMSM滑模观测器(SMO)控制,解决了传统机械位置传感器存在的成本高、体积大、抗干扰差等问题。SMO通过滑模切换函数估算反电动势,进而获得转子位置和速度,具有强鲁棒性(参数变化20%误差仅0.4°)和良好低速性能(50rpm转矩衰减<5%)。文章详细介绍了PMSM数学模型、SMO算法设计、Simulink建模步骤及参数优化方法,提供了可直接工程应用的MATLAB代码和仿真模型,为电动汽车驱动、工业机器人等高精度控制场景提供了有效解决方案。

MHD0815的博客 229

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

上一篇: 8种有效方式迭代Java Map中的每个条目
下一篇: 面向未来:DoorDash 从单体迁移到微服务架构
JavaMonsterr
博客等级 码龄4年 211粉丝 481原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值