关于一些Vue的文章。(4)

VueJS+ElementUI学习(一)环境搭建与简单登录界面实现 环境:Windows7+node-v10.15.1-win-x64+WebStorm 2018.1.4 1.安装nodeJS和npm 由于我们要使用npm这个包管理器,所以要安装nodeJS。现在版本的nodeJS已经集成了npm,所以我们只需要安装一次即可。我们访问nodejs中文网,下载对应自己系统的版本就可以了。下载地址:http://nodejs.cn/download/   这里我们下... 阅读详情

原文链接我的blog,欢迎STAR。

接着上一篇,我们继续来讲Vue的Virtual Dom diff 算法中的patchVnode方法,以及核心updateChildren方法。


在上篇中,我们谈到,当vnode不为真实节点,且vnode与oldVnode为同一节点时,会调用patchVnode方法。
我们直接从源码上进行分析:

  // patchVnode()有四个参数
  // oldVnode: 旧的虚拟节点
  // vnode: 新的虚拟节点
  // insertedVnodeQueue:  存在于整个patch中,用于收集patch中插入的vnode;
  // removeOnly: 这个在源码里有提到,removeOnly is a special flag used only by<transition-group>也就是说是特殊的flag,用于transition-group组件。

  function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) {
    // 如果oldVnode与vnode为同一引用, 不进行任何处理。
    if (oldVnode === vnode) {
      return
    }

    // 如果不为同一引用,那说用新的vnode创建了。
    // 如果vnode, oldVnode都为静态节点,且vnode.key === oldVnode.key相等时,当vnode为克隆节点,或者vnode有v-once指令时,只需把oldVnode对应的真实dom,以及组件实例都复制到vnode上。
    if (isTrue(vnode.isStatic) &&
        isTrue(oldVnode.isStatic) &&
        vnode.key === oldVnode.key &&
        (isTrue(vnode.isCloned) || isTrue(vnode.isOnce))) {
      vnode.elm = oldVnode.elm
      vnode.componentInstance = oldVnode.componentInstance
      return

    // 在进行下一步操作之前会调用prepatch hook,但是这个是vnode在data里定义的prepatch hook,并不是全局定义的prepatch hook
    let i
    const data = vnode.data
    if (isDef(data) && isDef(i = data.hook) && isDef(i = i.prepatch)) {
      i(oldVnode, vnode)
    }

    // 让vnode引用到现在的真实DOM,当elm修改的时候,会同步修改vnode.elm
    const elm = vnode.elm = oldVnode.elm
    const oldCh = oldVnode.children
    const ch = vnode.children

    // 我们先patchVnode, 方法就是先调用全局的update hook
    // 然后调用data里定义的update hook
    if (isDef(data) && isPatchable(vnode)) {
      for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode)
      if (isDef(i = data.hook) && isDef(i = i.update)) i(oldVnode, vnode)
    }

    // 如果vnode.text未定义
    // 这里有个值得注意的地方,具有text属性的vnode不应该具备有children
    // 对于<p>abc<i>123</i></p>的写法应该是
    // h('p', ['abc', h('i', '123')])
    // 而不是, h('p', 'abc', [h('i', '123')])
    // 因此,对text存在与否的情况需单独拿出来分析
    if (isUndef(vnode.text)) {

      // 如果oldVnode与vnode都存在children
      if (isDef(oldCh) && isDef(ch)) {

        // 如果两个children 不相同,调用updateChildren()方法更新子节点的操作。(接下来将讲解)
        if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly)
      } else if (isDef(ch)) {
        // 如果只有vnode.children 存在
        // 当oldVnode.text不为空,vnode.text未定义时,清空elm.textContent
        // 添加vnode.children
        if (isDef(oldVnode.text)) nodeOps.setTextContent(elm, '')
        addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue)
      } else if (isDef(oldCh)) {
        // 如果只有oldVnode.children存在,移除oldVnode.children
        removeVnodes(elm, oldCh, 0, oldCh.length - 1)
      } else if (isDef(oldVnode.text)) {
        // 同上,如果oldVnode.text存在,vnode.text不存在,清空elm.textContent
        nodeOps.setTextContent(elm, '')
      }
    } else if (oldVnode.text !== vnode.text) {

      // 如果vnode.text存在(vnode是一个text node),且不等于oldVnode.text
      // 更新elm.textContent
      nodeOps.setTextContent(elm, vnode.text)
    }

    // 最后再调用 postpatch hook。
    if (isDef(data)) {
      if (isDef(i = data.hook) && isDef(i = i.postpatch)) i(oldVnode, vnode)
    }
  }

接着说重点 当oldVnode.children与vnode.children都存在,且不相同时调用的updateChildren()方法, 同样的,咱们从源码上分析:

 // updateChildren(),有五个参数
 // parentElm: oldVnode.elm 的引用
 // oldCh, newCh: 分别是上面分析中的oldVnode.children, vnode.children
 // insertedVnodeQueue, removeOnly 请参考上面。

 function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) {
    let oldStartIdx = 0
    let newStartIdx = 0
    let oldEndIdx = oldCh.length - 1
    let oldStartVnode = oldCh[0]
    let oldEndVnode = oldCh[oldEndIdx]
    let newEndIdx = newCh.length - 1
    let newStartVnode = newCh[0]
    let newEndVnode = newCh[newEndIdx]
    let oldKeyToIdx, idxInOld, elmToMove, refElm

    // removeOnly is a special flag used only by <transition-group>
    // to ensure removed elements stay in correct relative positions
    // during leaving transitions
    const canMove = !removeOnly

    // 遍历过程共有5种情况
    // 比较判断的依据是,sameVnode(),值不得值得比较。
    // key,tag(当前节点标签名),isComment(是否是注释节点)
    // data,节点的数据对象是否都存在或都不存在
    // (a, b)=> {
    //   return (
    //      a.key === b.key &&
    //      a.tag === b.tag &&
    //      a.isComment === b.isComment &&
    //      isDef(a.data) === isDef(b.data) &&
    //      sameInput(a, b)
    //  )
    // }
    // 当oldStartIndex > oldEndIdx 或者 newStartIndex > newEndIdx, 停止遍历。
    while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {

      // 对于vnode.key的比较,会把oldVnode = null
      if (isUndef(oldStartVnode)) {
        oldStartVnode = oldCh[++oldStartIdx]

        // 同上
        oldEndVnode = oldCh[--oldEndIdx]
      } else if (sameVnode(oldStartVnode, newStartVnode)) {

        // 第一种情况:
        // 从oldCh与newCh的第一个开始,逐步往后遍历。
        // 如果oldStartVnode与newStartVnode值得比较,
        // 执行pathchVnode()方法
        // oldStartVnode, newStartVnode相对位置不变。
        patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue)
        oldStartVnode = oldCh[++oldStartIdx]
        newStartVnode = newCh[++newStartIdx]
      } else if (sameVnode(oldEndVnode, newEndVnode)) {

        // 第二种情况:
        // 从oldCh与newCh的最后一个开始,逐步往前遍历。
        // 如果oldEndVnode,newEndVnode值得比较
        // 执行pathchVnode()
        // oldEndVnode, newEndVnode相对位置不变
        patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue)
        oldEndVnode = oldCh[--oldEndIdx]
        newEndVnode = newCh[--newEndIdx]
      } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right

        // 第三种情况:
        // 从oldCh的第一个,newCh的最后一个开始,oldCh往后,newCh往前遍历,
        // 如果oldStartVnode与newEndVnode值得比较
        // 此时需要把oldStartVnode放到oldEndVnode后面
        // oldCh往后,newCh往前
        patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue)
        canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm))
        oldStartVnode = oldCh[++oldStartIdx]
        newEndVnode = newCh[--newEndIdx]
      } else if (sameVnode(oldEndVnode, newStartVnode)) {

        // 第四种情况:
        // 从oldCh的最后一个,newCh的第一个,oldCh往前,newCh往后,遍历。
        // 如果oldEndVnode与newStartVnode值得比较
        // 此时需要把oldEndVnode放到oldStartVnode前边
        // oldCh往前,newCh往后
        patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue)
        canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm)
        oldEndVnode = oldCh[--oldEndIdx]
        newStartVnode = newCh[++newStartIdx]
      } else {

        // 第五种情况:
        // 使用key比较
        // 首先会调用createKytoOldIdx()方法,产生一个key-index对象列表
        // 然后根据这个表来进行更改
        if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)

        // 如果newStartVnode.key存在,根据key来找到对应的index,命名为idxInOld 
        // 如果不存在,设置为null
        idxInOld = isDef(newStartVnode.key) ? oldKeyToIdx[newStartVnode.key] : null
        if (isUndef(idxInOld)) {

          // 如果idxInOld不存在时,此时是一个新的vnode
          // 将这个vnode插入到oldStartVnode.elm 的前边
          // 把newStartVnode设置为下一个节点
          createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm)
          newStartVnode = newCh[++newStartIdx]
        } else {

          // 如果idxInOld存在时,那么对应的oldVnode存在
          // 根据index,找到oldVnode对应的children
          elmToMove = oldCh[idxInOld]

          // 如果不是生产环境,且elmToMove不存在
          // 此时因为idxInOld已经存在,而oldCh[idxInOld]不存在
          // 只有可能keys重复了
          /* istanbul ignore if */
          if (process.env.NODE_ENV !== 'production' && !elmToMove) {
            warn(
              'It seems there are duplicate keys that is causing an update error. ' +
              'Make sure each v-for item has a unique key.'
            )
          }

          // 如果根据vnode.key找出的elmToMove与newStartVnode值得比较比较
          // patchVnode这两个节点
          // 之后,需要把这个child设置为undefined
          // 同时需要把oldStartVnode.elm的位置移到newStartVnode.elm之前,以免影响接下来的遍历。
          if (sameVnode(elmToMove, newStartVnode)) {
            patchVnode(elmToMove, newStartVnode, insertedVnodeQueue)
            oldCh[idxInOld] = undefined
            canMove && nodeOps.insertBefore(parentElm, newStartVnode.elm, oldStartVnode.elm)
            newStartVnode = newCh[++newStartIdx]**重点内容**
          } else {
            // same key but different element. treat as new element
            // 如果不值得比较,此时key已经相同,说明是tag不同,或者其他不同,此时创建一个新节点
            // 将这个vnode插入到oldStartVnode.elm 的前边
            // 把newStartVnode设置为下一个节点
            createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm)
            newStartVnode = newCh[++newStartIdx]
          }
        }
      }
    }

    // 遍历完成之后,存在两种情况
    // 如果 oldStartIdx > oldEndIdx, 即oldCh先遍历完
    // 位于 newStartIdx与newEndIdx之间的节点都可认为是新的节点
    if (oldStartIdx > oldEndIdx) {
      refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm
      addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue)
    } else if (newStartIdx > newEndIdx) {

      // 如果newStartIdx > newEndIdx, 即newCh先遍历完
      // 此时,位于oldStartIdx与oldEndIdx之间的节点已经不存在了
      // 调用removeVnodes()方法移除节点。
      removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx)
    }
  }

直接在源码上分析,可能有点乱,总结一下:

patchVnode共有以下情况:

  • 如果oldVnode与vnode引用完全一致,则可以认为没有变化,无需进行任何操作。

  • 如果vnode, oldVnode都为静态节点,且vnode.key === oldVnode.key相等时,当vnode为克隆节点,或者vnode有v-once指令时,只需把oldVnode对应的真实dom,以及组件实例都复制到vnode上。

  • 如果vnode不是text node:

    • 如果vnode.children与oldVnode.children都存在,调用updateChildren()方法。

    • 当vnode.children存在,oldVnode.children不存在时,添加vnode.children。

    • 当vnode.children不存在,oldVnode.children存在时,需要移除oldVnode.children。

    • 当两者的children都不存在时,如果oldVnode为text node,则需清空elm.textContent。

  • 如果vnode是text node,改变elm.textContent。

patchVnode有一个值得注意的地方是,vdom中规定,具有text属性的vnode不应该具备children,因此需把text node单独拿出来分析。


updateChildren()方法共有5种比较方式,前四种无key的情况,后一种为有key的情况,当oldStartIdx > oldEndIdx或者newStartIdx > newOldStartIdx的时候停止遍历。

引用推荐的那篇文章图:

遍历示意图

  • 第一种比较方式从oldCh与newCh各自第一个vnode开始比较,当值得比较时,调用上述中的patchVnode方法进行比较, 同时将oldCh与newCh的下一个vnode分别设为oldStartVnode与newStartVnode(比较的相对位置不变), startVnode既是开始比较的vnode。

  • 第二种比较方式从oldCh 与newCh各自最后一个vnode开始比较,当值得比较时,调用上述中的patchVnode方法进行比较,同时将oldCh与newCh的上一个vnode分别设置为oldEndVnode与newEndVnode(比较的相对位置不变),, endVnode既是结束比较的vnode。

  • 第三种比较方式,从oldCh的第一个vnode与newCh的最后一个vnode开始比较,当值得比较时,调用上述中的patchVnode方法比较,同时将oldCh的下一个vnode设置为oldStartVnode,将newCh的上一个vnode设置为newEndVnode,并且此时说明oldStartVnode.elm向右移动,并且已经移动到oldEndVnode.elm的后边了,调用相应的方法移动位置。

  • 第四种比较方式,从oldCh的最后一个vnode与newCh的第一个vnode开始比较,当值得比较时,调用上述中的patchVnode方法比较,同时将oldCh的上一个vnode设置为oldEndVnode,将newCh的上一个vnode设置为newStartVnode,并且此时说明oldEndVnode.elm向左移动,并且已经移动到oldStartVnode.elm的前边了,调用相应的方法移动位置。

  • 第五种,使用key比较,先会产生一个key-index表,然后判断vnode.key存在与否?

    • 如果不存在,是一个新的vnode,将这个vnode插入到oldStartVnode.elm 的前边,并且把newStartVnode设置为下一个节点。

    • 如果存在,那么对应的oldVnode应该存在,此时可以根据key来找到对应的vnode,然后判断这个vnode与newStartVnode是否值得比较?

      • 当值得比较时,调用patchVnode,并且需要把这个child设置为undefined,同时需要把oldStartVnode.elm的位置移到newStartVnode.elm之前,以免影响接下来的遍历。

      • 如果不值得比较,此时key已经相同,说明是tag不同,或者其他不同,此时创建一个新节点将这个vnode插入到oldStartVnode.elm 的前边。

遍历完成后,如果oldCh先遍历完,位于newStartIdx与newEndIdx之间的节点都可认为是新的节点,调用相应的方法插入节点。如果newCh先遍历完,此时,位于oldStartIdx与oldEndIdx之间的节点已经不存在了,调用removeVnodes()方法移除节点。

完。

相关推荐

Cadence Allegro新手避坑:从原理图到PCB,解决‘netrev.lst does not exist’的完整流程

本文详细介绍了Cadence Allegro从原理图设计到PCB导入网表的完整流程,特别针对新手常见的'netrev.lst does not exist'错误提供了系统解决方案。内容包括环境准备、原理图设计规范、网表生成与导入技巧,以及设计数据管理最佳实践,帮助工程师高效完成PCB设计任务。

weixin_42685438的博客 486

virtual-dom(Vue实现)简析

virtual-dom(后文简称vdom)的概念大规模的推广还是得益于react出现,virtual-dom也是react这个框架的非常重要的特性之一。相比于频繁的手动去操作dom而带来性能问题,vdom很好的将dom做了一层映射关系,进而将在我们本需要直接进行dom的一系列操作,映射到了操作vdom,而vdom上定义了关于真实dom的一...

weixin_33772645的博客 229

顶会新宠!Gate+Attention创新思路发A会

性能提升:在Places2自然场景和CelebA-HQ人脸数据集上,与以往方法相比,该系统在自由形式掩码修复任务中取得了更高的质量和更低的误差(例如,平均ℓ1误差和ℓ2误差显著降低)。硬件效率提升:Griffin和Hawk在TPU-v3上的训练效率与Transformer相当,且在推理时具有更低的延迟和显著更高的吞吐量。门控卷积:提出了一种新的门控卷积机制,通过学习每个通道在每个空间位置的动态特征选择机制,解决了传统卷积将所有输入像素视为有效像素的问题。

2501_92785035的博客 974

vue学习笔记 解析diff算法

在vue中,DOM被抽象为一个以JavaScript对象为节点的virtual DOM(虚拟DOM)树,当数据发生改变时,会通过修改virtual DOM,使用diff算法,修改局部的内容,然后将这部分内容以打补丁的方式来修改真实的DOM,来达到视图修改的作用。 因为通过diff算法,能得出需要修改的最小单位,所以我们在更新视图的时候,只需要修改这些最小单位,这么做减小了更新的消耗。 diff算法...

zem 842

【2022KaliLinux】openvas/gvm 没有scan configs 或者是 scan config error “XXXXXXXXXXX”

gvm/openvas的configuration的scan config为空

zbossz的学习小分队 3604

halcon C++编程 第4讲 HObject/HImage Mat相互转换(tcy)

网上有很多相互转换程序,但并不知那个正确,本文对相互转换后的结果和原对象比较是否相同判断转换是否正确。经测试ok.本文包括转换代码及测试是否相同。 1.转换程序: /************************************ HObject转为Mat:time:2021/3/16 V1.0 *************************************/ cv::Mat HalconClass::HObjectToMat(const HalconCpp::HObject&..

tcy-阿春 4929

vue源码解析-diff过程一探究竟

也看过其他讲vue diff过程的文章,但是感觉都只是讲了其中的一部分(对比方式),没有对其中细节的部分做详细的讲解,如 匹配成功后进行的patchVnode是做了什么?为什么的有的紧接着要进行dom操作,有的没有? 在diff的过程中,指针的具体如何移动?及哪些部分发生了变化? insertedVnodeQueue 又是何用?为何一直带着? 然后也是困惑很久的,很多文章在移动这部分直接操作的o...

weixin_34237596的博客 579

智能汽车嘚啵嘚 --- 智能座舱第七稿:智能座舱的升级OTA

智能汽车嘚啵嘚 --- 智能座舱第七稿:智能座舱的升级OTA

Soly_kun的博客 414

Duplicate keys detected: ‘xxx‘. This may cause an update error.解决方案

Vue报此警告,是因为for循环的key值重复了,只要变成不一样的就好。可以看到我每一个都使用 index,所以会有相同的 key。在每一个 index 前面加一个不同的自负,这样就不一样了。

weixin_72949205的博客 2485

基于深度学习的X光安检危险品检测系统(YOLOv8 + UI界面 + 数据集)

随着全球安全形势的变化,机场、车站、地铁等场所的安检工作日益重要。X光安检系统已经成为现代公共安全领域中不可或缺的部分,能够有效地检测物品的内部结构,识别潜在的危险品。然而,传统的X光图像分析方法仍然依赖人工操作,检测效率较低,并且易受到人为因素的影响。近年来,深度学习技术的应用在图像分析领域取得了显著的突破,特别是在目标检测任务中,YOLO(You Only Look Once)模型因其高效性和精度,成为了许多目标检测任务的首选模型。

YOLO 1059

STM32芯片解锁读写保护:更改Option Byte [Error已解决]

解锁读保护:STLink更改Option Byte 变Level从1变为0,点击Apply即可。(程序执行读保护,其实是将Level从0变为1) 默认情况下该保护功能是不开启的,若要开启该功能,需要改写内部FLASH选项字节(Option Bytes)中的配置。 RDP读保护级别 级别0,无保护, 级别1,使能读保护, 这种保护下,若使用调试功能(使用下载器、仿真器)或者从内部SRAM自举时都不能对内部FLASH及备份SRAM作任何访问(读写、擦除都被禁止); 当芯片处于级别1的时候,可以把选项字节

HowieXue 薛永浩的博客 2万+

解决vue中报错 Duplicate keys detected:‘1‘. This may cause an update error.

解决vue中报错 Duplicate keys detected:'1'. This may cause an update error.

希望看完文章的你能够带着答案离开。 1万+

2024年数字IC秋招-海康威视-数字逻辑设计工程师-笔试题

笔试题型:单选 + 多选笔试平台:百一测试(电脑监控)笔试时间:1h30minA. AW通道B. D通道C. B通道D. AR通道return x++;x = 5;y = Foo(x);

qq_42135020的博客 3199

Vue Router 4 的使用,一篇文章给你讲透彻

Vue 3.X 使用Vue Router 4.x 进行路由配置,本文我们就来研究下如何使用Vue Router 4.x,本文中所有的使用方式都是使用 Composition API的方式。 本文通过一步步介绍Vue Router 4.x的使用,来搭建一个简单的博客系统,让你对新版的Vue Router 4.x有一个完整的认识,然后能够非常轻松滴将Vue Router 4.x应用在自己的项目中。 项目初始化 项目搭建 项目使用vite进行创建。 npm init vite@latest vue-router-

lcl130的专栏 1万+

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

【水平:编写简单的Vue】用一篇文章精通Vue-4

本文介绍了基于Vue.js+Spring Boot的电商后台管理系统中商品管理模块的设计与实现。系统采用前后端分离架构,前端使用Vue 3+Element Plus,后端采用Spring Boot+MySQL。商品管理模块包含CRUD功能、分类树形管理、SKU规格生成等核心功能,通过组件化设计和分层架构实现。关键技术包括图片上传处理、富文本编辑器集成和数据筛选优化,并采用虚拟滚动、API缓存等性能优化手段。模块具有良好的扩展性,支持插件式设计和动态配置,经过优化可支持日均10万级商品操作,响应时间控制在30

ZGW0513的博客 775

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

vue - 4 解上个文章留下的bug

解 bug

an_julia的博客 165

深度学习工具包 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")

Vue系列文章(4)键盘事件及键盘修饰符

在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为v-on在监听键盘事件时添加按键修饰符: <!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` --> <input v-on:keyup.enter="submit"> 你可以直接将KeyboardEvent.key暴露的任意有效按键名转换为 kebab-case 来作...

D.K专栏 658

Django Web 国内运动男装小红书文章数据可视化分析系统系统源码-Django4+Vue3+Django ORM+MySQL8.0【含文档】

开源免费分享Django Web 国内运动男装小红书文章数据可视化分析系统系统源码-Django4+Vue3+Django ORM+MySQL8.0【含文档】可提供说明文档 可以通过*AIGC**技术包括:MySQL、VueJS、ElementUI、(Python或者Java或者.NET)等等*功能如图所示。可以滴我获取详细的视频介绍

k13579_97531的博客 1015

全景图嵌入商品_使用VueJS将全景图嵌入您的网站

全景图嵌入商品 VueJS全景查看器 (VueJS Panorama Viewer) Embed panorama into your website (lightweight~4.56 kB) VueJS version of JQuery Panorama Viewer. 将全景图嵌入到您的网站中(轻量级〜4.56 kB)VueJS版本的JQuery Panorama Viewer。 Vi...

cuk5340的博客 567

基于springboot+vue.js的丰田4s店系统附带文章源码部署视频讲解等

🌞博主介绍:✌优快云特邀作者、资深全栈开发程序员,曾在互联网大厂担任高级职位、码云/掘金/华为云/阿里云/InfoQ/StackOverflow/github等平台优质作者、专注于Java、小程序、前端、python等技术领域毕业项目实战,以及程序定制化开发、全栈讲解、就业辅导、面试辅导、简历修改。✌🌞👇🏻精彩专栏 推荐订阅👇🏻2024-2025年最值得选的微信小程序毕业设计选题大全:100个热门选题推荐✅2024-2025年最值得选的Java毕业设计选题大全:100个热门选题推荐✅。

wishcoding的博客 1452

用vue开发一个app(4,一个久等了的文章)H5直播平台登录注册(1)

我上一篇关于vue的文章和这一篇时间隔了有点久了。最近终于写完了。 因为我一直想写个有点实绩的东西,而不是随便写一个教程一样东西。结合最近在项目中学到的经验和我的一点创意。 首先介绍下这是个什么! H5直播平台! 不是一个标题,我已经开发完了。 接着这里是登录注册的流程图 这边微信登录,因为没有我个人没有权限开通服务号,所以没有测试。用的还是16年我上个公司的代码。 验证码我用的是aliyun的短信平台,大部分短信平台都有个需要企业资质的东西。 因为这是个个人站,只有腾讯云和阿里云有个人的...

u011927449的博客 405

4 5区别 angular 和_前端开发实用比较,一篇文章告诉你到底是用Vue还是用Angular4、5?...

从Angular2时代开始,前端开发就逐渐开始用用Angular了,当时全国都没什么人敢碰Angular2,多数开发者就靠着啃它源代码中的注释,熟悉了Angular2的用法,并在实用中,还给Angular2团队提交bug。但是现在,Vue的出现,让很多还没接触Angular多久的开发者开始纠结,这两个到底用哪个好?用Vue还是用Angular?因此,这里提供给大家最实用的比较,帮助大家在Vue和A...

weixin_39562338的博客 110
上一篇: 关于一些Vue的文章。(3)
下一篇: 关于一些Vue的文章。(5)
三毛丶
博客等级 码龄10年 9粉丝 27原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值