精华内容
下载资源
问答
  • 针对常用的迭代追踪类算法难以保证低采样下光谱重构的成功率与精度的问题,提出了一种在低采样下光谱重构中字典原子选取的优化方法。利用AVIRIS和ROSIS高光谱数据构建光谱稀疏字典并进行压缩感知光谱重构实验,分别...
  • 摘要:让我们再回到重构的基本概念,思考我们需要怎样的重构辅助服务。 一、背景 代码重构是每一位开发者最熟悉不过的字眼,其出现通常伴随着开发过程。在程序开发、迭代与演进的漫漫长路中,某次不经意的修改就...

    摘要:让我们再回到重构的基本概念,思考我们需要怎样的重构辅助服务。

    一、背景

    代码重构是每一位开发者最熟悉不过的字眼,其出现通常伴随着开发过程。在程序开发、迭代与演进的漫漫长路中,某次不经意的修改就可能破坏程序原有的设计与结构,造成代码结构的流失,而这种流失是具有累积性的,若未及时发现与重构,程序就会逐渐腐烂甚至变质,形成巨大的历史债务。其实重构就好比收拾房间,如果我们天天打扫,那么每天花3分钟就能打扫干净,可如果一个月不打扫,你想想需要多久才能打扫完。

    既然代码重构在开发过程中这么重要,怎么能没有相应的服务来支撑它呢?我们能不能开发出相应的“扫帚”辅助我们每天打扫房间?亦或是“扫地机器人”自动的帮我们打扫一个月未收拾的房间?

    带着上述疑问,让我们再回到重构的基本概念,思考我们需要怎样的重构辅助服务。

    1. 什么是重构

    如此书中所说,所谓重构(Refactoring)是这样一个过程:在不改变代码外在行为的前提下,对代码做出修改,以改进程序的内部结构。这里的重构有两层含义,一个名词含义,一个动词含义:

    重构(名词):对软件内部结构的一种调整, 目的是在不改变软件可观察行为的前提下,提高其可理解性, 降低其修改成本。

    重构(动词):使用一系列重构手法, 在不改变软件可观察行为的前提下,调整其结构。

    至此,我们应该明白,一款好的重构辅助服务应该至少兼具不变与变两个特征:不改变软件可观测行为;优化代码结构,降低修改成本,提高可理解性。

    2.什么时候重构(何时应做怎样的重构)

    就重构时机问题,业界也有比较激烈的讨论,有人认为重构应该随时随地地进行,不应该为了重构而重构,就比如我在添加新功能时、修补错误时、或者复审代码时都可以进行重构,我们暂且称之为“开发时重构”,也有人认为“添加新功能”和“重构”是两顶帽子,在添加新功能时,就不应该修改既有代码,只管添加新功能,而在重构时,就不能添加功能,只管改进程序结构,一次只做一件事,我们暂且称之为“维护式重构”。我个人认为这两种说法并不矛盾,真正好的重构应该是两者的有机结合。
    在这里插入图片描述

    如上图所示,红色范围是我认为比较好的重构实践。

    我认为无论在做新功能开发时还是在做老版本维护时,都适合做代码重构,只是适合的重构粒度不同而已。对于开发时重构,比较适合做个人级小范围的微重构,这种重构往往影响范围小,且较为简单,不会对开发增加工作难度,例如“重命名”、“函数提取”等原子重构;对于维护时重构,比较适合做架构级大范围的复杂重构,这种重构往往是为了解决项目代码中遗留的技术债务,且通常和代码坏味道的消除结合在一起,例如依恋情结(Feature Envy)、数据泥团(Data Clumps)等,而这些坏味道的重构往往由一系列的重构原子操作组合而成。当然,最好将重构工作尽可能多地做在开发阶段,尽量减少新增代码对已有设计与架构的破坏。

    看到这里,我们是否有些似曾相识,这不就对应了上文中提到的“扫帚”以及“扫地机器人”在实际重构工作中的应用?

    3.为什么需要代码智能重构服务

    使用过现代IDE开发代码的同学们应该都知道,以IntelliJ IDEA为代表的很多IDE多少都自带一些重构功能,但目前为止,这些重构都是例如“重命名”、“函数提取”等原子性重构,只对重构过程提供了部分支持,绝大部分的代码、架构坏味道重构工作仍然得靠手工完成,就好比你需要打扫一个月未打扫的房子,但手中只有一把扫帚一样。Kent Beck 说过:“手工重构仍然是很耗时的工作。正是这个简单的事实造成了很多程序愿不愿意进行重构,尽管他们知道自己应该重构,但毕竟重构的成本太大了。如果能够把重构变的像调整代码格式那么简单,程序员自然也会乐意像整理代码格式那样整理系统的设计。而这样的整理对代码的可读性、可复用性和可理解性,都能带来深远的正面影响。”正因如此,一款智能的、可以帮助开发者发现代码、架构中的坏味道并且引导开发者完成代码重构的服务尤为重要。

    二、Devops全流程下的重构服务需求

    在这里插入图片描述

    对于持续交付过程中的代码开发与发布环节,如上图虚线框所示,几乎每一步都与代码质量的看护或代码重构相关。

    1. 开发环节可大致分为两种类型:用于添加新功能的“增量式开发”以及维护老版本的“存量式维护”。对于“增量式开发”而言,需要重构服务的编码规范重构和原子重构能力在开发过程中帮助开发人员提升代码质量与开发效率;对于“存量式整改”而言,则需要重构服务具备架构、代码坏味道的检查、重构机会点挖掘以及重构方案的推荐能力,并将相应的重构方案拆解为彼此独立且正交的原子重构能力,最终作为一个原子重构序列推荐给开发人员,在与人机交互中一步步完成重构应用。
    2. 持续发布环节,MR门禁中的代码静态检测需要触发对坏味道代码的识别,作为一种增量式检测,主要识别由新增代码引入的代码及架构坏味道,
      并自动生成一次重构任务,引导开发人员进行一次重构,避免代码中技术债堆积。
    3. 生产运维环节,需要做定期的架构看护,将相应度量结果通过架构可视化图形界面展示出来,当架构某个模块腐化到一个阈值时自动报警,提示版本负责人做相应重构。

    三、如何辅助开发人员实现代码分层重构

    1.都有哪些层级的重构
    在这里插入图片描述

    个人认为重构大致可以分为4个层级,这些层级之间的关系可以从上图看出,并非是自底向上依次包含的关系,它们之间会有些重叠也有些不同。单纯从重构本身来讲,越上层级的重构操作非确定性越强,更偏业务性,而越下层级的重构操作确定性越强,更偏技术性。从智能重构服务的角度来讲,越上层越偏检测能力,越下层越偏纯重构能力。下面我们由下至上依次来看看不同层级重构操作的特点与异同。

    原子重构能力:上文中也有提到原子重构,原子重构到底有哪些呢?顾名思义,即不可再分的重构操作,例如重命名、移动、删除等重构操作,这些重构操作是完全确定性的,例如我想要抽取一段代码形成一个新方法,是否可抽,可以抽成什么样都是完全确定的。这些重构操作因为其不可再分性位于重构最底层。

    编码规范重构:有些同学可能会对这个层级的重构比较陌生,其实它就是基于规范和规则的重构,通常包含了我们所说的微重构,例如对违反了命名风格的标识符进行重命名重构,亦或是对无用代码进行删除的安全删除重构等等,并且这层的重构操作完全可以通过调用下层的1个原子重构来实现。正因为这些重构操作基于规则,其重构结果也是相对确定的。

    代码坏味道重构:代码坏味道也包括了架构坏味道,例如Feature Envy、God Class等类型,这些层级重构的目的是为了消除相应的代码坏味道,所以相对来说更复杂,一次重构的完成往往要调用下层多个原子重构操作,例如对God Class进行重构,需要调用至少一次Extract Class原子重构。同时这层重构的非确定性也更高,对一种代码坏味道的重构消除往往可以通过多种手段。

    设计模式坏味道重构:这层重构应该属于金字塔顶端的重构,因为它涉及范围太广,更偏向于对业务的理解与预测,从具象到抽象,显得有些虚无缥缈。设计模式有7中坏味道和11中原则,目前无论学术界还是工业界对于这类问题检测、重构相关的研究都还不多。

    2.智能重构服务在不同层级下的应用

    结合Devops下的重构服务需求与上图中的四层重构,我们基本可以看出智能重构服务不同层级的重构能力主要运用在开发工作流中的哪个阶段。对于原子重构来说,因为其确定性以及业务无关性,最适合作为插件集成在IDE上,由开发者做增量开发时调用;对于编码规范重构来说,适合同原子重构一起集成进IDE插件,在开发过程中自动且快速的识别到违反特定规则的代码,并辅助开发者重构;对于代码坏味道重构来说,适合在持续发布环节的门禁阶段拦截问题并引导开发者回到IDE进行代码智能重构;对于设计模式坏味道重构来说,因为其涉及业务理解与预测,更适合放进生产运维环节,结合版本演进与迭代历史,给出架构腐化的预测以及相应重构方案的推荐。

    3.搭积木式的重构应用
    在这里插入图片描述

    既然上层重构操作都可以转化为最底层的原子重构操作,那如何表达这种转化呢?表格中列举了几种常见的重构原子操作,每种重构原子操作都可以用一个函数来表达。例如Move Method,函数名为Move Method,我们用三个参数来明确它的行为:Source(所属类型)、Target(目标类型)以及(需要移动的方法),有了这些信息就可以明确一次Move Method原子重构。对于任何一个复杂的重构来说,都可以表示成如下形式的原子重构序列,即一系列原子重构的组合。
    在这里插入图片描述

    就像搭积木一样,任何上层重构都可以通过搭积木的方式组合底层原子重构来实现。

    四、重构服务设计原则

    重构服务的设计亦如其它很多开发服务一样,最终目标都是提升用户开发效率与代码质量,如果二者皆得不到保证,那这款服务将被永远丢进垃圾堆里。从我们在华为内部的实践经验,总结了以下几点原则:

    充分的用户交互:经典的重构工作流程为“小步前进,随时可用,随时可停,随时回退”,小步修改意味着每一步出错的可能性大大减小,要遵循这个流程,就离不开工具和用户频繁的交互,要引导用户一步步的完成复杂的代码重构,每个过程都要做到随时可用,随时可停,随时可退

    友好的重构工作界面:代码重构有点类似代码自动修复,但比代码自动修复涉及范围更广,如何让用户更好的表达重构意图、并且一目了然的看到重构对原代码架构的影响非常重要,这一部分有很多可以创新的地方。

    个性化用户配置:上层级的重构往往可以有不同的执行路径,根据代码工程不同、业务场景不同,同一种坏味道重构的实现方式也可能不同,要以用户为中心,根据业务不同、用户不同给出个性化、定制化的重构解决方案,这一部分刚好是AI擅长的领域。

    Devops服务深度集成:任何一款开发服务如果离开Devops服务就会成为一个孤立的散点,无法在开发过程中被顺畅的使用,如果我们能把重构服务集成进IDE、代码检视环节、代码入库环节以及验证发布环节,就可以让重构工具Build In在可信开发过程中,让重构服务触手可及。

    高效:特别是在IDE上的重构分析服务,如果分析过程需要花费太长时间,程序员很可能就不会使用这些重构服务,他们宁可手工重构。

    点击关注,第一时间了解华为云新鲜技术~

    展开全文
  • Facebook 重构:抛弃 Sass / Less ,迎接原子化 CSS 时代

    千次阅读 多人点赞 2021-01-15 17:31:39
    在这篇文章中,我们将看到什么是Atomic CSS(原子 CSS),它如何与 Tailwind CSS 这种实用工具优先的样式库联系起来,目前很多大公司在 React 代码仓库中使用它们。 由于我不是这方面的专家,所以我不会去深入探讨它...

    本文转载自 前端从进阶到入院,作者 ssh前端

    随着 Facebook 和 Twitter 最近的产品部署,我认为一个新的趋势正在缓慢增长:Atomic CSS-in-JS。

    在这篇文章中,我们将看到什么是Atomic CSS(原子 CSS),它如何与 Tailwind CSS 这种实用工具优先的样式库联系起来,目前很多大公司在 React 代码仓库中使用它们。

    由于我不是这方面的专家,所以我不会去深入探讨它的利弊。我只是希望能帮助你了解它的大致内容。

    先抛出一个令人开心的结论,新的 CSS 编写和构建方式让 Facebook 的主页减少了 80% 的 CSS 体积。

    什么是原子 CSS?

    你可能听说过各种 CSS 方法,如 BEM, OOCSS…

    <button class="button button--state-danger">Danger button</button>

    现在,人们真的很喜欢 Tailwind CSS 和它的 实用工具优先(utility-first)的概念。这与 Functional CSS 和 Tachyon[3] 这个库的理念非常接近。

    <button
      class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
    >
      Button
    </button>

    用海量的实用工具类(utility classes)组成的样式表,让我们可以在网页里大显身手。

    原子 CSS 就像是实用工具优先(utility-first)CSS 的一个极端版本: 所有 CSS 类都有一个唯一的 CSS 规则。原子 CSS 最初是由 Thierry Koblentz (Yahoo!)在 2013 年挑战 CSS 最佳实践时使用的。

    /* 原子 CSS */
    .bw-2x {
      border-width: 2px;
    }
    .bss {
      border-style: solid;
    }
    .sans {
      font-style: sans-serif;
    }
    .p-1x {
      padding: 10px;
    }
    /* 不是原子 CSS 因为这个类包含了两个规则 */
    .p-1x-sans {
      padding: 10px;
      font-style: sans-serif;
    }

    使用实用工具/原子 CSS,我们可以把结构层和表示层结合起来:当我们需要改变按钮颜色时,我们直接修改 HTML,而不是 CSS!

    这种紧密耦合在现代 CSS-in-JS 的 React 代码库中也得到了承认,但似乎 是 CSS 世界里最先对传统的关注点分离有一些异议。

    CSS 权重也不是什么问题,因为我们使用的是最简单的类选择器。

    我们现在通过 html 标签来添加样式,发现了一些有趣的事儿:

    • 我们增加新功能的时候,样式表的增长减缓了。
    • 我们可以到处移动 html 标签,并且能确保样式也同样生效。
    • 我们可以删除新特性,并且确保样式也同时被删掉了。

    可以肯定的缺点是,html 有点臃肿。对于服务器渲染的 web 应用程序来说可能是个缺点,但是类名中的高冗余使得 gzip 可以压缩得很好。同时它可以很好地处理之前重复的 css 规则。

    一旦你的实用工具/原子 CSS 准备好了,它将不会有太大的变化或增长。可以更有效地缓存它(你可以将它附加到 vendor.css 中,重新部署的时候它也不会失效)。它还具有相当好的可移植性,可以在任意其他应用程序中使用。

    实用工具/原子 CSS 的限制

    实用工具/原子 CSS 看起来很有趣,但它们也带来了一些挑战。

    人们通常手工编写实用工具/原子 CSS,精心制定命名约定。但是很难保证这个约定易于使用、保持一致性,而且不会随着时间的推移而变得臃肿。

    这个 CSS 可以团队协作开发并保持一致性吗?它受巴士因子的影响吗?

    巴士系数是软件开发中关于软件专案成员之间讯息与能力集中、未被共享的衡量指标,也有些人称作“货车因子”、“卡车因子”(lottery factor/truck factor)。一个专案或计划至少失去若干关键成员的参与(“被巴士撞了”,指代职业和生活方式变动、婚育、意外伤亡等任意导致缺席的缘由)即导致专案陷入混乱、瘫痪而无法存续时,这些成员的数量即为巴士系数。

    你还需要预先开发好一个不错的实用工具/原子样式表,然后才能开始开发新功能。

    如果实用工具/原子 CSS 是由别人制作的,你将不得不首先学习类命名约定(即使你知道 CSS 的一切)。这种约定是有主观性的,很可能你不喜欢它。

    有时,你需要一些额外的 CSS,而实用工具/原子 CSS 并不提供这些 CSS。没有约定好的方法来提供这些一次性样式。

    Tailwind 赶来支援

    Tailwind 使用的方法是非常便捷的,并且解决了上述一些问题。

    它通过 Utility-First 的理念来解决 CSS 的一些缺点,通过抽象出一组类名 -> 原子功能的集合,来避免你为每个 div 都写一个专有的 class,然后整个网站重复写很多重复的样式。

    传统卡片样式写法:

     

    图片

     

    Tailwind 卡片样式写法:

     

    图片

     

    它并不是真的为所有网站提供一些唯一的实用工具 CSS,取而代之的是,它提供了一些公用的命名约定。通过一个配置文件,你可以为你的网站生成一套专属的实用工具 CSS。

    ssh 注:这里原作者没有深入介绍,为什么说是一套命名约定呢而不是生成一些定死的 CSS 呢?

    举几个例子让大家感受一些,Tailwind 提供了一套强大的构建系统,比如默认情况下它提供了一些响应式的断点值:

    // tailwind.config.js
    module.exports = {
      theme: {
        screens: {
          'sm': '640px',
          // => @media (min-width: 640px) { ... }
    
          'md': '768px',
          // => @media (min-width: 768px) { ... }
    
          'lg': '1024px',
          // => @media (min-width: 1024px) { ... }
    
          'xl': '1280px',
          // => @media (min-width: 1280px) { ... }
        }
      }
    }
    

    你可以随时在配置文件中更改这些断点,比如你所需要的小屏幕 sm 可能指的是更小的 320px,那么你想要在小屏幕时候采用 flex 布局,还是照常写 sm:flex,遵循同样的约定,只是这个 sm 已经被你修改成适合于项目需求的值了。

    在比如说,Tailwind 里的 spacing 掌管了 margin、padding、width 等各个属性里的代表空间占用的值,默认是采用了 rem 单位,当你在配置里这样覆写后:

    // tailwind.config.js
    module.exports = {
      theme: {
        spacing: {
          '1': '8px',
          '2': '12px',
          '3': '16px',
          '4': '24px',
          '5': '32px',
          '6': '48px',
        }
      }
    }

    你再去写 h-6(height), m-2(margin), mb-4(margin-bottom),后面数字的意义就被你改变了。

    也许从桌面端换到移动端项目,这个 6 代表的含义变成了 6rem,但是这套约定却深深的印在你的脑海里,成为你知识的一部分了。

    Tailwind 的知识可以迁移到其他应用程序,即使它们使用的类名并不完全相同。这让我想起了 React 的「一次学习,到处编写」理念。

    我看到一些用户反馈说,Tailwind 提供的类名能覆盖他们 90% - 95% 的需求。这个覆盖面似乎已经足够广了,并不需要经常写一次性的 CSS 了。

    此时,你可能想知道为什么要使用原子 CSS 而不是 Tailwind CSS?强制执行原子 CSS 规则的一个规则,一个类名,有什么好处?你最终会得到更大的 html 标签和更烦人的命名约定吗?Tailwind 已经有了足够多的原子类了啊。

    那么,我们是否应该放弃原子 CSS 的想法,而仅仅使用 Tailwind CSS?

    Tailwind 是一个优秀的解决方案,但仍然有一些问题没有解决:

    • 需要学习一套主观的命名约定

    • CSS 规则插入顺序仍然很重要

    • 未使用的规则可以轻松删除吗?

    • 我们如何处理剩下的一次性样式?

    与 Tailwind 相比,手写原子 CSS 可能不是最方便的。

    和 CSS-in-JS 比较

    CSS-in-JS 和实用工具/原子 CSS 有密切关系。这两种方法都提倡使用标签进行样式化。以某种方式试图模仿内联样式,这让它们有了很多相似的特性(比如在移动某些功能的时候更有信心)。

    Christopher Chedeau 一直致力于推广 React 生态系统中 CSS-in-JS 理念。在很多次演讲中,他都解释了 CSS 的问题:

    1. 全局命名空间
    2. 依赖
    3. 无用代码消除
    4. 代码压缩
    5. 共享常量
    6. 非确定性(Non-Deterministic)解析
    7. 隔离

    实用工具/原子 CSS 也解决了其中的一些问题,但也确实没法解决所有问题(特别是样式的非确定性解析)。

    如果它们有很多相似之处,那我们能否同时使用它们呢?

    探索原子 CSS-in-JS

    原子 CSS-in-JS 可以被视为是“自动化的原子 CSS”:

    • 你不再需要创建一个 class 类名约定

    • 通用样式和一次性样式的处理方式是一样的

    • 能够提取页面所需要的的关键 CSS,并进行代码拆分

    • 有机会修复 JS 中 CSS 规则插入顺序的问题

    我想强调两个特定的解决方案,它们最近推动了两个大规模的原子 CSS-in-JS 的部署使用,来源于以下两个演讲。

    • React-Native-Web at Twitter。

    • Stylex at Facebook。

    也可以看看这些库:

    • Styletron
    • Fela
    • Style-Sheet
    • cxs
    • otion
    • css-zero
    • ui-box
    • style9
    • stitches
    • catom

    React-Native-Web

    React-Native-Web 是一个非常有趣的库,让浏览器也可以渲染 React-Native 原语。不过我们这里并不讨论跨平台开发(演讲里有更多细节)。

    作为 web 开发人员,你只需要理解 React-Native-Web 是一个常规的 CSS-in-JS 库,它自带一些原始的 React 组件。所有你写 View 组件的地方,都可以用 div 替换。

    React-Native-Web 的作者是 Nicolas Gallagher,他致力于开发 Twitter 移动版。他们逐渐把它部署到移动设备上,不太确定具体时间,大概在 2017/2018 年左右。

    从那以后,很多公司都在用它(美国职业足球大联盟、Flipkart、Uber、纽约时报……),但最重要的一次部署,则是由 Paul Armstrong 领导的团队在 2019 年推出的新的 Twitter 桌面应用。

    Stylex

    Stylex 是一个新的 CSS-in-JS 库,Facebook 团队为了 2020 年的 Facebook 应用重构而开发它。未来可能会开源,有可能用另一个名字。

    值得一提的是,React-Native-Web 的作者 Nicolas Gallagher 被 Facebook 招安。所以里面出现一些熟悉的概念一点也不奇怪。

    我的所有信息都来自演讲 :),还需要等待更多的细节。

    可扩展性

    不出所料,在 Atomic CSS 的加成下,Twitter 和 Facebook 的 CSS体积都大幅减少了,现在它的增长遵循的是对数曲线。不过,简单的应用则会多了一些 初始体积

    Facebook 分享了具体数字:

    • 旧的网站仅仅首页就用了 413Kb 的 CSS
    • 新的网站整个站点只用了 74Kb,包括暗黑模式

    源码和输出

    这两个库的 API 看起来很相似,但也很难说,因为我们对 Stylex 了解不多。

    值得强调的是,React-Native-Web 会扩展 CSS 语法糖,比如 margin: 0,会被输出为 4 个方向的 margin 原子规则。

    以一个组件为例,来看看旧版传统 CSS 和新版原子 CSS 输出的区别。

    <Component1 classNames="class1" /> <Component2 classNames="class2" />
    .class1 {
      background-color: mediumseagreen;
      cursor: default;
      margin-left: 0px;
    }
    .class2 {
      background-color: thistle;
      cursor: default;
      jusify-content: flex-start;
      margin-left: 0px;
    }
    

    可以看出这两个样式中 cursor 和 margin-left 是一模一样的,但它在输出中都会占体积。

    再来看看原子 CSS 的输出:

    <Component1 classNames="classA classC classD" />
    <Component2 classNames="classA classB classD classE" />
    class a {
      cursor: default;
    }
    class b {
      background-color: mediumseagreen;
    }
    class C {
      background-color: thistle;
    }
    class D {
      margin-left: 0px;
    }
    class E {
      jusify-content: flex-start;
    }
    
    

    可以看出,虽然标签上的类名变多了,但是 CSS 的输出体积会随着功能的增多而减缓增长,因为出现过一次的 CSS Rule 就不会再重复出现了。

    生产环境验证

    我们看看 Twitter 上的标签是什么样子的:

    现在,让我们来看看新 Facebook:

    很多人可能会被吓到,但是其实它很好用,而且保持了可访问性。

    在 Chrome 里检查样式可能有点难,但 devtools 里就看得很清楚了:

    CSS 规则顺序

    与手写的工具/原子 CSS 不同,JS 库能让样式不依赖于 CSS 规则的插入顺序。

    在规则冲突的情况下,生效的不是标签上 class attribute 中的最后一个类,而是样式表中最后插入的规则。

    以这张图为例,我们期望的是书写在后blue 类覆盖前面的类,但实际上 CSS 会以样式表中的顺序来决定优先级,最后我们看到的是红色的文字。

    在实际场景中,这些库避免在同一个元素上写入多个规则冲突的类。它们会确保标签上书写在最后的类名生效。其他的被覆盖的类名则被规律掉,甚至压根不会出现在 DOM 上。

    const styles = pseudoLib.create({
      red: {color: "red"},
      blue: {color: "blue"},
    });
    
    // 只会输出 blue 相关的 CSS
    <div style={[styles.red, styles.blue]}>
      Always blue!
    </div>
    
    // 只会输出 red 相关的 CSS
    <div style={[styles.blue, styles.red]}>
      Always red!
    </div>
    

    注意:只有使用最严格的原子 CSS 库才能实现这种可预测的行为。

    如果一个类里有多个 CSS 规则,并且只有其中的一个 CSS 规则被覆盖,那么 CSS-in-JS 库没办法进行相关的过滤,这也是原子 CSS 的优势之一。

    如果一个类只有一个简单的 CSS 规则,如 margin: 0,而覆盖的是 marginTop: 10。像 margin: 0 这样的简写语法被扩展为 4 个不同的原子类,这个库就能更加轻松的过滤掉不该出现在 DOM 上的类名。

    仍然喜欢 Tailwind?

    只要你熟悉所有的 Tailwind 命名约定,你就可以很高效的完成 UI 编写。一旦你熟悉了这个设定,就很难回到手写每个 CSS 规则的时代了,就像你写 CSS-in-JS 那样。

    没什么能阻止你在原子 CSS-in-JS 的框架上建立你自己的抽象 CSS 规则,Styled-system 就能在 CSS-in-JS 库里完成一些类似的事情。它基于一些约定创造出一些原子规则,在 emotion 中使用它试试:

    import styled from '@emotion/styled';
    import { typography, space, color } from 'styled-system';
    
    const Box = styled('div')(typography, space, color);
    

    等效于:

    <Box
      fontSize={4}
      fontWeight="bold"
      p={3}
      mb={[4, 5]}
      color="white"
      bg="primary"
    >
      Hello
    </Box>

    甚至有可能在 JS 里复用一些 Tailwind 的命名约定,如果你喜欢的话。

    先看些 Tailwind 的代码:

    <div className="absolute inset-0 p-4 bg-blue-500" />

    我们在谷歌上随便找一个方案,比如我刚刚发现 react-native-web-tailwindcss:

    import { t } from 'react-native-tailwindcss';
    
    <View style={[t.absolute, t.inset0, t.p4, t.bgBlue500]} />;
    

    就生产力的角度而言,并没有太大的不同。甚至可以用 TS 来避免错别字。

    结论

    这就是我要说的关于原子 CSS-in-JS 所有内容。

    我从来没有在任何大型生产部署中使用过原子 CSS、原子 CSS-in-JS 或 Tailwind。我可能在某些方面是错的,请随时纠正我。

    我觉得在 React 生态系统中,原子 CSS-in-JS 是一个非常值得关注的趋势,我希望你能从这篇文章中学到一些有用的东西。

    展开全文
  • 压缩感知

    千次阅读 2018-10-07 21:26:43
    本文综述了压缩感知的理论框架及关键的技术问题,并着重介绍了压缩感知稀疏重构中的主流贪婪算法,通过算法实验分析了各种算法的重构性能。 压缩感知理论主要包括信号的稀疏表示,编码测量和信号...

    压缩感知理论及其算法研究报告

    摘 要:随着信息技术的发展,人们对信息的巨量需求以及硬件的发展缓慢造成了信号采样,传输和存储的巨大压力。如何解决在现有的硬件基础上传输大量的信息成为热点研究的内容。近年来压缩感知的出现为缓解这些压力提供了解决的办法。本文综述了压缩感知的理论框架及关键的技术问题,并着重介绍了压缩感知稀疏重构中的主流贪婪算法,通过算法实验分析了各种算法的重构性能。
    关键词:压缩感知 贪婪算法 稀疏重构
    1.引言
    传统的信号采样定律-那奎斯特采样定律定理:为了不失真地恢复模拟信号,采样频率应该不小于模拟信号频谱中最高频率的2倍[1]。这样对于系统处理信息的硬件需求提出了很高的要求,同时在实际应用当中为了节约存储空间和降低传输成本,需要对采集的数据进行压缩处理,这样会造成大量采集的数据浪费。因而压缩感知技术应运而生,打破了传统的信号采样定理,从不同的角度解决了信号采样的问题。使得在保证信息不损失的情况下,用远低于奈奎斯特采样定理要求的速率采样信号。压缩感知理论指出只要信号是可压缩的或在某个变换域是稀疏的,那么就可以用一个与变换基不相关的观测矩阵将变换所得高维信号投影到一个低维空间上,然后通过求解一个优化问题就可以从这些少量的投影中以高概率重构出原信号[2]。在该理论框架下,采样速率不决定于信号的带宽,而决定于信息在信号中的结构和内容。压缩感知理论使得采样和计算的成本大大降低。
    当前主流的压缩感知重构算法主要包括三类:凸优化方法,贪婪算法和基于贝叶斯框架提出的算法[3]。本文主要以压缩感知重构算法为主线,介绍了主流的贪婪追踪类算法包括正交匹配追踪(OMP)算法,正则化正交匹配追踪(ROMP)算法,分段正交匹配追踪(STOMP)算法,稀疏度自适应匹配追踪(SAMP)算法,并且对这些算法的优缺点进行了比较通过仿真实验分析了各种算法的重构性能。
    2.压缩感知基本理论
    压缩感知理论主要包括信号的稀疏表示,编码测量和信号重构算法三个方面。信号的稀疏表示是压缩感知的先验条件,信号的稀疏表示是将信号投影到正交变换基时,绝大多数的变换稀疏的绝对值很小,所得到的变换向量是稀疏的或者是近似稀疏的。任意的N维信号都可以通过某个稀疏矩阵线性表示。例如x为N维的信号,Ψ是x对应的稀疏矩阵,则x可以表示为:x = ∑_(i=1)^N▒〖θ_i ψ_i 〗其中,Ψ是N列ψ_i组成的矩阵,θ_i是x在ψ_i下的投影系数,θ是投影系数向量,θ=Ψ^Tx。稀疏矩阵一般根据信号本身特点灵活选取,常见的是离散余弦变换基,快速傅里叶变换基,离散小波变换基。在编码测量中首先选定一个平稳的,与稀疏基Ψ不相关的M × N 维的观测矩阵Ф,对θ进行观测得到观测集合Y = Фx = ФΨθ。令A=ФΨ为M × N 的矩阵,称为感知矩阵。Y可以看作是稀疏信号θ关于测量矩阵A的测量值,上式整体可以表示为图(1)。
    在这里插入图片描述

    在压缩感知的整个过程中,测量矩阵的设计是一个关键步骤。测量矩阵性质的好坏,关系到能否达到压缩的目的,同时又直接关系到信号能否被精确重构。设计一个合适的观测矩阵应该既能达到压缩采样的目的,同时又可以保证信号可以无失真的重构。有限等距性质[4]在理论上较好的解决了这个问题,只要感知矩阵A能够满足RIP条件,那么信号可以由少量的测量值经过重构算法精确的恢复出来,也就是说,理论上我们可以设计一个测量矩阵使得感知矩阵A满足RIP规则,这样既可以达到压缩采样的目的,又能保证信号无失真的恢复出来。RIP规则的数学表达描述为:设A=ФΨ为M × N 的矩阵,假设一个常数δ_k,使得对于任意向量s和所有的矩阵A_k,满足以下关系4
    (1-δ_k)〖||s||〗_2≤〖||A_k s||〗_2≤(1+δ_k)〖||s||〗2 (2-1)
    其中A_k是A子矩阵,大小为M×K,有限等距常数为δ_k∈(0,1)。
    如果A满足约束等距原则,保证了信号恢复的唯一性。实际上要直接验证矩阵是否满足RIP条件是一件很困难的事情。在实际应用中,我们可以用RIP准则的一种等价情况,即非相干性来指导测量矩阵的设计。非相干性指测量矩阵中的行向量不能被稀疏矩阵线性表出同理稀疏矩阵中的列向量也不能被测量矩阵中的任意行向量线性表出。相干性的度量由相干度[5]如图(2-2)所示,关系数旳取值范围为U∈(1,√N)
    U(Ф,Ψ)=√Nmax{|Ф_k,Ψ_J|} (2-2)
    Donoho等人在文献[6]中指出服从高斯分布的随机矩阵可以高概率满足不相关性,对于一个大小为M×N的随机高斯矩阵Ф,Ф中每个值满足均值为0,方差为1/M的高斯分布,即Ф
    (i,j) ~ N(0,1/M)。可以证明当M>cKlog(N/K)时,A = ФΨ在很大概率下能满足RIP条件。而且随机高斯矩阵与大多数固定正交基构成的矩阵不相关,因此随机高斯测量矩阵满足理论上的最优性。目前大多数情况下都采用随机高斯矩阵作为压缩感知的测量矩阵,本文实验所用到的观测矩阵也是随机高斯矩阵。当选取好观测矩阵,压缩感知问题转化为求解(2-1)式的最优l_0范数问题
    min〖||θ||〗_0 s.t. Aθ = Y (2-3)
    如果得到x的稀疏表示θ,可以进一步由变换基Ψ通过下式(2-2)重构原始信号
    x = Ψθ (2-4)
    由于矩阵A的维度为M × N(M << N),所以方程(1)有无穷多解,通过贪婪算法可以逐步逼近最优解,直到求出原始信号。最早提出的是匹配追踪算法(MP),MP算法的基本思想是在每一次迭代过程中。从感知矩阵中选择与信号最匹配的原子来进行稀疏逼近求出余量,在稀疏度已知的情况下继续迭代选出与余量最匹配的原子。最匹配是指当前余量与原子的内积最大。经过数次迭代,该信号便可由这些原子线性表示,但是当前的余量仅与当前的原子正交而不是与已选定的所有的原子正交使,得每次迭代的结果可能是次最优的往往需要迭代多次。下面介绍四种主流的贪婪类重构算法并分析它们的优缺点进行比较。
    3.正交匹配追踪类算法
    3.1正交匹配追踪(OMP)算法
    OMP算法作为MP算法的延申,仍然沿用了MP算法中原子选择的标准,不同的是OMP算法利用Gram-Schmidt正交化对已选定的原子进行正交化处理,再将信号在这些正交原子构成的张量空间投影,得到信号在选定原子上的分量和余量,然后用相同的方法迭代分解余量。通过每次对所选原子的正交化处理保证了迭代的最优性,从而减少了迭代的次数[7]。
    OMP的具体步骤如下:
    (1)令初始余量r_0 = Y,稀疏度为K,索引值集合J为空集,支撑集合Λ为空集;
    (2)计算相关系数u(余量与原子的内积),并将u中最大值对应的索引值存入J;
    (3)更新支撑集合 ,将更新索引对应的原子存入Λ;
    (4)利用最小二乘法得到重建信号,同时对余量进行跟新;
    (5)若迭代次数小于K,r = r_new,n = n+1,转到第二步继续迭代;否则,停止迭代。
    为了说明OMP算法的重建性能,利用MATLAB R2016a作为平台,分两次实验验证。第一次实验,假定信号是稀疏的并且稀疏度为10,定常信号256 × 1的列向量中随机选取10个随机数随机排列到定长信号中。观测矩阵为128×256高斯随机矩阵。初始信号和恢复信号之间的误差用二者相减的二范数表示。实验结果如图(2)所示,实验误差为o(10e-15 )
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    第二次实验,测试对象为256×256lena图像。观测矩阵采用随机高斯矩阵,M和N表示观测矩阵的行数和列数,M/N表示压缩比0.5,实验结果如图(3),PSRN值为26.5536。

    在这里插入图片描述
    在这里插入图片描述

    OMP算法虽然保证了每次迭代的最优性,减少了迭代的次数。但是,它每次迭代中仅选取一个原子来跟新原子的集合,这样必然会付出巨大的重建时间代价。OMP算法首次把最小二乘法引入压缩感知重建中,用正交化的思想来计算重建信号使得结果更加准确,这是压缩感知重建算法取得重大研究进展的一个标志[8]。
    3.2正则化正交匹配追踪(ROMP)算法
    ROMP算法首先根据相关原则进行原子的一次筛选,通过求余量r与测量矩阵Ф中各个原子之间的内积的绝对值,来计算相关系数u,并按照此方法筛选出的K个原子的索引值存到候选集J中以便进行原子的二次筛选。
    ROMP算法采用正则化过程进行原子的二次筛选,将J中索引值对应的原子的相关系数分成若干,要求分组的原子在各自所在子集内的原子同误差向量的内积的最大值与最小值的比值在两倍以内[6]。数学表达式为(3-1)
    |u(i)| ≤ 2|u(j)|, i,j ∈J (3-1)
    然后选择能量最大的一组相关系数对应的原子索引值存入J_0中,该正则化过程可以使得ROMP算法最多经过K次迭代便可得到一个原子数|Λ|小于2K的支撑集Ф_Λ用于重建信号,对于没有选入支撑集的原子,正则化过程则能保证它们的能量一定远小于被选原子的能量,是一种简单有效的原子筛选方法。
    ROMP的步骤:
    (1)初始化余量r_0 = Y,估计信号稀疏度为K,迭代次数n = 1,索引值Λ为空集,J为空集;
    (2)计算相关系数u,并从u中寻找K个最大值对应的索引值存入J中;
    (3)对J中索引值对应原子的相关系数进行正则化,并将正则化的结果存入J_0;
    (4)更新支撑集Ф_Λ,其中Λ=Λ∪J_0;
    (5)利用最小二乘法得到重建信号,同时对余量进行跟新;
    (6)若|Λ| 2K,则停止迭代,否则令r =r_new,n = n+1,转到步骤(2)继续迭代。
    为了说明ROMP算法的重建性能,分两次实验实现算法重构,利用MATLAB R2016a作为平台。实验1假定信号是稀疏的并且稀疏度为10,定常信号256 × 1的列向量中随机选取10个随机数随机排列到定长信号中。观测矩阵为高斯随机矩阵。初始信号和恢复信号之间的误差用二者相减的二范数表示。实验结果如图(4)误差为o(10 )

    实验2假定信号是四个余弦函数式表示
    x=0.3cos(2π50t)+0.6cos(2π100t)+0.1cos(2π200t)+0.9cos(2π400t)
    我们运用快速傅里叶变换对一维信号 x 进行变换,稀疏度为7,测量矩阵为64×256高斯矩阵实验结果如图(5),误差为o(10 )。

    ROMP算法在OMP算法的基础上加入了正则化方法,以实现一次迭代选择多个原子的目的,从而提高重建速度,减少了算法的复杂度。但其代价是需要预估计信号的稀疏度,并且需要较多的采样数据
    3.3分段正交匹配追踪(STOMP)算法
    STOMP 算法采用分阶段的思想首先根据相关原则来筛选原子,利用阈值的方法从原子集合中选择和迭代余量匹配的原子,与OMP 算法不同的是,它并不是每次固定选择一个匹配原子,而是给定标准为大于门限值t_s δ_t的原子。δ_t为规范噪音水平, δ_t=〖||r_t ||〗2/√M。r_t是上一次跟新的余量值[9]。利用此标准可以一次找到多个原子,减少了匹配的次数,提高了追踪的效率; 然后更新支撑集和原子,并用最小二乘法求得近似解,同时完成对余量的更新。
    STOMP算法步骤:
    (1)初始化余量r_0 = Y,迭代次数默认为10,门限参数t_s默认为2.5。计数器t=1;
    (2)计算感知矩阵各列原子与余量的内积,选择大于门限值t_s δ_t的感知矩阵对应的原子列向量存入集合J_0 ;
    (3)跟新支撑集Λ_t = Λ
    (t-1) ∪ J_0,在支撑集上利用最小二乘法求出跟新余量;
    (4)若t值小于迭代次数s,返回(2)继续执行,否则退出循环。
    为了说明STOM算法的重建性能,利用MATLAB R2016a作为平台。假定信号是稀疏的并且稀疏度为10,定常信号256 × 1的列向量中随机选取10个随机数随机排列到定长信号中。观测矩阵为高斯随机矩阵。初始信号和恢复信号之间的误差用二者相减的二范数表示。实验结果如图(6)所示
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    STOMP 算法将 OMP 算法进行了一定程度的简化,提高了计算速度,但是由于其在每次迭代的过程中寻找的都不是信号的最佳表示,致使重构的精度降低,导致在实际中其重构的信号的精度远不如OMP 算法重构的信号的精度。门限参数和默认迭代次数的设置很大程度决定了算法的精度,使得算法的灵活度差。
    3.4稀疏度自适应匹配追踪(SAMP)算法
    以上算法均建立在稀疏度已知的情况下才能有效,但在实际情况中,信号的稀疏度信息往往事先是不可得的,SAMP相比较其他算法最吸引的就是可以不需要知道稀疏度的先验信息 ,这使得SAMP重建算法在实际应用中更加广泛[10]。
    SAMP算法中采用转换阶段(stage) 的方式逐步增加该原子数,将同一个迭代过程分成多个阶段,设置一个可变步长(size)代替所选原子数目,相邻两个阶段所对应的支撑集的大小之差即为当前步长,随着步长的增加和支撑集的不断增大,实现了在未知稀疏度的前提下步长逐步逼近稀疏度K进而实现精确重建出原始信号的目的[11]。SAMP算法引入了回溯的思想,每次迭代都重新评估原子的有效性。
    SAMP算法步骤:
    (1)初始化余量r_0= Y,支撑集F_0为空集,候选集S_0为空集,初始步长为s,步长增量初始倍数j=1;
    (2)选择感知矩阵内的原子和余量内积最大的s个列向量,将对应的原子列向量放入候选集s_k中;
    (3)合并支撑集F_k和候选集s_k得到跟新后的支撑集C_k;
    (4)以C_k的原子为基准,由最小二乘法得到重建信号并选择最大的s个元素所对应的原子,组成新的的支撑集F;
    (5)由初始余量,支撑集F,利用最小二乘法计算更新余量r;
    (6)如果满足迭代停止条件〖||r||〗_2 ≤ε(固定阈值)则退出循环,如果满足〖||r_k ||〗2 〖||r(k-1) ||〗_2则跟新步长倍数j = j + 1,跟新的步长为s = j × s转入步骤二继续迭代,否则更新支撑集,更新余量,转入步骤二继续迭代。
    为了说明SAMP算法的重建性能,利用MATLAB R2016a作为平台,分2次实验验证。第一次实验,假定信号是稀疏的并且稀疏度为10,定常信号256 × 1的列向量中随机选取10个随机数随机排列到定长信号中。固定阈值为0.1,观测矩阵为128×256高斯随机矩阵。初始信号和恢复信号之间的误差用二者相减的二范数表示。实验结果如(7)所示,误差为o(10 )。

    第二次实验,测试对象为256×256lena图像。观测矩阵采用随机高斯矩阵,M和N表示观测矩阵的行数和列数,M/N表示压缩比,实验的压缩比为0.5,阈值为100,验的PSRN值为24.3。实验结果如图(8)
    在这里插入图片描述
    在这里插入图片描述

    SAMP算法通过提供了严格的误差界限(固定阈值)且不需已知信号的稀疏度 K 就可以重构信号,固定阈值的选取同测量矩阵有着很大的联系。初始步长的选取目前任然是一个问题,SAMP算法的初始步长只需要小于稀疏度K,为了避免过度检测,如果不知道稀疏度,选择初始步长为1可以确保足够的精度。但是初始步长越小,算法运行的时间也就越大,这就造成了过度检测与运行时间的矛盾。经验表明,对于指数衰减的信号初始步长选的较小比较好,对于二进制稀疏信号选择步长较大比较好。如果算法能随着算法逐渐接近真实的稀疏度K值而逐渐缩小这样会提高算法的精度。另外,有学者提出了稀疏度自适应子空间追踪算法,该算法能较为精确完成信号重构,不需要设定步长,能够估计稀疏度大小,但是输入参数对算法影响较大。也有学者提出变步长的自适应步长的稀疏度估计的方法[12],根据每次迭代得到的残差值,通过函数Ln=[L_(n-1)log⁡(γ)/log⁡((γ+0.9ε)) /2.1],其中γ=1-|(|r_2 |)|/||y_2 ||,来确定步长的大小,当步长远离稀疏度K时步长较大,当接近K时稀疏度较小。
    3.5基于小波变换的分块压缩感知
    根据压缩感知理论,图像重构时如果图像尺寸太大,为了维持一定的精度,测量矩阵所需要的观测值随之增加,造成了观测矩阵对于有限的存储空间显得十分巨大,而硬件难于满足需求。Lu Gan [13]提出了分块压缩感知12,该方法指出: 可以将原始图像分成一些大小相等的图像块,采用相同的观测矩阵单独对每个图像块进行观测,大大简化了计算复杂度,这种方法能解决大尺度图像实时传输的问题。分块图像的观测矩阵远远小于未分块的图像,降低了对硬件的需求,利用PC端将采集的样本重构恢复,并实现图像融合。
    本实验利用MATLAB R2016a作为平台,对每一个子块采用小波变换,保留每块的低频小波稀疏,对高频小波稀疏进行采样得到测量向量。13重构时利用正交匹配追踪(OMP) 算法对高频系数进行恢复,再进行小波反变换重构图像。
    实验步骤:
    选取大小为256 × 256的二维图像,将图像分为16块大小为64 × 64的图像;
    采用小波变换对图像进行稀疏化表示,利用50 × 64的观测矩阵进行观测得到观测向量;
    采用OMP算法对观测向量进行重构恢复;
    对重构的恢复矩阵进行小波反变换,得到重构图像。
    实验结果如图(9)所示
    在这里插入图片描述
    在这里插入图片描述

    为了比较几种算法的恢复精度,在固定的稀疏度12下对上述算法进行实验,实验信号为定常信号256 × 1的列向量,观测随着观测矩阵行数M的数目变化对一维信号恢复正确率的变化,实验中对每次M的取值实验100次,计算恢复率,信号之间的误差达到10 即视为正确,M的取值为从稀疏度K每次增加十个直到观测矩阵列数256。实验结果如下图所示(10)所示

    图(10)为四种算法随着测量值M取值的不同,恢复值百分数变化
    图中可以看出ROMP算法到达较高的精确度所需要的观测矩阵行数较其余的算法高,压缩量较低。SAMP算法在稀疏度未知的情况下,由较小的测量值得到恢复精确度较高。
    4.总结
    压缩感知利用信号稀疏的特性将原来基于奈奎斯特采样定理的信号采样过程转化为基于优化计算恢复信号的观测过程。有效缓解了高速采样实现的压力,减少了处理、存储和传输的成本,使得用低成本的传感器将模拟信息转化为数字信息成为可能,同时压缩感知使得信号的恢复率理论上比传统压缩算法更加精准。
    研究还存在如下问题:
    (1)对于一个稳定的优化算法,是否存在最优的观测矩阵使得观测值在达到一定的精度范围而观测数目控制在较少的范围。
    (2)如何设计有效的软硬件来应用压缩感知理论解决大量的实际问题,这方面的研究还不成熟。
    (3)含噪信号或采样过程中引入噪声时的信号重构问题也是难点所在。
    5.参考文献
    [1] 石光明, 刘丹华, 高大化等. 压缩感知理论及其研究进展[D]. 2009.
    [2] 李卓凡, 闫敬文. 压缩感知及应用[J]. 微计算机应用, 2010, 31(03): 12–16.
    [3] 李珅, 马彩文, 李艳等. 压缩感知重构算法综述[J]. 红外与激光工程, 2013, 42(S1): 225–232.
    [4] 吴赟, 丛琳. 压缩感知测量矩阵的研究[D]. 西安电子科技大学, 2012.
    [5] DONOHO D L. Compressed sensing[J]. IEEE Transactions on Information Theory, 2006, 52(4): 1289–1306.
    [6] NEEDELL D, VERSHYNIN R. Signal Recovery From Incomplete and Inaccurate Measurements Via Regularized Orthogonal Matching Pursuit[J]. Ieee Journal of Selected Topics in Signal Processing, 2010, 4(2): 310–316.
    [7] 杨真真, 杨震, 孙林慧. 信号压缩重构的正交匹配追踪类算法综述[J]. 信号处理, 2013, 29(04): 486–496.
    [8] TROPP J A, GILBERT A C. Signal Recovery From Random Measurements Via Orthogonal Matching Pursuit[J]. IEEE Transactions on Information Theory, 2007, 53(12): 4655–4666.
    [9] 汪浩然, 夏克文, 牛文佳. 分段正交匹配追踪(StOMP)算法改进研究[J]. 计算机工程与应用, 2017, 53(16): 55–61.
    [10] DO T T, GAN L, NGUYEN N等. Sparsity adaptive matching pursuit algorithm for practical compressed sensing[C]//2008 42nd Asilomar Conference on Signals, Systems and Computers. 2008: 581–587.
    [11] 杜秀丽, 胡兴, 顾斌斌等. 基于变步长的正则回溯SAMP压缩感知重构算法[J]. 计算机应用研究, 2018, 35(04): 1084–1087.
    [12] FU Y, LIU S, REN C. Adaptive Step-Size Matching Pursuit Algorithm for Practical Sparse Reconstruction[J]. Circuits Systems and Signal Processing, 2017, 36(6): 2275–2291.
    [13] 曹玉强, 柏森, 曹明武. 图像自适应分块的压缩感知采样算法[J]. 中国图象图形学报, 2016, 21(04): 416–424.

    展开全文
  • 根据访问控制策略中的操作类型、主体属性、客体属性和环境属性将基于属性的访问控制策略划分为多个不相交的原子访问控制规则,并通过与、或等逻辑关系构成的代数表达式,将原子访问控制规则重构出复杂访问控制策略;...
  • 具有轻量级运行时的原子CSS-in-JS 背景故事 设计系统包含面向组件的思维方式。 受启发,实用程序类提供了可重用的样式,而没有任何不良的副作用。 但是,必须先生成它们。 原子性通过按需实例化样式规则来概括前一...
  • 来自同一合成批次的纳米晶体通常在尺寸、晶格畸变和缺陷方面具有很大的差异,精确测定单个纳米晶体的三维原子结构是了解和预测其物理性质的前提。本文作者通过开发了的具有原子分辨率的3D液体池电子显微镜,展现了由...
    来自同一合成批次的纳米晶体通常在尺寸、晶格畸变和缺陷方面具有很大的差异,精确测定单个纳米晶体的三维原子结构是了解和预测其物理性质的前提。本文作者通过开发了的具有原子分辨率的3D液体池电子显微镜,展现了由单个批次合成的具有关键结构差异的Pt纳米晶的高分辨率3D原子排列。得到的结构信息能够为今后改进合成和理解当前材料的性能提供重要的新指导。

    精确测定单个纳米晶体的三维(3D)原子结构是了解和预测其物理性质的前提。但来自同一合成批次的纳米晶体通常显示出很小差异,但在尺寸、晶格畸变和缺陷方面具有很大的差异,而且这些差异只有通过具有高空间3D分辨率的结构表征才能够被理解。

    基于此,来自于韩国基础科学研究院Jungwon Park教授,澳大利亚莫纳什大学Hans Elmlund教授和美国劳伦斯伯克利国家实验室 Peter Ercius(共同通讯作者)利用微纳加工制备的微流芯片作为液体池(liquid-cell),制备了具有原子分辨率的3D液体池电子显微镜(SINGLE)研究了单个Pt纳米晶的结构,揭示了Pt纳米晶在液相中的内在异质性,包括结构退化、晶格参数偏差、内部缺陷和应变等。由此引发的这些结构上的差异导致了对自由能的产生了巨大贡献,在任何关于纳米晶性质或应用中应该引起足够的重视。相关论文以题为“Critical differences in 3D atomic structure of individual ligand-protected nanocrystals in solution”发表在2020年4月3日出版的《Science》上。

    论文链接

    https://science.sciencemag.org/content/368/6486/60

    2eb2879030a2a45f0d4a0fb8e59dc36d.png

    众所周知,材料的3D原子排列决定了其物理和催化性质。但由于表面悬空键、缺陷和位错的存在,以及有限尺寸引起的内在量子效应,纳米晶的3D结构通常会偏离其整体对应的周期性原子排列,尤其是在直径小于4nm的小纳米晶体中表现得更为突出。正因为如此,这些独特的物理性质使纳米晶体在多相催化剂方面具有极大的吸引力。同时由于在单个纳米晶体的合成水平上很难得到均匀的控制,因此合成的纳米晶的总体倾向于具有异质原子结构。此外,典型胶体合成中的有机配体和溶剂会调控表面原子,从而进一步影响纳米晶体的晶体结构和电子结构。因此,基于大多数催化和反应都发生在液相中的事实,从液相直接测定单个原子在单晶水平上的位置对于更深层次理解其独特性质必不可少。

    纳米晶体的3D原子结构可以通过电子断层成像技术确定,同时通过倾斜系列透射电子显微镜(TEM)图像重构这些结构。然而,该方法依赖于真空和衬底上的图像采集,将会导致纳米晶的结构变形。此外,由于投影方向的缺失,空间分辨率在3D空间中往往液是不均匀的。其中,基于Cryo-TEM的单粒子重构作为一种替代方法实际上也不适合研究异质纳米晶体,因为该分析严重依赖于从假设结构相同上收集的不同粒子的2D图像。在之前的研究中,通过3D SINGLE(石墨烯液体池电子显微镜对纳米粒子结构的鉴定)作为解决溶液中纳米晶的3D结构的直接方法,但所得到的分辨率仅足以确定3D的整体形貌,对如何分析这些信息以提取关键结构因素的理解仍然有限。

    在本文中,作者基于“布朗单粒子重构”的方法,设计了一种具有原子分辨率3D SINGLE,并将其应用于分析溶液中单个Pt纳米晶的3D原子排列。同时从来自同一合成批次和拟合的原子模型中得到的8个单个Pt纳米晶的高分辨率3D密度图显示了具有结构异质性的fcc结构,包括单晶性、畸变和位错。此外,3D原子位置的精确分布(±19pm)的特性使得能够直接研究晶格膨胀、内部缺陷、表面和位错面附近的应变以及它们对自由能的贡献。研究结构表明,在基于SINGLE方法的实际溶液中得到的结构信息能够为今后改进合成和理解当前材料的性能提供重要的新指导。

    7647f5997f1ce971410b8e64c0a41eae.png

    图1. 液相中Pt纳米晶的原子分辨率3DSINGLE。(A-C)8个单独的纳米晶的高分辨率3D密度图,原子位置图和应变(εxx)图;(D) 粒子4的应变(εxx)图像。

    7a7af276bbd0fdb32c67904a019dafb3.png

    图2.单晶Pt纳米晶的原子结构分析。(A-C)3D密度图和粒子4沿[100]、[110]和[111]轴的原子位置;(D)纳米晶体的结构;(E)六种不同尺寸的纳米晶沿<110>(红色)、<100>(黑色)和111>(蓝色)方向的原子层间距。

    4424b5f6d8846ca7c2cf857b14e779d1.png

    图3. 从三维原子图谱推断出的Pt纳米晶对尺寸依赖性。(A,B) 六种不同尺寸单晶的晶格参数和平均径向应变值;(C)XRD图谱;(D)在真空环境中利用原子坐标计算重构Pt纳米晶的形成能;(E,F)PVP配体在五个不同面的Pt表面的结合模式及其电荷密度分布;(G)六种单晶粒子的径向应变图。

    d4fa0e5c8de08afacf1f19af37380d5b.png

    图4.具有复杂结构的纳米晶3D结构分析。(A-C)畸变纳米晶体3D结构分析(粒子7);(D-F)位错纳米晶体的3D结构分析(粒子8)。

    91a73c80f71ce531f2913640d30bdfe9.png

    图5. Pt纳米晶3D应变张量分析。(A)单晶粒子(粒子4)应变张量六个分量的切片图;(B)粒子4的所有原子(顶部)、核心原子(中间)和表面原子(底部)的应变张量的直方图;(C)具有畸变晶格粒子的应变张量的六个分量的切片图(粒子7);(D)粒子7的所有原子(顶部)、核心原子(中间)和表面原子(底部)的应变张量的直方图。

    总之,作者通过开发的具有原子分辨率的3D SINGLE,展现了由单个批次合成的具有关键结构差异的Pt纳米晶的高分辨率3D原子排列。同时原子分辨率3D SINGLE也能够应用于各种组成的纳米晶,包括胶体纳米材料和生物大分子。(文:Caspar)

    本文来自微信公众号“材料科学与工程”。欢迎转载请联系,未经许可谢绝转载至其他网站。

    展开全文
  • 图像融合算法(像素级)

    万次阅读 多人点赞 2019-10-25 09:26:06
    数字图像分离处理主要是通过利用信号和图像的成分来对信号和图像进行分析,主要有主成分分析、次成分分析、态成分分析等,人们认为,主要在信号重构和压缩、以及稀疏成分分析和独立成分分析、形抑制噪声和特征提取等...
  • 利用正交匹配追踪算法对高光谱图像进行压缩感知重构,是通过寻找最优原子对原始信号进行线性表示,使残差不断减小以获取重构信号。在处理基于冗余字典的重构问题时,其耗时主要存在于原子匹配过程和残差更新过程,导致...
  • SpringCloud

    千次阅读 2019-11-18 08:54:06
    SpringCloud 作者:小阳 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ia5iSekQ-1574038415836)(D:\TinkingCat\SpringCloud\assets\1571138581444.png)] 微服务介绍 ...
  • 压缩采样匹配追踪(CoSaMP)算法是一种有效的压缩感知重构算法,针对其每次迭代选择与去除原子的原则不同导致支撑集估计不够准确,提出一种压缩采样硬阈值追踪重构算法。该算法去除原子时结合硬阈值追踪(HTP)算法...
  • 【数据库学习】数据库总结

    万次阅读 多人点赞 2018-07-26 13:26:41
    2)范式 各个范式联系: 5NF⊂4NF⊂BCNF⊂3NF⊂2NF⊂1NF ①1NF(满足最低要求的范式:字段不可再分,原子性) 如果一个关系模式R的所有属性都是不可分的基本数据项,则R∈1NF。 自我理解1NF就是无重复的列。 如:...
  • 针对原子力显微镜(AFM)纳米成像中存在的失真问题,研究了通过探针建模实现AFM扫描图像重构方法.目前探针盲建模算法在重构AFM图像时存在较大误差,因此提出基于探针模型预估计的AFM扫描图像重构方法.该方法采用分区...
  • 该方法构建相关原子库,并将原子离散的参数连续化,能减少重构信号所需的原子数并使分解结果更准确;针对频率范围较大的谐波、衰减振荡等信号,采用快速傅里叶变换对最优原子频率进行预求解,从而降低原子库规模;...
  • 数据库面试

    千次阅读 多人点赞 2019-02-13 09:03:42
    原子性Atomicity,指事务由原子的操作序列组成,所有操作要么全部成功,要么全部失败回滚。 一致性Consistency,指事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行之前和执行之后,数据库都必须处以...
  • 重构设计模式_重构设计

    千次阅读 2020-06-28 13:03:58
    在“ 测试驱动的设计,第1部分 ”和“ 测试驱动的设计,第2部分 ”中,我介绍了测试如何为新项目带来更好的设计。... 在他的经典著作《 重构》中 ,马丁·福勒(Martin Fowler)将重构定义为“一种...
  • 重构地震信号时,根据油气响应特征、地质现象 描述的需求,先对原子函数库进行筛选、优化,再按照频率属性对 Morlet子波函数进行线性求 和。在对地震信号进行分解与重构的过程中,实现了将地震信号在时间域内、时间-...
  • 《数据库原理》— 数据库系统概论第五版习题解析

    万次阅读 多人点赞 2017-05-29 14:57:48
    数据库系统概论前七章习题解析 第1章绪论 1.试述数据、数据库、数据库系统、数据库管理系统的概念。答: (l)数据(Data):描述事物的符号记录称为数据。数据的种类有数字、文字、图形、图像、声音、正文等。...
  • AAFBP算法的重构过程可分为2个阶段,在前向阶段利用自适应阈值来选取适量原子加入支撑集,在后向回溯过程中以原子的投影系数大小作为删除依据,利用自适应删除阈值来进行原子的删除,同时克服了自适应过程中存在的...
  • 为了分解多分量雷达辐射源信号,提出一种基于级联...仿真实验结果表明,对多分量雷达辐射源信号进行时频原子分解,该方法在重构精度、衰减率和重构信号时频聚集性3个方面均优于单一时频原子库下的时频原子分解方法。
  • 该方法利用相空间重构产生与混沌信号微分同胚的相空间集,采用匹配追踪方法将信号分解为匹配信号结构的时频原子的线性和,达到无损去噪的目的。对Lorenz混沌系统模拟试验表明,该方法具有良好的去噪效果和计算收敛性。...
  • java重复代码重构_重构重复代码

    千次阅读 2020-08-29 18:37:48
    java重复代码重构As a software engineer working on a large project, you’ll likely be asked to do cleanup work on the code to make it more readable and more maintainable. There are several different ...
  • 稀疏度自适应正则回溯匹配追踪算法(SAMP algorithm based on regularized backtracking,SAMP-RB)是一种有效的压缩感知重构算法,在原子选择阶段引入回溯的思想,提高了重构精度,减少了重构时间。但SAMP-RB算法...
  • 本文采用电子断层扫描技术,结合原子级分辨率离子弹道仿真实验,以修正原子探针层析技术的三维重构图像失真。APT三维重构技术能够对样品器件进行详细的化学分析。 在超大规模集成电路上的纳米级晶体管中,特别是...
  • CS重构之CoSaMP

    千次阅读 2017-04-13 21:47:45
    CoSaMP也是对OMP的一种改进,每次迭代选择多个原子,除了原子的选择标准之外,它有一点不同于ROMP:ROMP每次迭代已经选择的原子会一直保留,而CoSaMP每次迭代选择的原子在下次迭代中可能会被抛弃。 在这之前先读了下...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,949
精华内容 5,979
关键字:

原子重构