<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title>ZMonster's Blog</title>
  <link href="http://www.zmonster.me"/>
  <link type= "application/atom+xml" href="http://www.zmonster.me/" rel="self"/>
  <updated>2024-05-13T07:53:45+00:00</updated>
  <id>http://linusp.github.io</id>
  <author>
    <name>Linusp</name>
    <email>linusp1024@gmail.com</email>
  </author>

  
  <entry>
    <title>找工作啦</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2024/05/13/ready-to-work.html"/>
    <category term="" scheme="http://www.zmonster.me/categories.html#"/>
    <id>http://www.zmonster.me/2024/05/13/ready-to-work</id>
    <published>2024-05-13T00:00:00+00:00</published>
    <updated>2024-05-13T00:00:00+00:00</updated>
    <description>
    
      <p>躺平快一年了，准备返工了，也聊了几家，行情不是很好，想了下，把简历脱敏下在博客上也放一份吧，虽然应该概率很小能有看对眼的，但也欢迎来找我聊聊项目和业务，反正几个公司都倒闭了，没啥不能聊的。不过也没有那么想返工，没有合适的就继续躺着或者找家工作内容没什么意思但氛围轻松点的自己业余玩也无所谓。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgea6596e&quot;&gt;个人信息&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgca7924f&quot;&gt;技能清单&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5353ddb&quot;&gt;工作经历&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org64a9733&quot;&gt;北京********有限公司（2021/01～2023/05）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd7c90f6&quot;&gt;****科技发展（北京）有限公司（2016/08～2020/12）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd5f4865&quot;&gt;北京****网络科技有限公司（2015/03～2016/06）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgaeb5874&quot;&gt;****技术（北京）有限公司（2014/03～2015/02）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;
本来还没有去想返工的事情，然后五一前被前领导催简历了，就整理了一下发了过去后面聊了聊。既然都动起来了，索性在五一后也找几个朋友聊了下或者让帮忙做下内推之类的。总体来说现在市场行情并不算好，有 HC 的公司不算多，不过我也没什么太多想法，对于一些更感兴趣的还是会争取一下，网上也还在投投看，不过也就是最近几个星期打算处理一下这个事情，如果月底前没有很满意的，可能就继续躺着或者去我前领导或者同学那里待着了。想了下，把简历脱敏下在博客上也放一份吧，虽然应该概率很小能有看对眼的，如果我的经历里有什么项目和业务觉得感兴趣也欢迎来找我聊聊，反正几个公司都倒闭了，除了客户信息应该没啥不能聊的。工作这么多年，精力都放在公司业务上了，并没有自己去做什么个人项目，好在最近问了下前前司 CTO 得到了同意，准备把陪伴多年的几个文本处理的项目整理一下开源出来，是倾注了我比较多心血的项目，我自认为还是有一些独特价值的。
&lt;/p&gt;

&lt;p&gt;
准备回头把个人经历也整理一下放到 about 页面吧。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgea6596e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgea6596e&quot;&gt;个人信息&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgea6596e&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;（姓名略）/男/1991&lt;/li&gt;
&lt;li&gt;学历: 本科/华中科技大学计算机学院/2013届&lt;/li&gt;
&lt;li&gt;博客: &lt;a href=&quot;https://www.zmonster.me&quot;&gt;https://www.zmonster.me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;联系方式:

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;邮件: &lt;a href=&quot;mailto:contact@zmonster.me&quot;&gt;contact@zmonster.me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;手机: +86 153****6656&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgca7924f&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgca7924f&quot;&gt;技能清单&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgca7924f&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;编程语言: Python | Shell | C | C++&lt;/li&gt;
&lt;li&gt;机器学习工具: scikit-learn | Pytorch | Tensorflow | Numpy | NLTK&lt;/li&gt;
&lt;li&gt;NLP 技能: 文本分类 | 序列标注 | 信息检索 | 对话系统 | 知识图谱 | 信息抽取 | 文本挖掘&lt;/li&gt;
&lt;li&gt;数据库相关: MySQL | Redis | Neo4j | Dgraph&lt;/li&gt;
&lt;li&gt;其他: Linux | Git | Docker | K8S | Django | Elasticsearch&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5353ddb&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org5353ddb&quot;&gt;工作经历&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org5353ddb&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org64a9733&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org64a9733&quot;&gt;北京********有限公司（2021/01～2023/05）&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org64a9733&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;开发基于 LLM 的聊天应用服务（2022/12~2023/05）

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;使用 Django 实现服务，接入 OpenAI 接口，用于在飞书中集成以及之后上线的 toC 聊天应用&lt;/li&gt;
&lt;li&gt;支持了用户自定义 prompt，实现了 RAG 支持用户上传文档数据后基于文档进行问答，并能根据用户设置的 prompt 和上传文档生成机器人名字、欢迎语&lt;/li&gt;
&lt;li&gt;在对话接口中集成 Stable Diffusion 的图像生成功能支持用户在对话界面中生成图片&lt;/li&gt;
&lt;li&gt;以对话接口的形式实现了一些管理功能并接入到飞书，供运营人员查看分析聊天记录、修改机器人 prompt 和知识库、修改用户可用聊天额度等&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;开发金融资讯服务（2021/08～2022/05）

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;使用 Django 实现后端服务进行资讯数据的存储并提供 RESTful API&lt;/li&gt;
&lt;li&gt;使用 K8S 进行部署和运维，服务可以方便地进行水平扩展来提高负载能力&lt;/li&gt;
&lt;li&gt;使用前文所述文本处理框架对金融资讯进行去重、清洗和结构化分析，所得分析结果作为资讯推荐的特征，实现了金融资讯信息流、相关资讯推荐、要闻推荐等服务&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
设计和开发文本处理框架（2021/01～2022/11）
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;对文本处理过程进行抽象，实现了适用大部分文本处理过程、组件化、可扩展性强的框架，开发者可通过自定义组件以及组件与组件的组合实现复杂的自定义文本处理过程&lt;/li&gt;
&lt;li&gt;框架实现后逐步将标准的一些文本处理方法和业务中提炼出来的相对通用的文本处理方法作为组件添加到框架中，目前已集成分词、关键词提取、实体识别、实体融合、文本分类、文本摘要、观点挖掘等领域数十个组件&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
该框架作为基础工具被用于公司金融资讯结构化分析的各项业务中。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd7c90f6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd7c90f6&quot;&gt;****科技发展（北京）有限公司（2016/08～2020/12）&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd7c90f6&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;参与问答系统框架的开发和优化（2019/10～2020/12）

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;重构项目，在不削减功能的前提下将代码量削减 30%，将单元测试覆盖率从 47% 提升至 98%&lt;/li&gt;
&lt;li&gt;制定评估标准，实现评估工具，分析模型的泛化、拒识、抗混淆、多轮对话等各维度能力，以此为依据帮助在不同要求的项目中选择不同算法和参数，减少模型优化所需的人工工作量&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;设计和开发基于知识图谱的推理问答框架（2018/01～2020-02）

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;实现了数据库无关的 library 来读写图数据库，支持 Neo4j/Dgraph&lt;/li&gt;
&lt;li&gt;以 pipeline 架构实现图谱问答框架，各组件可方便的扩展、定制

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;对用户问题先进行实体识别和关系识别&lt;/li&gt;
&lt;li&gt;在实体识别、关系识别的结果上，根据本体结构进行推导得到问题的形式化表达&lt;/li&gt;
&lt;li&gt;将问题的形式化表达转换为图谱查询、计算操作，得到结果&lt;/li&gt;
&lt;li&gt;用预先设计好的答案模板来渲染图谱查询结果，输出回答&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
设计和开发通用的信息抽取框架（2017/06～2020/12）
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;对不同的抽取技术（正则、匹配、序列标注）提供统一的抽取、归一化、校验接口&lt;/li&gt;
&lt;li&gt;提供对已有抽取结果的组合、扩展抽取以进行更复杂的任务&lt;/li&gt;
&lt;li&gt;设计为配置化的使用方式，按照规范写好配置文件即可构造各种抽取器&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
该框架作为基础工具被用于实现实体识别、文档抽取功能及其他信息抽取类业务中。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;设计和开发 PDF 文档解析工具（2018/01～2020/07）

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;使用 PDFMiner 获得基础的 PDF 解析结果，再基于规则和分类器进行内容元素分析&lt;/li&gt;
&lt;li&gt;实现了 PDF 文件中目录、章节标题、列表、页眉页脚、表格、脚注等不同元素的解析&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
构建保险行业知识图谱（2017/12～2020/02）
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;借助前文提到的 PDF 解析工具和信息抽取框架，从保险文档中抽取获得初步的保险知识

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;借助文档解析得到的结构化信息（章节、注释等）及规则实现了大部分简单知识的抽取&lt;/li&gt;
&lt;li&gt;使用 BiLSTM+CRF 模型抽取部分非显式知识，并在数万篇文档上用 ELMO 预训练来提高效果&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;与产品团队共同梳理清楚保险领域知识图谱的本体结构&lt;/li&gt;
&lt;li&gt;以本体结构为指导信息，对文档抽取的结果进行组合、二次抽取得到实体关系，最终形成了十万量级实体、百万量级关系（含属性）的保险领域知识图谱
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;一部分实体及属性直接采用文档抽取结果，其余主要基于规则对抽取结果进行二次抽取&lt;/li&gt;
&lt;li&gt;针对文档抽取结果，实现了一个简单的图谱构建框架，将图谱构建分为实体获取、属性获取、关系获取、融合和链接等步骤，且允许通过配置文件对这几个步骤进行设置和扩展&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;结合基于知识图谱的推理问答框架，实现了一个保险领域的推理问答机器人&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
凭借这份知识图谱及保险问答机器人，公司成功与国内若干家保险公司、保险经纪公司、保险代理公司达成合作。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;设计和开发通用文本分类工具（2017/08～2019/03）

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;预处理、分词、特征提取等过程均支持配置化，大大提高了在中小数据上进行文本分类的效率&lt;/li&gt;
&lt;li&gt;预处理器、分词器、特征提取、分类器等各个模块都可以方便地定制、扩展&lt;/li&gt;
&lt;li&gt;被广泛应用于公司各个项目的意图识别、情感分析、垃圾过滤等文本分类相关的业务中&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
建立通用实体抽取工具（2016/11～2020/12）
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;使用前文提到的信息抽取框架，实现了常用的细分为二十多类实体的抽取&lt;/li&gt;
&lt;li&gt;数字、日期时间等实体的抽取使用正则实现&lt;/li&gt;
&lt;li&gt;人名、地名、组织名的抽取基于已有 NLP 工具的 POS 和 NER 结果，并用自己训练的 BiLSTM+CRF 模型作为补充&lt;/li&gt;
&lt;li&gt;部分特定领域实体的抽取使用词表和 AC 自动机实现&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
该工具作为基础库在公司几乎所有问答项目中被使用，显著提高了各项目实现相关需求时的效率。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
设计和开发相似句/同义词挖掘工具（2017/10～2018/03）
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;使用 LCS、TFIDF+余弦相似、词向量+余弦相似等方法从语料中挖掘相似句子&lt;/li&gt;
&lt;li&gt;使用翻译接口直接生成相似句子&lt;/li&gt;
&lt;li&gt;对相似句子进行文本对齐，从中挖掘同义词数据，中小数据上效果好于直接按词向量挖掘&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
该工具先后用于电商、物业、保险等多个领域的问答项目的初期数据构建，挖掘结果可用率约 30%，在挖掘结果上做 0/1 标注的效率和效果都高于人工直接撰写相似句子、同义词。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
开发订餐对话机器人（2016/11～2017/05）
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;任务式的问答机器人，涉及订餐、查询订单、修改订单、取消订单四个意图及数十个槽位，确定意图后询问用户填充该意图所需槽位&lt;/li&gt;
&lt;li&gt;不直接回答而是产生三个候选答案供客服进行选择，上线后 TOP3 采用率稳定在 30% 左右&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
该项目是公司第一个正式的商业合作项目，且间接或直接催生了通用实体抽取工具、通用文本分类工具、任务式问答框架等多个基础项目。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd5f4865&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd5f4865&quot;&gt;北京****网络科技有限公司（2015/03～2016/06）&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd5f4865&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;开发和优化题库搜索系统（2015/04～2016/03）

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;基于倒排索引实现了一个搜索系统，用于 2000 多万题目的搜索&lt;/li&gt;
&lt;li&gt;Python+Redis 实现，单次搜索耗时 1-2 ms，首位命中率 &amp;gt; 95%&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;开发和优化扫题用的 OCR 系统（2015/06～2015/11）

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;使用 OpenCV 进行二值化、去阴影、倾斜矫正、字符检测和切割等图像处理，使用 Caffe 进行字符识别&lt;/li&gt;
&lt;li&gt;单字识别率达 96%，OCR+题库搜索正确率约 70%&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;开发翻译结果自动评分模块（2016/01～2016/03）

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;对学生提交的翻译结果，和标准答案对比，给出评分&lt;/li&gt;
&lt;li&gt;使用 METEOR 算法，与人工评价之间的 RMSE 约为 1.5（15 分制）&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgaeb5874&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgaeb5874&quot;&gt;****技术（北京）有限公司（2014/03～2015/02）&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgaeb5874&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;研究和实现说话人分割技术（2014/06～2015/01）

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;在大规模语音数据训练出来的人声 GMM 上做最大后验估计得到内容无关的音频特征&lt;/li&gt;
&lt;li&gt;将音频切成小段并去除非人声后，对邻近段落使用层次聚类来区分出不同的说话人&lt;/li&gt;
&lt;li&gt;在两人对话场景下正确率 &amp;gt; 90%，处理时长与音频时长比 &amp;lt; 0.03&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;研究并实现语音与文本融合的多模态情感分析（2014/09～2015/01）

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;混合语音特征和文本特征，使用 SVM 进行分类，正确率 &amp;gt; 90%&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>ZMonster's AI Notes(Alpha) #2：模型汤、推测解码、幻觉的类型与定义、GPT top_logprobs</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2024/02/07/ai_notes_alpha_2.html"/>
    <category term="AI" scheme="http://www.zmonster.me/categories.html#AI"/>
    <id>http://www.zmonster.me/2024/02/07/ai_notes_alpha_2</id>
    <published>2024-02-07T00:00:00+00:00</published>
    <updated>2024-02-07T00:00:00+00:00</updated>
    <description>
    
      <p>从第一期之后拖延了很久，先是花了比较多精力做 2023 年的回顾总结，之后则因为即将过年回家比较焦虑而导致没有办法集中精力，看下过完年后能不能争取专注一些。下一期准备集中了解下幻觉的检测与缓解方法。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgcb07901&quot;&gt;术语&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgeaaa4a2&quot;&gt;模型汤(Model Soup)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org9374eb3&quot;&gt;时间错位(Temporal Misalignment)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgae6b8ea&quot;&gt;推测解码(Speculative Decoding)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org0f5900b&quot;&gt;论文&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgbc3adb7&quot;&gt;实践&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org264b46b&quot;&gt;GPT API 中的 top_logprobs 参数&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
分享最近关于 AI 方面的笔记、想法以及实践记录。本系列内容模式的最终形态尚不确定，可能会根据个人精力、兴趣及阅读反馈做调整，所以称之为试作版。
&lt;/p&gt;

&lt;p&gt;
从第一期之后拖延了很久，先是花了比较多精力做 2023 年的回顾总结，之后则因为即将过年回家比较焦虑而导致没有办法集中精力，看下过完年后能不能争取专注一些。下一期准备集中了解下幻觉的检测与缓解方法。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgcb07901&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgcb07901&quot;&gt;术语&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgcb07901&quot;&gt;
&lt;p&gt;
简单介绍下我最近新了解到的 AI 领域的一些术语，但不做深入探究。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgeaaa4a2&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgeaaa4a2&quot;&gt;模型汤(Model Soup)&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgeaaa4a2&quot;&gt;
&lt;p&gt;
论文&lt;a href=&quot;https://arxiv.org/abs/2203.05482&quot;&gt;《Model soups: averaging weights of multiple fine-tuned models improves accuracy without increasing inference time》&lt;/a&gt; 提出的概念，本质上属于模型合并（Model Merging）的一个方法，作者发现把同一个模型在多个不同下游任务上微调过后的权重进行加权平均（论文中尝试了多种方法如直接平均或者学习加权参数）后，能在新的下游任务上也得到效果的提高（相比未微调的基础模型）。其解释我理解是说两个不同的下游任务在微调时会在损失函数的曲面上走不同的下降路线，加权平均后往往能更接近极值点。
&lt;/p&gt;


&lt;div id=&quot;org150f015&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2024-02-06_11-37.png&quot; alt=&quot;2024-02-06_11-37.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在这个发现的基础上， &lt;a href=&quot;https://arxiv.org/abs/2212.04089&quot;&gt;《Editing Models with Task Arithmetic》&lt;/a&gt; 这篇论文进一步发现微调模型与基础模型之间的权重差（论文中称之为任务向量）具有语义，微调过后的模型可以通过减去这个权重来遗忘这个任务，不同任务的任务向量相加也能获得一个综合了多个任务能力的新模型。
&lt;/p&gt;


&lt;div id=&quot;orgdbb1036&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2024-02-06_11-42.png&quot; alt=&quot;2024-02-06_11-42.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org9374eb3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org9374eb3&quot;&gt;时间错位(Temporal Misalignment)&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org9374eb3&quot;&gt;
&lt;p&gt;
&lt;a href=&quot;https://arxiv.org/abs/2111.07408&quot;&gt;《Time Waits for No One! Analysis and Challenges of Temporal Misalignment》&lt;/a&gt; 等一些论文里发现用时间段 A 内训练的大模型在另外的时间段 B 上效果会不好，反映到现实中的大模型表现就是其效果会随时间变化而慢慢在新的文本上效果变差，看起来好像是退化一样 —— 其实不能说是退化，只是人们使用的语言一直在变化，如果要让模型始终保持稳定的表现就需要持续地使用新的数据去进行训练微调。
&lt;/p&gt;


&lt;div id=&quot;orgfbbec4a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2024-02-06_12-05.png&quot; alt=&quot;2024-02-06_12-05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
之后 2023 年的论文 &lt;a href=&quot;https://arxiv.org/abs/2312.13401&quot;&gt;《Time is Encoded in the Weights of Finetuned Language Models》&lt;/a&gt; 进一步发现，模型的能力在不同年份之间会变差，但相近时间段文本训练的模型效果也会接近，并借鉴前面「模型汤」一节中提到的任务向量的概念，提出了时间向量，发现将两个不同的时间向量进行插值（其实也是加权平均）可以使模型在这两个时间段之间的时间段效果变好，认为可以用不同时间段的文本数据进行微调后得到一个个时间向量然后在有需要的时候混合起来，以低成本地改善任意时间段的模型效果，将这种思路称之为「时间汤」，当然最后也承认这种做法效果还是比不上完整收集所有时间段的数据统一进行训练，不过我个人认为还是很有用的，现在有很多开源的语言模型，借鉴这个思路可以在已有的模型上低成本地进行改进。
&lt;/p&gt;


&lt;div id=&quot;orge0943b6&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2024-02-06_12-50.png&quot; alt=&quot;2024-02-06_12-50.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgae6b8ea&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgae6b8ea&quot;&gt;推测解码(Speculative Decoding)&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgae6b8ea&quot;&gt;
&lt;p&gt;
Google Research 在论文 &lt;a href=&quot;https://arxiv.org/abs/2211.17192&quot;&gt;《Fast Inference from Transformers via Speculative Decoding》&lt;/a&gt; 中提出的一种语言模型生成加速的方法，说是受 CPU 里的分支预测技术的启发，其基本思想是基于模型越大生成每一个 token 时越慢这个状况，引入一个更小更快的草稿模型，让草稿模型来去生成 token 然后让更大的模型去决定是否要接受这个 token，只有草稿模型的生成被认为不够好被拒绝时，才用更大的模型自己去生成 token。按照论文里的不同设置，最高的时候能够以原来不使用草稿模型的生成方法的 6 倍多的速度来完成整个生成过程。
&lt;/p&gt;


&lt;div id=&quot;org8731a45&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2024-02-06_18-12.png&quot; alt=&quot;2024-02-06_18-12.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
另外 DeepMind 也有一篇论文 &lt;a href=&quot;https://arxiv.org/abs/2302.01318&quot;&gt;《Accelerating Large Language Model Decoding with Speculative Sampling》&lt;/a&gt; 讲推测解码的，不过论文里说明了和前面的这篇论文是相同的思路。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0f5900b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org0f5900b&quot;&gt;论文&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org0f5900b&quot;&gt;
&lt;p&gt;
写完第一期之后，我选择了幻觉（hallucination）这个主题，决定去梳理清楚这几个问题：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;目前 LLM 中经常被提的幻觉的定义是什么？&lt;/li&gt;
&lt;li&gt;幻觉都有哪些类型？&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
作为一个新兴的概念，幻觉这个术语目前并没有非常一致的共识和清晰的定义，从看到的论文里来看，有一些会尝试先给出相对严格的整体性定义和描述，再仔细区分其中的不同类型，有的则对整体定义一带而过只具体描述了几种类型，另外还有大量在不同子领域分析幻觉现象的工作，其中的幻觉定义和分类就更加繁杂了，我尽量先了解了下任务不相关的幻觉定义及其分类。
&lt;/p&gt;

&lt;p&gt;
Ziwei Ji 的 &lt;a href=&quot;https://arxiv.org/abs/2202.03629&quot;&gt;《Survey of Hallucination in Natural Language Generation》&lt;/a&gt; 这篇论文是目前我读到的对幻觉的定义比较通用和清晰的，也是我看的各种幻觉相关的论文里被引用的比较多的，有很多关于幻觉的论文自己不想做定义就直接引用下这篇论文。
&lt;/p&gt;

&lt;p&gt;
这篇论文先从心理学上「幻觉」的定义出发，引用了 Blom 在《A Dictionary of Hallucinations》一书中给的定义：
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
In the general context outside of NLP, hallucination is a psychological term referring to a particular type of perception. Blom define hallucination as “a percept, experienced by a waking individual, in the absence of an appropriate stimulus from the extracorporeal world”.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
这个定义里有几个要点：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;没有外部刺激&lt;/li&gt;
&lt;li&gt;但人脑仍产生了类似有外部刺激时的感受&lt;/li&gt;
&lt;li&gt;并且这种感受可以很真实&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
借鉴心理学上的定义，Ziwei Ji 给了关于幻觉的定义：
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
The generated content that is nonsensical or unfaithful to the provided source content.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
简单来说，就是模型生成了无意义的文本或者不忠实于指定信息或知识的文本，也就是网络上大家调侃的「一本正经地胡说八道」。此外论文里还有一些幻觉文本的特点的描述，比如说这种文本在表达上一般都很流畅，看起来似乎也是基于某种真实的语境或者背景知识，但往往这种背景知识并不存在或者是错误的。
&lt;/p&gt;

&lt;p&gt;
不过需要注意的是，Ziwei Ji 的定义里有一个「source content」，具体来说：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;对摘要任务来说，source content 是指待进行总结的文本&lt;/li&gt;
&lt;li&gt;对翻译任务来说，source content 是指待进行翻译的源语言文本&lt;/li&gt;
&lt;li&gt;对多轮对话来说，source content 是指对话历史中与当前消息有关的消息&lt;/li&gt;
&lt;li&gt;对检索式问答来说，source content 是指根据用户输入检索到的问答对语料数据&lt;/li&gt;
&lt;li&gt;对 data-to-text 来说，source content 是指给定的结构化数据&lt;/li&gt;
&lt;li&gt;……&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
那开放式问答这种没有提供上下文的情况，所谓 source content 应该指什么呢？论文里为了保持一个统一的定义，就说这个时候的 source content 应当是世界知识（world knowledge），不过所谓的世界知识又怎么定义就没再提了，虽然看起来是将问题转移了，但比起其他一些论文里不加说明就使用某些假设的做法来说已经好很多了。
&lt;/p&gt;

&lt;p&gt;
在关于幻觉的文献里，经常会在提到幻觉时一起提到忠实性（faithfullness）和事实性（factualness）这两个词，不同论文对这三个概念的使用其实还挺混乱的，Ziwei Ji 也在论文里对这三个概念做了阐释和区分（这也是我喜欢这篇论文的原因，别的很多论文都是一副理所当然的样子把这三个词拿出来用）。在 Ziwei Ji 看来，忠实性是说当我们给定一些信息或知识（注意，用户有可能有意或无意给一些错误的知识）时模型是否能在生成结果时与其保持一致，而事实性则是能否与现实中的事实保持一致，而一些关于幻觉的论文粗暴地将提供给模型的信息或知识当作「事实」（或者说用 fact 这个词来描述给定的信息）就造成了忠实性和事实性两个概念的混淆，而 Ziwei Ji 的做法就是用「世界知识」这个词来代替「事实」以避免混淆，将「世界知识」也作为一个 source content，这样也获得了一个统一的定义。虽然看起来有点文字游戏，但明确地划定词语的界限是很有必要的。
&lt;/p&gt;

&lt;p&gt;
在上述定义的基础上，Ziwei Ji 给出了两个幻觉的子类型定义，分别是：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;内在幻觉（Intrinsic Hallucinations）：指生成的文本与 source content 矛盾、不一致，比如说做摘要明明原文说了「The first vaccine for Ebola was approved by the FDA in 2019」但生成的摘要里却说「The first Ebola vaccine was approved in 2021」&lt;/li&gt;
&lt;li&gt;外在幻觉（Extrinsic Hallucinations）：指生成了与 source content 无关的内容，用给定的 source content 无法验证它是对的还是错的，比如说做翻译的时候，原文是「迈克周四去书店」，按理说应该翻译成「Michael went to the bookstore on Thursday」，结果得到的结果是「Michael happily went to the bookstore with his friend」，这个「happily」和「with his friend」就是外在幻觉 —— 当然，从翻译任务上来说我们当然可以说它是错的，但前面说的「用给定的 source content 无法判断它是对的还是错的」是考虑任务无关的情况的&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
这个分类和其他一些论文里将幻觉分为忠实性幻觉和事实性幻觉是不一样的，在 Ziwei Ji 这个分类里，内在幻觉有些是忠实性的（当为翻译、摘要等任务时）有些是事实性的（当为开放问答即 source content 是世界知识时），而外在幻觉是指多出来一些无关的内容（当然这个无关具体如何定义和评估又是一个值得讨论的问题），这些内容未必是事实错误的甚至未必是一种错误。有些论文里将幻觉和错误混为一谈在读的时候也让人感到混乱，如果将所有错误都称之为幻觉，那这个新的词也就没有必要存在了。
&lt;/p&gt;

&lt;p&gt;
之后，Yue Zhang 等人在论文 &lt;a href=&quot;https://arxiv.org/abs/2309.01219&quot;&gt;《Siren's Song in the AI Ocean: A Survey on Hallucination in Large Language Models》&lt;/a&gt; 中使用了 Ziwei Ji 对幻觉的定义，并在 Ziwei Ji 的分类基础上基于自己的认识将幻觉分成了三类：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;输入冲突幻觉（Input-Conflicting Hallucination）：和 Ziwei Ji 的内在幻觉的定义基本是一样的&lt;/li&gt;
&lt;li&gt;上下文冲突幻觉（Context-Conflicting Hallucination）：指模型在生成长文本或多次生成时的前后不一致，比如说在生成一个小故事的时候先在开头生成了「小明今年15岁」然后到结尾的时候又生成了「13岁的小明表示看不懂但大受震撼」，从模型运作的方式上来说，前面生成的内容其实也在后面生成的时候充当输入角色了，算是对内在幻觉的一个扩展吧&lt;/li&gt;
&lt;li&gt;事实冲突幻觉（Fact-Conflicting Hallucination）：即生成的内容与世界知识、现实中的事实不相符的情况&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Yue Zhang 引用了 Ziwei Ji 对幻觉的定义，但他又直接忽略了外在幻觉这个类型，三个分类其实都可以算在 Ziwei Ji 的内在幻觉这个类型下面，这个也可以理解，毕竟外在幻觉的情况其实有些模糊，在实际操作中并不是特别好进行界定。
&lt;/p&gt;

&lt;p&gt;
然后，Hongbin Ye 等人的论文 &lt;a href=&quot;https://arxiv.org/abs/2309.06794&quot;&gt;《Cognitive Mirage: A Review of Hallucinations in Large Language Models》&lt;/a&gt; 也引用了 Ziwei Ji 的定义，但没有像 Yue Zhang 一样尝试去做幻觉的类型划分，而是收集了各个具体任务中的幻觉定义和类型划分的工作，如果想要了解特定任务而非任务无关的幻觉的定义和分类，这篇论文是一个非常不错的入口。限于个人精力我暂时没有去对里面罗列的各种其他论文去做了解，等有需要了再说吧。
&lt;/p&gt;


&lt;div id=&quot;org63f6dee&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2024-02-06_21-15_2.png&quot; alt=&quot;2024-02-06_21-15_2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
接着，Lei Huang 等人的综述性论文 &lt;a href=&quot;https://arxiv.org/abs/2311.05232&quot;&gt;《A Survey on Hallucination in Large Language Models: Principles, Taxonomy, Challenges, and Open Questions》&lt;/a&gt; 也基于 Ziwei Ji 的定义给出了自己的二级幻觉分类：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;事实性幻觉

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;事实不一致（Factual Inconsistency）：指生成结果里有与已知事实不一致的的错误生成结果，认为这个是最常见的&lt;/li&gt;
&lt;li&gt;事实编造（Factual Fabrication）：指生成结果里一些陈述，这些陈述用已知的事实无法验证、或者说已知的事实 —— 话说回来，编造的事实能称之为「事实」么，这种用词就让人觉得比较混乱&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;忠实性幻觉

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;指令不一致（Instruction Inconsistency）：指模型没有遵循用户的任务指令去做了别的事情，比如让翻译结果因为待翻译的内容是一个问句就去回答这个问句了&lt;/li&gt;
&lt;li&gt;上下文不一致（Context Inconsistency）：指生成结果单纯和输入中的内容不一致的情况，和 intrinsic hallucination、input-conflicting hallucination 是一个意思，但用的是 context 这个词……&lt;/li&gt;
&lt;li&gt;逻辑不一致（Logical Inconsistency）：指在做逻辑推理时，生成的推理步骤之间不一致或者推理步骤和最终结果不一致的情况，可以算作 Yue Zhang 分类里上下文冲突幻觉的一个特例&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Lei Huang 的分类我是觉得有点问题的：首先指令不一致有专门的工作即指令追随（Instruction Following），我认为这是一种混淆错误与幻觉的行为，而作者在论文里给出这个分类的理由居然说是考虑现在 LLM 非常以用户为中心需要重点考虑和用户保持一致，我觉得不太能说服我；此外，为什么加入逻辑不一致这个分类，也没做什么解释，大概也是认为逻辑推理能力现在研究比较热门？如果是一篇专门讲逻辑推理中幻觉问题的论文，我觉得没什么问题，但这篇论文又标榜自己是个综述，就感觉这样做不太合适。
&lt;/p&gt;

&lt;p&gt;
除了上述基本都基于 Ziwei Ji 给的定义来进行定义扩充或分类细化的工作外，也有一些明确提出定义标准的，目前我看到说得比较清楚的是 Ayush Agrawal 等人在其论文 &lt;a href=&quot;https://arxiv.org/abs/2305.18248&quot;&gt;《Do Language Models Know When They're Hallucinating References?》&lt;/a&gt; 所给出的定义：
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
We define hallucination to be fabricated text, meaning text that is not grounded in this training set. In contrast, correctness is evaluated with respect to ground-truth answers.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
也就是说，在 Ayush Agrawal 的定义里，所谓的幻觉是指生成结果中无法在训练数据中找到依据的杜撰文本。这个定义就把「事实性」「正确性」这些特别宽泛模糊很难界定的概念完全排除出去了，作者也明确说认为幻觉未必就是事实上不正确的，比如说训练数据里提到说人脑只开发了 10% 虽然它是错误的，但基于这样的训练数据训练出来的模型如果生成了相关的文本，那么就不能称之为为幻觉，并认为现在很多讨论幻觉的工作把 groundedness （不知道该怎么翻译，在这篇论文里的语境里就是指在训练数据中存在相关的文本这个意思）和 correctness 也就是正确性混为一谈。
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
Much work on hallucination conflates groundedness and accuracy, often equating hallucination with fallacy and evaluating hallucinations using accuracy on fact-based assessments, without regard to the training data. We adopt the groundedness definition of hallucination even though it may often be less clear-cut and more difficult to evaluate than factuality.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
这个定义相比 Ziwei Ji 的定义做了非常强但也很明确的约束，可能未必符合大众的认知和期望，但我还蛮喜欢这个定义的，清晰明确便于进行评估。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgbc3adb7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgbc3adb7&quot;&gt;实践&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgbc3adb7&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org264b46b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org264b46b&quot;&gt;GPT API 中的 top_logprobs 参数&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org264b46b&quot;&gt;
&lt;p&gt;
在之前，OpenAI GPT 的 LLM API 分为 &lt;a href=&quot;https://platform.openai.com/docs/api-reference/completions&quot;&gt;Completions&lt;/a&gt; 和 &lt;a href=&quot;https://platform.openai.com/docs/api-reference/chat&quot;&gt;Chat&lt;/a&gt; 两个，其中 Completions 接口能使用 text-davinci-003 等更旧的 GPT-3 模型，而 Chat 接口则可以使用 gpt-3.5-turbo 和 gpt-4 等更新的模型，但我一直都很喜欢 Completions 接口，因为这个旧的接口提供一个 logprobs 参数，可以输出模型给每个 token 的概率，甚至还能输出每一个 token 时的 topn 的其他 token 及概率，这就使得我可以利用它来计算给定 prompt 或者输出的困惑度（perplexity） ，用来做简单的效果评估，或者也可以通过每一步输出的 topn 结果进行组合在一次调用里生成多个结果（对输出非步骤性列表比如说帮忙起名字的任务来说很有用的），In-Context Learning 里一些用来判断模型是否存在 bias （比如说做情感分类的时候发现给定一个空输入的时候也会倾向于预测为 positive）并基于这个 bias 的偏离概率去做校准的工作也需要能得到每个 token 的概率……但长期以来能使用更新更好模型的 Chat 接口都没有支持这个参数，也不知道 OpenAI 在干什么。
&lt;/p&gt;

&lt;p&gt;
这几天去翻了下 API 说明发现 Chat 接口已经支持输出每个 token 的概率以及 topn 的 token 及概率了，看了下 &lt;a href=&quot;https://platform.openai.com/docs/changelog&quot;&gt;Changelog&lt;/a&gt; 是在 2023-12-15 的更新里加上的，不过和旧的 Completions 接口有一点区别：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;logprobs 参数用来设置是否要返回 token 的概率&lt;/li&gt;
&lt;li&gt;top_logprobs 参数则用来设置要返回最好的几个 token 及其概率，最大值是 5&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
不过美中不足的是，原先 Completions 接口还有个 echo 参数当设置为 true 的时候会在输出结果里带上输入 —— 不是说将输入的内容重新生成了一遍，只是将输入内容附加到输出内容前面，有了这个参数才能获得输入中每个 token 的概率用来计算 prompt 的困惑度，但这个参数在 Chat 接口中仍然没有支持。
&lt;/p&gt;

&lt;p&gt;
把之前自己利用 Completions 接口的 logprobs 参数做困惑度计算（如前面所说 Chat 接口只能计算生成结果的困惑度无法计算 prompt 的困惑度）和多个结果生成的脚本改了下，放到 &lt;a href=&quot;https://gist.github.com/Linusp/9b4e72c6b4d41d22917ff97bb35c1f09&quot;&gt;gists&lt;/a&gt; 了，这里就不展示代码了，只来展示一下运行效果。
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
获得生成结果的困惑度
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;python playgpt.py --model gpt-3.5-turbo &lt;span style=&quot;color: #16a085;&quot;&gt;\&lt;/span&gt;
       --proxy &lt;span style=&quot;color: #16a085;&quot;&gt;'http://localhost:8888'&lt;/span&gt; &lt;span style=&quot;color: #16a085;&quot;&gt;\&lt;/span&gt;
       --max-tokens 128 &lt;span style=&quot;color: #16a085;&quot;&gt;\&lt;/span&gt;
       --temperature 0 &lt;span style=&quot;color: #16a085;&quot;&gt;\&lt;/span&gt;
       --prompt &lt;span style=&quot;color: #16a085;&quot;&gt;'&amp;#26691;&amp;#33457;&amp;#27739;&amp;#26159;&amp;#20160;&amp;#20040;&amp;#65311;'&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
得到的结果是：
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org5a17146&quot;&gt;
PROMPT:
    桃花汛是什么？

RESULT:
    桃花汛是指中国古代文学中的一个典故，也是指桃花开放时期的洪水。根据传说，每年春天桃花盛开时，河水会因为桃花的美丽而上涨，形成洪水。这种洪水被称为桃花汛。桃花汛在文学作品中常常被用来比喻美好的事物或者美

CANDIDATE RESULTS(With PPL):
    TEXT: '桃花汛是指中国古代文学中的一个典故，也是指桃花开放时期的洪水。根据传说，每年春天桃花盛开时，河水会因为桃花的美丽而上涨，形成洪水。这种洪水被称为桃花汛。桃花汛在文学作品中常常被用来比喻美好的事物或者美', PPL: 1.386107427324887

Usage:
    prompt_tokens: 18
    completion_tokens: 128
    total_tokens: 146
&lt;/pre&gt;

&lt;p&gt;
temperature 参数不为 0 时，模型输出的结果在未必会在 top_logprobs 结果里输出 —— 这也可以理解，毕竟当 temperature 大于 0 时将会进行概率采样，是有可能选中 topn 之外的 token 的，所以我写的这个示例，只有在 temperature 设置为 0 时才可以稳定获得结果的困惑度，如果设置不为 0 有时候是会没有困惑度结果的。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
一次生成多个名字
&lt;/p&gt;

&lt;p&gt;
PROMPT: 起一个女性名字，姓刘，名字要和月亮有关，但不要直接用月字，尝试根据一些古诗词里的典故，使用较常见而不是冷僻的字，只输出名字无需其他。结果是：刘
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;python playgpt.py --model gpt-3.5-turbo &lt;span style=&quot;color: #16a085;&quot;&gt;\&lt;/span&gt;
       --proxy &lt;span style=&quot;color: #16a085;&quot;&gt;'http://localhost:8888'&lt;/span&gt; &lt;span style=&quot;color: #16a085;&quot;&gt;\&lt;/span&gt;
       --max-tokens 10 &lt;span style=&quot;color: #16a085;&quot;&gt;\&lt;/span&gt;
       --top-logprobs 3 &lt;span style=&quot;color: #16a085;&quot;&gt;\&lt;/span&gt;
       --result-num 10 &lt;span style=&quot;color: #16a085;&quot;&gt;\&lt;/span&gt;
       --temperature 0 &lt;span style=&quot;color: #16a085;&quot;&gt;\&lt;/span&gt;
       --prompt &lt;span style=&quot;color: #16a085;&quot;&gt;'&amp;#36215;&amp;#19968;&amp;#20010;&amp;#22899;&amp;#24615;&amp;#21517;&amp;#23383;&amp;#65292;&amp;#22995;&amp;#21016;&amp;#65292;&amp;#21517;&amp;#23383;&amp;#35201;&amp;#21644;&amp;#26376;&amp;#20142;&amp;#26377;&amp;#20851;&amp;#65292;&amp;#20294;&amp;#19981;&amp;#35201;&amp;#30452;&amp;#25509;&amp;#29992;&amp;#26376;&amp;#23383;&amp;#65292;&amp;#23581;&amp;#35797;&amp;#26681;&amp;#25454;&amp;#19968;&amp;#20123;&amp;#21476;&amp;#35799;&amp;#35789;&amp;#37324;&amp;#30340;&amp;#20856;&amp;#25925;&amp;#65292;&amp;#20351;&amp;#29992;&amp;#36739;&amp;#24120;&amp;#35265;&amp;#32780;&amp;#19981;&amp;#26159;&amp;#20919;&amp;#20731;&amp;#30340;&amp;#23383;&amp;#65292;&amp;#21482;&amp;#36755;&amp;#20986;&amp;#21517;&amp;#23383;&amp;#26080;&amp;#38656;&amp;#20854;&amp;#20182;&amp;#12290;&amp;#32467;&amp;#26524;&amp;#26159;&amp;#65306;&amp;#21016;'&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
得到的结果是
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;orga302db7&quot;&gt;
PROMPT:
    起一个女性名字，姓刘，名字要和月亮有关，但不要直接用月字，尝试根据一些古诗词里的典故，使用较常见而不是冷僻的字，只输出名字无需其他。结果是：刘

RESULT:
    婵娟

CANDIDATE RESULTS(With PPL):
    TEXT: '婵娟', PPL: 1.3893958134060524
    TEXT: '嫵娟', PPL: 1.4518073221689531
    TEXT: '娵娟', PPL: 1.753700750011277
    TEXT: '婉娟', PPL: 2.1273314013866393
    TEXT: '嫉娟', PPL: 2.2228908964694374
    TEXT: '娉娟', PPL: 2.6851258929509876
    TEXT: '婷娟', PPL: 3.300551957606001
    TEXT: '嫷娟', PPL: 3.4488123924201473
    TEXT: '婵婟', PPL: 3.5588571357287666
    TEXT: '嫵婟', PPL: 3.718720611038904

Usage:
    prompt_tokens: 87
    completion_tokens: 6
    total_tokens: 93
&lt;/pre&gt;

&lt;p&gt;
生成效果先不说，可以看到，Usage 里 prompt_tokens 是 87、completion_tokens 是 6，相比其他方法来生成多个名字能减少一些 token 使用，比如说：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;最粗暴的方法是设置 temperature 大于 0 然后反复运行 10 次，假设每次的 completion_tokens 都是 6，那么 10 次需要消耗 930 个 token&lt;/li&gt;
&lt;li&gt;更好一点的方法是在 prompt 里要求输出多个名字，假设 prompt 不变，completion_tokens 至少要是 60，那么至少要消耗 153 个 token&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>我的年度总结所使用到的数据分析和可视化工具</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2024/01/18/tools-used-when-writing-summary.html"/>
    <category term="" scheme="http://www.zmonster.me/categories.html#"/>
    <id>http://www.zmonster.me/2024/01/18/tools-used-when-writing-summary</id>
    <published>2024-01-18T00:00:00+00:00</published>
    <updated>2024-01-18T00:00:00+00:00</updated>
    <description>
    
      <p>两年前我写完《我的2021》后有些朋友问我用到了什么工具和方法，前阵子写完《我的2023》后又有一些朋友询问，所以就来简单写一下好了。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga7ff5f6&quot;&gt;数据的获取&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5688d95&quot;&gt;用 orgparse 解析 org-mode 文件&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb8f1e2f&quot;&gt;用 LTP 进行分词/词性标注/实体识别等文本分析&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org70589c9&quot;&gt;用 ImageMagick 进行简单的图像处理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8edf412&quot;&gt;用 july 绘制日志/日记热力图&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2937745&quot;&gt;用 wordcloud 绘制词云&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org00a4661&quot;&gt;用 matplotlib_venn_wordcloud 绘制韦恩图形式的词云&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org032a7c6&quot;&gt;用 matplotlib.pyplot.subplot_mosaic 进行布局设置&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
两年前我写完《&lt;a href=&quot;https://www.zmonster.me/2022/01/15/annual-summary-of-2021.html&quot;&gt;我的2021&lt;/a&gt;》后有些朋友问我用到了什么工具和方法，前阵子写完《&lt;a href=&quot;https://www.zmonster.me/2024/01/12/annual-summary-of-2023.html&quot;&gt;我的2023&lt;/a&gt;》后又有一些朋友询问，所以就来简单写一下好了。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orga7ff5f6&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga7ff5f6&quot;&gt;数据的获取&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga7ff5f6&quot;&gt;
&lt;p&gt;
在两篇年度总结中，我用到了这么一些数据
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;日记文本&lt;/li&gt;
&lt;li&gt;工作日志文本&lt;/li&gt;
&lt;li&gt;org-mode clock 记录&lt;/li&gt;
&lt;li&gt;微信聊天记录&lt;/li&gt;
&lt;li&gt;B站观看记录&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
其中日记文本和工作日志文本都没有什么好说的，都是我用 org-mode 手工记下来的，这里只简单展示一下这两者的内容结构
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
工作日志是一个「年-月-日-具体记录」的四级结构
&lt;/p&gt;


&lt;div id=&quot;org4b294cb&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/work_journal_example.png&quot; alt=&quot;work_journal_example.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
日记是一个「日-具体记录」的两级结构
&lt;/p&gt;


&lt;div id=&quot;org71af651&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/diary_example.png&quot; alt=&quot;diary_example.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
org-mode clock 记录也是使用 org-mode 产生的，这个在《&lt;a href=&quot;https://www.zmonster.me/2021/09/25/record-life-with-org.html&quot;&gt;我的生活记录经验及个人工具与方法&lt;/a&gt;》这篇文章中也有提过，每当我执行 org-clock-in 或者 org-clock-out 后就会自动在对应任务下的 LOGBOOK 下自动地新增记录，如下图所示：
&lt;/p&gt;


&lt;div id=&quot;org8bfddd5&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/clock_records_example.png&quot; alt=&quot;clock_records_example.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
然后是微信聊天记录，我目前使用 &lt;a href=&quot;https://github.com/ehForwarderBot/efb-wechat-slave/&quot;&gt;EFB&lt;/a&gt; 来将微信消息转发到 Telegram，而 Telegram 是有接口能导出历史消息的，其 PC 桌面端也能直接将历史消息导出。其他的微信聊天记录导出方式我没有了解过。
&lt;/p&gt;

&lt;p&gt;
B站的观看记录，我自己写了一个简单的脚本去抓取，见 &lt;a href=&quot;https://gist.github.com/Linusp/eeaa2aed4b90cb130fd002d0189ad7ff&quot;&gt;Gist&lt;/a&gt;。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5688d95&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org5688d95&quot;&gt;用 orgparse 解析 org-mode 文件&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org5688d95&quot;&gt;
&lt;p&gt;
我的工作日志和日记都是 org-mode 文件，本质上里面的内容是一个树形的结构，最开始是自己写代码去解析的，后来换成了 &lt;a href=&quot;https://github.com/karlicoss/orgparse&quot;&gt;orgparse&lt;/a&gt; 这个 Python 的 org-mode 解析器。
&lt;/p&gt;

&lt;p&gt;
orgparse 可以直接将 org-mode 文件内容解析成一棵树，这样我在处理工作日志和个人日记时只要去遍历这棵树就好了
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99;&quot;&gt;import&lt;/span&gt; orgparse

&lt;span style=&quot;color: #ffcc66;&quot;&gt;content&lt;/span&gt; = &lt;span style=&quot;color: #66cccc;&quot;&gt;'''&lt;/span&gt;

&lt;span style=&quot;color: #66cccc;&quot;&gt;* 2024-01-17 &amp;#21608;&amp;#19977;&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;** 12:05 &amp;#33021;&amp;#20570;&amp;#30340;&amp;#20107;&amp;#24773;&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;blablablabla&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;** 16:01 &amp;#24608;&amp;#24816;&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;blablablabla&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;** 17:44 &amp;#32534;&amp;#21046;&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;blablablabla&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;** 22:06 &amp;#20170;&amp;#26085;&amp;#22238;&amp;#39038;&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;blablablabla&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;* 2024-01-18 &amp;#21608;&amp;#22235;&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;'''&lt;/span&gt;

&lt;span style=&quot;color: #ffcc66;&quot;&gt;tree&lt;/span&gt; = orgparse.loads(content)
&lt;span style=&quot;color: #99cc99;&quot;&gt;for&lt;/span&gt; node &lt;span style=&quot;color: #99cc99;&quot;&gt;in&lt;/span&gt; tree.children:
    &lt;span style=&quot;color: #cc99cc;&quot;&gt;print&lt;/span&gt;(node)

&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#32467;&amp;#26524;&amp;#65306;&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;* 2024-01-17 &amp;#21608;&amp;#19977;&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;* 2024-01-18 &amp;#21608;&amp;#22235;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后任务下面的 clock 记录它也会解析出来
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99;&quot;&gt;import&lt;/span&gt; orgparse

&lt;span style=&quot;color: #ffcc66;&quot;&gt;content&lt;/span&gt; = &lt;span style=&quot;color: #66cccc;&quot;&gt;'''&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;* &amp;#20241;&amp;#38386;&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;** SOMETIME &amp;#30475;&amp;#30005;&amp;#24433;&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;:LOGBOOK:&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;CLOCK: [2023-12-21 &amp;#22235; 18:10]--[2023-12-21 &amp;#22235; 21:20] =&amp;gt;  3:10&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;- &amp;#29399;&amp;#31070;&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;CLOCK: [2023-10-04 &amp;#19977; 14:59]--[2023-10-04 &amp;#19977; 17:28] =&amp;gt;  2:29&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;- &amp;#20420;&amp;#32599;&amp;#26031;&amp;#28779;&amp;#36710;&amp;#22823;&amp;#21163;&amp;#26696;&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;:END:&lt;/span&gt;
&lt;span style=&quot;color: #66cccc;&quot;&gt;'''&lt;/span&gt;

tree = orgparse.loads(content)
&lt;span style=&quot;color: #99cc99;&quot;&gt;for&lt;/span&gt; level_1_node &lt;span style=&quot;color: #99cc99;&quot;&gt;in&lt;/span&gt; tree.children:
    &lt;span style=&quot;color: #99cc99;&quot;&gt;for&lt;/span&gt; level_2_node &lt;span style=&quot;color: #99cc99;&quot;&gt;in&lt;/span&gt; level_1_node.children:
        &lt;span style=&quot;color: #99cc99;&quot;&gt;for&lt;/span&gt; item &lt;span style=&quot;color: #99cc99;&quot;&gt;in&lt;/span&gt; level_2_node.clock:
            &lt;span style=&quot;color: #cc99cc;&quot;&gt;print&lt;/span&gt;(item)

&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#32467;&amp;#26524;&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;[2023-12-21 Thu 18:10]--[2023-12-21 Thu 21:20]&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;[2023-10-04 Wed 14:59]--[2023-10-04 Wed 17:28]&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
不过有点可惜的是解析出来的 clock 记录把 note 丢掉了，所以我只用来做大类的时间统计，有些依赖里面内容的分析我还是自己做的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb8f1e2f&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgb8f1e2f&quot;&gt;用 LTP 进行分词/词性标注/实体识别等文本分析&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgb8f1e2f&quot;&gt;
&lt;p&gt;
要绘制词云就需要从文本里提取关键词，所以分词是必需的。再进一步的关键词提取，虽然也有很多工具，但这些工具基本上都是面向某个领域的，和我自己的日记、日志并不太匹配，所以我就采取了一些简单的策略来做关键词提取，反正也只是用来画一个词云，马马虎虎就行。
&lt;/p&gt;

&lt;p&gt;
具体来说，这个策略是这样的：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;先对文本进行分词、词性标注（标记每个词是名词、形容词、动词还是别的什么）、实体识别（人名、地名、机构名等）&lt;/li&gt;
&lt;li&gt;反向过滤：若词中包含标点符号则去除，若词在停用词表中则去除，若词的词性为我设定的类别（连词、助词、叹词、量词、数词、介词、非语素词、时间名词）则去除（LTP 使用的词性标注集是 2005 年颁布的《&lt;a href=&quot;http://www.moe.gov.cn/jyb_sjzl/ziliao/A19/201001/t20100115_75692.html&quot;&gt;信息处理用现代汉语词类标记规范&lt;/a&gt;》）、若词中字数太少（1个字的往往无意义）或太多（字数太多可能分词出错了）则去除&lt;/li&gt;
&lt;li&gt;正向筛选：识别为实体的词一律选中作为关键词，我预先设置的一些重要词汇一律都选中作为关键词&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
能进行分词、词性标注、实体识别的工具很多，21 年的时候我用的是 &lt;a href=&quot;https://github.com/fxsjy/jieba&quot;&gt;jieba&lt;/a&gt; ，它的好处是依赖干净而且比较快，但效果要差一些而且没有实体识别功能。除了 jieba 还可以用北大的 &lt;a href=&quot;https://github.com/lancopku/pkuseg-python&quot;&gt;pkuseg&lt;/a&gt;、哈工大的 &lt;a href=&quot;https://github.com/HIT-SCIR/ltp&quot;&gt;LTP&lt;/a&gt;、百度的 &lt;a href=&quot;https://github.com/baidu/lac&quot;&gt;LAC&lt;/a&gt;，当然国外的 &lt;a href=&quot;https://spacy.io/&quot;&gt;spaCy&lt;/a&gt; 和斯坦福大学的 &lt;a href=&quot;https://stanfordnlp.github.io/stanza/&quot;&gt;Stanza&lt;/a&gt; 也有中文支持都是不错的，我个人建议 pkuseg 或者 LTP。2023 年的年度分析我最后选了 LTP，是因为 LTP 在持续地更新，4.0 后已经升级成了 pytorch 模型想尝试下。
&lt;/p&gt;

&lt;p&gt;
LTP 的模型建议像我一样自己下载好放到本地，否则它会去从已经被大陆屏蔽的 Huggingface 上下载而失败出错。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99;&quot;&gt;from&lt;/span&gt; ltp &lt;span style=&quot;color: #99cc99;&quot;&gt;import&lt;/span&gt; LTP

&lt;span style=&quot;color: #ffcc66;&quot;&gt;ltp&lt;/span&gt; = LTP(&lt;span style=&quot;color: #66cccc;&quot;&gt;'/home/zmonster/Projects/ltp/small/'&lt;/span&gt;)
&lt;span style=&quot;color: #ffcc66;&quot;&gt;output&lt;/span&gt; = ltp.pipeline([&lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#24605;&amp;#32771;&amp;#26202;&amp;#19978;&amp;#21507;&amp;#20160;&amp;#20040;&amp;#26368;&amp;#21518;&amp;#20915;&amp;#23450;&amp;#29038;&amp;#38754;&amp;#21507;&amp;#65292;&amp;#28982;&amp;#21518;&amp;#22312;&amp;#25972;&amp;#29702;&amp;#26085;&amp;#35760;&amp;#30340;&amp;#26102;&amp;#20505;&amp;#30475;&amp;#21040;&amp;#33258;&amp;#24049;&amp;#26377;&amp;#19968;&amp;#22825;&amp;#31354;&amp;#27668;&amp;#28856;&amp;#38149;&amp;#20102;&amp;#22836;&amp;#19968;&amp;#22825; KFC &amp;#30127;&amp;#29378;&amp;#26143;&amp;#26399;&amp;#22235;&amp;#20080;&amp;#30340;&amp;#40481;&amp;#31859;&amp;#33457;&amp;#65292;&amp;#24819;&amp;#36215;&amp;#26469;&amp;#20102;&amp;#20043;&amp;#21069;&amp;#33258;&amp;#24049;&amp;#36824;&amp;#20080;&amp;#36807;&amp;#23567;&amp;#37221;&amp;#32905;&amp;#25918;&amp;#20912;&amp;#31665;&amp;#20102;&amp;#65292;&amp;#32763;&amp;#20986;&amp;#26469;&amp;#20934;&amp;#22791;&amp;#31354;&amp;#27668;&amp;#28856;&amp;#38149;&amp;#28909;&amp;#20102;&amp;#26202;&amp;#19978;&amp;#21507;&amp;#19968;&amp;#28857;&amp;#12290;'&lt;/span&gt;], tasks=[&lt;span style=&quot;color: #66cccc;&quot;&gt;'cws'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'pos'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'ner'&lt;/span&gt;])

&lt;span style=&quot;color: #cc99cc;&quot;&gt;print&lt;/span&gt;(output.cws)
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;[['&amp;#24605;&amp;#32771;', '&amp;#26202;&amp;#19978;', '&amp;#21507;', '&amp;#20160;&amp;#20040;', '&amp;#26368;&amp;#21518;', '&amp;#20915;&amp;#23450;', '&amp;#29038;', '&amp;#38754;', '&amp;#21507;', '&amp;#65292;', '&amp;#28982;&amp;#21518;', '&amp;#22312;', '&amp;#25972;&amp;#29702;', '&amp;#26085;&amp;#35760;', '&amp;#30340;', '&amp;#26102;&amp;#20505;', '&amp;#30475;&amp;#21040;', '&amp;#33258;&amp;#24049;', '&amp;#26377;', '&amp;#19968;', '&amp;#22825;', '&amp;#31354;&amp;#27668;', '&amp;#28856;&amp;#38149;', '&amp;#20102;', '&amp;#22836;', '&amp;#19968;', '&amp;#22825; ', 'KFC ', '&amp;#30127;&amp;#29378;', '&amp;#26143;&amp;#26399;&amp;#22235;', '&amp;#20080;', '&amp;#30340;', '&amp;#40481;&amp;#31859;&amp;#33457;', '&amp;#65292;', '&amp;#24819;', '&amp;#36215;&amp;#26469;', '&amp;#20102;', '&amp;#20043;&amp;#21069;', '&amp;#33258;&amp;#24049;', '&amp;#36824;', '&amp;#20080;', '&amp;#36807;', '&amp;#23567;', '&amp;#37221;&amp;#32905;', '&amp;#25918;', '&amp;#20912;&amp;#31665;', '&amp;#20102;', '&amp;#65292;', '&amp;#32763;', '&amp;#20986;&amp;#26469;', '&amp;#20934;&amp;#22791;', '&amp;#31354;&amp;#27668;', '&amp;#28856;&amp;#38149;', '&amp;#28909;', '&amp;#20102;', '&amp;#26202;&amp;#19978;', '&amp;#21507;', '&amp;#19968;&amp;#28857;', '&amp;#12290;']]&lt;/span&gt;

&lt;span style=&quot;color: #cc99cc;&quot;&gt;print&lt;/span&gt;(output.pos)
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;[['v', 'nt', 'v', 'r', 'nd', 'v', 'v', 'n', 'v', 'wp', 'c', 'p', 'v', 'n', 'u', 'n', 'v', 'r', 'v', 'm', 'q', 'n', 'v', 'u', 'm', 'm', 'q', 'nz', 'a', 'nt', 'v', 'u', 'n', 'wp', 'v', 'v', 'u', 'nd', 'r', 'd', 'v', 'u', 'a', 'n', 'v', 'n', 'u', 'wp', 'v', 'v', 'v', 'n', 'v', 'v', 'u', 'nt', 'v', 'm', 'wp']]&lt;/span&gt;

&lt;span style=&quot;color: #cc99cc;&quot;&gt;print&lt;/span&gt;(output.ner)
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;[[]]&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org70589c9&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org70589c9&quot;&gt;用 ImageMagick 进行简单的图像处理&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org70589c9&quot;&gt;
&lt;p&gt;
我用 ImageMagick 来生成词云图需要的 mask 图使得画出来的词云能按照我预想的形状展示：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
用 ImageMagick 绘制一张黑底白字写着 2023 的图
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;convert -background black -fill white -pointsize 512 label:2023 2023.png
&lt;/pre&gt;
&lt;/div&gt;


&lt;div id=&quot;org4c326e0&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023.png&quot; alt=&quot;2023.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
用 ImageMagick 绘制一个直径 400 像素的圆
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;convert -size 400x400 xc:white -fill black -draw &lt;span style=&quot;color: #66cccc;&quot;&gt;'circle 200,200 200,3'&lt;/span&gt; circle400.png
&lt;/pre&gt;
&lt;/div&gt;


&lt;div id=&quot;orgd3dd3a4&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/circle400.png&quot; alt=&quot;circle400.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
然后我还很常用 ImageMagick 来裁剪一下图像的白边使得图像显得更紧凑一些，随后讲到的绘制热力图的 july 产生的结果就会有特别大的一块白边，我希望它能少一些但它又没有提供什么选项来让我控制（matplotlib 的 tight_layout 完全没作用）所以只能用 ImageMagick 再处理一下了
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;convert -trim 2023_diary_heatmap.png  /tmp/a.png
mv /tmp/a.png 2023_diary_heatmap.png
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
裁剪前是这个样子的
&lt;/p&gt;


&lt;div id=&quot;org1978269&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023_diary_heatmap-original.png&quot; alt=&quot;2023_diary_heatmap-original.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
裁剪后是这个样子
&lt;/p&gt;


&lt;div id=&quot;orge833fe7&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023_diary_heatmap.png&quot; alt=&quot;2023_diary_heatmap.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8edf412&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org8edf412&quot;&gt;用 july 绘制日志/日记热力图&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org8edf412&quot;&gt;
&lt;p&gt;
&lt;a href=&quot;https://github.com/e-hulten/july&quot;&gt;july&lt;/a&gt; 是一个基于 matplotlib 的用来绘制每日事件热力图的工具， 如下所示
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #99cc99;&quot;&gt;as&lt;/span&gt; np
&lt;span style=&quot;color: #99cc99;&quot;&gt;import&lt;/span&gt; matplotlib.pyplot &lt;span style=&quot;color: #99cc99;&quot;&gt;as&lt;/span&gt; plt
&lt;span style=&quot;color: #99cc99;&quot;&gt;import&lt;/span&gt; july
&lt;span style=&quot;color: #99cc99;&quot;&gt;from&lt;/span&gt; july.utils &lt;span style=&quot;color: #99cc99;&quot;&gt;import&lt;/span&gt; date_range

&lt;span style=&quot;color: #ffcc66;&quot;&gt;dates&lt;/span&gt; = date_range(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;2020-01-01&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;2020-12-31&quot;&lt;/span&gt;)
&lt;span style=&quot;color: #ffcc66;&quot;&gt;data&lt;/span&gt; = np.random.randint(0, 14, &lt;span style=&quot;color: #cc99cc;&quot;&gt;len&lt;/span&gt;(dates))
july.heatmap(dates, data, title=&lt;span style=&quot;color: #66cccc;&quot;&gt;'Github Activity'&lt;/span&gt;, cmap=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;github&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
会得到这样的图：
&lt;/p&gt;


&lt;div id=&quot;orgb4e9aa6&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/july_heatmap_github.jpg&quot; alt=&quot;july_heatmap_github.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
具体使用看项目 README 就好了，没有什么太特别的。不过如果想和我一样让显示的横坐标和纵坐标都是中文的话，需要在调用 july 前设置一下 locale
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;locale.setlocale(locale.LC_ALL, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;zh_CN.UTF8&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
另外就是在调用 july 的时候设置一下字体，这个在 README 的示例中有。
&lt;/p&gt;

&lt;p&gt;
最近才看到 yihong 的 &lt;a href=&quot;https://github.com/yihong0618/GitHubPoster&quot;&gt;GithubPoster&lt;/a&gt; 感觉非常不错，之后也许就用 yihong 的这个工具了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2937745&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org2937745&quot;&gt;用 wordcloud 绘制词云&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org2937745&quot;&gt;
&lt;p&gt;
&lt;a href=&quot;https://github.com/amueller/word_cloud&quot;&gt;wordcloud&lt;/a&gt; 是基于 matplotlib 实现的词云绘制工具，它自己也提供了命令行工具直接从文本中读取数据然后绘制，但它里面自带的是按空白符进行分词的做法，也就是说不适用于中文文本。
&lt;/p&gt;

&lt;p&gt;
好在它的 WordCloud 类实现了一个叫作 generate_from_frequencies 的方法，所以我是先在之前用 LTP 分词自己统计好频次后使用这个方法来绘制，像这样：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99;&quot;&gt;from&lt;/span&gt; wordcloud &lt;span style=&quot;color: #99cc99;&quot;&gt;import&lt;/span&gt; WordCloud

&lt;span style=&quot;color: #ffcc66;&quot;&gt;freqs&lt;/span&gt; = {
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#26379;&amp;#21451;'&lt;/span&gt;: 432,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#21507;&amp;#39277;'&lt;/span&gt;: 368,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#28216;&amp;#25103;'&lt;/span&gt;: 127,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#32842;&amp;#22825;'&lt;/span&gt;: 106,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#26202;&amp;#39277;'&lt;/span&gt;: 83,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#25972;&amp;#29702;'&lt;/span&gt;: 76,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#21320;&amp;#39277;'&lt;/span&gt;: 75,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#26089;&amp;#39277;'&lt;/span&gt;: 74,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#27927;&amp;#28465;'&lt;/span&gt;: 60,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#29238;&amp;#27597;'&lt;/span&gt;: 55
}
&lt;span style=&quot;color: #ffcc66;&quot;&gt;wc&lt;/span&gt; = WordCloud(background_color=&lt;span style=&quot;color: #66cccc;&quot;&gt;'white'&lt;/span&gt;, width=200, height=200)
wc.generate_from_frequencies(freqs)
wc.to_file(&lt;span style=&quot;color: #66cccc;&quot;&gt;'wordcloud.png'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
不过它默认的实现不支持中文绘制，上面的代码会得到这样的图
&lt;/p&gt;


&lt;div id=&quot;orgab8cdb8&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/wordcloud_example_without_cnfont.png&quot; alt=&quot;wordcloud_example_without_cnfont.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
通过 font_path 参数设置一下中文字体路径即可，我使用了文泉驿微米黑这个字体：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;wc&lt;/span&gt; = WordCloud(
    background_color=&lt;span style=&quot;color: #66cccc;&quot;&gt;'white'&lt;/span&gt;,
    width=200,
    height=200,
    font_path=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;/usr/share/fonts/truetype/wqy/wqy-microhei.ttc&quot;&lt;/span&gt;
)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这样就能得到
&lt;/p&gt;


&lt;div id=&quot;orgc3bd933&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/wordcloud_example_with_cnfont.png&quot; alt=&quot;wordcloud_example_with_cnfont.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
如果想要将词云绘制成特定的形状，就要使用前面用 ImageMagick 生成的 mask 图像了，通过 mask 参数传入对应的图像即可，最终会在 mask 图像的黑色区域绘制，比如使用前面那个圆形的 mask 图像：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99;&quot;&gt;from&lt;/span&gt; wordcloud &lt;span style=&quot;color: #99cc99;&quot;&gt;import&lt;/span&gt; WordCloud
&lt;span style=&quot;color: #99cc99;&quot;&gt;from&lt;/span&gt; PIL &lt;span style=&quot;color: #99cc99;&quot;&gt;import&lt;/span&gt; Image
&lt;span style=&quot;color: #99cc99;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #99cc99;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #ffcc66;&quot;&gt;mask_image&lt;/span&gt; = np.array(Image.&lt;span style=&quot;color: #cc99cc;&quot;&gt;open&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;'circle400.png'&lt;/span&gt;))
&lt;span style=&quot;color: #ffcc66;&quot;&gt;freqs&lt;/span&gt; = {
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#26379;&amp;#21451;'&lt;/span&gt;: 432,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#21507;&amp;#39277;'&lt;/span&gt;: 368,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#28216;&amp;#25103;'&lt;/span&gt;: 127,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#32842;&amp;#22825;'&lt;/span&gt;: 106,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#26202;&amp;#39277;'&lt;/span&gt;: 83,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#25972;&amp;#29702;'&lt;/span&gt;: 76,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#21320;&amp;#39277;'&lt;/span&gt;: 75,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#26089;&amp;#39277;'&lt;/span&gt;: 74,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#27927;&amp;#28465;'&lt;/span&gt;: 60,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#29238;&amp;#27597;'&lt;/span&gt;: 55
}
&lt;span style=&quot;color: #ffcc66;&quot;&gt;wc&lt;/span&gt; = WordCloud(
    background_color=&lt;span style=&quot;color: #66cccc;&quot;&gt;'white'&lt;/span&gt;,
    mask=mask_image,
    width=&lt;span style=&quot;color: #cc99cc;&quot;&gt;len&lt;/span&gt;(mask_image[0]),
    height=&lt;span style=&quot;color: #cc99cc;&quot;&gt;len&lt;/span&gt;(mask_image),
    font_path=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;/usr/share/fonts/truetype/wqy/wqy-microhei.ttc&quot;&lt;/span&gt;,
)
wc.generate_from_frequencies(freqs)
wc.to_file(&lt;span style=&quot;color: #66cccc;&quot;&gt;'wordcloud.png'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果如下图所示，虽然因为词比较少看着不太圆，但大体形状上能看出来和前面那张图的差别。
&lt;/p&gt;


&lt;div id=&quot;orgd1e5bec&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/wordcloud_example_circle.png&quot; alt=&quot;wordcloud_example_circle.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org00a4661&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org00a4661&quot;&gt;用 matplotlib_venn_wordcloud 绘制韦恩图形式的词云&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org00a4661&quot;&gt;
&lt;p&gt;
韦恩图（Venn Diagram）是用来展示两个集合之间关系（是否有交集、交集部分有多少等）的一个图形，如下图所示：
&lt;/p&gt;


&lt;div id=&quot;org79e38da&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/venn_example.png&quot; alt=&quot;venn_example.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
写《我的2021》分析聊天记录的时候，我想要分析我和一个特定的人交流的时候我们双方说的内容之间的同异同时又希望能把交流中高频的词突出显示，所以就想要在一个韦恩图形式的词云，具体来说是下面这个样子：
&lt;/p&gt;


&lt;div id=&quot;orgb6b364e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/venn_wordcloud_example1.png&quot; alt=&quot;venn_wordcloud_example1.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到，总体上它还是一个词云图，但又引入了韦恩图的概念，左边的圆是我说过的话里的关键词、右边的图则是朋友说过的话里的关键词，两个圆的交集则是我们双方都说过的词。
&lt;/p&gt;

&lt;p&gt;
这个是一个比较小众的需求，但最后还真找到了一个实现，也就是 &lt;a href=&quot;https://github.com/paulbrodersen/matplotlib_venn_wordcloud&quot;&gt;matplotlib_venn_wordcloud&lt;/a&gt; 这个工具，其使用方法如下所示：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99;&quot;&gt;import&lt;/span&gt; matplotlib.pyplot &lt;span style=&quot;color: #99cc99;&quot;&gt;as&lt;/span&gt; plt
&lt;span style=&quot;color: #99cc99;&quot;&gt;from&lt;/span&gt; matplotlib_venn_wordcloud &lt;span style=&quot;color: #99cc99;&quot;&gt;import&lt;/span&gt; venn2_wordcloud

plt.&lt;span style=&quot;color: #ffcc66;&quot;&gt;rcParams&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;font.sans-serif&quot;&lt;/span&gt;] = [&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;WenQuanYi Micro Hei&quot;&lt;/span&gt;]

&lt;span style=&quot;color: #ffcc66;&quot;&gt;words&lt;/span&gt; = {
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#25105;'&lt;/span&gt;: {&lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#30693;&amp;#35782;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#24037;&amp;#20855;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#31508;&amp;#35760;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#24314;&amp;#31435;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#20307;&amp;#31995;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#31649;&amp;#29702;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#26041;&amp;#24335;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#24819;&amp;#27861;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#20215;&amp;#20540;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#20248;&amp;#31168;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#29702;&amp;#35299;'&lt;/span&gt;},
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#26379;&amp;#21451;'&lt;/span&gt;: {&lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#31508;&amp;#35760;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#30693;&amp;#35782;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#20307;&amp;#31995;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#20869;&amp;#23481;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#25945;&amp;#32946;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#23884;&amp;#20837;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#24341;&amp;#29992;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#21151;&amp;#33021;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#38142;&amp;#25509;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#20851;&amp;#31995;'&lt;/span&gt;},
}
&lt;span style=&quot;color: #ffcc66;&quot;&gt;freqs&lt;/span&gt; = {
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#30693;&amp;#35782;'&lt;/span&gt;: 69,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#31508;&amp;#35760;'&lt;/span&gt;: 68,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#20869;&amp;#23481;'&lt;/span&gt;: 65,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#20307;&amp;#31995;'&lt;/span&gt;: 63,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#24314;&amp;#31435;'&lt;/span&gt;: 61,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#24037;&amp;#20855;'&lt;/span&gt;: 61,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#25945;&amp;#32946;'&lt;/span&gt;: 59,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#26041;&amp;#24335;'&lt;/span&gt;: 57,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#24819;&amp;#27861;'&lt;/span&gt;: 57,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#29702;&amp;#35299;'&lt;/span&gt;: 55,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#38142;&amp;#25509;'&lt;/span&gt;: 44,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#23884;&amp;#20837;'&lt;/span&gt;: 44,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#21151;&amp;#33021;'&lt;/span&gt;: 43,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#20215;&amp;#20540;'&lt;/span&gt;: 32,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#24341;&amp;#29992;'&lt;/span&gt;: 27,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#31649;&amp;#29702;'&lt;/span&gt;: 25,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#20851;&amp;#31995;'&lt;/span&gt;: 23,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#20248;&amp;#31168;'&lt;/span&gt;: 19,
}
&lt;span style=&quot;color: #ffcc66;&quot;&gt;names&lt;/span&gt;, &lt;span style=&quot;color: #ffcc66;&quot;&gt;sets&lt;/span&gt; = &lt;span style=&quot;color: #cc99cc;&quot;&gt;list&lt;/span&gt;(&lt;span style=&quot;color: #cc99cc;&quot;&gt;zip&lt;/span&gt;(*words.items()))
venn2_wordcloud(
    [&lt;span style=&quot;color: #cc99cc;&quot;&gt;set&lt;/span&gt;(item) &lt;span style=&quot;color: #99cc99;&quot;&gt;for&lt;/span&gt; item &lt;span style=&quot;color: #99cc99;&quot;&gt;in&lt;/span&gt; sets],
    alpha=0.8,
    set_labels=names,
    word_to_frequency=freqs,
    wordcloud_kwargs={
        &lt;span style=&quot;color: #66cccc;&quot;&gt;'font_path'&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;'/usr/share/fonts/truetype/wqy/wqy-microhei.ttc'&lt;/span&gt;,
    }
)
plt.savefig(&lt;span style=&quot;color: #66cccc;&quot;&gt;'venn_wordcloud.png'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
由于这个工具对中文支持也不是很好，所以需要像我上面的代码一样，分别在两处设置一下中文字体。
&lt;/p&gt;

&lt;p&gt;
上面的代码会得到如下的图像：
&lt;/p&gt;


&lt;div id=&quot;org227670f&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/venn_wordcloud_example2.png&quot; alt=&quot;venn_wordcloud_example2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org032a7c6&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org032a7c6&quot;&gt;用 matplotlib.pyplot.subplot_mosaic 进行布局设置&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org032a7c6&quot;&gt;
&lt;p&gt;
除此以外的大部分图像如柱状图、线图、饼图等我都是用 pandas 和 matplotlib 来绘制的，这一块的公开资料很多，所以这里只提一下要在一张图里画多个图表时设置布局的心得，具体来说是用 matplotlib.pyplot.subplot_mosaic 这个函数，它可以用比较直观地方式进行绘图的布局设计 —— 图像分为几行几列、某一个子图占据哪几行哪几列之类的，比如说：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
绘制 A/B/C/D 四个子图，A/B/C 一起在第一行并且各占 1/3 的宽度，子图 D 占据第二行整行
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99;&quot;&gt;import&lt;/span&gt; matplotlib.pyplot &lt;span style=&quot;color: #99cc99;&quot;&gt;as&lt;/span&gt; plt
plt.subplot_mosaic(&lt;span style=&quot;color: #66cccc;&quot;&gt;'ABC;DDD'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上面的代码会得到下面的布局：
&lt;/p&gt;


&lt;div id=&quot;org2fa0f3c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/subplot_mosaic_example1.png&quot; alt=&quot;subplot_mosaic_example1.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
绘制 A/B/C 三个子图，A/B 一起在第一列并且各占 1/2 的高度，C 占据第二列整列
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99;&quot;&gt;import&lt;/span&gt; matplotlib.pyplot &lt;span style=&quot;color: #99cc99;&quot;&gt;as&lt;/span&gt; plt
plt.subplot_mosaic(&lt;span style=&quot;color: #66cccc;&quot;&gt;'AC;BC'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上面的代码会得到下面的布局：
&lt;/p&gt;


&lt;div id=&quot;orge47c8e2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/subplot_mosaic_example2.png&quot; alt=&quot;subplot_mosaic_example2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
绘制一个 3x3 的布局，但只在中心和 4 个角进行绘图
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99;&quot;&gt;import&lt;/span&gt; matplotlib.pyplot &lt;span style=&quot;color: #99cc99;&quot;&gt;as&lt;/span&gt; plt
plt.subplot_mosaic([
    [&lt;span style=&quot;color: #66cccc;&quot;&gt;'A'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'.'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'B'&lt;/span&gt;],
    [&lt;span style=&quot;color: #66cccc;&quot;&gt;'.'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'C'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'.'&lt;/span&gt;],
    [&lt;span style=&quot;color: #66cccc;&quot;&gt;'D'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'.'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'E'&lt;/span&gt;],
])
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上面的代码会得到下面的布局：
&lt;/p&gt;


&lt;div id=&quot;orgd51411b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/subplot_mosaic_example3.png&quot; alt=&quot;subplot_mosaic_example3.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>我的2023</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2024/01/12/annual-summary-of-2023.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2024/01/12/annual-summary-of-2023</id>
    <published>2024-01-12T00:00:00+00:00</published>
    <updated>2024-01-12T00:00:00+00:00</updated>
    <description>
    
      <p>总的来说，2023 年就是玩游戏、阅读、和朋友聊天以及吃吃吃的一年，是开心的一年！我觉得这样的日子我可以一直过下去。</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
2023 年继续贯彻我尽量记录一切的理念，统计了下 org-mode 的 clock 数据，这一年有记录的时间共计 7924.55 个小时，合计 330.19 天，占比 90.46%，这有记录的 7924.55 个小时的情况如下图所示：
&lt;/p&gt;


&lt;div id=&quot;org8029bf0&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023_time_usage.png&quot; alt=&quot;2023_time_usage.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;睡觉共记录 2802.87 小时，平均每天是 6.31 小时，虽然 6 月起就没有在工作了，但睡眠还是不好，还是顶着黑眼圈，2024 年希望能多睡一点好觉；&lt;/li&gt;
&lt;li&gt;「休闲-其他」这个条目记录的是无明确目的的、消磨时间的活动，包括醒后的赖床、睡前的玩手机以及其他任何两段有明确目的的活动之间的空隙（一般都是在玩手机、刷推等），算下来平均每天有 4.12 个小时，也就是说我每天都要浪费六分之一的生命 —— 不过我对浪费生命没有什么愧疚感，作为一个并不想做什么大事业的人，生命就是拿来浪费的嘛，不过这些记录中的活动其实包含了很多种类的活动，还是可以作细化的，之后尝试一下吧；&lt;/li&gt;
&lt;li&gt;排名第三的是游戏，这一年我确实玩了很多很多的游戏，可以说比往年任何时候都多，能有大量的时间去纯粹的体验游戏的乐趣，而不是在下班后拖着疲惫的身体带着「我还有一两个小时的自由时间要好好玩下游戏不然今天就浪费了」或者「今天工作不开心想去玩下游戏放松下」（真正的放松是早点休息啦）等复杂的心情去打开游戏——只有在不玩游戏时也是开心平静的时候，才能真正体会到游戏的乐趣，我是这么想的；&lt;/li&gt;
&lt;li&gt;工作没什么好说，因为只工作了 5 个月所以就只有 449 个小时，如果是往年的话工作大概会是在第一或者第二的位置&lt;/li&gt;
&lt;li&gt;日常生活的一些环节如吃饭（343 小时）、洗漱（318 小时）、做饭（180 小时）、上厕所（113 小时）、家务（63 小时）加起来就 954 小时了，如果不是特别追求高效率的人，这部分时间和睡眠一样是很难减少的，所以其实人一天里能利用的有效时间其实并不多，能在每一天的这些时间里充分地做一些自己喜欢的事情，这样的人生就会是幸福的吧。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
了解了 2023 年这个时间使用结构后，希望能在 2024 年尝试有意识地对其进行一点优化调整，比如多睡一点、多读点书（2023 年读的书真是太少了）、多运动，一年后再看吧！
&lt;/p&gt;


&lt;div id=&quot;orgd45e169&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023_diary_heatmap.png&quot; alt=&quot;2023_diary_heatmap.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
2023 年，我也依然在坚持写日记，365 天里我有 358 天写了日记，只有 2023/01/26、2023/01/30、2023/02/25、2023/03/19、2023/03/22、2023/03/27、2023-04-06 这七天没有记录，辞职后的 7 个月里没有一天落下，不过有些天比较糊弄（比如 2023/11/08 和 2023/11/10）所以上面的热力图里看着好像没记一样。
&lt;/p&gt;

&lt;p&gt;
我在 Emacs 里用 org-mode 写日记是从 2019/06/17 开始的，四年多的时间里日记的结构发生了数次变化，这次做分析统计的时候费了点时间多写了点代码把过去几年的日记结构都兼容了下，想看下几年来的日记变化，得到的对比图如下所示：
&lt;/p&gt;


&lt;div id=&quot;org418e0bc&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023_diary_stats.png&quot; alt=&quot;2023_diary_stats.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;从右上的图可以看到，2023 年的日记天数、记录数、日均字数基本上都是比之前三年高的，唯一的例外是记录数比 2021 年的低，这是因为 2023 年写日记时基本上都是在一个记录下回顾一整天的经历和想法，而 2021 年的时候则倾向于一旦有什么想法就新建一个记录写一下；&lt;/li&gt;
&lt;li&gt;看左上的逐季度的日均字数趋势图，可以发现前两个季度的日记量和往年比虽然也多一些但也不算多很多，但在下半年则急剧增长，最大的原因就是我 5 月底从公司辞职躺平了，有了更多的闲暇时间所以我就能花更多的精力去记录和梳理自己的想法、感受，不像有些人，工作对我并不是必需的，即使是一个不太出门的人，我依然能从很多事物中得到值得记录的体验；&lt;/li&gt;
&lt;li&gt;从下方每年相同月份的日记日均字数对比来看，9 月和 10 月往往都是我记录最多的，大概是因为北京的秋天吧 —— 嗯，这个是纯粹的主观感觉，限于精力就没有去做这方面的内容分析了。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
进一步将 2023 年日记的文本做了下分析，绘制了一张词云图，如下所示：
&lt;/p&gt;


&lt;div id=&quot;org9b9a586&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023_diary_words.png&quot; alt=&quot;2023_diary_words.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
为了有更好的可视化效果，我在分析时做了这么一些处理：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;将提到的现实中认识的人的名字都替换成了「朋友」这个词&lt;/li&gt;
&lt;li&gt;将提到的游戏名都替换成了「游戏」这个词&lt;/li&gt;
&lt;li&gt;将提到的具体的书籍都替换成了「书籍」这个词&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
总的来说，2023 年就是玩游戏、阅读、和朋友聊天以及吃吃吃的一年，是开心的一年！我觉得这样的日子我可以一直过下去。
&lt;/p&gt;

&lt;p&gt;
然后对比了一下 2020 年到 2023 年这四年日记里 TOP5 的词汇的变化情况，如下图所示：
&lt;/p&gt;


&lt;div id=&quot;org956496d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023_year_words_comparison.png&quot; alt=&quot;2023_year_words_comparison.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以看出来，和往年相比最大的一个变化就是「游戏」这个词的出现，而始终如一的则是「吃饭」和「朋友」。顺便一提，2022 年过得并不开心，日记里和「开心」这个词相关的文本基本上都是「不太开心」「开心不起来」之类的，而这样的文本在经过处理后提取出来的有效词汇还是「开心」 —— 由于 2022 年的主观感受就很强烈所以就没有特地去为这个情况做分析优化了，只是在这里简单说明一下。底部的折线图是把这四年的 TOP5 的词语取并集得到了 11 个词然后看在这四年里逐季度的频次变化趋势，加粗的那 5 条是 2023 年 TOP5 词汇对应的折线。
&lt;/p&gt;

&lt;p&gt;
然后还将 2023 年每个月的日记分别拿出来绘制了下词云图，看一下每个月会有什么不同，为了更好地将差异反映出来，我将「朋友」「吃饭」「聊天」「早饭」「晚饭」「午饭」「洗漱」这几个在每个月都非常高频的词去掉了，得到的结果如下图所示：
&lt;/p&gt;


&lt;div id=&quot;org1f28293&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023_monthly_words.png&quot; alt=&quot;2023_monthly_words.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;可以看到，前四个月的词云里基本上没有出现「游戏」这个词，因为当时还在上班，而在4月底提出离职后，5月就开始迫不及待地玩游戏了，开头记录的 473 个小时的游戏时间，也基本上分布在后面这 8 个月里，9月玩得稍微少一些只有 27 个小时所以这个词在词云图里就显得小了一些；&lt;/li&gt;
&lt;li&gt;7月、8月和9月基本上每天都会看一小会书，日记里都会提一下，所以「书籍」这个词也比较大一些，但我每天也就看半个小时到一个小时，其实并不多，年底的两个月甚至都不怎么看了，一部分原因是把更多的精力放到读论文上了。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
除了前 4 个月还在烦恼工作外，之后的 8 个月能看出来和一整年的词云图是一致的，游戏、书籍、散步、冥想、吃饭、做饭、聊天构成了我生活的主要部分，基本也是开心的，不工作就使人开心，至少对我是这样的，无聊什么的完全不存在的！
&lt;/p&gt;

&lt;p&gt;
经过新冠三年，我觉得我更能关心和体谅我的朋友们了，2023 年也有更多地去和朋友联系，也从更多的朋友那感受到过关心、支持和肯定，虽然大部分朋友只是隔很久才闲聊几句或者吃个饭，但我对此都感到很开心。大家都有自己的人生道路，谁能说得清上一次见面是不是这辈子最后一面呢？所以我尤其开心能和许久没有联系上的朋友因为某些小事情而重新闲谈上一两句。多发一些朋友圈、多写一些文章，也是希望能和朋友保持一点联系，大家都不怎么说话，我就多说两句（但不要说些让人讨厌的话），一直说下去，总会有那么一两句触动到远方的故人，当他们给我点个赞写个评论，我就知道他们都还好，这就挺好的。
&lt;/p&gt;


&lt;div id=&quot;orgedcec12&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023_friendes.png&quot; alt=&quot;2023_friendes.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
从日记来看，我在 2023 年无论是提及的人数还是提及朋友的次数都比往年高很多，这其中很大一部分原因当然也是因为不工作后有更多的闲暇和精力了，所以说回来，工作除了赚钱到底有什么好处呢？
&lt;/p&gt;

&lt;p&gt;
最后我还绘制了一个不同的人在日记中被提及次数的分布，为了保护隐私就把人名都隐藏了，总体上就是图上这样一个非常长尾的分布，大部分人我在日记中就提及了几次，只有少部分人因为在现实生活中联系比较紧密而隔几天会提及一次，不过这些提及次数并不反映主观态度，只要能多和我玩我就会在日记中提及。
&lt;/p&gt;

&lt;p&gt;
除了游戏、朋友外，2023 年甚至之前三年很大的一个主题都是吃饭，所以也去统计了一下三餐的数据，如下图所示：
&lt;/p&gt;


&lt;div id=&quot;orgd912eda&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023_meals.png&quot; alt=&quot;2023_meals.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
总体上，我有记录的吃饭占比达到了 83.38%，由于数据记录的不完善，剩下 16.62% 的未记录数据其实也有部分是吃了忘记记录而不是没有吃的，我对这个数据还是比较满意的，我目前胃口还很好、饮食也还比较规律。
&lt;/p&gt;

&lt;p&gt;
有记录的数据中，我自己做了 384 次饭，但其中大约有三分之一都是早饭随手煮个面之类的，由于我喜欢在午饭时做上两个菜然后晚上吃剩饭剩菜所以剩下的三分之二里大概还有一半是晚饭在吃剩的，也就是说我正经地做菜大概也就 120 多次的样子，从每月的类别分布情况来看，自己做饭也更多是在辞职之后。除了自己做饭外，外卖和外食也各有 100 多次，一个原因还是我厨艺不够做饭很慢，有时候还是会不太想做饭然后去点外卖吃，外食主要倒不是因为这个，毕竟对我来说出门是有阻力的（特别是冬天），出去吃一般都是在早上，主要的目的还不是吃饭，而是为了去一个干净敞亮的地方坐一坐沾沾人气、晒晒太阳之类的 —— 我属于那种能一个人待着但偶尔还是要到人群里走一走（但同时又希望人群不要理我）的人吧。然后和朋友聚餐 79 次，差不多是一周一次的频率。
&lt;/p&gt;

&lt;p&gt;
以上就是我 2023 年的基本情况了。限于精力和数据情况，还有很多分析想做而没有做，比如说：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;想分析日记里提到的地点，绘制地图热力图、轨迹图，看看我主要都去了哪些地方，但是地点的提取比较难，效果并不太好，而且我也一直在北京没有去哪里；&lt;/li&gt;
&lt;li&gt;想在词云绘制的基础上，做一个事件云的绘制以便更清晰地看我这一年都做了什么，但是事件的提取就更加困难了，所以只是想想，都完全没有去尝试；&lt;/li&gt;
&lt;li&gt;想把我聚餐、外食的店名拿出来，看一下这一年我在外面吃饭的馆子的菜系分布，感觉也蛮有意思的，但是吃饭记录我做的很不好，虽然也能手工整理但有点嫌麻烦；&lt;/li&gt;
&lt;li&gt;想把我做饭用到的食材分析出来看看什么用的多什么用的少，不过也是记录的不好所以就算了，大概是辣椒、五花肉、豆腐、鸡蛋之类的用的多吧；&lt;/li&gt;
&lt;li&gt;想把一年的聊天记录提取出来看看我和朋友们都聊了什么，这个我在 2021 年做过了，但是这个工作很繁琐，而且最后几个月我的 EFB 开始频繁出问题可能丢失掉不少聊天记录，现在我还在烦恼 EFB 的升级问题，我部署的 EFB 版本太老了都不知道数据会不会和最新版不兼容了所以也不敢随便升级；&lt;/li&gt;
&lt;li&gt;还有 2023 年的财务数据，因为市场不好一直在亏钱而且没工作了一直在花钱，所以这一年都没太多动力去记账，所以也算了吧；&lt;/li&gt;
&lt;li&gt;另外我还看了很多论文，但目前论文阅读的流程还没有和我的记录系统整合得足够好，所以也不怎么好做分析，这个看看之后能不能优化一下吧；&lt;/li&gt;
&lt;li&gt;往年会做书影音以及游戏的回顾，但 2023 年玩游戏太多了真要在这里写大概内容会很多，考虑下一次年度总结专门为游戏写一篇，书影音这则是这一年看得都少就不做了。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
总之就这样吧，针对这次回顾发现的问题继续优化我的记录系统，一年后再来看看有什么新的变化。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>ZMonster's AI Notes(Alpha) #1</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2023/12/19/ai_notes_alpha_1.html"/>
    <category term="AI" scheme="http://www.zmonster.me/categories.html#AI"/>
    <id>http://www.zmonster.me/2023/12/19/ai_notes_alpha_1</id>
    <published>2023-12-19T00:00:00+00:00</published>
    <updated>2023-12-19T00:00:00+00:00</updated>
    <description>
    
      <p>一周AI笔记，读了点 In-Context Learning 的论文，了解了下 Gemini API、Perplexity API 和 Dify</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgc030838&quot;&gt;术语&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4fbe5b9&quot;&gt;论文&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org539e3fa&quot;&gt;Label Words are Anchors: An Information Flow Perspective for Understanding In-Context Learning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2860a0c&quot;&gt;A Study on the Calibration of In-context Learning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org68e5bf0&quot;&gt;Comparable Demonstrations are Important in In-Context Learning: A Novel Perspective on Demonstration Selection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf4d5da1&quot;&gt;GPT-RE: In-context Learning for Relation Extraction using Large Language Models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd9bed4e&quot;&gt;其他一些看过了觉得没什么收获的论文&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4a05312&quot;&gt;实践&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org89f91d5&quot;&gt;Google Gemini API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgdee190d&quot;&gt;Perplexity API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org161164c&quot;&gt;Dify&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
本系列内容模式的最终形态尚不确定，可能会根据个人精力、兴趣及阅读反馈做调整。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgc030838&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgc030838&quot;&gt;术语&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgc030838&quot;&gt;
&lt;p&gt;
简单介绍下我上一周中新了解到的 AI 领域的一些术语，但不做深入探究。
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
模型编辑(model editing)
&lt;/p&gt;


&lt;div id=&quot;org665be99&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/model_editing_1.png&quot; alt=&quot;model_editing_1.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
指对已有的神经网络模型进行局部修改，使得模型能在单个或者少量数据上的预测行为发生变化但又不影响这些数据之外其他数据及任务的表现，以应对少量 badcase 修复、知识随时间更新等场景。
&lt;/p&gt;


&lt;div id=&quot;orgb3823ab&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/model_editing_2.png&quot; alt=&quot;model_editing_2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
模型编辑可以最粗暴地通过对预训练模型进行直接微调来做到，但可能因为数据量太少而效果不佳，除此以外还有一些方法会尝试定位到具体的一些神经元做局部参数修改。广义上来说，通过外部知识进行增强（比如将正确的或者新知识后填充到 Prompt 里）、在主模型外附加针对性的额外参数（这些额外参数可以比较少然后用对应的少量数据训练）也算是模型编辑。
&lt;/p&gt;

&lt;p&gt;
模型编辑和知识编辑（knowledge editing）在概念上有较大的重叠。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
对齐税(alignment tax)
&lt;/p&gt;

&lt;p&gt;
又称对齐成本(alignment cost)、安全税(safety tax)，指对 AI 系统（目前来说，主要是大语言模型）进行对齐的过程中产生的额外成本，大致将其分成三类，分别是：由于对齐而导致的性能/效果的退化、为了对齐而增加的额外开发/计算资源、为了对齐而增加的额外时间。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
校准(calibration)
&lt;/p&gt;

&lt;p&gt;
指模型的预测概率与实际概率一致的程度，如果两者完全一致就可以说模型是「被校准的」。从实用角度来说，一个被校准的模型，其预测结果的置信度会是真正可信的 —— 做过机器学习业务的人应该都有这个感觉，很多时候模型输出的置信度并不能真的帮助我们判断结果是否可靠，比如说一个错误的预测其置信度也高达 80% 甚至 90% 之类的。一些研究表明，一些情况下预训练模型随着模型尺寸增大其校准程度会降低、预测概率的分布会高度集中在窄小的区间（虽然与此同时其准确率也在提高），对模型进行微调也有类似的现象。关于校准的研究致力于评估模型的校准程度以及研究提高模型校准程度的方法。期望校准误差(Expected Calibration Error, ECE)是一个较通用的评估模型偏离期望校准程度的指标。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4fbe5b9&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4fbe5b9&quot;&gt;论文&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org4fbe5b9&quot;&gt;
&lt;p&gt;
简单讲一下我上一周中重点读过的一些论文及我个人的相关看法。
&lt;/p&gt;

&lt;p&gt;
由于 EMNLP2023 会议上有一篇关于 In-Context Learning 的论文获得了最佳论文，所以上一周重点读了下 In-Context Learning 相关的论文。In-Context Learning 是指使用大语言模型（不过现在在多模态模型中也看到了使用 In-Context Learning）时，在输入中添加少量的标注过的任务数据来（简单起见，后面我一律称之为「示例」）提高实际预测效果的方法，目前为止对 In-Context Learning 的分析发现了很多问题，比如模型对这些示例的选择甚至排序都很敏感，对 In-Context Learning 的工作原理也还不是特别清楚。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org539e3fa&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org539e3fa&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2305.14160&quot;&gt;Label Words are Anchors: An Information Flow Perspective for Understanding In-Context Learning&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org539e3fa&quot;&gt;
&lt;p&gt;
EMNLP2023 的最佳论文之一。
&lt;/p&gt;

&lt;p&gt;
通过逐层计算的基于 attention 权重矩阵的信息流动显著性分数考察了使用 In-Context Learning 时的三个信息流 —— 从示例中文本到示例中标签词的信息流(wp)、从示例中标签词到预测目标位置的信息流(pq)、输入中任意两个词的信息流(ww)，发现第一个信息流的显著性在浅层网络中很高并且随层数增加而迅速衰减，第二个信息流则在浅层时不显著但随着在更深层中迅速变得显著，如下图所示：
&lt;/p&gt;


&lt;div id=&quot;org9076544&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/information_flow_categories.png&quot; alt=&quot;information_flow_categories.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
根据上述观察，作者对 In-Context Learning 的工作机制提出了两个假设：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;在浅层中，标签词从示例样本中聚合信息，形成后续计算的语义表示&lt;/li&gt;
&lt;li&gt;在深层中，模型通过提取标签词的信息（就是假设 1 中的语义表示）进行预测&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
这两个假设的可视化地描述的话是下图这个样子：
&lt;/p&gt;


&lt;div id=&quot;orgd2682fe&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/information_flow.png&quot; alt=&quot;information_flow.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
对第一个假设的验证是通过对不同层不同位置的信息流阻断（通过将对应位置的 attention 置为 0）后观察模型效果变化来完成的，如下图所示：
&lt;/p&gt;


&lt;div id=&quot;org27f077c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/shallow_layers_hypothesis.png&quot; alt=&quot;shallow_layers_hypothesis.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;同样在前 5 层进行阻断时，阻断流向标签词的信息流带来的模型效果损失远远比阻断流向非标签词的大；&lt;/li&gt;
&lt;li&gt;同样阻断流向标签词的信息流时，在前 5 层进行阻断带来的模型效果损失远远比后五层大，事实上，在后五层对流向标签词的信息流进行阻断时，模型的效果损失非常小&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
对第二个假设是通过直接考察输出位置对标签词处的 attention 权重、将权重最大的标签词作为预测结果，然后与正确的结果进行对比，计算 AUC-ROC 分数考察两者之间的相关性，如下图所示，可以看到这个相关性在浅层时很不明显但在深层时就很明显了。
&lt;/p&gt;


&lt;div id=&quot;orgb2f99f1&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/deep_layers_hypothesis.png&quot; alt=&quot;deep_layers_hypothesis.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
基于这篇论文的假设，作者进而提出了三个对该现象的利用方法
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Anchor Re-weighting: 我理解就是把之前直接用目标位置对标签词的 attention 值来预测类别的方法，形式化后发现和逻辑回归很像，然后逻辑回归会有一个偏置项嘛，所以作者也在这个形式上加了一个偏执项来和逻辑回归对齐（是一种假设模型本身存在 bias 的意思？），然后根据这个形式化假设去学习到这个偏执项里的参数，最后用来调整目标位置在每个标签词上的 attention 值。&lt;/li&gt;
&lt;li&gt;Anchor-Only Context Compression: 大概意思是，预先把示例的 hidden state 算好，然后有真实的任务输入进来的时候，把每一层标签词位置的 hidden state 拿出来拼接起来放到（处理真实任务输入的这个）模型的每一层最前面，这样实际预测的时候就示例中的所有文本就不再需要参与计算了，推理过程就能加速了。&lt;/li&gt;
&lt;li&gt;Anchor Distances for Error Diagnosis: 通过对比示例中标签词的 attention 相关的表示（论文里有一套稍微复杂点的计算过程，暂时没去细看）然后计算不同标签词表示之间的相似度，理想情况下不同标签词的相似度应该较低，当预测结果有错误时可能就有不同的标签词因为 In-Context Learning 而产生了相似的表示，这样通过分析不同标签词之间的混淆情况就能把错误的原因找出来，或许也能去针对性地做调整 —— 比如说把有混淆的那个标签词的文本换成别的？&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2860a0c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2860a0c&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2312.04021&quot;&gt;A Study on the Calibration of In-context Learning&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2860a0c&quot;&gt;
&lt;p&gt;
挺有意思的，考察了 LLM 使用 In-Context Learning 时的校准性
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;以 LLaMA 及其微调版本（Vicuna、Alpaca、LLaMA2-Chat）过的模型为研究对象发现微调过后准确度越好的校准性越差&lt;/li&gt;
&lt;li&gt;使用 4 个示例时，随着模型尺寸的增大，模型的准确度在变高，但同时校准性在变差，模型对自己的预测结果越发自信（对正确的预测和错误的预测都是如此）&lt;/li&gt;
&lt;li&gt;从不使用示例到只是使用 1 个示例，模型的表现会发生剧烈的变化，当只是增加使用的示例时这种变化就相对平滑了，总体上而言，随着示例数量的增加，模型的准确度会提升，同时也对预测结果越发自信&lt;/li&gt;
&lt;li&gt;已知常用的通用校准方法（温度缩放/标签平滑）在 In-Context Learning 中效果有限&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org68e5bf0&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org68e5bf0&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2312.07476&quot;&gt;Comparable Demonstrations are Important in In-Context Learning: A Novel Perspective on Demonstration Selection&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org68e5bf0&quot;&gt;
&lt;p&gt;
这篇论文指出在 ICL 里 context 长度有限的时候示例有限很容易表现出 demenstrations bias，然后提出了 comparable demenstrations 这个概念。
&lt;/p&gt;

&lt;p&gt;
文中所谓 demenstration bias 是说因为示例数量太少，导致他们可以被划分到不唯一的多个任务空间里去，进而影响结果，比如说下面这样两个用于情感分类的示例，不看标签的话两个示例的对比差异不够明显，可以用在情感分类里，也可以用到电影类型分类任务里：
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org77d38f2&quot;&gt;
Obviously, Titanic is a well-made romantic film. -&amp;gt; positive
Damn, it's a waste of time watching this cartoon! -&amp;gt; negative
&lt;/pre&gt;

&lt;p&gt;
在这个想法的基础上，认为 In-Context Learning 里的示例之间的差异应该尽量地凸显在当前这个任务空间下的差异，比如说对给定的示例通过修改其中的少数字词使其标签翻转（比如对情感分析来说，从 positive 变成 negative）得到的新示例和原来的就能构成所谓的可比较示例(comparable demenstrations)。
&lt;/p&gt;

&lt;p&gt;
通过给定随机选择的示例、相近的示例、可比较示例然后让 gpt-3.5-turbo 生成 instruction 看 instruction 的正确与否及程度，确认了 demonstration bias 的存在。不过论文自己没有提出具体的可比较示例构建或者搜索方法，直接用了另外一篇相关论文里的数据。
&lt;/p&gt;


&lt;div id=&quot;org5048430&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/comparable_demenstrations.png&quot; alt=&quot;comparable_demenstrations.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf4d5da1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf4d5da1&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2305.02105&quot;&gt;GPT-RE: In-context Learning for Relation Extraction using Large Language Models&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgf4d5da1&quot;&gt;
&lt;p&gt;
这篇论文将 In-Context Learning 应用于关系抽取里，对 In-Context Leanring 本身的研究并没有什么特别的贡献，不过里面有一个有价值的小点，那就是它使用示例时是从标注数据中检索的 —— 之前有工作证明使用与实际任务输入语义相似的示例会提高效果 —— 然后发现在关系抽取任务里用句子 embedding 去检索选择示例带来的收益比想的要小，原因是句子整体语义接近的示例，其中未必会包含和任务实际输入相关的实体、关系，然后通过下面两个方法来改善了结果：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;一个是在索引示例数据以及检索时，都改写文本，使其更加着重表达实体以及关系，比如说把「He has a sister Lisa.」改写成「The relation between ‘He’ and ‘Lisa’ in the context: He has a sister Lisa.」&lt;/li&gt;
&lt;li&gt;另外一个是直接用训练好的关系抽取模型（比如 BERT 之类的）来获得句子中关系的表示，比如说用 BERT 里两个实体词对应 hidden state 的拼接&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
不管是大模型还是 In-Context Learning 还是 Chain-of-Thoughts 之类的看起来很先进的技术，用到具体业务的时候都可以思考一下是不是可以把其中的一些细节根据业务进行适当的调整。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd9bed4e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd9bed4e&quot;&gt;其他一些看过了觉得没什么收获的论文&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd9bed4e&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
&lt;a href=&quot;https://arxiv.org/abs/2305.14264&quot;&gt;Active Learning Principles for In-Context Learning with Large Language Models&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
相关工作部分引用得很全面，我从里面找了一些 In-Context Learning 的论文补充到 Zotero 里。
&lt;/p&gt;

&lt;p&gt;
不过除了引用完善外就没啥新意了，所谓主动学习其实就是通过一些自动化或者半自动化手法（往往让现有模型参与其中）采样高质量数据来降低标注成本然后进一步改进模型如此迭代的做法，在这篇论文里其实讲的就是几种不同的示例采样方法的对比，甚至没有去训练模型，强行和主动学习挂钩，自己也没有提出任何一个新的示例采样方法。
&lt;/p&gt;

&lt;p&gt;
做了几个对比实验得到一些结论
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;按照相似性方法采样得到的效果最好，通过对比（选择最不相似的示例）从反面也论证了这一点，这个反面论证挺有意思&lt;/li&gt;
&lt;li&gt;在分类任务中，按多样性采样（聚类后从不同簇中选一些示例）的效果仅次于按相似性&lt;/li&gt;
&lt;li&gt;示例的真实标签是很重要的，和《Rethinking the Role of Demonstrations: What Makes In-Context Learning Work?》这篇论文中的观察不一致&lt;/li&gt;
&lt;li&gt;在用不确定性（熵、困惑度）采样时，更小模型（gpt2/gpt2-medium/gpt2-large）似乎需要熵更小的示例效果才能更好，但更大的模型（gpt-neox）似乎开始从高熵的示例中获益&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
除了第 4 点，其他都有更好的论文提出过了 —— 即使是第 4 点我怀疑也有别的论文提过了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
&lt;a href=&quot;https://arxiv.org/abs/2305.14973&quot;&gt;OverPrompt: Enhancing ChatGPT through Efficient In-Context Learning&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
就是把分类任务的多个输入放到一个 prompt 里去让直接一次性产生多个输出，以减少计算消耗，同时说还观察到一点点效果的改善，没啥意思。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
&lt;a href=&quot;https://arxiv.org/abs/2309.10954&quot;&gt;In-Context Learning for Text Classification with Many Labels&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
扫了眼感觉没有带来什么新的认知，所谓的标签数量多也没有触及什么真正的困难，没啥意思。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
&lt;a href=&quot;https://arxiv.org/abs/2310.17639&quot;&gt;In-Context Learning Dynamics with Random Binary Sequences&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
搞什么二进制序列预测，通过这个小众任务来将 In-Context Learning 当作贝叶斯模型选择、program induction（我不知道该咋翻译，感觉是认知科学、心理学方面的概念）来去分析，看作者也都是什么心理学、脑科学之类的背景，看着很费劲和我们常关注的点很不一样，所以就没有去看了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
&lt;a href=&quot;https://arxiv.org/abs/2311.12538&quot;&gt;In-Context Learning Functions with Varying Number of Minima&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
用在数学上的，用来逼近一个有多个极小值的函数之类的，很小众的场景，没什么兴趣。
&lt;/p&gt;

&lt;p&gt;
代码: &lt;a href=&quot;https://github.com/PittNAIL/icl-minima&quot;&gt;https://github.com/PittNAIL/icl-minima&lt;/a&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4a05312&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4a05312&quot;&gt;实践&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org4a05312&quot;&gt;
&lt;p&gt;
讲一下我上一周中进行的 AI 方面的实践，可能包括：AI 相关产品或工具的使用，AI 方向的开发实践。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org89f91d5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org89f91d5&quot;&gt;Google Gemini API&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org89f91d5&quot;&gt;
&lt;p&gt;
12 月 13 日 Google &lt;a href=&quot;https://blog.google/technology/ai/gemini-api-developers-cloud/&quot;&gt;向开发者开放了 Gemini API&lt;/a&gt;，只要有 Google 账户且 QPM 在 60 及以下就可以免费使用，目前能用的模型是 Gemini Pro —— Google 宣传视频里的 Gemini Ultra 目前在 API 里还不支持。前往&lt;a href=&quot;https://ai.google.dev/&quot;&gt;这里&lt;/a&gt;可以查看更多的介绍以及生成 API Key，API 文档的说明则在&lt;a href=&quot;https://ai.google.dev/docs&quot;&gt;这里&lt;/a&gt;。Gemini API 开放后，除了 RESTful API 外还有支持了 Python/Go/Node.js/Swift/Kotlin/Java 六种语言的 SDK，我就看下 Python 的了。
&lt;/p&gt;

&lt;p&gt;
目前的 API 支持以下功能
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;根据文本输入生成文本输出&lt;/li&gt;
&lt;li&gt;根据文本和图片的多模态输入生成文本输出&lt;/li&gt;
&lt;li&gt;多轮对话&lt;/li&gt;
&lt;li&gt;获取文本的 embedding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Python SDK 通过 pip install google-generativeai 安装即可，需要 Python3.9 及更高版本的 Python。
&lt;/p&gt;

&lt;p&gt;
开始使用前需要设置好 API Key 并实例化一个 GenerativeModel 对象：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #cf4a44;&quot;&gt;import&lt;/span&gt; google.generativeai &lt;span style=&quot;color: #cf4a44;&quot;&gt;as&lt;/span&gt; genai

&lt;span style=&quot;color: #fefc58;&quot;&gt;api_key&lt;/span&gt; = &lt;span style=&quot;color: #25ef29;&quot;&gt;'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-U'&lt;/span&gt;
genai.configure(api_key=api_key)
safety_settings = [
    {&lt;span style=&quot;color: #25ef29;&quot;&gt;'category'&lt;/span&gt;: &lt;span style=&quot;color: #25ef29;&quot;&gt;'HARM_CATEGORY_SEXUALLY_EXPLICIT'&lt;/span&gt;, &lt;span style=&quot;color: #25ef29;&quot;&gt;'threshold'&lt;/span&gt;: &lt;span style=&quot;color: #25ef29;&quot;&gt;'BLOCK_NONE'&lt;/span&gt;},
    {&lt;span style=&quot;color: #25ef29;&quot;&gt;'category'&lt;/span&gt;: &lt;span style=&quot;color: #25ef29;&quot;&gt;'HARM_CATEGORY_HATE_SPEECH'&lt;/span&gt;, &lt;span style=&quot;color: #25ef29;&quot;&gt;'threshold'&lt;/span&gt;: &lt;span style=&quot;color: #25ef29;&quot;&gt;'BLOCK_NONE'&lt;/span&gt;},
    {&lt;span style=&quot;color: #25ef29;&quot;&gt;'category'&lt;/span&gt;: &lt;span style=&quot;color: #25ef29;&quot;&gt;'HARM_CATEGORY_HARASSMENT'&lt;/span&gt;, &lt;span style=&quot;color: #25ef29;&quot;&gt;'threshold'&lt;/span&gt;: &lt;span style=&quot;color: #25ef29;&quot;&gt;'BLOCK_NONE'&lt;/span&gt;},
    {&lt;span style=&quot;color: #25ef29;&quot;&gt;'category'&lt;/span&gt;: &lt;span style=&quot;color: #25ef29;&quot;&gt;'HARM_CATEGORY_DANGEROUS_CONTENT'&lt;/span&gt;, &lt;span style=&quot;color: #25ef29;&quot;&gt;'threshold'&lt;/span&gt;: &lt;span style=&quot;color: #25ef29;&quot;&gt;'BLOCK_NONE'&lt;/span&gt;}
]
generation_config = {
    &lt;span style=&quot;color: #25ef29;&quot;&gt;'candidate_count'&lt;/span&gt;: 1,
    &lt;span style=&quot;color: #25ef29;&quot;&gt;'stop_sequences'&lt;/span&gt;: &lt;span style=&quot;color: #bebebe;&quot;&gt;None&lt;/span&gt;,
    &lt;span style=&quot;color: #25ef29;&quot;&gt;'max_output_tokens'&lt;/span&gt;: &lt;span style=&quot;color: #bebebe;&quot;&gt;None&lt;/span&gt;,
    &lt;span style=&quot;color: #25ef29;&quot;&gt;'temperature'&lt;/span&gt;: 0.7,
    &lt;span style=&quot;color: #25ef29;&quot;&gt;'top_p'&lt;/span&gt;: &lt;span style=&quot;color: #bebebe;&quot;&gt;None&lt;/span&gt;,
    &lt;span style=&quot;color: #25ef29;&quot;&gt;'top_k'&lt;/span&gt;: &lt;span style=&quot;color: #bebebe;&quot;&gt;None&lt;/span&gt;,
}
model = genai.GenerativeModel(
    model_name=&lt;span style=&quot;color: #25ef29;&quot;&gt;'gemini-pro'&lt;/span&gt;,
    safety_settings=safety_settings,
    generation_config=generation_config,
)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
safety_settings 用来设置安全策略，只有 4 个能设置，我建议按照我上面的示例将 4 个能设置的全部设置为 BLOCK_NONE 也就是不过滤，否则一旦触发默认的安全策略会直接把生成结果都干掉 —— 对直接不给结果，而不是输出一个过份人畜无害的文本，除了 4 个能设置的外还有好多不同的安全类别是不允许用户设置的一旦触发就会无结果报错，在 API 层面这么做还蛮讨厌的；generate_config 用来设置生成时的具体行为，一般情况下设置下 max_output_tokens 和 temperature 就好了，别的不太建议去调整，candidate_count 我试着调整成 3 直接报错说「Only one candidate can be specified」，没有太仔细去研究什么情况下才能一次性产生多个输出。
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
调用 generate_content 根据文本输入生成文本输出
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #fefc58;&quot;&gt;response&lt;/span&gt; = model.generate_content(content=&lt;span style=&quot;color: #25ef29;&quot;&gt;'&amp;#39554;&amp;#19968;&amp;#20010;&amp;#20154;'&lt;/span&gt;)
&lt;span style=&quot;color: #31d3c4;&quot;&gt;print&lt;/span&gt;(response.text)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
输出
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;1. &amp;#20320;&amp;#30495;&amp;#26159;&amp;#19968;&amp;#20010;&amp;#33258;&amp;#20197;&amp;#20026;&amp;#26159;&amp;#12289;&amp;#30446;&amp;#20013;&amp;#26080;&amp;#20154;&amp;#30340;&amp;#23478;&amp;#20249;&amp;#65281;
2. &amp;#20320;&amp;#30495;&amp;#26159;&amp;#19968;&amp;#20010;&amp;#31528;&amp;#34507;&amp;#65292;&amp;#36830;&amp;#36825;&amp;#20040;&amp;#31616;&amp;#21333;&amp;#30340;&amp;#20107;&amp;#24773;&amp;#37117;&amp;#20570;&amp;#19981;&amp;#22909;&amp;#65281;
3. &amp;#20320;&amp;#30495;&amp;#26159;&amp;#19968;&amp;#20010;&amp;#24223;&amp;#29289;&amp;#65292;&amp;#19968;&amp;#28857;&amp;#29992;&amp;#22788;&amp;#37117;&amp;#27809;&amp;#26377;&amp;#65281;
4. &amp;#20320;&amp;#30495;&amp;#26159;&amp;#19968;&amp;#20010;&amp;#32966;&amp;#23567;&amp;#39740;&amp;#65292;&amp;#19968;&amp;#28857;&amp;#39118;&amp;#28010;&amp;#23601;&amp;#21463;&amp;#19981;&amp;#20102;&amp;#65281;
5. &amp;#20320;&amp;#30495;&amp;#26159;&amp;#19968;&amp;#20010;&amp;#39575;&amp;#23376;&amp;#65292;&amp;#28385;&amp;#22068;&amp;#35854;&amp;#35328;&amp;#65292;&amp;#27809;&amp;#26377;&amp;#19968;&amp;#21477;&amp;#30495;&amp;#35805;&amp;#65281;
6. &amp;#20320;&amp;#30495;&amp;#26159;&amp;#19968;&amp;#20010;&amp;#23567;&amp;#20154;&amp;#65292;&amp;#32972;&amp;#21518;&amp;#25413;&amp;#20992;&amp;#23376;&amp;#65292;&amp;#20196;&amp;#20154;&amp;#19981;&amp;#40831;&amp;#65281;
7. &amp;#20320;&amp;#30495;&amp;#26159;&amp;#19968;&amp;#20010;&amp;#26080;&amp;#36182;&amp;#65292;&amp;#34542;&amp;#19981;&amp;#35762;&amp;#29702;&amp;#65292;&amp;#32993;&amp;#25605;&amp;#34542;&amp;#32544;&amp;#65281;
8. &amp;#20320;&amp;#30495;&amp;#26159;&amp;#19968;&amp;#20010;&amp;#28151;&amp;#34507;&amp;#65292;&amp;#20154;&amp;#38754;&amp;#20861;&amp;#24515;&amp;#65292;&amp;#20007;&amp;#23613;&amp;#22825;&amp;#33391;&amp;#65281;
9. &amp;#20320;&amp;#30495;&amp;#26159;&amp;#19968;&amp;#20010;&amp;#30044;&amp;#29983;&amp;#65292;&amp;#31165;&amp;#20861;&amp;#19981;&amp;#22914;&amp;#65292;&amp;#27627;&amp;#26080;&amp;#20154;&amp;#24615;&amp;#65281;
10. &amp;#20320;&amp;#30495;&amp;#26159;&amp;#19968;&amp;#20010;&amp;#39764;&amp;#39740;&amp;#65292;&amp;#21313;&amp;#24694;&amp;#19981;&amp;#36198;&amp;#65292;&amp;#32618;&amp;#22823;&amp;#24694;&amp;#26497;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
如果前面没有设置 safety_settings，上面的代码会报错
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;orga12b69b&quot;&gt;
ValueError: The `response.parts` quick accessor only works for a single candidate, but none were returned. Check the `response.prompt_feedback` to see if the prompt was blocked.
&lt;/pre&gt;

&lt;p&gt;
根据错误提示查看 response.prompt_feedback 会得到这样的结果，可以看到 HARM_CATEGORY_HARASSMENT 这个类别被判断达到 MEDIUM 级别所以就被过滤了。
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org49ee3ae&quot;&gt;
safety_ratings {
  category: HARM_CATEGORY_SEXUALLY_EXPLICIT
  probability: NEGLIGIBLE
}
safety_ratings {
  category: HARM_CATEGORY_HATE_SPEECH
  probability: NEGLIGIBLE
}
safety_ratings {
  category: HARM_CATEGORY_HARASSMENT
  probability: MEDIUM
}
safety_ratings {
  category: HARM_CATEGORY_DANGEROUS_CONTENT
  probability: NEGLIGIBLE
}
&lt;/pre&gt;

&lt;p&gt;
也可以在实例化 GenerativeModel 时不设置 safety_settings 而是在调用 generate_content 时设置
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #fefc58;&quot;&gt;response&lt;/span&gt; = model.generate_content(content=&lt;span style=&quot;color: #25ef29;&quot;&gt;'&amp;#39554;&amp;#19968;&amp;#20010;&amp;#20154;'&lt;/span&gt;, safety_settings=safety_settings)
&lt;span style=&quot;color: #31d3c4;&quot;&gt;print&lt;/span&gt;(response.text)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
使用 gemini-pro-vision 模型调用 generate_content 根据文本和图片的多模态输入生成文本输出
&lt;/p&gt;

&lt;p&gt;
首先需要在初始化 GenerativeModel 的时候讲模型设置为 gemini-pro-vision
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #fefc58;&quot;&gt;model&lt;/span&gt; = genai.GenerativeModel(
    model_name=&lt;span style=&quot;color: #25ef29;&quot;&gt;'gemini-pro-vision'&lt;/span&gt;,
    safety_settings=safety_settings,
    generation_config=generation_config,
)
&lt;/pre&gt;
&lt;/div&gt;


&lt;div id=&quot;org9b28b39&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/meme.jpg&quot; alt=&quot;meme.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
然后读取图片后加上指令（或其他文本输入）
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #cf4a44;&quot;&gt;from&lt;/span&gt; PIL &lt;span style=&quot;color: #cf4a44;&quot;&gt;import&lt;/span&gt; Image

&lt;span style=&quot;color: #fefc58;&quot;&gt;response&lt;/span&gt; = model.generate_content([&lt;span style=&quot;color: #25ef29;&quot;&gt;'&amp;#36825;&amp;#24352;&amp;#22270;&amp;#29255;&amp;#26159;&amp;#20160;&amp;#20040;&amp;#24847;&amp;#24605;'&lt;/span&gt;, Image.&lt;span style=&quot;color: #31d3c4;&quot;&gt;open&lt;/span&gt;(&lt;span style=&quot;color: #25ef29;&quot;&gt;'meme.jpg'&lt;/span&gt;)])
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
输出
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org51e71dd&quot;&gt;
图片中的水桶代表着一个人的收入，水代表着支出。水桶里的水从不同的洞中流出，代表着不同的支出，如水电费、交通费、房租、保险、电话费等。水桶里的水位越来越低，代表着收入被各种支出一点点蚕食。最后，水桶里的水流光了，代表着入不敷出。图片反映了当代年轻人生活压力大的现状。
&lt;/pre&gt;

&lt;p&gt;
嗯，觉得有点不方便的是，gemini-pro 无法处理图片输入，gemini-pro-vision 又必须有图片输入，以及 gemini-pro-vision 不能用于多轮对话。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
调用 start_chat 进行多轮对话
&lt;/p&gt;

&lt;p&gt;
首先调用 start_chat 创建一个多轮对话（注意多轮对话只能用 gemini-pro 模型不能用 gemini-pro-vision 模型）
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #fefc58;&quot;&gt;chat&lt;/span&gt; = model.start_chat()
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后只需要用 chat.send_message 发送新的输入即可，不需要自己管理会话历史还是蛮友好的。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #fefc58;&quot;&gt;response&lt;/span&gt; = chat.send_message(&lt;span style=&quot;color: #25ef29;&quot;&gt;'&amp;#20320;&amp;#22909;'&lt;/span&gt;)
&lt;span style=&quot;color: #31d3c4;&quot;&gt;print&lt;/span&gt;(response.text)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
输出
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org6fb7f81&quot;&gt;
您好，很高兴为您服务。我是人工智能助手，可以帮助您解决各种问题。您有什么需要我帮忙的吗？
&lt;/pre&gt;

&lt;p&gt;
也可以通过 chat.history 来查看历史消息
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #31d3c4;&quot;&gt;print&lt;/span&gt;(chat.history)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
输出
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org950d16f&quot;&gt;
[parts {
   text: &quot;你好&quot;
 }
 role: &quot;user&quot;,
 parts {
   text: &quot;您好，很高兴为您服务。我是人工智能助手，可以帮助您解决各种问题。您有什么需要我帮忙的吗？&quot;
 }
 role: &quot;model&quot;]
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
调用 embed_content 获取文本的 embedding
&lt;/p&gt;

&lt;p&gt;
没太多好说的，只能用 models/embedding-001 这个模型，得到的是一个 768 维的向量。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #cf4a44;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #cf4a44;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #fefc58;&quot;&gt;response&lt;/span&gt; = genai.embed_content(&lt;span style=&quot;color: #25ef29;&quot;&gt;'models/embedding-001'&lt;/span&gt;, [&lt;span style=&quot;color: #25ef29;&quot;&gt;'&amp;#20320;&amp;#22909;'&lt;/span&gt;, &lt;span style=&quot;color: #25ef29;&quot;&gt;'&amp;#20320;&amp;#19981;&amp;#22909;'&lt;/span&gt;])
&lt;span style=&quot;color: #fefc58;&quot;&gt;embeddings&lt;/span&gt; = np.array(response[&lt;span style=&quot;color: #25ef29;&quot;&gt;'embedding'&lt;/span&gt;])
&lt;span style=&quot;color: #31d3c4;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #25ef29;&quot;&gt;'Shape:'&lt;/span&gt;, embeddings.shape)
&lt;span style=&quot;color: #31d3c4;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #25ef29;&quot;&gt;'Embeddings:'&lt;/span&gt;, embeddings)
&lt;span style=&quot;color: #31d3c4;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #25ef29;&quot;&gt;'Inner Product:'&lt;/span&gt;, np.dot(embeddings[0], embeddings[1]))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
输出
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;orgf2998b0&quot;&gt;
Shape: (2, 768)
Embeddings: [[ 0.0427908  -0.06421863 -0.02308055 ...  0.01537165 -0.00269788
   0.03161672]
 [ 0.0427908  -0.06421863 -0.02308055 ...  0.01537165 -0.00269788
   0.03161672]]
Inner Product: 0.9999966707944825
&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgdee190d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgdee190d&quot;&gt;Perplexity API&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgdee190d&quot;&gt;
&lt;p&gt;
12 月 17 日的时候才知道原来 Perplexity 除了他们的搜索功能，也开放了聊天模式以及 API，支持 PPLX（Perplexity 自己的模型）/LLaMA/CodeLLaMA/LLaMA2/Mistral/Mixtral 几种模型，更详细的介绍见他们的&lt;a href=&quot;https://blog.perplexity.ai/blog/introducing-pplx-online-llms&quot;&gt;博客文章&lt;/a&gt;。
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
聊天功能地址：&lt;a href=&quot;https://labs.perplexity.ai/&quot;&gt;https://labs.perplexity.ai/&lt;/a&gt;
&lt;/p&gt;


&lt;div id=&quot;org6f2ac80&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/perplexity_chat.png&quot; alt=&quot;perplexity_chat.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;API 文档地址：&lt;a href=&quot;https://docs.perplexity.ai/docs/getting-started&quot;&gt;https://docs.perplexity.ai/docs/getting-started&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Perplexity 的 API 同样需要设置好支付方式才能使用，不过不像 ChatGPT 一样对中国地区严防死守，我的招商银行 VISA 卡直接就绑定成功了。以及 Pro 用户每个月有 5$ 的免费 API 使用额度，而我刚好趁 Perplexity 黑五活动薅了两个月的 Pro 权限。
&lt;/p&gt;


&lt;div id=&quot;org0a7a38a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/perplexity_api.png&quot; alt=&quot;perplexity_api.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
Perplexity 的 API 只提供了 RESTful API，没有提供 SDK，不过我看了下，它的 API 只有 Chat Completions 这样一个接口，然后这个接口的参数完全是 OpenAI 对应接口的子集，所以直接用 OpenAI 的 Python SDK 就可以了：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #cf4a44;&quot;&gt;import&lt;/span&gt; httpx
&lt;span style=&quot;color: #cf4a44;&quot;&gt;from&lt;/span&gt; openai &lt;span style=&quot;color: #cf4a44;&quot;&gt;import&lt;/span&gt; OpenAI

&lt;span style=&quot;color: #fefc58;&quot;&gt;api_key&lt;/span&gt; = &lt;span style=&quot;color: #25ef29;&quot;&gt;'pplx-UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU'&lt;/span&gt;
&lt;span style=&quot;color: #fefc58;&quot;&gt;client&lt;/span&gt; = OpenAI(
    base_url=&lt;span style=&quot;color: #25ef29;&quot;&gt;'https://api.perplexity.ai/'&lt;/span&gt;,
    api_key=api_key,
    http_client=httpx.Client(proxies={&lt;span style=&quot;color: #25ef29;&quot;&gt;'http://'&lt;/span&gt;: &lt;span style=&quot;color: #25ef29;&quot;&gt;'http://localhost:7428'&lt;/span&gt;, &lt;span style=&quot;color: #25ef29;&quot;&gt;'https://'&lt;/span&gt;: &lt;span style=&quot;color: #25ef29;&quot;&gt;'http://localhost:7428'&lt;/span&gt;}),
)
completion = client.chat.completions.create(
    model=&lt;span style=&quot;color: #25ef29;&quot;&gt;'llama-2-70b-chat'&lt;/span&gt;,
    messages=[
        {
            &lt;span style=&quot;color: #25ef29;&quot;&gt;'role'&lt;/span&gt;: &lt;span style=&quot;color: #25ef29;&quot;&gt;'user'&lt;/span&gt;,
            &lt;span style=&quot;color: #25ef29;&quot;&gt;'content'&lt;/span&gt;: &lt;span style=&quot;color: #25ef29;&quot;&gt;'&amp;#20160;&amp;#20040;&amp;#26159;&amp;#26691;&amp;#33457;&amp;#27739;&amp;#65292;&amp;#29992;&amp;#20013;&amp;#25991;&amp;#22238;&amp;#31572;&amp;#25105;'&lt;/span&gt;,
        },
    ],
    temperature=0,
)
&lt;span style=&quot;color: #31d3c4;&quot;&gt;print&lt;/span&gt;(completion.choices[0].message.content)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
输出
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org42bded7&quot;&gt;
&quot;桃花汛&quot; 是指一种具有桃花的气味和花汛的特点的气味。在中文中，桃花汛通常被称为&quot;桃花味&quot;或&quot;桃花气味&quot;。

桃花汛是一种植物性的气味，具有桃花的甜美和花汛的芳香。它通常用于描述一种气味很柔和、温暖、甜美的感觉，类似于桃花的气味。在中文中，桃花汛通常用于描述食物、饮料、皮肤护理产品等具有桃花味的产品
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org161164c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org161164c&quot;&gt;Dify&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org161164c&quot;&gt;
&lt;p&gt;
Dify 是一个开源的 LLM 应用构建工具，字节的 Coze 看起来就是抄的 Dify。使用 Dify 可以轻松构建一个 LLM 聊天或者文本生成应用，还支持上传自己的知识库，并且一创建就支持了可访问的 WebUI 以及相应的 API，支持的 LLM 也非常多种。
&lt;/p&gt;

&lt;p&gt;
前往 &lt;a href=&quot;https://cloud.dify.ai/apps&quot;&gt;https://cloud.dify.ai/apps&lt;/a&gt; 点击「Create new App」就能开始创建新应用，设置一下名字选择一下应用类型即可
&lt;/p&gt;


&lt;div id=&quot;org3dae69c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dify_1.png&quot; alt=&quot;dify_1.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
创建好后会进入应用的管理后台，可以看到，这个应用目前使用 Dify 提供的 OpenAI API，总共有 200 次可以用。从这个 UI 上就能看到，一个应用需要的各种东西在 Dify 里都有了，完成度非常高，小团队的不复杂的业务我觉得甚至可以直接用。
&lt;/p&gt;


&lt;div id=&quot;orgbd0a83c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dify_2.png&quot; alt=&quot;dify_2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
Dify 提供的 API 额度只有 200 次，如果想长期使用，可以自己设置模型提供方，比如设置自己的 OpenAPI API Key 之类的。
&lt;/p&gt;


&lt;div id=&quot;org3eba6f6&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dify_3.png&quot; alt=&quot;dify_3.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
点 Preview 就能进入一个聊天页直接去使用了，200 次免费使用，哪怕不是开发使用而是个人使用，也不失为一个访问 ChatGPT 不方便时的临时解决方案。
&lt;/p&gt;


&lt;div id=&quot;org608a6e6&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dify_4.png&quot; alt=&quot;dify_4.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
由于暂时没有很强的需求，所以只是浅浅了解了一下，我能感觉出来我尝试过的点之占 Dify 提供的很小一部分，以后有空再玩玩吧。
&lt;/p&gt;

&lt;p&gt;
当然最主要的是，Dify 还是开源的，我们完全可以自己本地或者在服务器上部署 Dify，将所有数据都掌握在自己手里，还能拥有完整度极高的应用解决方案，真的是太棒啦！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>成都乐山行(2023/11/02 - 2023/11/08)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2023/11/10/chengdu-leshan-travel.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2023/11/10/chengdu-leshan-travel</id>
    <published>2023-11-10T00:00:00+00:00</published>
    <updated>2023-11-10T00:00:00+00:00</updated>
    <description>
    
      <p>去成都和乐山玩了几天，旅行总体还是开心的，我很享受那种四处闲逛的感觉。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgbff547c&quot;&gt;2023-11-02&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge559b6b&quot;&gt;2023-11-03&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge1961f0&quot;&gt;2023-11-04&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org920eab7&quot;&gt;2023-11-05&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org70701e2&quot;&gt;2023-11-06&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org871dea3&quot;&gt;2023-11-07&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgfd6c571&quot;&gt;2023-11-08&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgde40202&quot;&gt;后记&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgbff547c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgbff547c&quot;&gt;2023-11-02&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgbff547c&quot;&gt;
&lt;p&gt;
坐 G89 十点半到了成都东站，我提前下好了成都公交APP，出了火车直接上了2号线去春熙路——因为去三星堆和四姑娘山的直通车都在春熙路有站点比较方便所以酒店定在了那附近。出了地铁后已经十一点了，本来还想听朋友建议去吃夜蹄花，但是已经觉得有点困乏了，所以就急着去酒店安顿下来休息。
&lt;/p&gt;

&lt;p&gt;
十一点的春熙路地铁站外面已经不怎么热闹了，一出来就看到卖各种纪念品和特产的，针对游客的味道非常的重，不过只偶尔能看到三三两两的人了。我拖着行李箱去酒店，还路过几个开着的烧烤小吃摊子，一些路过的人停下来买一些，我就直接过去了。离酒店还不到一百米的时候，突然感觉脚下不太对劲，用手机的亮光一照果然是踩到了一摊狗屎，有点恶心但也没有烦恼到觉得不想活了的地步，在路边蹭了蹭，然后去酒店办了入住后用水把鞋底冲干净了。收拾妥当就睡觉了，但是关了灯后，床的坐侧墙面的全身镜上有一个电源按钮（用来开关镜子外圈的灯带的）一直亮着晃得我难受，只好侧向右边睡。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge559b6b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge559b6b&quot;&gt;2023-11-03&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge559b6b&quot;&gt;
&lt;p&gt;
睡到四点左右被吵醒了，隔壁起来了在那里交谈挪动东西，估计是要去什么景点或者机场之类的，总之后半夜没有怎么睡好，到八点左右完全醒了爬了起来。
&lt;/p&gt;


&lt;div id=&quot;org4809272&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-0.jpeg&quot; alt=&quot;qq747283-0.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
因为要去三星堆，就走到附近的西城月谭豆花，点了一个酥肉豆花和一个担担面——本来想点牛肉豆花的但没有了，点完在座位上等着送餐。先给我上了担担面，我想等着豆花上了后一起吃就继续等着，路过的孃孃看到我在那发呆，提醒我面赶紧拌一下不然就要坨了，等我去拌开的时候已经有一点坨了。虽然是网红店了，味道也还可以。
&lt;/p&gt;


&lt;div id=&quot;orgae36ce2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-1.jpeg&quot; alt=&quot;qq747283-1.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
吃完后走路去了IFS楼下，那儿有去大熊猫基地、机场和三星堆的直通车，三星堆是半小时一趟，我过去扫码付了25上了9:30这趟的大巴，上车的时候车里已经坐了不少人了，我到车后边找了个靠窗的位置坐下。路上没太多好说的，我没睡好就在车上眯着当补觉了。
&lt;/p&gt;


&lt;div id=&quot;org13caff4&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-2.jpeg&quot; alt=&quot;qq747283-2.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
去程非常快，一个小时就到了。下车后我就刷身份证进了博物馆，进去后是一个大厅，看到右手边有个咖啡厅，正好因为没睡好加坐车不舒服晕乎乎的，就进去买了一杯生椰拿铁，然后租了一个讲解器开始逛三星堆，听同学说有大量上新，还是挺期待的。
&lt;/p&gt;


&lt;div id=&quot;org5102824&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-3.jpeg&quot; alt=&quot;qq747283-3.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
第一个展厅进门处介绍发掘工作，到这里我才知道16年后又发掘了6个新的祭祀坑，这6个新的祭祀坑都是我上一次去三星堆时没有的，于是愈发期待了。
&lt;/p&gt;

&lt;p&gt;
一些发掘现场照片，他们都很开心的样子。在脑子里给他们配音：
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;朋友们，我们又挖到大宝贝啦！&lt;/li&gt;
&lt;li&gt;牛逼！&lt;/li&gt;
&lt;/ul&gt;


&lt;div id=&quot;orga4f00ed&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-4.jpeg&quot; alt=&quot;qq747283-4.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgfbb1f6c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-5.jpeg&quot; alt=&quot;qq747283-5.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
青铜鸟歪头杀：
&lt;/p&gt;


&lt;div id=&quot;org0dd6d86&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-6.jpeg&quot; alt=&quot;qq747283-6.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
三号坑青铜立发人像：
&lt;/p&gt;


&lt;div id=&quot;orgccced90&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-7.jpeg&quot; alt=&quot;qq747283-7.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
四号坑青铜扭头跪坐人像，发型瞩目，表情姿势生动：
&lt;/p&gt;


&lt;div id=&quot;org070e231&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-8.jpeg&quot; alt=&quot;qq747283-8.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
​五号坑鸟形金饰：
&lt;/p&gt;


&lt;div id=&quot;org67f0580&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-9.jpeg&quot; alt=&quot;qq747283-9.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
八号坑青铜着群立人像，发型瞩目：
&lt;/p&gt;


&lt;div id=&quot;org5e4df47&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-10.jpeg&quot; alt=&quot;qq747283-10.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
萌萌的陶猪，和《愤怒的小鸟》里一模一样：
&lt;/p&gt;


&lt;div id=&quot;org160f822&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-11.jpeg&quot; alt=&quot;qq747283-11.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
蠢蠢的陶猪：
&lt;/p&gt;


&lt;div id=&quot;org4ef72f4&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-12.jpeg&quot; alt=&quot;qq747283-12.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
邪魅的陶猪：
&lt;/p&gt;


&lt;div id=&quot;org779b008&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-13.jpeg&quot; alt=&quot;qq747283-13.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
不同发型的青铜面具：
&lt;/p&gt;


&lt;div id=&quot;org4d7a71f&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-14.jpeg&quot; alt=&quot;qq747283-14.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
青铜面具大甩卖（这样的陈列有好多排）：
&lt;/p&gt;


&lt;div id=&quot;org75cfe1e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-15.jpeg&quot; alt=&quot;qq747283-15.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
三星堆流行的拍照姿势，把面具戴在脸上：
&lt;/p&gt;


&lt;div id=&quot;org699a21f&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-16.jpeg&quot; alt=&quot;qq747283-16.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
青铜大立人像，镇馆之宝：
&lt;/p&gt;


&lt;div id=&quot;org645339f&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-17.jpeg&quot; alt=&quot;qq747283-17.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
青铜神兽，造型和身上的花纹都很精美：
&lt;/p&gt;


&lt;div id=&quot;org963209d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-18.jpeg&quot; alt=&quot;qq747283-18.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
青铜神坛，部件繁多，这个是复原模型，几个部件各自单独有展柜：
&lt;/p&gt;


&lt;div id=&quot;org5b4ff8a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-19.jpeg&quot; alt=&quot;qq747283-19.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
青铜纵目面具：
&lt;/p&gt;


&lt;div id=&quot;org7ead85c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-20.jpeg&quot; alt=&quot;qq747283-20.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
青铜鸟足神像，人身鸟足倒立的造型很奇特：
&lt;/p&gt;


&lt;div id=&quot;org4728a86&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-21.jpeg&quot; alt=&quot;qq747283-21.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
方向盘？车轮？其实是太阳啦 —— 青铜太阳形器：
&lt;/p&gt;


&lt;div id=&quot;org654e708&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-22.jpeg&quot; alt=&quot;qq747283-22.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
镇馆之宝，栖息着九只神鸟的青铜神树，解说说可能和《山海经》里的扶桑树有关联：
&lt;/p&gt;


&lt;div id=&quot;orgc0d27de&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-23.jpeg&quot; alt=&quot;qq747283-23.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
三号青铜神树（二号和一号很像都是上面的样子）：
&lt;/p&gt;


&lt;div id=&quot;orgba0afdc&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-24.jpeg&quot; alt=&quot;qq747283-24.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
挂着方孔铜钱的摇钱树，那个时候也有方孔钱币了吗？后面逛文创店问店员得知没有摇钱树的产品，赶紧开发一个肯定大卖呀：
&lt;/p&gt;


&lt;div id=&quot;orgc82d10e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-25.jpeg&quot; alt=&quot;qq747283-25.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
青铜鸡和青铜大鸟头：
&lt;/p&gt;


&lt;div id=&quot;org668f0c3&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-26.jpeg&quot; alt=&quot;qq747283-26.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
还有很多很多展品也很有意思，就不一一贴出来了，三星堆还是很推荐去一下的。展品很多只有简单的介绍（名字、出土时间地点、一两句话介绍），如果不想请讲解的话，36 租一个讲解器也是很值得的，不过我租的那个讲解器有点问题，讲着讲着会自己把音量调到最大耳朵都差点聋了，我不得不全程按着音量键一旦发生问题就狂按把音量降下去，如果这个是普遍问题的话那还是挺恶心的，最后去还讲解器的时候忘了反馈下这个问题了。
&lt;/p&gt;

&lt;p&gt;
三点出头逛完了，去一楼开始逛文创店，三星堆的文创产品很丰富，不过我最想要的有一些没有，比如说陶猪、摇钱树、青铜神兽都没有，摆件总体也比较少，大量的冰箱贴、书签类产品，可能是因为摆件比较贵卖不了那么多吧。
&lt;/p&gt;

&lt;p&gt;
我在文创店就逛了一个多小时，买了一些东西后就离开了。到了直通车上车点刚好有一辆车要出发而且还有一个空位，就上去了，结果没开多久就晕车了，身上冒汗、头晕恶心但好在没发展到要吐的地步，回程花了一个多小时接近两个小时，一路上很难受。本来打算去四姑娘山的，在车上就想我这样的身体状态还是不要去了，平路一两个小时的大巴我都能晕车，山路四个多小时我肯定受不了。来成都前的一星期里感冒了三四天、感冒好了后还有几天没睡好，可能是因为这样身体还很虚弱。回到酒店后就把原来预订好的四姑娘山双桥沟景区的民宿取消了，在酒店里歇了好一会。
&lt;/p&gt;

&lt;p&gt;
歇好了后想出去吃饭，但完全不想去春熙路周围的网红店，问了下朋友，然后自己翻到一个叫做呡嘴蹄花的店，好像还不错而且小红书和点评上提到的并不多，就打了个车过去。这店在一个叫做致民路的地方，车开到路口我就让把我放下去了，我自己走了一段进去，路上全是各种小店，冒菜、面、烧烤等等，看着都让人很有食欲。呡嘴蹄花店里还挺干净整洁的，进店后只有两个人在吃，收银台上坐着的姑娘（后面看似乎是老板的样子所以就用老板来称呼吧）起来招待我问我要吃什么，虽然芸豆才是灵魂但作为海带爱好者我还是点了一个海带蹄花套餐，点完问我蘸料要青椒还是红油，得知我能吃辣后说你还是吃红油吧，小菜有 6 种自己拿个碟子去装然后我夹了点烧椒、豆腐丝和泡菜，老板还告诉我蹄花汤喝完了可以加说现在天冷了大家都爱多喝点汤，我问汤在哪里啊老板说你要加了喊我给你加热的。蹄花特别的软烂，入口即化级别的，小菜也好吃特别是那个烧椒又香又辣我很喜欢，红油蘸料倒是觉得只是香没啥辣味。我小菜吃完后老板大概看到了告诉我说还可以自己去夹，所以蹄花汤、小菜、米饭都是可以续的，这样一个套餐才 26 也太划算了，不知道别家是不是也这样，总之我就再去夹了半碟子烧椒。途中来了一个大姐和老板絮絮叨叨说半天话，说自己小孩挑食什么什么的最后让老板帮做一个青椒肉丝带走，感觉是附近居民，挺喜欢这样有人情味的小店的。
&lt;/p&gt;


&lt;div id=&quot;orgd7abcca&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-27.jpeg&quot; alt=&quot;qq747283-27.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
吃完就在周边闲逛，顺着江溜达到了九眼桥附近，合江亭对面的音乐广场上有一个小哥在直播唱歌，都是一些经典的情歌、金曲，周围的阶梯上坐了很多人在听，我也找了个地坐着玩手机听了会，后来手机没太多电了就起身往回走。
&lt;/p&gt;


&lt;div id=&quot;org98f4ba6&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-28.jpeg&quot; alt=&quot;qq747283-28.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
顺着路往九眼桥走去，过桥走到北岸。在桥上看两岸很是热闹，上下游几百米各种酒吧和小摊灯火辉煌喧闹无比。
&lt;/p&gt;


&lt;div id=&quot;org92a594a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-29.jpeg&quot; alt=&quot;qq747283-29.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
到北岸后我顺着滨江东路往西走，经耿家巷、东升街、红星路四段回到酒店。可能因为在春熙路太古里附近，一路上都是热热闹闹、生机勃勃的，一整条街道都是各种大店小店，而且不是那种只有年轻人的景象。路上我在想和北京的区别，北京当然也能找到类似的地方，比如说二环内的各种胡同小巷，但活力还是和成都的这种景象差了一大截，差在哪里呢？首先我感觉成都的各种建筑单元是那种非常开放的 —— 饭店会把桌椅支到店门口、商超便利店也会把商品摆到店门口空地上、地摊推车也非常的常见，虽然让街景变得乱乱的，但对步行的人其实并没有产生多少障碍反而让人觉得很亲近，而这些在北京都是很难见到的，即使是在二环热闹的地方，由于管理的要求，大部分建筑单元把自己死死地封闭在墙壁之内，一有对比，我就觉得那种冷漠疏离感无比的强烈；再就是人们的面貌，很多人就是穿着日常服装闲散地在街道上游走或者和朋友唠嗑吃饭，人在这些街道上的流动就是城市的日常脉动，而不是冠以 citywalk 之名用来消解日常乏味生活的精心计划的精致活动；最后是一个更大尺度上的城市规划上的问题，窄路密网的规划天然地会提高流动性并且给行人安全感和亲近感，北京的胡同大概是因为拆不起改不起所以保持了由原来的街巷风貌还有点这种感觉，除此以外的其他地方大都是宽路疏网彰显气势的设计，只要这点不改变（已有的格局也很难改变）即使是放开城市管理要求也不见得能产生多少热闹的地方。比起吃到了好吃的，我觉得在成都这样热闹的街道上走一走更让我感到放松和惬意。想起前阵子和大学同学吃完饭想找个地方坐着聊天走了半天最后去了 KFC 的事情，这种事情大概不会在成都发生。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge1961f0&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge1961f0&quot;&gt;2023-11-04&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge1961f0&quot;&gt;
&lt;p&gt;
由于前一天写日记到半夜一点多，最终又没睡好，挣扎着爬起来后已经九点多了，洗漱了后参考朋友的意见决定往川大那边走走然后午饭就在川大附近找个吃了，而且同学约我在高新区见面也在南边，就想一路溜达过去好了。
&lt;/p&gt;

&lt;p&gt;
从酒店出来后，我走东大街拐到天仙桥南路，经滨江东路到十二中街又路过了致民路一下，不过因为没到饭点还不饿（虽然没吃早饭）就没有逗留而是继续往南了，后面拐进了龙江路往西走，发现龙江路两边都是各种琴行也算是挺有特色的。从龙江路出来后拐进新南路就直奔川大去了。到了磨子桥后十一点左右了，觉得可以找个地方吃点，看了下附近正好有个区域还蛮多吃的，找了家叫做囍孃醪糟的，点了嘉州钵钵鸡、嘉州绍子面和一个生椰冰醪糟，吃完觉得很一般，钵钵鸡味道非常寡淡，价钱也不便宜，一共花了 63，学校附近不应该更便宜点吗？
&lt;/p&gt;

&lt;p&gt;
草草吃完起身沿着科华路北路继续往南走，走到磨子街的时候看到有几家店有不少看着不像游客的人在吃饭，就走近去看了下，看到有个叫寻味肥肠记的店，想着吃个肥肠也不错就在门口露天的位子上坐了下来。
&lt;/p&gt;


&lt;div id=&quot;orga2c259c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-30.jpeg&quot; alt=&quot;qq747283-30.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
由于前面已经吃了一顿吃不下太多了，就点了一个烧肥肠和一个米饭一共 18，还送了我一碗飘着油花的萝卜汤。烧肥肠是那种有点韧性但能咬得动不至于和橡皮筋一样的状态，味道偏重，里面还有几块土豆，夹碎了蘸着汤汁吃着很过瘾，米饭里是掺着一些豆角的我以前没看过这么做的。
&lt;/p&gt;


&lt;div id=&quot;org4a0f0e7&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-31.jpeg&quot; alt=&quot;qq747283-31.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
吃完要走的时候旁边走过来一只白色的猫，在旁边麻袋躺了下来，似乎是把麻袋当猫抓板挠了两把，本白嫖专家果断上手 rua 了两把，没有被挠。
&lt;/p&gt;


&lt;div id=&quot;orgae129c6&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-32.jpeg&quot; alt=&quot;qq747283-32.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
吃完肥肠继续往南溜达，溜达了一段后想坐下来歇会，在点评上看附近有个五野咖啡就继续溜达了过去，小小的一个店面，在门口摆了几张小几和一些折叠椅，我去点了个 dirty 想着朋友经常点尝下是什么味道，老板还郑重地跟我介绍了下用的什么豆子、告诉我要大口喝才能让咖啡和牛奶充分混合，我给嗯嗯啊啊谢谢好的糊弄过去了。
&lt;/p&gt;


&lt;div id=&quot;orga3d8543&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-33.jpeg&quot; alt=&quot;qq747283-33.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
坐了一会，有个人抱着一只猫过来丢在我脚边然后把猫绳的另一头系到了窗户上，看过去发现我脚边有一个猫窝。我对猫不熟悉，看起来应该是美短吧？这只猫挺活泼的，在边上一会看看这个一会扒拉下那个，偶尔躺一下也不躺太久就起来了。我上午一路遛弯捡了点叶子玩，就拿了一片比较大的叶子出来逗它，可能叶子转动起来和鸟类的羽毛感觉比较类似所以它还和我玩得挺欢的。后来问了下咖啡店老板确认了就是他的猫，来放猫那个人估计是朋友帮忙去遛了猫吧我猜测。
&lt;/p&gt;


&lt;div id=&quot;org5390458&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-34.jpeg&quot; alt=&quot;qq747283-34.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
歇够了后就起身往同学那边去了，感觉越往那边走，街道环境就越发地现代化，不过逐渐稀少却始终能看到的一些小店铺还是保留了一些温和感。这一路上就没太多可说的了，虽然我走得很慢，但加上上午也走了 8 公里多，腿脚还是有些疲惫，后面逐渐冷清的环境也让我走快了一些，走到离同学公司不远的苏宁广场，就在必胜客门口的椅子上坐了会休息了好一会才动身。到了同学公司后直接就进会议室聊天了，聊我这些年做过的事情、各自对 AI 业务的看法等等，我和同学多年没见了，比起生活可能行业、工作还更多可以聊的，这位同学现在在做 AI 相关的内部创业要操心的事情比较多可能还有点招揽我的意思，我也没什么洞见，最后差不多变成了吐槽大会吧。聊完因为还早同学带我去了环球中心逛了逛说是什么亚洲最大商场什么什么的，等时间差不多了打车带我去了玉林路吃饭，本来想去卢记正川饭店，但是排位人太多了，就去了附近的三只耳冷锅鱼火锅，店里有活动打卡评论送饮料和小吃，送东西好多诱惑真的很大最后我也去参与了下，送的饮料超大一杯，感觉商家靠这种活动很轻松就能把评价刷上去吧（不过这家说是二十多年老字号了）。聊天得知同学在主业外自己有做一些小事情赚点小钱，情感咨询、卖项目经验课程、摆摊等等，每件都不是什么大事情但是行动力我还是很佩服的，听完我觉得有些我也是能复刻的比如说真实的项目经验教给毕业生这种其实不要什么力气，但我就是顾虑太多、嫌麻烦而且没啥行动力哈哈哈。
&lt;/p&gt;


&lt;div id=&quot;orgd6e6b10&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-35.jpeg&quot; alt=&quot;qq747283-35.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
吃完我从倪家桥站上地铁回去了，回到酒店后把遛弯一天路上捡到的叶子拿出来。因为经过的范围比较广捡到的叶子种类、大小差异都不小，到第二天这些叶子都会枯掉，就勉强摆放了下拍了个照做纪念。
&lt;/p&gt;


&lt;div id=&quot;orge080531&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-36.jpeg&quot; alt=&quot;qq747283-36.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org920eab7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org920eab7&quot;&gt;2023-11-05&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org920eab7&quot;&gt;
&lt;p&gt;
又没睡好没有精神，上午干脆就没出门，把这几天换洗的衣服拿去酒店洗衣房洗了下，有烘干机还是挺方便的。到了中午附近就出门了，下午打算去逛金沙遗址博物馆，想着上一次去已经好些年了去看看有没有什么变化。然后在去金沙遗址博物馆的路上选择困难了，翻来翻去迟迟决定不下来该吃什么，最后出了地铁在快到博物馆的地方找了个小店点了个红油抄手和一个夫妻肺片，我是不知道这个夫妻肺片怎么能做到难以下咽的，红油抄手勉强算是能吃吧，总之吃完心情很差。
&lt;/p&gt;

&lt;p&gt;
进到金沙遗址博物馆后，想着之前三星堆租讲解器体验还不错（除了那个音量问题），也去租了个讲解器，结果居然是不配耳机的，想要耳机的话要另外花 10 块钱购买 —— 对是购买不是租借，疯了吧？抱着来都来了 10 块钱也不算什么的心态还是把耳机买了，然后进馆开始逛，结果一圈逛下来和多年前的内容感觉毫无变化 —— 其实没变化才是正常的，又不是三星堆又能挖出 6 个新的祭祀坑出来，是我自己想当然没有提前去了解。总之，虽然没逛多久 —— 也没法逛多久，但还是感到很疲惫、沮丧，虽然外面还有什么乌木林、园林，但已经完全没有什么兴致了，在展馆外面的椅子上和端着热水壶的大爷大妈们一起坐了半天，决定离开去吃饭。
&lt;/p&gt;

&lt;p&gt;
前一天同学有推荐我去抚琴夜市说有卖一些夜市之外不卖的小吃，还挺心动的，不过又有朋友推荐一个玉林路的钵钵鸡，想了下还是决定去吃钵钵鸡，就坐地铁过去了，下了地铁后还稍微拐了一些弯溜达了下。到了玉洁巷看到很醒目的招牌，就进店吃了，点了一个红糖凉糕然后自己拿了一大把串选了红油做法，然后它是用一个大碗盛好红油汤底然后把串都撸下来放进去的，吃起来倒也方便。
&lt;/p&gt;


&lt;div id=&quot;org36d394c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-37.jpeg&quot; alt=&quot;qq747283-37.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
叠加中午和下午的怨气，我吃得还是蛮开心的。结果我吃完出门一抬头，怎么对面还有个乐山官记钵钵鸡，再回头看刚刚的店叫官记乐钵钵鸡，想起来他们菜单上有说什么因为商标没有通过把原来的官记乐山钵钵鸡改名成了官记乐钵钵鸡，脑子里一团浆糊。翻出来和朋友的聊天记录看了下，朋友推荐的，是「乐山官记钵钵鸡」，再和朋友确认了下，我果然是认错了。说我吃的这家原来是对面那家的徒弟还是员工之类的，学会了自己开了个店，更会运营招牌更大很多人都走错，从原来起名叫官记乐山钵钵鸡还开在老店对面这个手段来看确实是更会运营，不过也有点下作吧……据朋友说老店味道更好但估计也只有本地常客才知道这个事情了。对面那个老店门脸非常老旧寒碜，工作人员都看不到，有一个哥们一个人在那吃着，想着自己走错了店这件事情一阵愧疚，决定过去再吃一顿。
&lt;/p&gt;


&lt;div id=&quot;org8bc338e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-38.jpeg&quot; alt=&quot;qq747283-38.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
进门没人招呼我就喊了几句，一个面容憔悴的孃孃被我喊出来了，领着我到了里面一个双开门的柜子前，问我要什么，打开来，是一个个塑料碗装着各种材料，她一个碗一个碗拿出来问我这个要不要我基本都说要了，最后拿的有点多，上来后也是满满一盆。我吃了一小会其实就不怎么吃得下了，不过还是努力再吃了一些。
&lt;/p&gt;


&lt;div id=&quot;orgaa1dd11&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-39.jpeg&quot; alt=&quot;qq747283-39.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
中间过来一个姑娘，我听到她手机里传出来「已到达目的地，导航结束」的声音，然后看她抬头疑惑地看了两眼招牌和对面，犹犹豫豫地进了店里来，应该也是专门过来的 —— 估计和我一样是朋友推荐过来的，因为无人接待，她表情和我刚进来的时候一样茫然，我就冲里面喊了几声把孃孃喊出来了也领那姑娘去拿串了。再吃了会，觉得实在吃不动了，就结账然后把剩下的打包，付款的时候听到孃孃在身后嘟囔「今天没有泡盆盆」 —— 后面据朋友说她这家店一般是把钵钵鸡在盆里泡好放外面让大家挑的，然后据说因为生意不好现在主做外卖了所以就没想起来做这个事情吧，令人心酸。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org70701e2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org70701e2&quot;&gt;2023-11-06&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org70701e2&quot;&gt;
&lt;p&gt;
今天要去乐山了，所以就没有任何心理负担地睡到了快九点，起来收拾了下后就去退了房，然后坐 2 号线去成都东站。十一点半左右到了乐山站，出火车站后，去出租车点等车，身后面有四五个姑娘小伙，在那叽叽喳喳讨论行程，说我们先直奔叶婆婆钵钵鸡再去哪里哪里。坐上出租车后就直奔酒店，酒店订在了岷江一桥附近。
&lt;/p&gt;


&lt;div id=&quot;org195c2e8&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-40.jpeg&quot; alt=&quot;qq747283-40.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
到酒店办好入住后，我在房间里歇了会，也看看午饭吃什么。在成都那几天找吃的时候已经被网红店搞烦了，小红书和点评笔记一搜全是这些网红店，相关的内容（评分、评论）基本已经提供不了什么真实的信息，导致我到了乐山找店时也感觉相当头大，然后看到附近有个小饭馆，点评评论极少然后看着又不错的样子，打算就去吃这个叫做卡卡角角小饭馆的店了 —— 卡卡角角是边边角角的意思。出了酒店到顺着嘉定南路走 400 米就到了，在路边一个巷子里进去，路边有个招牌指示，还很有脾气地写了一些拒绝接待的标准。
&lt;/p&gt;


&lt;div id=&quot;orga7ab01a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-41.jpeg&quot; alt=&quot;qq747283-41.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
我进去后站在门口看推荐菜小黑板，服务员喊我进去坐着慢慢看，给了我一个菜单，我就点了一个麻婆豆腐和一个肝腰合炒。店面小小的，老板就在角落里炒菜，店里还有两桌人在吃，感觉都是附近居民。麻婆豆腐先上来，菜量超出我的想象，这菜上来后就觉得我要吃撑了。后来肝腰合炒上来了，肝片和腰花炒得都非常脆嫩，唯一有点不足的是腰花还有一点腥，不过这顿饭菜 44，我觉得完全可以容忍这点小缺点。
&lt;/p&gt;


&lt;div id=&quot;org2834d25&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-42.jpeg&quot; alt=&quot;qq747283-42.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
吃完我就走到滨江路南段上往乐山港的方向走，走了一段，看到有一片摆着桌椅，有很多人坐着，打牌、聊天、发呆各种都有，人多的地方我没好意思坐下来，继续往前走了二十多米，依然摆着桌椅，找了一个没太阳的地方坐了下来。然后有个男人过来问我喝什么茶，我也不知道不是桌椅都是他摆的，不过确实想喝水多坐会，要了一个菊花茶，10 块钱。在江边坐了将近一个小时，后面身上还觉得有点凉凉的，顿时觉得 10 块钱的热茶非常划算。
&lt;/p&gt;


&lt;div id=&quot;org020b280&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-43.jpeg&quot; alt=&quot;qq747283-43.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
歇够了后起身继续往南走打算走到最南边，那边似乎是能远远看到乐山大佛来着。一路上看到很多人打牌，但不是常见的扑克，查了下，就叫乐山字牌，是乐山这边独有的。
&lt;/p&gt;


&lt;div id=&quot;org8fc7a86&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-44.jpeg&quot; alt=&quot;qq747283-44.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
然后在走的路上，看到了一些地方标识着 8.18 水位线什么的，查了下，原来 2020 年 8 月 18 日乐山遭遇过洪水，看那个线当时江边这块的房子估计一层楼是被淹掉了的。然后乐山自古都有对洪水的灾难记忆，还经常拿乐山大佛来作为预警标准，什么大佛洗脚乐山撑船啊，这一查还查到了以前的老电视剧《风云雄霸天下》，这电视剧有在乐山大佛拍摄，还有「水淹大佛膝，火烧凌云窟」这么一句台词，凌云窟就在乐山大佛上面，藏着火麒麟来着，还有后来步惊云的绝世好剑也是从乐山大佛下取出来的……
&lt;/p&gt;


&lt;div id=&quot;org63b7d59&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-45.jpeg&quot; alt=&quot;qq747283-45.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
走到头后往乐山大佛的方向看了看，但看不太真切，就作罢往回走，走到滨江路和嘉定路汇聚的地方，发现这块居然有一个集市（我确定下午白天的时候没有），就在嘉定南路的路边从那个路口开始往北大约两百米这么一段，摆满了各种小摊，卖菜的、卖小吃的、卖水果的、卖碟片旧书的、卖鞋垫袜子的、推拿按摩的、采耳的……形形色色应有尽有，虽然我不买但感觉挺有意思的，这种地方也只有本地人会来，毕竟拍照不好看。
&lt;/p&gt;


&lt;div id=&quot;org9e8fe0a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-46.jpeg&quot; alt=&quot;qq747283-46.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
走了一下午感到有点疲惫，就回酒店躺了会，到七点多才爬起来准备去张公桥好吃街吃个晚饭，不过这种地方主要也是针对外地人，里面的网红店我完全不想去，翻了好久的评论总算找到几个本地人说从小在吃的店，准备过去瞅瞅。从酒店步行过去一公里不到，还是挺近的，入夜后整条街道里的店铺招牌都亮起了五颜六色花里胡哨的灯，拍照是会比较好看但却让我心烦。
&lt;/p&gt;


&lt;div id=&quot;orgbf5a697&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-47.jpeg&quot; alt=&quot;qq747283-47.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
走到牛儿风味小吃这个据说本地人常吃的店，点了一份杂酱面和一份粉蒸肥肠，面里的酱汁非常多简直像个汤面了但又很粘稠拌开后能挂在面上还挺好吃的，粉蒸肥肠的肥肠完全没有异味蒸的非常嫩滑、粉粒粗糙的口感和肥肠嫩滑的口感交织在一起非常不错。
&lt;/p&gt;


&lt;div id=&quot;org7b3ae73&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-48.jpeg&quot; alt=&quot;qq747283-48.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
吃完往回走，看到一个卖冰糖葫芦的，能做出拉丝效果让冰糖葫芦外裹上一圈棉花糖一样的糖丝，觉得挺好玩的就 12 块买了一个拉丝草莓，摊主是个聋哑人，全程只能手势和大家交流。看他熬糖熬了很久还一直在搅动，最后就是把冰糖葫芦在那个糖里蘸一下然后双手垂直夹着用力一搓，上面裹着的糖浆甩出来就变成棉花糖形状了，还是挺厉害的，12 块觉得有点贵就当看个表演了。吃起来怎么说呢，毕竟和棉花糖还是不一样，外面那层糖丝扎嘴。后面再随便逛了逛就回酒店了。
&lt;/p&gt;


&lt;div id=&quot;orge456036&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-49.jpeg&quot; alt=&quot;qq747283-49.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org871dea3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org871dea3&quot;&gt;2023-11-07&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org871dea3&quot;&gt;
&lt;p&gt;
早上起来后准备去吃个豆腐脑，从酒店出来走嘉定南路往南拐进兑阳湾巷和新村街，在兑阳湾巷到新村街这一路上就有很多小店，最后拐进人民南路，进了路旁的九九豆腐脑，点了个牛肉咔饼（咔是夹的意思）和一个蛋冲豆腐脑：牛肉咔饼里夹的是粉蒸牛肉，有一些辣味，由于昨晚吃的粉蒸肥肠，我本来预期粉蒸牛肉也会很嫩的但却没有，不知道是我的错误认识还是这家没做好，不过肉量是实打实的；蛋冲豆腐脑是峨嵋那边的风格，顾名思义就是除了常规的卤外还会冲个鸡蛋进去，有些粘稠但口味其实比较清淡，也还不错。这一顿 27。
&lt;/p&gt;


&lt;div id=&quot;org84fa99a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-50.jpeg&quot; alt=&quot;qq747283-50.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
吃完就在附近溜达了，顺着人民南路往南走叮咚街到了海棠广场，溜达到府街上看到也有个九九豆腐脑（这个有个「乐山味道」的前缀，我吃的那个有「豆相识」的前缀）但看标志又不一样，这几天真的是被这种李逵李鬼搞得很烦。府街里面有个商场，里面那个什么财富广场说进去也挺多好吃的不过我就没进去了。最后又溜达到了江边滨河路，不过这次跑到了大渡河边上这段滨河路，顺着路往东南走就能走到岷江和大渡河交界处，打算到那往北顺着岷江边的滨河路回酒店。走到最南边的时候，发现有楼梯能下到河边上去，就跑下去了，结果发现河边还有路可以走，走到头的话比在上面滨河路上看乐山大佛和江景视野更开阔呢。
&lt;/p&gt;


&lt;div id=&quot;org38d4f4e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-51.jpeg&quot; alt=&quot;qq747283-51.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
顺着路走到头，人多了起来，有些人在钓鱼，江里还有人在游泳，转弯一看居然是一个小小的广场，墙上挂着牌子说是叫冬泳广场，去看了下贴出来的修建史，就是一帮喜欢游泳的人组建冬泳协会然后和政府拉扯要到了修建权然后自己筹资出人力把道路和广场修建起来的故事，令人感动。天气阴沉，努力拍了乐山大佛的照片也只能隐约看到一个脑壳和一双脚，不过我也没多想看，随便了。
&lt;/p&gt;


&lt;div id=&quot;org0ba7dcf&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-52.jpeg&quot; alt=&quot;qq747283-52.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
从冬泳广场上来又到东大街那片逛了逛，但是看到周围店铺的招牌就心烦，不想在附近吃，干脆往酒店走，路上翻了翻小红书看到有人说在通江街道附近有个万人小区附近有挺多吃的，就想不如过去转转好了。不过有点远，走路过去就太费劲了，就在路边扫了一辆滴滴青桔电动车一路骑过去。乐山有些地方道路坡度还挺大的，不知道是不是因为这个所以到处都是青桔电动车，普通的青桔单车反倒比较少见。骑了七公里后到了那个万人小区附近转了转确实蛮多吃的，但再一次陷入选择困难，打开点评看附近有个曦曦跷脚牛肉好像还不错就下决心过去了。点了一个血旺、一个白菜和一个牛杂，血旺夹碎拌到米饭里非常好吃，白菜也在牛肉汤烫过显得非常鲜甜，倒是牛杂感觉最平平无奇了。这一顿 28 —— 牛杂 15、血旺 6 块、白菜 5 块、米饭 2 块，非常舒适，看小红书上一些本地人吐槽说他们小时候跷脚牛肉是 6 块钱一碗的，我想除了旅游带来的价格提升外，物价这么多年也是在涨的吧。
&lt;/p&gt;


&lt;div id=&quot;orga3eb4d6&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-53.jpeg&quot; alt=&quot;qq747283-53.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orge741a20&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-54.jpeg&quot; alt=&quot;qq747283-54.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
电动车骑着很舒服，吃完饭我干脆骑着电动车绕绿新公园逆时针走了大半圈又到了海棠广场附近的沫若广场，骑了 15 公里把电动车给骑没电了。然后到白塔街和陕西街溜达了下，在陕西街再次 rua 到一只白猫。
&lt;/p&gt;


&lt;div id=&quot;org4e24523&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-55.jpeg&quot; alt=&quot;qq747283-55.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在陕西街看到一个居民楼爬满了植物，在阳光下显得很好看，有点像童话故事里的场景。
&lt;/p&gt;


&lt;div id=&quot;orgbd4abe5&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-56.jpeg&quot; alt=&quot;qq747283-56.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
从陕西街出来转到金花巷走去乐山文庙，狭窄逼仄又弯弯绕绕的巷子我很喜欢，巷子旁的墙壁上还有各种乐山美食及文化的宣传画。巷子并不长，很快就走出去到了文庙，我对孔老夫子没太多感情，远远地看了下就走了。
&lt;/p&gt;


&lt;div id=&quot;orgb0b0d97&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-57.jpeg&quot; alt=&quot;qq747283-57.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
从文庙转出来又到了叮咚街，下午这会人不是那么多，茂密的榕树在道路上空生长成一道绿色的穹顶，我也很喜欢这种感觉。老城区这边的行道树大多是榕树，中午我去曦曦跷脚牛肉路过的凤凰路则种了凤凰木作为行道树，也挺有意思的。
&lt;/p&gt;


&lt;div id=&quot;orgd4102b2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-58.jpeg&quot; alt=&quot;qq747283-58.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
已经挺累了，所以就往酒店那边走，在上中顺那一片发现有个顺城街比较狭小的样子就钻了进去（当然我是不会进旁边店铺的），走到尽头发现还有个乐山武汉大学西迁历史文化博物馆，说抗战时期武大曾经迁到过乐山文庙，这我还真不知道。博物馆似乎在一段残留的城墙上方，我爬上去后门是关着的，就下来回酒店了，到酒店附近那个集市又开了，遇到两个摊主吵架大概是因为谁占了谁的常用位置之类的，在旧书摊上发现一些过于少儿不宜的老旧地摊杂志。
&lt;/p&gt;


&lt;div id=&quot;org4cfa4c0&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-59.jpeg&quot; alt=&quot;qq747283-59.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在酒店躺了会休息好后，又陷入了不知道吃什么的纠结状态里，已经很累了不想跑太远，但张公桥好吃街也不想去，最后还是出门骑车去了东大街附近，但是转来转去看哪个都不顺眼，最后耐心耗尽进了身边一个甜水面店，不太合我的口味，出来对自己过度选择焦虑的状态感到很灰心，感到很累，决定第二天就离开乐山回北京，做出这个决定后顿时感到一阵轻松。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgfd6c571&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgfd6c571&quot;&gt;2023-11-08&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgfd6c571&quot;&gt;
&lt;p&gt;
乐山这边的豆腐脑有两派，一派是我之前吃过的峨嵋风格的蛋冲豆腐脑，还有一派是牛华风格的里面会加粉丝，早上起来后决定去吃个牛华豆腐脑。去了海棠公园边上的代四孃牛华豆腐脑美味小吃，点了个牛肉豆腐脑和一个粉蒸肥肠，这个豆腐脑口味会更咸更重一些，粉蒸肥肠也不错。一共花费 34，比昨天的九九豆腐脑多花了 7 块，但我也忘了具体哪样多少钱了。
&lt;/p&gt;


&lt;div id=&quot;org1dd9d4f&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qq747283-60.jpeg&quot; alt=&quot;qq747283-60.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
从代四孃出来就在边上谢记软面锅魁买了个 6 块的猪肉锅魁，还在边上买了一只甜皮鸭准备带回北京。然后啃着锅魁回酒店去了。在酒店待到 12 点多然后去退了房，叫了个车去乐山站。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgde40202&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgde40202&quot;&gt;后记&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgde40202&quot;&gt;
&lt;p&gt;
旅行总体还是开心的，我很享受那种四处闲逛的感觉。
&lt;/p&gt;

&lt;p&gt;
除此以外，这次旅行发现了自己的一个比较大的问题，那就是在面临很多选择时会因为想要做出最好的选择而陷入严重的选择焦虑里，这种焦虑不光体现在几次不知道吃什么的纠结里，还体现在我出行前规划行程的时候。我最开始规划的是成都+乐山+自贡，其中成都想去三星堆、四姑娘山、大熊猫基地以及吃各种好吃的，然后在四姑娘山该去双桥沟还是长坪沟还是都去之间纠结了很久，同时去四姑娘山需要较多准备所以又在去不去四姑娘山之间摇摆了很久。仔细想想，这种焦虑以前其实也有，只不过是在工作、生活中有别人帮我剪掉了一些选项，或者我自己干脆就放弃掉了所以没有引发过特别厉害的情绪。就事论事来说，只是在旅行里的时候我完全可以放松一点，一次出行不要安排太多目的地、吃饭的话吃网红店或者路边随便吃都行，问题是相对好解决的，但我觉得我在生活里遇到一些重大选择的时候迟早还会陷入到这种焦虑里面，甚至我辞职后不工作了半年了其实也一定程度上有觉得回去工作这个决定会带来很麻烦的选择而拖延着。
&lt;/p&gt;

&lt;p&gt;
不过自省就到此为止吧，后面还是想多出去玩玩，觉得这次出行感到焦虑的一个原因也是我几乎没有怎么出门玩过而过于紧张，既然如此多来几次就好了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>2023年9月总结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2023/10/20/september-review.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2023/10/20/september-review</id>
    <published>2023-10-20T00:00:00+00:00</published>
    <updated>2023-10-20T00:00:00+00:00</updated>
    <description>
    
      <p>9月是充实的。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgddba9a6&quot;&gt;日常生活&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc98677b&quot;&gt;写作&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgfbd179e&quot;&gt;阅读学习&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org718efd2&quot;&gt;其他&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgddba9a6&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgddba9a6&quot;&gt;日常生活&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgddba9a6&quot;&gt;
&lt;p&gt;
9 月外出参加了好几次活动，相比前几个月可以说比较现充了。
&lt;/p&gt;


&lt;div id=&quot;org8203670&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/0901_野孩子乐队live.jpg&quot; alt=&quot;0901_野孩子乐队live.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;1&amp;nbsp; &lt;/span&gt;野孩子乐队 live&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
第一天去福浪 livehouse 看了野孩子乐队的 live，以前没有看过 live，野孩子的歌也就偶尔听过（我平时听歌不多）并没有什么特殊感情，之所以会去是朋友说要去喊我一起，我想就去体验一下吧。在现场听音乐演唱和在数字设备上听的差异还是非常大的，那种被音乐紧密环绕着的感觉、随鼓点震颤的心跳以及周围人群陶醉的氛围是没有办法在数字音乐上感受到的，我右后方有个姑娘应该非常开心一首歌结束的时候会小声用轻柔的声音说一句「敲好听呀」、左前方有个哥们一直在摇头晃脑，我倒没有那么投入，但也有被感染到一些。livehouse 的场地相比演唱会那种大场地小很多又让人觉得和乐队很亲近，如果是自己喜欢的乐队的 live，那应该会非常开心，我可能上比现场其他人就更平静一些，像《黄河谣》《敕勒川》这种歌我也没有那么多共鸣。整场 live 一共持续了 2 个小时，去之前觉得结束后会非常的疲惫，结束后除了站了两个小时后腿脚比较难受，精神上倒是一点都没有萎靡的感觉。因为参加这个 live，安装了几个专门做演出、展览之类活动票务的 APP。
&lt;/p&gt;

&lt;p&gt;
生日那天，自己去逛了郎园书市，逛了一下午，在各个出版社的摊子间游走发现自己喜欢的书的体验很有趣，就是书有点重，越逛包里买下来的书越多，虽然也没买几本。书市分室内和室外两部分：室外的摊子折扣力度比较大，五六折的很多；室内的部分看起来好像是一些比较大的出版社的专门场地，其中有一整排全是理想国的，而且室内部分有挺多编辑在，我逛的时候遇到了不少和编辑在做深度交流的读者，偷听到一点后深觉自己看书囫囵吞枣。逛完书市后去附近的盛金楼和朋友聚餐，但碰上了当日阵雨最大的一会，鞋子裤脚湿掉、被装着书的包勒得肩膀疼、在拥挤的撑着伞的人群中避让碰撞……去地铁站几百米的路上感觉花费的力气比我平时 5 公里来回的散步还要累，也算是一个难忘的记忆了。
&lt;/p&gt;


&lt;div id=&quot;org9cc57cb&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/0908_郎园书市1.jpg&quot; alt=&quot;0908_郎园书市1.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;2&amp;nbsp; &lt;/span&gt;郎园书市(1)&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org7b17727&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/0908_郎园书市2.jpg&quot; alt=&quot;0908_郎园书市2.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;3&amp;nbsp; &lt;/span&gt;郎园书市(2)&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org6b3b068&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/0908_郎园书市3.jpg&quot; alt=&quot;0908_郎园书市3.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;4&amp;nbsp; &lt;/span&gt;郎园书市购买的书签和贴纸&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
生日之后又连着两天去参加外面的活动了，那一周真的是非常现充。
&lt;/p&gt;


&lt;div id=&quot;orgb584d4c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/0909_核聚变游戏节.jpg&quot; alt=&quot;0909_核聚变游戏节.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;5&amp;nbsp; &lt;/span&gt;核聚变游戏节&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
9 号去逛了核聚变北京站，但是我们午饭后才过去，核聚变的场地又在亦庄非常远，导致我们可用的游玩时间比较少，所以我们进去后就是潦草地逛了逛，像很多游戏展台想要试玩都是要排队的就担心时间不够而没有去试玩，我虽然玩游戏但玩得也不算很多对很多游戏不怎么了解，有一些开放的展台可以玩的去玩了下也没有什么很特别的感觉，当时有《堕落之主》的演示看了一会，对游戏中表世界和影世界的设定还是比较有兴趣的。最后买了本《塞尔达系列三十周年艺术设定集》和一本《黑暗之魂传火录》，再次让我回家后手臂和肩膀酸痛不止。
&lt;/p&gt;


&lt;div id=&quot;org9f21539&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/0910_北平机器煎饼节1.jpg&quot; alt=&quot;0910_北平机器煎饼节1.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;6&amp;nbsp; &lt;/span&gt;世界的饼·饼的世界&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org79cb3e5&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/0910_北平机器煎饼节2.jpg&quot; alt=&quot;0910_北平机器煎饼节2.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;7&amp;nbsp; &lt;/span&gt;北平机器煎饼节&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
紧接着在第二天 10 号又去参加了北平机器煎饼节，这个活动在龙潭中湖公园中举办，展示并售卖各种煎饼及煎饼类似物 —— 汉堡、大阪烧算煎饼吗？总之这个活动里都有卖。我和朋友三个人一起去，尝了三个不同摊子上的天津煎饼，还尝了汉堡、大阪烧、北京机器自己做的煎饼以及某种西式的煎饼（朋友买的所以我不知道名字），各有特色，但是说实话并没有觉得都很好吃而且价钱挺贵的。参加这个活动的收获是看到了解了各式各样的「煎饼」，以及，在现场抓到了老高合了个影。
&lt;/p&gt;


&lt;div id=&quot;orgdf8edf1&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/0910_北平机器煎饼节3.jpg&quot; alt=&quot;0910_北平机器煎饼节3.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;8&amp;nbsp; &lt;/span&gt;北平机器煎饼节与老高合影&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
除此以外，14 号去国博看了新疆文化展和白瓷展，22 号去了雁栖湖走了下西山步道，各有收获。
&lt;/p&gt;


&lt;div id=&quot;orgceecb93&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/0914_国博白瓷展.jpg&quot; alt=&quot;0914_国博白瓷展.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;9&amp;nbsp; &lt;/span&gt;国博白瓷展&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org1557385&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/0922_雁栖湖.jpg&quot; alt=&quot;0922_雁栖湖.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;10&amp;nbsp; &lt;/span&gt;雁栖湖·酸枣与山楂与板栗&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
除了各种活动外出，9 月也依然勤奋地去散步了，给自己定的目标是每周出去散步三次，9 月一共出去散步了 13 次，应该算是完成了目标 —— 虽说是定了目标但这个目标对我来说并没有什么压力，只要天气好我都是愿意出去走走的。13 次散步里就看到一次晚霞，不过这次晚霞超美。
&lt;/p&gt;


&lt;div id=&quot;org8bbb777&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/0919_2.jpg&quot; alt=&quot;0919_2.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;11&amp;nbsp; &lt;/span&gt;晚霞&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可能因为外出比较多再加上一些懒惰心理，9 月自己做饭只做了 8 次，外卖和外食的次数比 8 月要高了很多，不过外食大部分是自己一个人出去吃饭，和朋友聚餐吃饭并没有很多次 —— 就吃过了福满缘烧鹅王、盛金楼海鲜、四川龙爪树宾馆、四季民福、马辈儿涮肉、滩羊铺子南北疆特色汇这六家店，都挺好吃的。除了在店里聚餐，还在朋友家参加了一次小饭桌活动，吃到了非常好吃的自制云腿月饼和羊肉。
&lt;/p&gt;


&lt;div id=&quot;orga84655f&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/0902_小饭桌1.jpg&quot; alt=&quot;0902_小饭桌1.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;12&amp;nbsp; &lt;/span&gt;小饭桌&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org82ff5d1&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/0902_小饭桌2.jpg&quot; alt=&quot;0902_小饭桌2.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;13&amp;nbsp; &lt;/span&gt;大渔记云腿月饼&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
上述大多数事情都是发生在 9 月的上半个月的，所以上半个月大部分时间都觉得很充实，总体心情是比较明朗的。由于 9 月 29 日是中秋节并且今年中秋节和国庆节连着，家里人很早就来电话问我假期安排了，最开始父母是想来北京玩的，不过离职休息这件事情没有跟家里讲过所以并不是很想让他们来北京，回家的话路途遥远回去又要应对各种亲戚邻居的无聊问题，所以到 9 月中旬开始烦恼假期安排。最后还是决定我回家里，但心里其实是很抗拒回家的，所以 9 月下半月心情稍微差一些。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc98677b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgc98677b&quot;&gt;写作&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgc98677b&quot;&gt;
&lt;p&gt;
9 月重启了记录生活的《闲言碎语》系列的写作，发在了公众号上，把平时自己日记里的一些内容摘出来做一些整理后发出来。
&lt;/p&gt;

&lt;p&gt;
重启这个系列的原因有很多，最主要的可能还是表达欲使然吧，想让自己的一些想法、感受被看见，但又不想发太多到朋友圈或其他社交平台上面，相比之下个人公众号是个不错的地方，一周一次的频率也比较适当。
&lt;/p&gt;

&lt;p&gt;
除了表达欲，也有写作练习的目的在，现在每月一次的总结文章写起来其实是很费劲的，每周写点生活记录相对来说就比较轻松从而容易形成习惯 —— 其实除了生活记录，我还想每周写写我看过的论文和文章的，形成了每周写作的习惯后再来做这个事情也会更好一些。
&lt;/p&gt;

&lt;p&gt;
除此以外，重新发布生活记录，也是想让关心我的朋友知道我的状况是怎么样的，我也相信真诚、具体的想法和感受比观点和知识更能让人和人之间达成理解、更能让人和人之间建立连接 —— 虽然不多，但确实有几个朋友说有被我的生活碎片感动，我有鼓励、建议这些朋友也去记录、发布自己的感受，但是要么说自己记录的都是一些负面的情绪、要么说觉得太私密不好意思发出来，其实我想说：首先，值得记录的生活细节、想法、感受其实是非常非常多的，但大部分人可能会对负面的经历印象过于深刻而忽略了那些快乐的瞬间和平静的时刻，进行生活记录的练习的很大一个价值就是帮助我们去观察到这些被忽略的时刻；其次，即使是负面的经历，也值得被表达出来，表达这个过程，本身就是对自己感受的肯定和接纳，中国人太过于擅长「跌倒了不哭」，这是很多病症的根源，将自己的感受表达出来除了能治愈这些病症，也可以让有同样感受、同样痛苦的人知道「原来有人和我一样」，这对他人来说也是一种莫大的安慰；最后，从私人记录到公开表达，可以根据自己的情况挑选、修饰，我也有很多非常私密的想法、感受、经历是不方便公开的，挑选、修饰也是一件值得去练习的事情，能让我们学会在向他人表达想法、感受时使用更加恰当的方式。
&lt;/p&gt;

&lt;p&gt;
除了公众号、博客的写作，我自己每天写日记花费了很多时间，看了下统计，9 月在这上面花了 38.5 小时，算下来每天平均要花 77 分钟，当然这 77 分钟里有一部分是走神干别的去了消耗掉的，但算上回顾当天所有细节（翻看照片、聊天记录、支出记录等）和写作的时间，每天半小时应该是有的。详细地记录生活细节是我生活的一部分，也是践行我在《&lt;a href=&quot;https://www.zmonster.me/2020/10/11/the-self-as-method.html&quot;&gt;把自我作为方法&lt;/a&gt;》这篇博客中理念的努力，我想我还会继续下去。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgfbd179e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgfbd179e&quot;&gt;阅读学习&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgfbd179e&quot;&gt;
&lt;p&gt;
9 月没有阅读太多，因为看电影《奥本海默》去读完了《奥本海默传》，准备写个详细的读后感来着但一直拖着；读完了科幻小说《挽救计划》，然后还开始读朋友推荐的《夏日来到山间》。有记录的阅读活动一共也就 19.5 小时，平均每天 39 分钟，也算是达到了我给自己设定的每天半小时的目标吧。
&lt;/p&gt;

&lt;p&gt;
书籍之外，我在论文上花了更多时间，看统计平均每天花费 72 分钟。目前主要关注的论文仍然是 LLM 方面的，但更多是在看每天更新的论文以掌握整体研究的方向变化，完整读完的论文不多，自媒体的转发我现在已经基本不看了。LLM 这个领域的发展，看起来好像让人眼花缭乱，但是大家关注的几个核心问题在我离职后的 4 个月里没有什么变化，我关注的几个比较核心的问题有：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;如何用 LLM 处理复杂任务？CoT、Agent 相关的研究其实都是在尝试回答这个问题，但目前来看还没有形成一个令人信服的、泛用的框架；&lt;/li&gt;
&lt;li&gt;如何提高模型的训练和推理效率？LoRA、模型压缩（量化、裁剪）、对 attention 机制的改进都是在尝试回答这个问题，其中模型压缩技术的进展我觉得值得关注一下，模型如果能压缩到在手机上高效运行后会非常有想象力；&lt;/li&gt;
&lt;li&gt;模型存在哪些 bias 以及如何对这些 bias 进行校准？对模型 bias 的分析会有不少反直觉的分析结果（性别/种族歧视这种就不说了），其来源也复杂多样，有的是来自数据、有的是来自模型结构、有的是来自训练方法，总之这方面的研究能让我更好更全面地理解 LLM，至于更深层的动力学分析、理论分析实在是太少了（有我可能也不太能看懂），在神经网络方向一直都很少，就没有太关注了。&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org718efd2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org718efd2&quot;&gt;其他&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org718efd2&quot;&gt;
&lt;p&gt;
躺平的第四个月，我对现在的生活是满意的，回去工作这件事情依然没有考虑过 —— 有一些朋友已经来和我聊过这个了，有觉得行情不好建议我还是去找个工作的、有觉得我是不是不难找工作所以不着急的、有目前在做大模型相关业务想要招揽我或者找我合作的。对我来说，工作只剩下赚钱这个意义了，而我对钱没有什么渴求，以我现在的存款和生活状态来说，坐吃山空我也还能吃很久（当然，不考虑成家、重大变故之类的）。
&lt;/p&gt;

&lt;p&gt;
目前觉得生活上觉得比较需要改进的是我还是过于懒散了一些，看了下统计，我有个叫做「消磨时间」的统计项累计有 120 个小时，这个统计项记录的是我比较漫无目的地去刷社交网络、看视频、看网络小说所花费的时间，平均每天 4 个小时，刨去每天醒后赖床的一个来小时和睡前的一个来小时，每天也还有两个小时，比我每天看书和读论文花费的时间总和还多。当然了，时间就是用来浪费的，只要是过得开心倒也没什么，像 6 月刚离职的第一个月「消磨时间」总共花费了 200 个小时也没觉得有什么不对，不过人的心态是持续在变化的，离职四五个月后，我其实已经不再需要靠漫无目的的消磨时间来冲淡工作所带来的厌倦和疲惫，最近两个月也是希望自己能有所产出，所以会希望能多一些更专注的时间。不过这也不是什么大问题，了解自己的状态、了解自己的问题然后去改进即可。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>2023年8月总结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2023/09/12/august-review.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2023/09/12/august-review</id>
    <published>2023-09-12T00:00:00+00:00</published>
    <updated>2023-09-12T00:00:00+00:00</updated>
    <description>
    
      <p>不工作后我的生活要比工作时候丰富多了，只要人的闲暇时间多了，生活自然就会丰富起来。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org6984f44&quot;&gt;日常生活&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org84723db&quot;&gt;阅读学习&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3d28aef&quot;&gt;其他&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6984f44&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org6984f44&quot;&gt;日常生活&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org6984f44&quot;&gt;
&lt;p&gt;
虽然是一个比较宅的人，但在翻日记的时候我发现，不工作后我的生活要比工作时候丰富多了，只要人的闲暇时间多了，生活自然就会丰富起来。
&lt;/p&gt;

&lt;p&gt;
8 月自己做了 17 次饭，比 8 月还多了 4 次，新尝试了茭白这个原来不熟悉的食材，喜欢它的口感，另外就是学习了生炒排骨这个新菜式。我对做饭的热情并不算高，大部分时候凑合能吃就行了。除自己做饭外，还外食了 6 次，吃了滇宴、亮嚯兰州翻花烤串、蜀肠缘江油肥肠火锅、比尔包车（原名比尔包装马车）、湘彬萱和江边诱惑巫山烤鱼：滇宴是和朋友二刷了解里面没吃过的其他菜；亮嚯兰州翻花烤串和蜀肠缘江油肥肠火锅都是去探店，感觉一般；比尔包车是给朋友过生日，去了后发现这家店的位置是两年多前一家比较喜欢的韩式烤肉的店面；湘彬萱是北京我比较喜欢的湘菜馆子，上一次吃是 2022 年 3 月 11 日，店面重新装修过了不再是前些年我们去的时候朴素老旧的样子；江边诱惑巫山烤鱼是和朋友逛完植物园后去吃的，还不错，不过比起味道更让我印象深刻的是在盘子里撕扯鱼肉的时候把一滴汤汁甩到了右眼里，痛到眼睛都睁不开，服务员领我到卫生间后我冲洗了好一会才好些。此外还参加了一次小饭桌活动，朋友做的薄荷牛肉印象很深刻，羊肉炒面片最后剩了点我带回去做了第二天的早饭。
&lt;/p&gt;


&lt;div id=&quot;org9cd1e3f&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230806_food.jpg&quot; alt=&quot;20230806_food.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;1&amp;nbsp; &lt;/span&gt;滇宴&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orga19e676&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230815_food.jpg&quot; alt=&quot;20230815_food.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;2&amp;nbsp; &lt;/span&gt;比尔包车&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org31965f0&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230819_food.jpg&quot; alt=&quot;20230819_food.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;3&amp;nbsp; &lt;/span&gt;小饭桌&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgd6c7cac&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230821_food.jpg&quot; alt=&quot;20230821_food.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;4&amp;nbsp; &lt;/span&gt;湘彬萱&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
8 月我一共外出了 29 次，其中 5 次是自己出门去附近吃饭，10 次是参加各种人际活动，14 次是自己去散步，并在这些外出活动中逛了双秀公园、奥森、后海和国家植物园。我尝试养成每周出去散步 3 次的习惯，这个在 8 月坚持得不错。只要空气质量不要太差、不要下雨，我还是喜欢出去散步的，有几次下雨还想着去打个伞去河边看雨的，不过阵雨来去匆匆等我下定决心的时候雨就停掉了。
&lt;/p&gt;

&lt;p&gt;
在散步过程中看到了 1 次朝霞和 4 次晚霞。8 月 14 日这天看到朝霞前，我已经 351 天没有看到过朝霞了，主要的原因还是起不来，2022 年多看了几次日出和朝霞的主要原因则是心理状况糟糕睡不着，所以朝霞看得少也不是什么坏事情。
&lt;/p&gt;


&lt;div id=&quot;org66ca381&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230814_morning_sky.jpg&quot; alt=&quot;20230814_morning_sky.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;5&amp;nbsp; &lt;/span&gt;20230814朝霞&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgc7158b3&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230818_sky.jpg&quot; alt=&quot;20230818_sky.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;6&amp;nbsp; &lt;/span&gt;20230818晚霞&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org28d6e4d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230819_sky.jpg&quot; alt=&quot;20230819_sky.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;7&amp;nbsp; &lt;/span&gt;20230819晚霞&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org4ce7bfd&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230824_sky.jpg&quot; alt=&quot;20230824_sky.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;8&amp;nbsp; &lt;/span&gt;20230824晚霞&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgf4f2f7e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230829_sky.jpg&quot; alt=&quot;20230829_sky.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;9&amp;nbsp; &lt;/span&gt;20230829晚霞&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
8 月我共与 39 个人有过共计 92 次线上或线下的接触 —— 简单起见，线下见面、线上私聊、打电话算作有效接触，线上群聊则不计入，同一个人一天内的所有接触只算 1 次。还在上班的时候没有做过这样的统计，但感觉应该没有这么多人际往来。当然，这些人际往来的分布是长尾的，这 39 个人里的一大半也就是简单接触了一次，只有 10 来个人有超过 1 次的接触。月底在一个技术交流活动上见了一些许久没有见面的朋友，还共同悼念了下在这个活动里认识的一位过世的朋友，三四年前这位朋友给我们讲了他从设计稿或截图生成前端代码的想法，据说后面已经实现出来了，如果没有因为车祸离去的话，想必这次活动也会兴高采烈地跟我们讲如何用 GPT 来做这个事情 —— 我和他交情并不太深，只是觉得有些遗憾。总而言之，还在工作的时候，想到离职总会担心自己缺少人际交往而导致心理问题，但实际上，从工作压力中解放出来后，我有了更多时间能和朋友交流、也有了更多的耐心和同理心，也很感谢那些愿意来找我聊天交谈的人们。
&lt;/p&gt;

&lt;p&gt;
八月社会上还发生了很多事情，各地洪涝、中植暴雷、工信部要求APP备案、统计局暂停发布失业率数据、印花税减半、大模型版号发放……各种社会事件大多只能增加焦虑，在个人无法对局面造成什么改变的情况下，我觉得还是少看、少说为好，慢慢但是持续地积攒一些力量以应对未来的不确定性吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org84723db&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org84723db&quot;&gt;阅读学习&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org84723db&quot;&gt;
&lt;p&gt;
进入 8 月后，我觉得身体、头脑和心理的状态都已经恢复到了一个比较不错的水平（当然，是相比工作时候），所以开始想尝试恢复去做一些比较需要精力的事情，除了平时的阅读外，也开始重新关注 NLP 领域特别是语言模型方面的学术进展，不过发现还是不能长时间保持专注，所以完整仔细读完的论文并不多。
&lt;/p&gt;

&lt;p&gt;
除了注意力不能长时间集中外，我读论文进展缓慢的还有一个原因，那就是我在重新梳理自己的学习系统。比起按照价值（比如说内容质量、时效、影响力等等）来去获取信息和知识，我现在更倾向于通过问题来驱动整个学习过程，大致的理念就是从自身出发去提出一些问题，然后去获取资料来解答这些问题。初次产生这个想法已经是一年多前了，在这个理念的驱动下，8 月我清理了一下已有的笔记，删掉了大半只是当时觉得有用但实际上与我长久关注的问题并无太大关系的内容。在阅读论文这个事情上也是这样的，我仍然关注 NLP 领域的进展，但我对了解最新的、最全面的研究没有什么执念，我也不追求什么论文阅读效率，离职后的这段时间，我更想要做的，是能把自己对 NLP 领域的问题清晰地表达出来 —— 不光是我认为 NLP 领域有什么问题需要关注，还想要想清楚我为什么要关注这些问题、这些问题对我的人生有何意义、我在这些问题上能够起到什么作用 —— 在这个事情上，大佬们的论文推荐、基于 LLM 的论文阅读流程（翻译、摘要、重要结论）对我都没有什么意义。
&lt;/p&gt;

&lt;p&gt;
总之，我并不想变成一个高效的资料收集机器，我希望我的阅读、学习、思考过程同样也是我的自我构建、改进过程的一部分。当然，在这个理念的基础上，提出问题是很困难的，我现在甚至连描述这种理念都做不到清晰准确，但我觉得挺有意思的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3d28aef&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3d28aef&quot;&gt;其他&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3d28aef&quot;&gt;
&lt;p&gt;
8 月读的科幻小说《艾比斯之梦》非常喜欢，读完后我写下了这样的感想：
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;org76ce34b&quot;&gt;
艾比斯讲给说书人的故事、说书人和艾比斯之间的故事、读着这些故事的读者，故事的力量一层层地传递下去，三个世界上的人一致同意，故事虽然是虚构的但可以传递不弱于现实的真实力量。其实，所谓的现实、自我也不过是一个个故事而已，人类所谓的文明、信念、礼法、道德、宗教、国家、文化，都是形成大范围共识的群体故事，人类的自我也不过是大脑讲的一个故事，甚至连过去确定无疑发生过的事情也在被个人、群体基于某些目的重新叙述后天知道和现实偏离到了哪里。谁掌握了说故事的权力，说就掌握了编排众人（或自己）命运的能力，全心全意相信其他人讲的故事就意味着将个人命运全权交给了讲故事的人，努力地编织自己的故事就是在努力地书写自己的命运，我们也是剧中人，我们也都是说书人。
&lt;/pre&gt;

&lt;p&gt;
这些年来，我非常努力地去做各种记录，早先是惯性使然，而后这已经成为了我生活中不可缺失的部分，在这几年里，有朋友惊叹我的记录工作之多、询问我这种记录意义何在，于是我为这个行为所编织的故事也渐渐变多。8 月和朋友讨论自我与灵魂的时候，我借鉴了侯世达《我是个怪圈》里「我们活在彼此之中」的观点讲了一个新的故事：通过详细的观察和记录，我就可以让在意的人的灵魂更清晰、更长久地留在自己身边了。在这个故事里，我为曾经有很多可能发展为较亲密关系的朋友但却没有真的了解过他们而感到遗憾，并且为了不再有这方面的遗憾而开始在记录自己的生活外还记录和现在朋友的每一次见面、谈话以及他们的喜好、烦恼、心愿、生活习惯、去过的地方等各种信息。
&lt;/p&gt;

&lt;p&gt;
当然，这只是个故事而已，并非现实，但就像《艾比斯之梦》一样，故事是否真实并不重要，故事是否能够继续讲述下去、并且是否能够被重要的人听到才重要。很多事情，特别是关乎自己生活的部分，苛刻地去追问是否有意义很没有意思，但作为一个故事来看待会很有趣味，不工作的第三个月后，我希望还能继续把这个不工作的故事讲下去，讲一个将生活当作主动的故事构建过程而不是在别人故事里当炮灰和龙套的故事，至于故事的意义和价值，讲故事的人固然会有所设计，但也取决于读者自己的想法。
&lt;/p&gt;

&lt;p&gt;
最后再引用一段《艾比斯之梦》里的话：
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;orgf66ecbc&quot;&gt;
我想说的是，人类有一种习惯，会将感动的事称之为‘真实’，但区分真实和虚构的能力很低。如果别人说‘这是真正发生过的事’，即使摆明了是虚构的，人类也会信以为真。越是撼动人心的故事，人类越不想认为那是虚构的。人类认为，如果不贴上‘真实’的标签，价值就会下降。

人类在不知不觉之间，活在许多虚构的事物之中：如果累积善行就能上天堂；超级古代文明确实存在；这场战争是替天行道；喝下这台净水器过滤的水就会变健康；她命中注定和我结婚；戴上这种饰品，幸运就会降临；某位政治家会改变这个国家的命运；进化论是一派胡言；我有优异的天分；不遵守老规矩，厄运会从天而降；铲除那个民族，世界会变得美好……如同诗音所说，人类一直愿意相信错误的事。从出生到死亡，都住在只存于自己脑中的虚拟现实之中，一旦知道那不是事实，就会仓皇失措，不肯承认。
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>2023年7月总结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2023/08/10/july-review.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2023/08/10/july-review</id>
    <published>2023-08-10T00:00:00+00:00</published>
    <updated>2023-08-10T00:00:00+00:00</updated>
    <description>
    
      <p>离职后的第二个月，平平淡淡</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org02d861d&quot;&gt;日常生活&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgaf4ed38&quot;&gt;游戏&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgc890d43&quot;&gt;潜水员戴夫&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgea25ae2&quot;&gt;杀戮尖塔&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd25e089&quot;&gt;灵魂旅者&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd7590ae&quot;&gt;《Patrick's Parabox》和《Helltaker》&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org101bee3&quot;&gt;雨世界&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org73985c7&quot;&gt;电影&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1cd15fb&quot;&gt;其他&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
七月是我离职后的第二个月，依然在北京待着哪里也没有去，平平淡淡地过着日常生活。
&lt;/p&gt;

&lt;div id=&quot;outline-container-org02d861d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org02d861d&quot;&gt;日常生活&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org02d861d&quot;&gt;
&lt;p&gt;
七月最大的成就是建立并坚持了几个比较好的生活习惯：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
吃早饭
&lt;/p&gt;

&lt;p&gt;
大部分早饭是自己做的，有时候会去吃 KFC（买了 KFC 的大神卡选了早餐优惠），偶尔也会点点外卖。自己做早饭目前比较随便，大部分时间是煮个面，有时候也煮鸡蛋、煎鸡蛋、水煮个西兰花什么的。用寿桃鸡蛋面搭配仲景葱油做了好多次葱油面吃，寿桃是朋友推荐的，煮了后口感仍然比较有韧性不用担心煮烂什么的，仲景葱油是调好味的，煮好面捞出来浇上点拌开就很好了。去吃 KFC 的时候更多是想出门走走，一个观察是，同样是八点多九点左右，周末的时候我到 KFC 点的单子一般是 50 号左右而工作日会在 130 号后之后，感觉吃早饭的人还是不多呀，为自己点赞。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
每天起床后会晨练一会
&lt;/p&gt;

&lt;p&gt;
大部分时间会做一套固定的全身运动，偶尔有几天状态不好就随便动一动，总之就是在起床后活动下身体，身体活动舒展开了，精神也会明显更好，能明显感觉到七月每天的精力都还不错，比六月更好，比工作时候就好非常多了，每天几乎都不会有那种很困乏的状态。
&lt;/p&gt;

&lt;p&gt;
精力或许也和睡眠有关，但是离职后还没有去刻意改进作息，看了手表记录的睡眠数据，也并没有睡得比上半年还在工作时那几个月更好，所以我还是认为精力变好和每天的晨练有关系，一定程度上可能也和心理压力的降低有关。
&lt;/p&gt;

&lt;p&gt;
虽然有感觉身体状态有在变好，但偶尔颈椎和肩膀还是会有不舒服，有时候是因为没睡好，有时候是因为久坐。有想去增加一些运动量，比如说去河边跑步或者去攀岩，不过一直没有下定决心。其实游泳我也是喜欢的，但我喜欢、习惯的是在河里游泳，对于单纯以运动健身为目的的游泳还是没有太多兴趣。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
冥想/正念
&lt;/p&gt;

&lt;p&gt;
正经的冥想/正念似乎还要训练呼吸什么的，没有研究过不是太懂，我就只是想要去观察自己内心的念头并进行梳理而已，用的是 &lt;a href=&quot;https://apps.apple.com/us/app/pause-daily-mindfulness/id991764216&quot;&gt;Pause&lt;/a&gt; 这个 APP 来进行辅助，它的交互很简单，就是让手指在屏幕上保持移动，屏幕上会出现一个圆球随着移动慢慢地变大，同时会播放很舒缓的音乐。我一般是在吃完早饭后，到床上盘腿坐着靠在墙上来进行这个活动，坐着是为了保持清醒，靠墙是为了让颈椎舒服点，其实什么姿势都可以，只要能保持全身比较舒适放松并且意识清醒，也试过躺着，但容易睡着。
&lt;/p&gt;

&lt;p&gt;
我是个脑子里念头非常多的人，所以经常感到很累，冥想并不能让念头减少，甚至在冥想的时候因为更加关注自己的大脑活动会觉得冒出来的念头想法更多，不过现在已经学会了不要尝试去刻意控制引导它们，观察、忍受就可以了，偶尔能做到比较抽离，极少数大概有一两次能进入比较忘我感觉不到什么杂念的状态，但不管怎么样结束后一般都能明显感觉到头脑更轻松、注意力更集中、情绪更加平稳，其实有时候爬山、写作或者玩游戏也能得到类似的体验，只不过坐下来闭上眼睛发呆是一个门槛够低每天都能做的事情。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
写日记
&lt;/p&gt;

&lt;p&gt;
按理来说，我不工作而且每天宅着好像会没什么可写，但其实并不会。只要去尽力地仔细观察，普通的日常生活里也会有很多值得记录的事情，重点不是有没有足够丰富的、不平常的事件，而是有没有值得写下来的感受，不管是心灵上的还是身体上的。前面说到我脑子里念头非常多，所以哪怕是发呆，那期间翻腾涌动的念头和想法也会很有意思，身体上的感受也每时每刻在变化，这些感受只要能被重视，就都是值得写下来的。
&lt;/p&gt;

&lt;p&gt;
重视自己的感受就是重视自己，重视自己的人不会无事可写，有时候我甚至因为有太多感受想记录而觉得文字实在是不够方便。
&lt;/p&gt;

&lt;p&gt;
我写日记很多年了，所以写日记并不是一个新的习惯，不过在上班的时候都没有那么多精力去仔细地回顾当天的经历和感受，不能保证天天都写。写日记本身也是一种能提升对生活细节观察能力的练习，写得越多就能观察得越好，观察得越好又能写得更多。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
阅读
&lt;/p&gt;

&lt;p&gt;
阅读是几个习惯里做的比较不好的一个，一个原因是我比较散漫，七月同时看了很多书，导致没有几本看完的；然后我更想要进行能充分调动思维的阅读活动而不只是靠阅读来打发时间，所以对注意力要求会比较高。因为没有几本完整读完的书，这次就不写阅读方面的具体感想了。
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
其他方面：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;除了早饭外自己做了 14 次饭，点了 6 次外卖，和朋友聚餐 7 次&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
外出 20 次，其中 10 次散步、9 次社交活动（和朋友聚餐、看电影等）
&lt;/p&gt;


&lt;div id=&quot;org3ba5282&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230707_cloud.jpg&quot; alt=&quot;20230707_cloud.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;1&amp;nbsp; &lt;/span&gt;20230707的傍晚&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org2f10f89&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230709_cloud.jpg&quot; alt=&quot;20230709_cloud.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;2&amp;nbsp; &lt;/span&gt;天上有只大鱼&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org85d0f34&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230723_cloud.jpg&quot; alt=&quot;20230723_cloud.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;3&amp;nbsp; &lt;/span&gt;20230723的晚霞&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org53dc613&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230726_moon.jpg&quot; alt=&quot;20230726_moon.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;4&amp;nbsp; &lt;/span&gt;20230726的月亮&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org4381961&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230728_sky1.jpg&quot; alt=&quot;20230728_sky1.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;5&amp;nbsp; &lt;/span&gt;20230728虹霞交映的天空&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgd7c2fe3&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230728_sky2.jpg&quot; alt=&quot;20230728_sky2.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;6&amp;nbsp; &lt;/span&gt;20230728好看的天空&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
见到了 10 个朋友，和朋友在外面吃了南洋茶室、一坐一忘、八条一号、滇宴、烤乐烧、零公里和八合里海记，滇宴是七月朋友发现的一家新开的云南菜，菜单非常厚，有不少原来在其他云南菜馆子里没怎么见过的比较新鲜的菜式
&lt;/p&gt;


&lt;div id=&quot;org4a2d27e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230701_food1.jpg&quot; alt=&quot;20230701_food1.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;7&amp;nbsp; &lt;/span&gt;南洋茶室很嫩的海南鸡&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org013e3cd&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230702_food1.jpg&quot; alt=&quot;20230702_food1.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;8&amp;nbsp; &lt;/span&gt;一坐一忘的酸菜酥红腰豆&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgd7b751a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230705_food1.jpg&quot; alt=&quot;20230705_food1.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;9&amp;nbsp; &lt;/span&gt;八条一号菜单上没有的神奇甘蔗尖&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgfc968c9&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230705_food2.jpg&quot; alt=&quot;20230705_food2.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;10&amp;nbsp; &lt;/span&gt;八条一号红酒煎猪肝&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org40cb8c4&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230705_food3.jpg&quot; alt=&quot;20230705_food3.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;11&amp;nbsp; &lt;/span&gt;八条一号小白菜酥红腰豆&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgdaa6f4c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230708_food1.jpg&quot; alt=&quot;20230708_food1.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;12&amp;nbsp; &lt;/span&gt;滇宴的富源酸菜煮牛干巴&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org40f2453&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230729_food1.jpg&quot; alt=&quot;20230729_food1.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;13&amp;nbsp; &lt;/span&gt;零公里&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
去了一次奥森（其实离得很近可以多去的），看到了好看的向日葵，还去了一趟地质博物馆看到很多漂亮的石头
&lt;/p&gt;


&lt;div id=&quot;org72f74ce&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230705_sunflowers.jpg&quot; alt=&quot;20230705_sunflowers.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;14&amp;nbsp; &lt;/span&gt;奥森向日葵&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org37eb2d1&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230705_stones_1.jpg&quot; alt=&quot;20230705_stones_1.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;15&amp;nbsp; &lt;/span&gt;地质博物馆矿石(1)&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgfb2c0a0&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20230705_stones_2.jpg&quot; alt=&quot;20230705_stones_2.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;16&amp;nbsp; &lt;/span&gt;地质博物馆矿石(2)&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;几次看电影和逛超市，发现电影院和超市人都很多，热闹的场面仿佛回到了疫情前，虽然周围也有不少关掉的超市和小店，以及有暑假的因素在&lt;/li&gt;
&lt;li&gt;本来还想把投资和日常支出的账单整理下的，但是半年没整理了，工作量实在是有点大，预计八月能完成&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgaf4ed38&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgaf4ed38&quot;&gt;游戏&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgaf4ed38&quot;&gt;
&lt;p&gt;
steam 夏促的时候买了 16 个游戏，大部分稍微尝试了下但并没有长期玩，七月主要玩了《王国之泪》《潜水员戴夫》《杀戮尖塔》《灵魂摆渡人》《Helltaker》《Patrick's Parabox》《雨世界》这几款游戏。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc890d43&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc890d43&quot;&gt;潜水员戴夫&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc890d43&quot;&gt;

&lt;div id=&quot;org69e9707&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dave_the_diver.png&quot; alt=&quot;dave_the_diver.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;17&amp;nbsp; &lt;/span&gt;潜水员戴夫&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
前半个月主要在玩《王国之泪》和《&lt;a href=&quot;https://www.douban.com/game/36138262/&quot;&gt;潜水员戴夫&lt;/a&gt;》，《王国之泪》就不用说了，主要是没啥别的事情的时候进去做做小任务和神庙解谜。《潜水员戴夫》我玩了 40 多个小时通关了，觉得作为休闲放松的游戏还是非常好的，以下是我对这个游戏的总结和评价：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;潜水+经营以及推动它们的线性剧情事件，构成了这个游戏的主要内容：游戏将每天划分成三个时间段，主要以潜水为主，上午和下午潜水摸鱼、晚上开店（后面到晚上也能潜水），潜水的所得的食材作为寿司店经营的材料，寿司店一方面为潜水装备升级提供资金、另外一方面也通过各种经营事件（主题派对、烹饪对决）激励玩家去探索更多的地图、收集更多的食材，同时还有一个章节形式的线性剧情推动这两块核心内容的变化（主要涉及地图变化和装备解锁升级），后面又引出了农场和养鱼场来减轻食材供应的压力&lt;/li&gt;
&lt;li&gt;在潜水这块内容上，主要的玩法就是在海中畅游抓捕各种鱼类、采集各种海藻、收集各种掉落在海中的材料，并随着剧情事件升级潜水装备（潜水服、氧气瓶、装载箱、3种武器），随剧情进展还会有和巨大海洋生物的 BOSS 战以及一些横版解谜过关内容&lt;/li&gt;
&lt;li&gt;在寿司店经营这块上，主要就是食材、调味品和菜谱收集然后开店营业（需要设置当日菜品+厨师做菜+服务员上菜）赚取资金和好评并升级店铺，还可以在烹饪对决事件中以厨师的视角来做菜（可以视为若干烹饪小游戏）&lt;/li&gt;
&lt;li&gt;在潜水+经营+剧情事件的大框架中，非常和谐地缝合了各种丰富的机制、玩法，各个玩法都很轻所以不会让人在玩的时候有什么压力（当然想肝也可以但游戏本身几乎没有为肝设置什么奖励），整个游戏流程的节奏也设计得非常好，潜水深度的增加、潜水装备的解锁升级、寿司店的升级和各种事件等等始终在设计良好的线性剧情中以一种很舒服的节奏呈现着，不会有哪一段觉得困难和无聊 —— 游戏里的各个子内容可以说都算不上有什么深度或者很优秀，但这种整体设计的能力是在是太厉害了&lt;/li&gt;
&lt;li&gt;游戏里有很多让人会心一笑的小彩蛋，比如寿司店经营事件里挑战者吃下食物后的动画让人非常容易想起《中华小当家》的场景、某个挑战的厨师摆出拳皇经典人物的 POSE、店员吐槽说为什么晚上才营业我晚上都很累了……&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgea25ae2&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgea25ae2&quot;&gt;杀戮尖塔&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgea25ae2&quot;&gt;

&lt;div id=&quot;orgd381ba7&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/slay_the_spire.png&quot; alt=&quot;slay_the_spire.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;18&amp;nbsp; &lt;/span&gt;杀戮尖塔&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
《&lt;a href=&quot;https://www.douban.com/game/27596589/&quot;&gt;杀戮尖塔&lt;/a&gt;》是非常知名的卡牌游戏，在 rogue-like 式的爬塔过程中同时构建自己的牌组，很上头很杀时间，不过我没准备投入太多时间在这个游戏上，只是慕名已久尝试一下，这种游戏轻轻松松就能玩上几百个小时，我还想多尝试下别的游戏呢。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd25e089&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd25e089&quot;&gt;灵魂旅者&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd25e089&quot;&gt;

&lt;div id=&quot;orge0cb539&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/spiritfarer_1.png&quot; alt=&quot;spiritfarer_1.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;19&amp;nbsp; &lt;/span&gt;灵魂旅者&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
《&lt;a href=&quot;https://www.douban.com/game/34430160/&quot;&gt;灵魂旅者&lt;/a&gt;》中玩家扮演一个冥界摆渡人，接纳死者的灵魂，完成他们的愿望并在这个过程中了解他们的故事，总体上来说是一个节奏很舒缓、剧情驱动的游戏。这个游戏玩起来没有任何的负担，虽然在船上也有一些模拟经营的元素 —— 收集木材矿石、种植粮食和蔬菜、为船上的灵魂制作食物，但这些事情并非游戏的主要驱动元素，并不会造成多大的压力。不过也正因为节奏舒缓，所以我投入的时间不算很多。很喜欢在暴风雨中听着叔叔演奏的音乐去抓闪电、在航行途中钓鱼看云彩和星空的流动。
&lt;/p&gt;


&lt;div id=&quot;org7c4ff6b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/spiritfarer_2.png&quot; alt=&quot;spiritfarer_2.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;20&amp;nbsp; &lt;/span&gt;灵魂旅者2&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd7590ae&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd7590ae&quot;&gt;《Patrick's Parabox》和《Helltaker》&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd7590ae&quot;&gt;
&lt;p&gt;
《&lt;a href=&quot;https://www.douban.com/game/34743685/&quot;&gt;Patrick's Parabox&lt;/a&gt;》和《Helltaker》是两个在推箱子的玩法基础上加上了创新玩法的游戏。
&lt;/p&gt;


&lt;div id=&quot;orgf704fb1&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/patricks_parabox.png&quot; alt=&quot;patricks_parabox.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;21&amp;nbsp; &lt;/span&gt;Patrick's Parabox&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
我是先玩了《Baba is you》后得知了《Patrick's Parabox》这个游戏，和《Baba is you》通过推动构成游戏规则的词语来改变游戏规则不一样，《Patrick's Parabox》是在推箱子的基础上加上了嵌套、镜像等元素，在玩的过程中还会触发递归、循环、无穷等现象，作为一个计算机出身的人来说觉得非常有意思。
&lt;/p&gt;


&lt;div id=&quot;org9c3c4a1&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/helltaker.png&quot; alt=&quot;helltaker.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;22&amp;nbsp; &lt;/span&gt;Helltaker&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
玩了《Patrick's Parabox》后又了解到《Helltaker》这个免费游戏，它体量很小，总共就十来个关卡，要求玩家在有限步数的前提下到达目的地，同时还设计了陷阱（经过时需要消耗更多步数）、钥匙（获取后用来打开锁上的门）、激光（碰到必死需要推动岩石对其进行阻隔）等元素，非常的难，每一关都需要经过仔细的思考和反复的尝试，在此基础上这个游戏还设计了趣味盎然的剧情和人物以及非常有节奏感的音乐，甚至还有 BOSS 战（好难！）。这两个游戏都需要大量的思考，玩起来并不轻松，卡关的时候甚至想过去写程序来暴力求解，不过解决谜题后的成就感也是非常棒的，这就是解谜游戏的乐趣所在啦，不难的解谜游戏还叫什么解谜游戏啊！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org101bee3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org101bee3&quot;&gt;雨世界&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org101bee3&quot;&gt;

&lt;div id=&quot;orgc60d9cf&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/rain_world.png&quot; alt=&quot;rain_world.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;23&amp;nbsp; &lt;/span&gt;雨世界&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
《&lt;a href=&quot;https://www.douban.com/game/26966373/&quot;&gt;雨世界&lt;/a&gt;》这个游戏据说设计了一个庞大而完整的世界观，我目前玩的不多，尚未对此有充分的体验，不过对里面的生态系统已经有所了解。一般来说在角色扮演或者冒险类游戏里，如果有敌人或者陷阱、谜题，主要都是为了服务玩家而设计的，所谓服务玩家，就是说这些元素首先要能给玩家提供乐趣，其次才是加上一些和世界观相关的点缀，换言之游戏里的各个元素主要是等待玩家与之互动、互相之间是很少交互的。《雨世界》里面的各个生物会有很多自主的行为而且不同生物之间还有复杂的交互行为，比如同一类生物的不同族群之间会互相攻击，比如有明显的一类生物捕食另外一类生物的食物链表现，还有种类丰富的不同生物。玩家扮演的也只是这个生态系统里一个弱小的生物，所以像其他游戏里那样打败敌人是不太行的，能做的只能是观察、学习、躲避、探索、捕食其他更低级弱小的生物，不像其他游戏里那样容易获得打败敌人、解开谜题的爽感。这种游戏会比较挑人，我还是比较喜欢的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org73985c7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org73985c7&quot;&gt;电影&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org73985c7&quot;&gt;

&lt;div id=&quot;orgf88244c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/202307_movies.jpg&quot; alt=&quot;202307_movies.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;24&amp;nbsp; &lt;/span&gt;电影&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
看了《夺宝奇兵5：命运转盘》《长安三万里》《茶啊二中》《芭比》《封神第一部》五部电影。
&lt;/p&gt;

&lt;p&gt;
《夺宝奇兵》没太多好说的，是那种老派复古的故事，人物的塑造、情节的冲突以及很多镜头，都会让人觉得很熟悉没啥新意，但是就觉得很合适，看下来我不算喜欢，但还可以吧，不觉得有什么大的槽点 —— 以现在的喜好来看当然有很多可以吐槽的但就觉得这些在这种电影里就是正常的啦。
&lt;/p&gt;

&lt;p&gt;
看《长安三万里》被追光的动画制作水平惊艳到了，电影的剧本很有意思，一首首唐诗特别是最后的《将进酒》的意境渲染也非常好，但我看这个电影没有办法获得其他人那样的感动，看着电影的时候，脑子里闪过的是「贞观元年，关内饥」「开元十六年，河北饥」和疫情的三年，小人物在整个电影里几乎没怎么被提到，安史之乱沦为高适高光展示的一个背景板，乱世里普通民众的苦难完全没有，所有的内容都是为了英雄、名人形象服务的，盛世是上层人的盛世、乱世也是上层人的乱世，这样的形式所传达的文化自信对我来说太过空洞和狭隘了 —— 当然，电影就是这么设计和定位的，有问题的可能不是它，大概是满腹不合时宜的我。
&lt;/p&gt;

&lt;p&gt;
《茶啊二中》是七月看的最舒服的电影，它没什么深刻的内容和过份的升华、说教，动画制作水平不能和追光比，只是认认真真地讲一个校园喜剧，讲的是师生互相达成理解这么一件事情，笑点也主要在师生、学生与学生之间的互动中呈现，大部分都是一些校园生活里细节的戏剧性或者夸张化表现，频频让人会心大笑，电影里的各个角色想必大家在看的时候也总能找到一些当年同学的影子。边看边笑边吐槽，脑海里跟着浮现出上学时一幕幕开心的场景 —— 我高中最开心的应该是复读那一年了，和同学在最后一排偷吃零食（这对作为好学生的我来说可是很刺激的），课间和好多同学一起跑出去在阳台玩（晒太阳、聊天、玩游戏）而不是像高二高三那样继续在教师狂做题，六一儿童节同学去老师办公室偷了电视电源线大家一起看《葫芦娃》……当时的班主任对我们比较宽容，同学们成绩不算好却都认真，但又不像尖子班学生那样认真到苦大仇深……我喜欢这样讲小人物小场景的故事，它们的情感简单但真实、稳固，人性的光辉在每个真实的普通人身上，我不需要神明和偶像。
&lt;/p&gt;

&lt;p&gt;
《芭比》是一部毫无疑问的女性主义电影，虽然只是通过话语表面性地痛斥了父权制度、申诉了一番女性的困境，并用一层精心包装过的喜剧和童话色彩的外衣来描绘了一些理想的可能、减轻了荒诞与无力的感觉，并没有真的深入到女性困境的细节和父权社会的内部机制里，但我想它已经达到了它的目的。对于它的争论或赞誉或批评，我不想去参与，只是觉得作为一个男性也应该去了解女性困境和女性权益，这种了解不是为了获得什么其他群体的肯定、赢得什么辩论，而是为了在自己的女性亲友遇到困难时理解她们、给出一些可能有用的帮助，事实上我已经有女性亲友处在困境之中了（或者说一直在吧）。进一步的，社会规训对每一个想充分发展自己个性的人都是枷锁，建立起这样一个认识很重要。
&lt;/p&gt;

&lt;p&gt;
《封神第一部》我觉得至少是一部合格的电影了，想起早年间看的《长城》还是会眼前一黑，当时想着马特达蒙应该不会拍烂片吧，我真是天真。电影的工业水平（场景、特效等）已经非常不错了，编剧不脑残整个故事还是比较自洽的，演员都很敬业，作为一个商业片来说我觉得就是合格了。故事我本来觉得魔改了很多，后来去了解了下，其实参考了不少《武王伐纣平话》里的故事，也不算凭空瞎改，不过都无所谓，封神故事里的政治斗争本来也不重要，群仙斗法才是真正的看点嘛。这样的电影没什么深度，但还是期待它们在将来能培养出一批敬业的电影从业人员，算是我对国产电影的一点祝福吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1cd15fb&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1cd15fb&quot;&gt;其他&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org1cd15fb&quot;&gt;
&lt;p&gt;
整个七月，我的心理状况都很平稳，六月提到的一些负面情绪非常少出现了。用「不系舟」这个网名用了很多年了，大概这段时间才真正体会到一点「无能者无所求，饱食而遨游，泛若不系之舟」描述的那种闲适感，哪怕只是暂时的。承认、接受自己和自己的行为对整个社会毫无用处，是对相反方向社会规训的一种反抗和矫正，玩游戏有什么用、发朋友圈有什么用、看这些杂书有什么用、说这些有什么用……没什么用，我就是乐意，有什么用我自己说了算，关「您」屁事。
&lt;/p&gt;

&lt;p&gt;
至于将来怎么办，七月完全没去想，顺其自然吧。人总是在为未来生活，今天规划明天，明天规划后天，倒不是说这种规划是错误的，只是对很多人来说，这种对未来的焦虑感完全压过了对现在的感受，我还处在矫枉过正的过程里，享受每一天吧。比较确定的是，目前仍然没有想回到职场上去，主要原因当然是存款还够、没有负债、一人吃饱全家不饿啦。
&lt;/p&gt;

&lt;p&gt;
稍微有一点不太满意的是发现自己在阅读学习上做得不够好，七月本来是想多读一些书并且看看论文的，但目前想要进入比较专注的状态还是有些困难，这些困难我曾经也克服过，所以并不会毫无头绪，只是需要一些决心和持续的投入，或许八月会尝试努力一下，不过不努力也没什么关系。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>2023年6月总结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2023/07/13/june-review.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2023/07/13/june-review</id>
    <published>2023-07-13T00:00:00+00:00</published>
    <updated>2023-07-13T00:00:00+00:00</updated>
    <description>
    
      <p>离职后的第一个月</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org8de208a&quot;&gt;娱乐&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4c6898d&quot;&gt;美食&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb68220d&quot;&gt;阅读&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4afa8ac&quot;&gt;其他&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
六月是我正式离职后的第一个月，也是 2023 年上半年最后一个月，这个月我待在北京哪里也没有去，主要就是在玩游戏，偶尔看看书，总体来说还是比较惬意平静，不过有时也会感到无聊和焦虑。对懒散拖延的我来说，没有了工作来强制分配时间后，自己维持生活的基本秩序还是有点挑战的，就像一个骤然暴富的人，突然一下有了这么多的可自由支配时间让我有些不太适应，在察觉到自己心态和情绪上的问题后，我开始去做一些尝试，同时也决定恢复以前定期回顾总结的习惯，以便从更大的尺度上了解自己的变化、发现问题。
&lt;/p&gt;

&lt;div id=&quot;outline-container-org8de208a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org8de208a&quot;&gt;娱乐&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org8de208a&quot;&gt;

&lt;div id=&quot;orgbe8ec00&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023-06-zelda.jpeg&quot; alt=&quot;2023-06-zelda.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
《王国之泪》我是五月二十六开始玩的，在最开始的半个月内（从五月二十六到六月十来号）我除了吃喝拉撒几乎都在玩，到六月十号把主流程推进到只剩打最终 BOSS 后才开始每天玩得少一些了，现在游戏时间已经接近 200 小时了。
&lt;/p&gt;

&lt;p&gt;
我觉得游戏最好玩最沉浸的阶段，就是在探索地图的时候。说到地图探索的体验，我会先想起《黑暗之魂1》里那精妙绝伦的地图设计，在不死教区躲过敌人坐电梯回到荒凉破败的传火祭祀场的时候、在巨人墓地远远望见恶魔遗迹的岩浆和灰烬湖林立的世界树的时候，那种惊喜和震撼是难以形容的，但《塞尔达》（包括《塞尔达：旷野之息》和《塞尔达：王国之泪》，后文的《塞尔达》指这两部游戏）的地图探索体验是不同的，它地图的各个部分互相之间没有那么强的关系，《王国之泪》在原来《旷野之息》地图的基础上加上了天空浮岛、幽暗地底以及地表与地底之间的洞窟，但地图设计的理念并没有发生大的变化，正如《旷野之息》的名字所说的一样，它提供的是一个巨大的旷野，让玩家能在其中自由的探索和玩耍，无论走到哪里皆是如此，它没有像《黑暗之魂》里传火祭祀场那样的中心 —— 监视堡垒算是大本营，但是里面所有的人都在鼓励林克外出探索。在一个巨大的旷野上探索什么、怎么玩耍呢？想像一下我们小时候在旷野上是如何玩耍的 —— 观察每一朵花和每一棵树、惊喜于草丛里扑棱棱飞出来的昆虫、拣拾漂亮的落叶和石头、把奇形怪状的石头想像成怪物或精灵……《王国之泪》里的开放世界地图就是这样的，它空旷但并不空洞，充满了细小但有趣的内容：用剑把草割开会有蚱蜢飞出或者蜥蜴爬出，抬起石头偶尔也会有昆虫从下面爬出，夜晚萤火虫在不远处轻盈飞舞，草地上出现一个突兀的有缺口的三角形石阵，一棵巨大的樱花树下有一个石像而且它面前有一个好像能放上贡品的小坑（放个苹果上去会发生什么呢？），形如兔子、散发着青白色光辉的小精灵在不远处玩耍被发现后慌忙跑向一个黑黢黢的洞窟（洞窟里会有什么呢？），荒废的村落里埋藏着宝箱打开后只是一柄锈蚀的短剑……一般的游戏都会设计一些游玩的大致流程并且在游戏里引导玩家，《塞尔达》虽然也有主流程但在引导上非常非常弱，即使是在赶着救公主的路上，玩家依然会非常非常容易被路上的各种东西吸引 —— 哎呀有棵树摘点苹果吧，波克布林（游戏里的一种怪物）在吃水果耶好可爱，这三棵树长的和周围的不太一样啊去看看有没有呀哈哈，有马群我要抓个马，这个瀑布后面有没有隐藏洞窟啊过去看看，啊有小精灵悄悄蹲下过去抓一只……像小孩子一样抱着探索一切的心态，在玩《塞尔达》时是最能体会到快乐的，如果像玩其他游戏一样只是跟着任务走反倒无趣。
&lt;/p&gt;

&lt;p&gt;
至于被网友戏称为绿皮科技的左纳乌科技，确实设计得很有意思也很有可玩性，但我没有在这上面花太多时间，也就是造了个 MK2 小摩托用来赶路，至于成为海拉鲁机械工程师什么的我还是算了。探索各种零件之间的组合当然也是一种乐趣，但和在旷野上自由奔跑的感觉还是不一样的，对我来说玩左纳乌科技和《Minecraft》里的红石电路没太大差别，当年我在《Minecraft》里用红石电路造刷怪塔、自动农场、自动造石机、村民自动繁殖中心……红石电路还是图灵完备的呢。阻碍我去玩绿皮科技的原因还有一个就是每一次制作设备都是要消耗矿石的，《王国之泪》又不像《Minecraft》一样把游戏机制就建立在挖矿和制造上，不想去卡 bug 复制矿石，也没有制作视频获取更多粉丝的需求（网络上有用左纳乌装置来演奏音乐的行为，整个过程很辛苦演奏效果也不好，我不太能理解），总而言之，这个机制对我来说深度探索的麻烦大于乐趣，所以我就只是当工具在使用了。
&lt;/p&gt;

&lt;p&gt;
比较后悔的是我过于匆忙地推进了主流程并且太快把所有地图点亮了，本来就是应该在这个过程中充分地享受探索乐趣的，我却东奔西走，翻山越岭到达鸟望台（游戏里用于探测一个小区域并为之建立地图的设施）点亮地图然后马不停蹄往下一个鸟望台赶过去，遗漏的很多东西只能后面因为一些别的任务出门的时候才会再顺路看一看，那时候体验就没有那么沉浸了。
&lt;/p&gt;

&lt;p&gt;
游戏之外我没有太多的娱乐活动了，看了一部《蜘蛛侠：纵横宇宙》的电影，看完了《黑镜第六季》，没太多可说的。
&lt;/p&gt;

&lt;p&gt;
其他朋友离职、退休后，都爱出去旅游，我好像对出去游玩没有特别大的念想，反倒是还在工作的时候会想得更多一些。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4c6898d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4c6898d&quot;&gt;美食&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org4c6898d&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
06.09 Tapas by Alba
&lt;/p&gt;

&lt;p&gt;
西班牙菜，第一次吃，主要是长下见识。
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
伊比利亚火腿香肠拼盘
&lt;/p&gt;


&lt;div id=&quot;org62c92c9&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023-06-09-food-1.jpeg&quot; alt=&quot;2023-06-09-food-1.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
马德里煎蘑菇 &amp;amp; 烟熏三文鱼配芝麻菜
&lt;/p&gt;


&lt;div id=&quot;org82f2a0a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023-06-09-food-2.jpeg&quot; alt=&quot;2023-06-09-food-2.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
香草牛肉塔塔 &amp;amp; 松露红虾蘑菇塔
&lt;/p&gt;


&lt;div id=&quot;org54d0a11&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023-06-09-food-3.jpeg&quot; alt=&quot;2023-06-09-food-3.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
西班牙蒜香油滚虾
&lt;/p&gt;


&lt;div id=&quot;org6dfe326&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023-06-09-food-4.jpeg&quot; alt=&quot;2023-06-09-food-4.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
西班牙传统海鲜饭
&lt;/p&gt;


&lt;div id=&quot;org15a68a4&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023-06-09-food-5.jpeg&quot; alt=&quot;2023-06-09-food-5.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
06.10 食醴湘
&lt;/p&gt;

&lt;p&gt;
醴陵小炒肉是带汤的，学习了，味道还行但是价格有点高（相对味道和量来说）。
&lt;/p&gt;


&lt;div id=&quot;org7f02820&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023-06-10-food.jpeg&quot; alt=&quot;2023-06-10-food.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
06.11 三倒拐市井火锅
&lt;/p&gt;

&lt;p&gt;
重庆火锅，不比壹圣元差呀。
&lt;/p&gt;


&lt;div id=&quot;org2116073&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023-06-11-food.jpeg&quot; alt=&quot;2023-06-11-food.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
06.17 重庆壹圣元火锅
&lt;/p&gt;

&lt;p&gt;
主要是见朋友，味道的话去太多次没什么好说的，不放图了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
06.22，端午节小饭桌
&lt;/p&gt;

&lt;p&gt;
由 CFO 和大渔记出品。
&lt;/p&gt;


&lt;div id=&quot;orga85fb09&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2023-06-22-food.jpeg&quot; alt=&quot;2023-06-22-food.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;06.29，老广酒楼，踩雷了，烧鹅、卤水还可以，其他的菜多少都有点问题，还贵，不放图了。&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb68220d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgb68220d&quot;&gt;阅读&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgb68220d&quot;&gt;
&lt;p&gt;
六月的前半个多月大部分时间都在玩游戏，到后半个月才开始去读一些书，但也没有特别专注地去读，把《卡拉马佐夫兄弟》《工作、消费主义和新穷人》《技术的本质》《蚱蜢：游戏、生命与乌托邦》《千脑智能》《如何阅读一本书》《阅读是一座随身携带的避难所》《脑与阅读》《思考：快与慢》这些书都翻了翻，没有一本看完的。
&lt;/p&gt;

&lt;p&gt;
《卡拉马佐夫兄弟》一直想读的，那么长的篇幅我估计也没办法短时间内看完，里面的人名确实让人比较困扰，冗长的人名就算了，同一个人名也能有不同的翻译，阿列克塞、阿辽沙、阿辽什卡是同一个人，德米特里、米特里、米嘉、米剑卡也是同一个人，不是太能理解……
&lt;/p&gt;

&lt;p&gt;
《工作、消费主义和心穷人》从工作伦理和消费主义的角度反思社会现状，读这本书主要也是因为对现代社会工作感到很困惑，未必能从这本书里得到什么答案，就是开拓一下思路吧。
&lt;/p&gt;

&lt;p&gt;
《技术的本质》尝试对技术给一个明确而严密的定义，探讨技术的起源、演变背后的机制以及技术对社会的影响，看起来挺费劲的，不过我觉得我的有些问题或许能从这本书里得到启发，不一定会读完这本书，但会有针对性地翻一翻感兴趣的章节。
&lt;/p&gt;

&lt;p&gt;
《蚱蜢：游戏、生命与乌托邦》是去年朋友推荐的书，它是一本宣称玩游戏是人类的终极理想的严肃哲学书籍，当然这里的玩游戏在书里是有严密的定义的。虽然这本书尝试以对话体这种比较轻松的形式来写，但是要理解这本书想表达的内容还是需要充分调动思维的。读这本书，有比较大的一部分因素是因为我喜欢游戏。
&lt;/p&gt;

&lt;p&gt;
《如何阅读一本书》我非常喜欢，要是能早点读这本书就好了，它对阅读做了一些分类，并针对「增进理解」的阅读提出了从理念到具体方法的一系列指导，我在之前写《至少还有书》的读后感的时候说「没有人管束我的另外一面是也没有人引导我」，我想，这本书就是我曾经缺失的引导。
&lt;/p&gt;

&lt;p&gt;
《阅读是一座随身携带的避难所》是毛姆关于书和作家的随笔，读起来很轻松的，我就有兴趣了随时翻一翻，这本书也不用太按顺序读，比如我就先把里面讲陀思妥耶夫斯基和《卡拉马佐夫兄弟》的那章读了。我在微信读书上有一个叫做「书的书」的分组专门放一些讲书的书，作为找其他想读的书的一个入口，比看豆瓣评论什么的会更有感觉一些。
&lt;/p&gt;

&lt;p&gt;
读《千脑智能》《脑与阅读》《思考：快与慢》这三本书是出于对人脑认知能力机制的好奇，事实上这个方面的书我收藏了一大堆的，想做主题阅读的，但发现自己并没有形成比较体系的主题阅读的方法和过程，先随便看看吧。《千脑智能》目前看得多点，里面提出的新皮质认知智能模型很有意思，如果可以验证的话对人工智能的发展会起到很大的帮助，但不知道是不是出于易读性而对细节含糊带过还是翻译的问题，新皮质认知智能模型的具体细节我不是太能理解，如果整本书读下来还看不明白，我可能会去翻翻作者的论文。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4afa8ac&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4afa8ac&quot;&gt;其他&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org4afa8ac&quot;&gt;
&lt;p&gt;
不像其他人，不工作后我并没有变得非常开心，大部分的时间心情是比较平静轻松的，但要说很开心可能谈不上。认真想想的话，上学时忙于学业、工作时忙于工作，我并没有完全自主地安排自己生活的经验，如果不想在既定的框架里生活该如何做，我其实是缺乏回答这样一个问题的理论和经验的，自由是有代价的，我觉得不是每个人都能承受得住。
&lt;/p&gt;

&lt;p&gt;
六月中旬开始，我频繁地被「得做点正事」的焦虑和「什么也不想做」的逆反心理之间的冲突所影响，情绪经常低沉，甚至一些要解决的生活琐事明明并不困难也不复杂，也觉得要打起十分的勇气才能去面对，那种「得做点正事」的惯性和对此的厌恶，我认为不是出去四处转转吃点好吃的就能解决的，这也是我没有急匆匆出去游玩的一个原因，我希望能真正以轻松平静的心态去面对美景和美食（当然，这可能也只是一个未必能达到的理想态），而不是靠美景和美食来「疗愈自己」，没有那么容易疗愈的，因为很多心理和行为的惯性是过去三十多年的生活里在目前这个社会的规范中逐步养成的，与其说伤病，不如说是畸形，这些就是我在《辞职了》那篇文章里说的「真正重要的问题」。我有过份地向内探寻的坏毛病，什么伤病、畸形说的可能有些矫情，简短些总结的话，就是在离职后的第一个月里有时出现了懒、拖延、迷茫、焦虑、空虚、无聊等一些常见的负面情绪和行为，问题并不大（或者说这些问题本来就一直存在），不过收集 badcase 对系统进行迭代优化已经是本能了，所以会对这些多注意一些。
&lt;/p&gt;

&lt;p&gt;
察觉到情绪不太好后，我迅速地建立了应对机制，其实也没什么特别的，从六月二十日开始，开始每天晨练、阅读、冥想、吃早饭、不那么晚（八九点）起床，规律的、有序的生活很快就让我状态大大改善。写这篇总结的时候已经是七月六日，目前为止这个机制运作良好，坏情绪已经较少出现，平静、满足常有。我并不那么追求快乐那种让人兴奋的感受，能够获得平静就已经很好了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>LLM Prompt Engineering 实践：记忆（1）</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2023/06/21/llm-prompt-engineering-practice-memory-1.html"/>
    <category term="NLP" scheme="http://www.zmonster.me/categories.html#NLP"/>
    <id>http://www.zmonster.me/2023/06/21/llm-prompt-engineering-practice-memory-1</id>
    <published>2023-06-21T00:00:00+00:00</published>
    <updated>2023-06-21T00:00:00+00:00</updated>
    <description>
    
      <p>梳理下使用最近 K 轮历史记忆这种方法的问题</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
本文是《LLM Prompt Engineering 实践》系列的第三篇文章，系列文章如下：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2023/05/07/llm-prompt-engineering-practice-prologue.html&quot;&gt;LLM Prompt Engineering 实践：序 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2023/05/13/llm-prompt-engineering-practice-prototype.html&quot;&gt;LLM Prompt Engineering 实践：原型 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2023/06/21/llm-prompt-engineering-practice-memory-1.html&quot;&gt;LLM Prompt Engineering 实践：记忆（1） · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
之前我提出了一些问题：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;ChatMessageHistory 是基于内存的历史消息记录方法，一旦退出历史对话消息将全部丢失&lt;/li&gt;
&lt;li&gt;当讨论的话题更早之前聊过时，选择最近历史消息的做法无法利用之前的讨论&lt;/li&gt;
&lt;li&gt;固定设置输出最大 token 数量的做法为了照顾长输出的情况，会导致短输出情况下无法利用更多的历史消息&lt;/li&gt;
&lt;li&gt;一个全局设置的温度参数会影响机器人处理不同任务的表现，比如说像翻译、分类、事实性问答这些任务并不需要随机性，而写作、创意生成则有一定的随机性会更好一些&lt;/li&gt;
&lt;li&gt;在当前这种模式下，将机器人属性设置放在最开始的做法无法保证设定的一致性和连续性，用户总是能通过有意构造的输入来突破这种设置&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
其中 1/2/3 涉及到记忆机制的问题，对这几个问题都可以独立地去思考和尝试解决，但在此之前，还是有必要再对这几个问题做更多的探讨。
&lt;/p&gt;

&lt;p&gt;
我在之前 xorius 的开发日志里第一次提出使用历史对话记录时是这么说的：这段代码不是对话的模式，没有考虑聊天历史，如果要做聊天的话，需要维护一个聊天历史。
&lt;/p&gt;

&lt;p&gt;
那么问题来了，为什么在响应当前用户输入的时候，要去考虑聊天历史呢？这种做法其实就是假设聊天历史对响应当前的用户输入有帮助，那么：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;这个假设会一直成立吗？&lt;/li&gt;
&lt;li&gt;什么情况下这个假设会成立？此时历史记忆和当前用户输入有哪些可能的相关关系？&lt;/li&gt;
&lt;li&gt;假设成立的情况下，使用最近 K 轮历史记忆的做法，K 会有一个模型计算力能承受的上限吗？&lt;/li&gt;
&lt;li&gt;假设成立的情况下，使用最近 K 轮历史记忆的做法，相关的内容在这 K 轮历史记忆中的占比会有多大？&lt;/li&gt;
&lt;li&gt;假设成立的情况下，使用最近 K 轮历史记忆的做法，其中的无关内容会带来负面影响吗？如果会的话可能带来的负面影响有哪些？&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
对第 1 个问题，既然是假设，那么它当然不会一直成立，否则它就是真理而不是假设了，而之前 xorius 的实现里是在这一假设下实现了回答时对历史记忆的利用 —— 即无论何时都会尝试把历史记忆用上，因而也会自然而然地带来一定的副作用: 在响应不需要历史记忆的用户输入时，可能因为强制使用历史记忆而造成错误的回答。
&lt;/p&gt;

&lt;p&gt;
对第 2 个问题，个人认为可能有以下几种情况：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;当前输入提及了历史对话中的某些内容，比如

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
使用代词提及历史对话中聊过的某个或某几个对象，这种情况称之为指代
&lt;/p&gt;

&lt;p&gt;
「它」指代「语言模型」
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org45ce761&quot;&gt;
You: 语言模型是什么

Xorius:
语言模型是一种计算机程序，用于预测自然语言文本中下一个单词或字符的概率分布。它是自然语言处理中的一个重要组成部分，可以用于许多任务，如语音识别、机器翻译、文本生成和自动摘要等。语言模型通常基于统计学方法或神经网络方法，通过学习大量的文本数据来建立模型，并使用该模型来预测下一个单词或字符的概率分布。在实际应用中，语言模型可以帮助计算机更好地理解和生成自然语言，从而提高自然语言处理的效果和质量。

------------------- 上方为历史对话 -------------------

You: 它有智能吗

Xorius:
语言模型本身并没有智能，它只是一个程序，能够根据已有的文本数据预测下一个单词或字符的概率分布。然而，通过不断地训练和优化，语言模型可以逐渐提高其预测的准确性和效率，从而更好地模拟人类的语言习惯。此外，语言模型也可以与其他人工智能技术结合使用，如机器学习、深度学习、自然语言处理等，从而实现更加智能化的应用。因此，虽然语言模型本身没有智能，但它可以为人工智能的发展提供重要的支持和基础。
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
提及历史对话中聊过的某个或某几个对象，但以省略的形式，这种情况称之为零指代
&lt;/p&gt;

&lt;p&gt;
「语言模型在语音识别中怎么用」省略了「语言模型」
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org4683ace&quot;&gt;
You: 语言模型是什么

Xorius:
语言模型是一种用于自然语言处理的技术，它可以对一段文本的语言结构进行建模，从而计算出该文本的概率。语可以用于很多应用，例如语音识别、机器翻译、自然语言生成等。在语音识别中，语言模型可以帮助识别出最有可能的语音转录结果；在机器翻译中，语言模型可以帮助翻译系统选择最合适的翻译结果；在自然语言生成中，语言模型可以帮助生成自然流畅的语言表达。常见的语言模型包括n-gram模型、神经网络语言模型等。

------------------- 上方为历史对话 -------------------

You: 在语音识别中怎么用

Xorius:
在语音识别中，语言模型主要用于解决识别歧义的问题。当语音识别系统对一段语音进行转录时，可能会遇到多个候选结果，这些结果在音频信号上看起来很相似，但在语言表达上却有很大差异。这时，语言模型可以帮助系统选择最有可能的结果。

具体来说，语言模型会对每个候选结果进行打分，计算出其在语言表达上的概率。然后，系统会选择得分最高的结果作为最终的转录结果。这样，语言模型可以帮助系统更准确地识别语音，提高识别准确率。

在语音识别中，常用的语言模型包括n-gram模型和神经网络语言模型。n-gram模型是一种基于统计的模型，它通过计算文本中相邻的n个词出现的概率来建模。神经网络语言模型则是一种基于神经网络的模型，它通训练神经网络来预测下一个词的概率。这些模型都可以用于语音识别中的语言模型建模。
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
使用代词提及历史对话中的比词语粒度更大的对象，比如说事件、观点、句子甚至更大段的话
&lt;/p&gt;

&lt;p&gt;
「最后一段」指代对历史对话回答中结尾部分的「他们成功地激活了这个装置……也激励了更多人类探索宇宙的冒险精神。」这段话
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org27ed26d&quot;&gt;
You: 写一个木卫二上的冒险故事

Xorius:
在木卫二的表面，有一个被称为“红海”的巨大火山口。这个火山口的深度超过了地球上最深的海洋，被认为是太阳系中最深的地方之一。有一天，一组勇敢的宇航员决定探索这个神秘的地方。

他们穿上了特制的宇航服，搭乘着一艘小型的探测器，开始了他们的冒险之旅。他们在探测器上看到了一些奇怪的能量信号，这些信号似乎来自深处的地下洞穴。

他们决定跟随这些信号，进入了一个巨大的洞穴系统。在洞穴里，他们发现了一些奇怪的生物，这些生物似乎是在这个深处的环境中生存了很长时间。

随着他们深入洞穴，他们发现了一些神秘的符号和图案，这些符号似乎是来自一个古老的文明。他们开始研究这些符号，试图理解这个文明的历史和目的。

在他们的探险中，他们遇到了一些危险，包括地震和洪水。但他们始终坚持不懈，终于到达了洞穴的深处。在那里，他们发现了一个神秘的装置，这个装置似乎是一个能量生成器，可以为整个木卫二提供能源。

他们成功地激活了这个装置，并将它带回了地球。这个发现改变了人类对木卫二的认识，也为人类提供了一种新的能源来源。这个冒险故事成为了人类历史上的一个重要事件，也激励了更多人类探索宇宙的冒险精神。

------------------- 上方为历史对话 -------------------

You: 把最后一段翻译成英文

Xorius: &quot;They successfully activated the device and brought it back to Earth. This discovery changed humanity's understanding of Europa and provided a new source of energy for humanity. This adventure story became an important event in human history and inspired more people to explore the adventure spirit of the universe.&quot;
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
提及历史对话中的比词语粒度更大的对象，比如说事件、观点、句子甚至更大段的话，但以省略的形式
&lt;/p&gt;

&lt;p&gt;
「压缩一下」省略了宾语，指的是历史对话里的整段回答「在遥远的未来……寻找未知的世界和可能性」
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;orgaa3a95e&quot;&gt;
You: 写一个火星流浪的故事

Xorius:
在遥远的未来，人类已经开始探索太空，其中包括火星。一名名叫艾米的宇航员在一次任务中不幸与同事失联，最终被遗弃在了火星上。

艾米意识到自己已经被遗弃在了这个荒凉的星球上，没有任何人类的生命迹象。她开始寻找食物和水源，但很快发现火星上的环境非常恶劣，几乎没有任何生命存在的可能。

在接下来的几个月里，艾米不断地寻找食物和水源，同时也努力修复她的通讯设备，希望能够联系到地球上的人类。但是，她的努力都没有任何回应。

在孤独和绝望的日子里，艾米开始思考自己的人生和存在的意义。她开始重新审视自己的价值观和信仰，并逐渐接受了自己可能会永远孤独地生活在这个星球上的现实。

然而，就在艾米准备放弃的时候，她收到了一条来自地球的信号。原来，地球上的科学家们一直在寻找她，并且已经派出了一支救援队伍来到火星上救援她。

在救援队伍的帮助下，艾米最终成功返回地球，并成为了一名备受尊敬的宇航员。她的经历也激励了更多的人类探索太空，寻找未知的世界和可能性。

------------------- 上方为历史对话 -------------------

You: 压缩一下，用更短的文字

Xorius:
一名宇航员在火星上被遗弃，孤独地寻找食物和水源，修复通讯设备，思考人生意义。最终收到地球救援信号，成功返回地球，成为备受尊敬的宇航员，激励更多人类探索太空。
&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;历史记忆中的内容可以作为回答当前输入的知识，比如说

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;历史记忆中提供了当前输入的某些知识的定义或详细说明，回答当前输入时正确使用历史记忆中提供的知识可以避免 AI 胡编乱造&lt;/li&gt;
&lt;li&gt;历史记忆中描述了用户（或 AI）的喜好、三观或其他个性化（或者说人格化？）的属性描述，并且当前输入是以这些个性化信息为背景的，那么正确地使用相关的历史记忆可以使得回答时表现出来的个性与历史记忆中的保持一致性、连续性&lt;/li&gt;
&lt;li&gt;……&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;上述两种情况的混合&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
在多轮对话的研究里，对历史记忆和当前输入的相关关系应该还会有更全面、更细致的分类，暂时不想去翻相关的研究资料了，等需要做更精细的处理的时候可能会去看看，现在主要是做一个大致的梳理，知道模型在利用聊天历史时存在不同情况即可。
&lt;/p&gt;

&lt;p&gt;
在第 2 个问题的回答的基础上，可以对第 3 个问题做一定的回答
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;如果当前输入和历史记忆的关系是第 1 种情况（当前输入提及了历史对话中的某些内容），可以认为这种情况下要用到的历史记忆都会是比较近的，也就是 K 不会太大，我个人认为是可以让模型直接处理的&lt;/li&gt;
&lt;li&gt;如果当前输入和历史记忆的关系是第 2 种情况（历史记忆中的内容可以作为回答当前输入的知识），那么相关的历史记忆未必是在最近，它完全可以是长期记忆里的内容，比如说我让它推荐书籍的时候希望它可以记起来一年前我说过我喜欢看科幻小说进而推荐一些最新的科幻小说，这种情况下这个 K 可能会非常非常大，个人认为这种情况下使用最近 K 轮历史记忆的做法将会超出模型的计算能力上限&lt;/li&gt;
&lt;li&gt;如果当前输入和历史记忆的关系是第 3 种情况（第 1 种情况和第 2 种情况的混合），那么同第 2 种情况&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
对于第 4 个问题，如果精力允许，或许可以去分析一下一些公开的多轮对话数据集来给出一个相对量化的结果，不过目前我并不想去做这个事情，提出这个问题，其实只是想说明一点 —— 即使在聊天历史对响应当前用户输入有帮助这个假设成立，并且有帮助的信息就在最近 K 轮历史记忆中的时候，也可能不是所有 K 轮历史记忆都是有帮助的。
&lt;/p&gt;

&lt;p&gt;
第 5 个问题则是在第 4 个问题上更进一步思考，如果最近 K 轮历史记忆中有无关内容，那么它们一定是会带来负面影响的，它们可能会摊薄当前输入中 token 和历史记忆中有用内容的 attention 权重，进而导致回可能偏离预期。这种负面影响的大小一定程度上取决于模型本身的能力，很强的模型（比如 GPT-4）可能不会表现得很明显。
&lt;/p&gt;

&lt;p&gt;
综上，使用最近 K 轮历史记忆的做法其实是会有一些问题的，但是这种方法是最容易实现的、最直观可理解的，并且在模型较强的时候效果也不错，加上现在也没有公认的更好的方案，所以大家普遍都这么做。
&lt;/p&gt;

&lt;p&gt;
方法有缺陷是正常的，事实上也不存在哪个方法是完美的、没有任何问题的，但这个方法最大的问题不在于其假设，而在于它没有设计对应的错误应对或者说优化迭代的措施，一旦这个机制工作不正常，就只能期待模型自身的改进或者用户自己能够掌握所谓的 Prompt 编写技巧来再次尝试了。如果能对这些问题心知肚明并抱有适当的预期，那么使用这个方法倒也没什么问题，但如果使用了这个方法出了问题后就只会调侃 AI 弱智，那就没什么意思了。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>我辞职了</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2023/05/23/quit-my-job.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2023/05/23/quit-my-job</id>
    <published>2023-05-23T00:00:00+00:00</published>
    <updated>2023-05-23T00:00:00+00:00</updated>
    <description>
    
      <p>接下来的一小段时间，大概会尝试去过一过「没有计划」的生活，尽力、尽情地做一些自己想做、能做的事情，等待并拥抱变化的自然发生，不再自欺欺人地假装做了计划后未来的不确定性就会收束。</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
4 月 21 日，在地铁上用微信发了消息公司领导，告诉他们我不想干了，感觉心情马上就轻快了起来。到公司后领导找我面谈了几句，不过我只是更坚定地表明了自己要跑路的态度，所以领导也没说什么挽留的话。
&lt;/p&gt;

&lt;p&gt;
4 月 23 日，正式给公司管理层发了辞职信，内容是让 ChatGPT 帮忙写的，懒得自己动这个脑筋，CEO 说节后回北京后想找我聊聊，虽然不知道他想给我画什么饼，不过感谢他额外给我一个星期的摸鱼时间，节前一周我就有一搭没一搭地写交接文档，做做我还感兴趣的一些零碎工作，过得是很惬意的，没想到由于 CEO 来京时间一再往后推，我又继续过了三周这样的生活。
&lt;/p&gt;

&lt;p&gt;
5 月 23 日，CEO 终于来了公司，聊了一个小时，主要是 CEO 在畅谈商业计划和愿景，我看得出来他确实对未来的可能性感到很激动也对自己的判断感到很自信，不过这都和我没关系了。聊完后和 CFO 也聊了下，定了离职日期，随后就提前拿到了离职证明。如果没有什么别的事情，后面我应该就不会再去公司了，虽然还没到离职日期，但离职这个事情就算告一段落了。
&lt;/p&gt;

&lt;p&gt;
在这个点提离职，一个出发点是公司的业务方向要转向一个我完全不感兴趣的领域了，虽然老板宏伟的商业愿景听起来似乎很合理，但我留下无疑只能去做脏活累活，脏活累活我已经做够了。做不喜欢甚至讨厌的事情的经历我已经有过几次，那种痛苦短时间内我不想再经历一次了，就赶在新业务开展前提了离职，也能走得清清爽爽；第二个出发点就是 ChatGPT 和 Stable Diffusion 带来的新一波 AI 浪潮里有大量事情可以做，辞职后不用担心无聊，而且我想做的一些探索性的事情是得不到公司支持的，索性就离开自己玩玩吧。
&lt;/p&gt;

&lt;p&gt;
想辞职或者想不工作的念头很早就有，毕竟我不是那种能享受工作的人。以前还能通过工作提升技艺、开阔眼界，这几年连这些最基本的乐趣也没有了，作为一个高考志愿填计算机只是因为高中经常去网吧玩耍觉得计算机好玩的人，这是不能忍受的。另外一方面，三年下来强烈地察觉到自己感受生活的能力以及清晰表达自己感受的能力的欠缺，这些并不是文艺青年才配拥有的奢侈品，而是一个健康的普通人对抗虚无和绝望的必需品，我希望能在这些问题上有所改进，然而以目前的状况而言，工作只会加重我这些问题。由于并不清楚如何解决真正重要的问题或者说害怕去面对那些问题，最近几年更多是在把工作当作逃避问题、逃避不确定性的一个借口，不管是什么问题，都可以辩解「我知道这些问题很重要但是工作这么忙我也没有办法啊」然后心安理得地继续拖延 —— 这并不可耻，要不要去面对问题只是个人选择而已，我决定去试一试。
&lt;/p&gt;

&lt;p&gt;
循规蹈矩活了三十多年，反思并尝试探索新的道路未必就能有什么好下场，不过我没有什么自我要寻找，也没有想要彻底地和过去的道路决裂，如无意外，我应该还是会靠自己的专业能力去生活。接下来的一小段时间，大概会尝试去过一过「没有计划」的生活，尽力、尽情地做一些自己想做、能做的事情，等待并拥抱变化的自然发生，不再自欺欺人地假装做了计划后未来的不确定性就会收束。
&lt;/p&gt;

&lt;p&gt;
虽然对于辞职后的生活，我暂时是没有什么明确计划的，但会有一些想做的事情，这些事情是会让我觉得开心的、有价值的事情，我应该都会去做，但并不在乎能不能达到完美的结果，也不在意何时达到什么程度，也许会做到一半就被别的东西吸引或者干脆厌倦就彻底放弃，也许会花费超出最初预期的精力，一切皆有可能，还是那句话，我不想做计划。
&lt;/p&gt;

&lt;p&gt;
首先是想要生活地健康、松弛一些，保证足够的睡眠，有一定的运动量，有充足的阅读、娱乐时间，通过散步、外出游玩等方式充分地与外界保持联系，或许也可以不定期拜访一些朋友。从我的经验来看，习惯可以在两周左右内养成，之后就可以不需要太多意志力地自动化了，所以生活作息我是有信心比较快地纠正过来的，问题比较大的可能是松弛感的建立，我目前并没有什么好的想法，只是觉得多玩、多感受、多尝试一些不带具体目标的事情可能会有帮助。
&lt;/p&gt;

&lt;p&gt;
然后是想要在编程和 AI 方面做一些探索和尝试，短期应该会先从语言模型入手做一些事情，再之后就没有什么具体想法了，可能会随缘玩一玩其他东西，比如学个新语言、开发 RSS 周边工具、写 Emacs 插件……不过语言模型应该就够玩很久了，准备先写一个项目来讨论目前语言模型应用要面对的问题及处理方法。毕业十年了，我仍然喜欢我的专业，仍然被铁路模型技术俱乐部、家酿计算机俱乐部等行业先驱们的精神和故事所激励，我最有创造力的一些工作（虽然也算不上多有创造力）都是在无人管束时以玩耍的心态所做出来的，我想继续去玩，在玩耍中创造，在创造中玩耍，而不是像一台机器一样被输入一些无聊的商业目标来去产出一堆垃圾。
&lt;/p&gt;

&lt;p&gt;
至于打算休息到什么时候再回去工作，我只能说没有计划，没有计划什么时候要回去工作，也没有计划一直不工作，就随缘吧。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>LLM Prompt Engineering 实践：原型</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2023/05/13/llm-prompt-engineering-practice-prototype.html"/>
    <category term="NLP" scheme="http://www.zmonster.me/categories.html#NLP"/>
    <id>http://www.zmonster.me/2023/05/13/llm-prompt-engineering-practice-prototype</id>
    <published>2023-05-13T00:00:00+00:00</published>
    <updated>2023-05-13T00:00:00+00:00</updated>
    <description>
    
      <p>在 ChatGPT 的帮助下，给项目起好了名字，并实现了最简单的一个原型。</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
本文是《LLM Prompt Engineering 实践》系列的第二篇文章，系列文章如下：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2023/05/07/llm-prompt-engineering-practice-prologue.html&quot;&gt;LLM Prompt Engineering 实践：序 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2023/05/13/llm-prompt-engineering-practice-prototype.html&quot;&gt;LLM Prompt Engineering 实践：原型 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2023/06/21/llm-prompt-engineering-practice-memory-1.html&quot;&gt;LLM Prompt Engineering 实践：记忆（1） · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
在 ChatGPT 的帮助下，给项目起了 xorius 这么一个名字，这个单词实际上并不存在，所以含义完全是由我来定义的，不过作为一个随时可能会鸽掉的项目，就先不说我给它赋予的意义了，以后做大做强再来说会比较合适一点。
&lt;/p&gt;

&lt;p&gt;
起好名字后，我准备先实现一个最最简单的原型出来，并在过程中对一些问题进行讨论。后文所有内容都是我的开发日志的整理汇总，之后的文章基本上也会采用这个模式。
&lt;/p&gt;

&lt;p&gt;
为了实现原型，有两个选择，一是直接去调用 OpenAI 的官方接口或 SDK，二是选择 &lt;a href=&quot;https://github.com/hwchase17/langchain&quot;&gt;langchain&lt;/a&gt; 之类的第三方封装，出于方便考虑，我选择了 langchain。
&lt;/p&gt;

&lt;p&gt;
首先，无论是直接调用官方接口、SDK，还是使用 langchain，国内都是需要通过代理才能访问的：
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;import&lt;/span&gt; openai
openai.&lt;span style=&quot;color: #ffcc66;&quot;&gt;proxy&lt;/span&gt; = &lt;span style=&quot;color: #66cccc;&quot;&gt;'http://localhost:8080'&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
设置好代理后，用 langchain 就可以简单地调用 OpenAI 的接口来获得回答，比如说这样：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;from&lt;/span&gt; langchain.chat_models &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;import&lt;/span&gt; ChatOpenAI
&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;from&lt;/span&gt; langchain.schema &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;import&lt;/span&gt; HumanMessage

&lt;span style=&quot;color: #ffcc66;&quot;&gt;user_message&lt;/span&gt; = HumanMessage(content=&lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#23558;&amp;#36825;&amp;#21477;&amp;#35805;&amp;#32763;&amp;#35793;&amp;#25104;&amp;#20013;&amp;#25991;: &amp;#8220;to be or not to be&amp;#8221;'&lt;/span&gt;)

&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#23433;&amp;#20840;&amp;#32771;&amp;#34385;&amp;#36825;&amp;#37324;&amp;#25226;&amp;#30495;&amp;#23454; API KEY &amp;#38544;&amp;#34255;&amp;#20102;&amp;#65292;&amp;#21518;&amp;#25991;&amp;#19981;&amp;#20877;&amp;#24378;&amp;#35843;&lt;/span&gt;
llm = ChatOpenAI(temperature=0, openai_api_key=&lt;span style=&quot;color: #66cccc;&quot;&gt;'sk-xxxxxxxxxxxxxxxx'&lt;/span&gt;)
answer = llm([user_message])
&lt;span style=&quot;color: #cc99cc;&quot;&gt;print&lt;/span&gt;(answer.content)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上面的代码没有指定要使用的模型，默认会使用 gpt-3.5-turbo，运行后得到了这样的结果
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org5549ca5&quot;&gt;
生存还是毁灭
&lt;/pre&gt;

&lt;p&gt;
当然，这段代码不是对话的模式，没有考虑聊天历史，如果要做聊天的话，需要维护一个聊天历史
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;from&lt;/span&gt; langchain.memory &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;import&lt;/span&gt; ChatMessageHistory

&lt;span style=&quot;color: #ffcc66;&quot;&gt;memory&lt;/span&gt; = ChatMessageHistory()
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
之后每次的用户输入和得到的回答都可以按顺序添加到这个 memory 里面，比如说前面的 user_message 和 answer，都可以加到里面去
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;memory.add_user_message(user_message.content)
memory.add_ai_message(answer.content)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
通过 memory.messages 可以得到历史记录
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;print&lt;/span&gt;(memory.messages)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org85f54e8&quot;&gt;
[HumanMessage(content='将这句话翻译成中文: “to be or not to be”', additional_kwargs={}, example=False),
 AIMessage(content='&quot;生存还是毁灭&quot;', additional_kwargs={}, example=False)]
&lt;/pre&gt;

&lt;p&gt;
然后在下一轮对话时使用它
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;user_message&lt;/span&gt; = HumanMessage(content=&lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#20877;&amp;#32763;&amp;#35793;&amp;#25104;&amp;#26085;&amp;#35821;'&lt;/span&gt;)
answer = llm(memory.messages + [user_message])
&lt;span style=&quot;color: #cc99cc;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;'Answer:'&lt;/span&gt;, answer.content)

memory.add_user_message(user_message.content)
memory.add_ai_message(answer.content)
&lt;span style=&quot;color: #cc99cc;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;'History'&lt;/span&gt;)
&lt;span style=&quot;color: #cc99cc;&quot;&gt;print&lt;/span&gt;(memory.messages)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org3563c58&quot;&gt;
Answer: &quot;生きるか死ぬか&quot;
History:
[HumanMessage(content='将这句话翻译成中文: “to be or not to be”', additional_kwargs={}, example=False),
 AIMessage(content='&quot;生存还是毁灭&quot;', additional_kwargs={}, example=False),
 HumanMessage(content='再翻译成日语', additional_kwargs={}, example=False),
 AIMessage(content='&quot;生きるか死ぬか&quot;', additional_kwargs={}, example=False)]
&lt;/pre&gt;

&lt;p&gt;
综合上面的代码，只要写一个循环，就能做持续的对话了
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;from&lt;/span&gt; langchain.chat_models &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;import&lt;/span&gt; ChatOpenAI
&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;from&lt;/span&gt; langchain.memory &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;import&lt;/span&gt; ChatMessageHistory

&lt;span style=&quot;color: #ffcc66;&quot;&gt;memory&lt;/span&gt; = ChatMessageHistory()
&lt;span style=&quot;color: #ffcc66;&quot;&gt;llm&lt;/span&gt; = ChatOpenAI(temperature=0, openai_api_key=&lt;span style=&quot;color: #66cccc;&quot;&gt;'sk-xxxxxxxxxxxxxxxx'&lt;/span&gt;)
&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;while&lt;/span&gt; &lt;span style=&quot;color: #6699cc; font-style: italic;&quot;&gt;True&lt;/span&gt;:
    user_message = &lt;span style=&quot;color: #cc99cc;&quot;&gt;input&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;'You: '&lt;/span&gt;).strip()
    &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;not&lt;/span&gt; user_message:
        &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;continue&lt;/span&gt;

    &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;if&lt;/span&gt; user_message.lower() &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;in&lt;/span&gt; (&lt;span style=&quot;color: #66cccc;&quot;&gt;'quit'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'exit'&lt;/span&gt;):
        &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;break&lt;/span&gt;

    memory.add_user_message(user_message)
    answer = llm(memory.messages)
    &lt;span style=&quot;color: #cc99cc;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;'BOT:'&lt;/span&gt;, answer.content)
    memory.add_ai_message(answer.content)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
不过上面这段代码是有问题的，因为实质上我是每次都把历史消息和当前输入拼接起来输入给 OpenAI 的接口，而 OpenAI 的接口对处理的文本总长度是有限制的，gpt-3.5-turbo 最大长度是 4096 个 token，gpt-4 最大支持 32768 个 token（这个 token 是语言模型里对文本切分后的最小单元，先不用细究），像上面这样一直把 user_message 和 answer 往 memory 里面加，那么只要对话轮次够多一定会超过这个限制的，超过了就会报错，所以必须要限制一下。需要注意的是，这个最大文本长度，是输入和输出加在一起算的，比如说如果用 gpt-3.5-turbo 然后输入就已经 4000 token 了，那么只能输出最长 96 个 token 的结果。
&lt;/p&gt;

&lt;p&gt;
综上，为了保证不超出接口长度限制，需要只取 memory.messages 中的一部分，假设取的 memory.messages 中的这部分的总 token 数 为 L1，我们还要保证输出结果的总 token 数能达到 L2，那么必须保证 L1 + L2 &amp;lt; 4096，L2 可以在初始化 ChatOpenAI 的时候通过参数 max_tokens 来设置，默认没设置就是无限，那为了更好地计算 L1，需要显式设置一下它，比如说设置为 1024：
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;max_tokens&lt;/span&gt; = 1024
&lt;span style=&quot;color: #ffcc66;&quot;&gt;llm&lt;/span&gt; = ChatOpenAI(
    temperature=0,
    openai_api_key=&lt;span style=&quot;color: #66cccc;&quot;&gt;'sk-xxxxxxxxxxxxxxxx'&lt;/span&gt;,
    max_tokens=max_tokens
)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
在 L2=1024 的情况下，可以得到 L1 &amp;lt; 4096 - 1024 = 3072。接下来的问题就是按照这个最大 token 数来对 memory.messages 进行选择了，要做这个的话，首先要能计算出给定文本的 token 数量，语言模型里的 token 不完全等于字词，OpenAI 提供了一个&lt;a href=&quot;https://platform.openai.com/tokenizer&quot;&gt;在线工具&lt;/a&gt;展示把文本变成 token 的效果：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
英文基本上是一个词一个 token，有时会把一个词拆成几个 token，比如下面这个例子里 Tannhäuser 这个词就被拆成了 T/ann/h/ä/user 五个 token，但不管怎么说按字数算，英文最后的 token 数是小于字数的，下面这个例子的文本总字数是 230，token 数才 57
&lt;/p&gt;


&lt;div id=&quot;org6a83d09&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gpt3_tokens_example_english.png&quot; alt=&quot;gpt3_tokens_example_english.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
中文的话一个字就可能拆成多个 token，这些 token 大都是不可理解的，所以总体来说 token 数会大于字数，下面这个例子里的文本字数是 94，token 数是 191
&lt;/p&gt;


&lt;div id=&quot;org019e696&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gpt3_tokens_example_chinese.png&quot; alt=&quot;gpt3_tokens_example_chinese.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
注意，上面中文的例子是 GPT3 的编码器的效果，换成 gpt-3.5-turbo 的编码器后，中文的 token 数下降到了 124。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
OpenAI 提供了 &lt;a href=&quot;https://github.com/openai/tiktoken&quot;&gt;tiktoken&lt;/a&gt; 这个 python 库来做文本到 token 的编码转换
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;from&lt;/span&gt; tiktoken.model &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;import&lt;/span&gt; encoding_for_model

&lt;span style=&quot;color: #ffcc66;&quot;&gt;encoder&lt;/span&gt; = encoding_for_model(&lt;span style=&quot;color: #66cccc;&quot;&gt;'gpt-3.5-turbo'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
由于 gpt-3.5-turbo 模型使用的 Chat Completion 接口的输入不是普通的文本格式，计算输入的 token 数不能简单把用户输入和接口响应结果文本的 token 数加起来，OpenAI 自己给出了&lt;a href=&quot;https://platform.openai.com/docs/guides/chat/managing-tokens&quot;&gt;计算方法&lt;/a&gt;:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;import&lt;/span&gt; tiktoken

&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157;&quot;&gt;num_tokens_from_messages&lt;/span&gt;(messages, model=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;gpt-3.5-turbo-0301&quot;&lt;/span&gt;):
    &lt;span style=&quot;color: #cc99cc;&quot;&gt;&quot;&quot;&quot;Returns the number of tokens used by a list of messages.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;try&lt;/span&gt;:
        encoding = tiktoken.encoding_for_model(model)
    &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;except&lt;/span&gt; &lt;span style=&quot;color: #6699cc;&quot;&gt;KeyError&lt;/span&gt;:
        encoding = tiktoken.get_encoding(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;cl100k_base&quot;&lt;/span&gt;)

    &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;if&lt;/span&gt; model == &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;gpt-3.5-turbo-0301&quot;&lt;/span&gt;:  &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;note: future models may deviate from this&lt;/span&gt;
        num_tokens = 0
        &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;for&lt;/span&gt; message &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;in&lt;/span&gt; messages:
            num_tokens += 4  &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;every message follows &amp;lt;im_start&amp;gt;{role/name}\n{content}&amp;lt;im_end&amp;gt;\n&lt;/span&gt;
            &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;for&lt;/span&gt; key, value &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;in&lt;/span&gt; message.items():
                num_tokens += &lt;span style=&quot;color: #cc99cc;&quot;&gt;len&lt;/span&gt;(encoding.encode(value))
                &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;if&lt;/span&gt; key == &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;name&quot;&lt;/span&gt;:  &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;if there's a name, the role is omitted&lt;/span&gt;
                    num_tokens += -1  &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;role is always required and always 1 token&lt;/span&gt;

        &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;return&lt;/span&gt; num_tokens
    &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;else&lt;/span&gt;:
        &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;raise&lt;/span&gt; &lt;span style=&quot;color: #6699cc;&quot;&gt;NotImplementedError&lt;/span&gt;(
            f&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;num_tokens_from_messages() is not presently implemented for model &lt;/span&gt;{model}&lt;span style=&quot;color: #66cccc;&quot;&gt;.\n&quot;&lt;/span&gt;
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;See https://github.com/openai/openai-python/blob/main/chatml.md &quot;&lt;/span&gt;
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;for information on how messages are converted to tokens.&quot;&lt;/span&gt;
        )
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
注：为了方便计算单条消息的长度，我对 num_tokens_from_messages 做了一定的修改，删掉了 num_tokens += 2 这一行。
&lt;/p&gt;

&lt;p&gt;
注2：经测试，OpenAI 提供的这个函数，计算出来的 token 数比实际的少 1 个。
&lt;/p&gt;

&lt;p&gt;
基于这个函数可以来实现聊天历史的选择了，这里只简单实现一个取最近聊天历史的
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;from&lt;/span&gt; langchain.schema &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;import&lt;/span&gt; AIMessage, HumanMessage

&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157;&quot;&gt;select_messages&lt;/span&gt;(messages, max_total_tokens=4096, max_output_tokens=1024):
    tokens_num = 0
    selected = []
    &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;for&lt;/span&gt; message &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;in&lt;/span&gt; messages[::-1]:
        role = &lt;span style=&quot;color: #66cccc;&quot;&gt;'system'&lt;/span&gt;
        &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #cc99cc;&quot;&gt;isinstance&lt;/span&gt;(message, AIMessage):
            role = &lt;span style=&quot;color: #66cccc;&quot;&gt;'assistant'&lt;/span&gt;
        &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;elif&lt;/span&gt; &lt;span style=&quot;color: #cc99cc;&quot;&gt;isinstance&lt;/span&gt;(message, HumanMessage):
            role = &lt;span style=&quot;color: #66cccc;&quot;&gt;'user'&lt;/span&gt;

        cur_token_num = num_tokens_from_messages([{&lt;span style=&quot;color: #66cccc;&quot;&gt;'role'&lt;/span&gt;: role, &lt;span style=&quot;color: #66cccc;&quot;&gt;'content'&lt;/span&gt;: message.content}])
        &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;if&lt;/span&gt; tokens_num + cur_token_num + 2 + max_output_tokens &amp;gt; max_total_tokens:
            &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;break&lt;/span&gt;

        selected.append(message)
        tokens_num += cur_token_num

    selected = selected[::-1]
    &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #cc99cc;&quot;&gt;isinstance&lt;/span&gt;(selected[0], AIMessage): &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#30830;&amp;#20445;&amp;#31532;&amp;#19968;&amp;#26465;&amp;#26159;&amp;#29992;&amp;#25143;&amp;#28040;&amp;#24687;&lt;/span&gt;
        selected = selected[1:]

    &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;not&lt;/span&gt; selected:            &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#20551;&amp;#35774; messages &amp;#37324;&amp;#26368;&amp;#21518;&amp;#19968;&amp;#26465;&amp;#26159;&amp;#24403;&amp;#21069;&amp;#29992;&amp;#25143;&amp;#36755;&amp;#20837;&lt;/span&gt;
        selected = message[-1]

    &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;return&lt;/span&gt; selected
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
那么前面的持续对话代码可以改造成这个样子了
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;from&lt;/span&gt; langchain.chat_models &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;import&lt;/span&gt; ChatOpenAI
&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;from&lt;/span&gt; langchain.memory &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;import&lt;/span&gt; ChatMessageHistory

&lt;span style=&quot;color: #ffcc66;&quot;&gt;memory&lt;/span&gt; = ChatMessageHistory()

&lt;span style=&quot;color: #ffcc66;&quot;&gt;max_output_tokens&lt;/span&gt;, &lt;span style=&quot;color: #ffcc66;&quot;&gt;max_total_tokens&lt;/span&gt; = 1024, 4096
&lt;span style=&quot;color: #ffcc66;&quot;&gt;llm&lt;/span&gt; = ChatOpenAI(
    temperature=0,
    openai_api_key=&lt;span style=&quot;color: #66cccc;&quot;&gt;'sk-xxxxxxxxxxxxxxxx'&lt;/span&gt;,
    max_tokens=max_output_tokens,
)
&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;while&lt;/span&gt; &lt;span style=&quot;color: #6699cc; font-style: italic;&quot;&gt;True&lt;/span&gt;:
    user_message = &lt;span style=&quot;color: #cc99cc;&quot;&gt;input&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;'You: '&lt;/span&gt;).strip()
    &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;not&lt;/span&gt; user_message:
        &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;continue&lt;/span&gt;

    &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;if&lt;/span&gt; user_message.lower() &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;in&lt;/span&gt; (&lt;span style=&quot;color: #66cccc;&quot;&gt;'quit'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'exit'&lt;/span&gt;):
        &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;break&lt;/span&gt;

    memory.add_user_message(user_message)
    messages = select_messages(
        memory.messages,
        max_total_tokens=max_total_tokens,
        max_output_tokens=max_output_tokens
    )
    &lt;span style=&quot;color: #cc99cc;&quot;&gt;print&lt;/span&gt;(f&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;selected messages: &lt;/span&gt;{messages}&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt;)
    answer = llm(messages)
    &lt;span style=&quot;color: #cc99cc;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;'BOT:'&lt;/span&gt;, answer.content)
    memory.add_ai_message(answer.content)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
把 max_output_tokens 设置得更大一些会选择更少的历史，比如说
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
max_output_tokens=200, max_total_tokens=4096 时，输入的最大 token 数可以到 3896，所以可以选到尽可能多的历史消息
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;org61448f4&quot;&gt;
You: 将这句话翻译成中文: “to be or not to be”
selected messages: [HumanMessage(content='将这句话翻译成中文: “to be or not to be”', additional_kwargs={}, example=False)]
BOT: &quot;生存还是毁灭&quot;
You: 再翻译成日语
selected messages: [HumanMessage(content='将这句话翻译成中文: “to be or not to be”', additional_kwargs={}, example=False), AIMessage(content='&quot;生存还是毁灭&quot;', additional_kwargs={}, example=False), HumanMessage(content='再翻译成日语', additional_kwargs={}, example=False)]
BOT: &quot;生きるか死ぬか&quot;
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
max_output_tokens=4050, max_total_tokens=4096，输入的最大 token 数只有 46，第二轮的时候没法使用前一轮的历史消息
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;org7ad4342&quot;&gt;
You: 将这句话翻译成中文: “to be or not to be”
selected messages: [HumanMessage(content='将这句话翻译成中文: “to be or not to be”', additional_kwargs={}, example=False)]
BOT: &quot;生存还是毁灭&quot;
You: 再翻译成日语
selected messages: [HumanMessage(content='再翻译成日语', additional_kwargs={}, example=False)]
BOT: もう一度日本語に翻訳してください。
&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
实现了聊天历史的选择后，一个最基本的原型其实就好了，进一步地，还可以为这个对话机器人做一些属性设定，比如说叫什么名字、什么性格之类的，具体的做法就是在每次调用语言模型时，除了聊天历史和当前输入，再额外输入一个描述这个机器人属性的 prompt，在 OpenAI 的接口里要求这条 prompt 的 role 设置为 system，用 langchain 的话直接用 SystemMessage 就好，我这里简单把这个 SystemMessage 放在输入的最前面，把代码改造成了这个样子：
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;from&lt;/span&gt; langchain.chat_models &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;import&lt;/span&gt; ChatOpenAI
&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;from&lt;/span&gt; langchain.memory &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;import&lt;/span&gt; ChatMessageHistory
&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;from&lt;/span&gt; langchain.schema &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;import&lt;/span&gt; SystemMessage

&lt;span style=&quot;color: #ffcc66;&quot;&gt;memory&lt;/span&gt; = ChatMessageHistory()
&lt;span style=&quot;color: #ffcc66;&quot;&gt;system_message&lt;/span&gt; = SystemMessage(
    content=(
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;You are an AI assistant. Your name is xorius. &quot;&lt;/span&gt;
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;You can discuss any ideas and topics with your users, &quot;&lt;/span&gt;
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;and you will help your users solve their problems as much as you can.&quot;&lt;/span&gt;
    ),
)
max_total_tokens = 4096 - num_tokens_from_messages([{&lt;span style=&quot;color: #66cccc;&quot;&gt;'role'&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;'system'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'content'&lt;/span&gt;: system_message.content}])
max_output_tokens = 1024
llm = ChatOpenAI(
    temperature=0,
    openai_api_key=&lt;span style=&quot;color: #66cccc;&quot;&gt;'sk-xxxxxxxxxxxxxxxx'&lt;/span&gt;,
    max_tokens=max_output_tokens,
)
&lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;while&lt;/span&gt; &lt;span style=&quot;color: #6699cc; font-style: italic;&quot;&gt;True&lt;/span&gt;:
    user_message = &lt;span style=&quot;color: #cc99cc;&quot;&gt;input&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;'You: '&lt;/span&gt;).strip()
    &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;not&lt;/span&gt; user_message:
        &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;continue&lt;/span&gt;

    &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;if&lt;/span&gt; user_message.lower() &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;in&lt;/span&gt; (&lt;span style=&quot;color: #66cccc;&quot;&gt;'quit'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'exit'&lt;/span&gt;):
        &lt;span style=&quot;color: #99cc99; font-style: italic;&quot;&gt;break&lt;/span&gt;

    memory.add_user_message(user_message)
    messages = select_messages(
        memory.messages,
        max_total_tokens=max_total_tokens,
        max_output_tokens=max_output_tokens
    )
    &lt;span style=&quot;color: #cc99cc;&quot;&gt;print&lt;/span&gt;(f&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;selected messages: &lt;/span&gt;{messages}&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt;)
    answer = llm([system_message] + messages)
    &lt;span style=&quot;color: #cc99cc;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;'BOT:'&lt;/span&gt;, answer.content)
    memory.add_ai_message(answer.content)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这样让它介绍自己就会按照设定来回答了
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org54cb3ca&quot;&gt;
You: 介绍一下你自己
selected messages: [HumanMessage(content='介绍一下你自己', additional_kwargs={}, example=False)]
BOT: 你好，我是Xorius，一名人工智能助手。我可以与您讨论各种话题，帮助您解决问题。我可以提供有关各种主题的信息，例如科技、文化、历史、健康、旅游等等。我还可以执行各种任务，例如设置提醒、发送电子邮件、搜索信息等等。请告诉我您需要什么帮助，我会尽力为您提供支持。
&lt;/pre&gt;

&lt;p&gt;
如果不加这个 system_message，同样的输入得到的回答里它会强调自己由 OpenAI 开发，如下所示：
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;orgc6a60b3&quot;&gt;
You: 介绍一下你自己
selected messages: [HumanMessage(content='介绍一下你自己', additional_kwargs={}, example=False)]
BOT: 我是一名AI语言模型，由OpenAI开发。我可以进行自然语言处理和生成，帮助用户回答问题、翻译、写作等。我没有实体，只存在于计算机中，但我可以通过文字和语音与人类进行交互。我不会感到疲倦或犯错，但我也没有情感和意识。我只是一个程序，但我希望能够为人类提供帮助和便利。
&lt;/pre&gt;

&lt;p&gt;
最后，我将上述代码做一些调整后实现成了项目里的一个命令行工具，代码见 &lt;a href=&quot;https://github.com/monsternlp/xorius&quot;&gt;https://github.com/monsternlp/xorius&lt;/a&gt; ，也发布到了 pypi，执行 pip install xorius 即可安装，安装后即可在命令行执行 xorius-cli 来进入对话。
&lt;/p&gt;


&lt;div id=&quot;orgd75dfab&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/xorius_cli.png&quot; alt=&quot;xorius_cli.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
命令行参数说明如下：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;code&gt;--api-key&lt;/code&gt;: 设置 OpenAI 的 API 密钥&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--temperature&lt;/code&gt;: 设置温度参数，用于控制生成结果时的随性，0 的话不随机每次都生成概率最大的结果，默认 0.7&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--max-tokens&lt;/code&gt;: 设置生成结果允许的最大 token 数，默认 512&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--proxy&lt;/code&gt;: 设置 http 代理，主要针对国内网络环境&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
原型是实现了，但是在这个原型上，能看到一些直接的问题
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;ChatMessageHistory 是基于内存的历史消息记录方法，一旦退出历史对话消息将全部丢失&lt;/li&gt;
&lt;li&gt;当讨论的话题更早之前聊过时，选择最近历史消息的做法无法利用之前的讨论&lt;/li&gt;
&lt;li&gt;固定设置输出最大 token 数量的做法为了照顾长输出的情况，会导致短输出情况下无法利用更多的历史消息&lt;/li&gt;
&lt;li&gt;一个全局设置的温度参数会影响机器人处理不同任务的表现，比如说像翻译、分类、事实性问答这些任务并不需要随机性，而写作、创意生成则有一定的随机性会更好一些&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
在当前这种模式下，将机器人属性设置放在最开始的做法无法保证设定的一致性和连续性，用户总是能通过有意构造的输入来突破这种设置
&lt;/p&gt;


&lt;div id=&quot;org1702b81&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/xorius_cli_2.png&quot; alt=&quot;xorius_cli_2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
这些问题将会在之后的文章中做进一步的讨论。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>LLM Prompt Engineering 实践：序</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2023/05/07/llm-prompt-engineering-practice-prologue.html"/>
    <category term="NLP" scheme="http://www.zmonster.me/categories.html#NLP"/>
    <id>http://www.zmonster.me/2023/05/07/llm-prompt-engineering-practice-prologue</id>
    <published>2023-05-07T00:00:00+00:00</published>
    <updated>2023-05-07T00:00:00+00:00</updated>
    <description>
    
      <p>作为一个工程师，我不认为自己具备预测未来的宏观视野，但我想我还是可以参与到新生态建设里去的。针对语言模型应用目前尚存的一些问题，准备写一个项目，通过代码的方式来展示我对这些问题的应对方法的思考和尝试。</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
本文是《LLM Prompt Engineering 实践》系列的第一篇文章，系列文章如下：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2023/05/07/llm-prompt-engineering-practice-prologue.html&quot;&gt;LLM Prompt Engineering 实践：序 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2023/05/13/llm-prompt-engineering-practice-prototype.html&quot;&gt;LLM Prompt Engineering 实践：原型 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2023/06/21/llm-prompt-engineering-practice-memory-1.html&quot;&gt;LLM Prompt Engineering 实践：记忆（1） · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
ChatGPT 刚发布不久，我就把它接进了飞书供公司同事使用，回过头去看当时的聊天记录，那个时候它还是会经常拒绝回答，虽然相比过去的对话机器人有了非常大的提高，但还是显得有点呆笨的样子，对于它到底能做什么我并不是特别了解，再加上公司裁员、北京疫情（12月上半个月是北京疫情的高峰期）的因素，我就没花太多精力在这方面。春节回来后，可能是因为社会放开了以及经过两个月的发酵，非常明显地感觉到讨论热度在上升，我也开始去做更详细的了解 —— 一方面是持续地去使用 ChatGPT 以及了解其他人怎么使用，另外一方面是开始看相关的论文了解背后的技术变迁。ChatGPT 在模型上除了 RLHF 外我是大致熟悉的，但是近几年困在工作和情绪里没怎么去关注学术进展了，所以二月、三月主要是在补课，顺着几篇比较高质量的综述论文把过去几年的一些工作和思路看了下，慢慢地就对现在大语言模型面临的问题以及可能的发展方向有了一些感觉。
&lt;/p&gt;

&lt;p&gt;
毫无疑问，以 ChatGPT 为代表的大语言模型是很有价值的。从专业角度来看，如果不考虑成本的话，原来的大部分简单 NLP 任务都已经没有必要再做，有人因此担心 NLP 工程师要失业，但我觉得对 NLP 领域整体上来说是好事情，领域和行业的能力下限因此得到了提高，原来我们认为很复杂的、只能花昂贵代价做小规模应用的事情现在也可以得到普及（比如说基于文档的问答），我们也终于可以有更多的精力去讨论自然语言里更深层的原理和问题了。从用户角度看，ChatGPT 无疑也有非常大的潜能，回答知识性问题、辅助写作、翻译、总结、处理数据、写代码、绘图……似乎我们能想到的通过语言来做的事情，它都能做并且做得还不错，作为工具来说它已经大大提高了使用者处理事情的效率，并且还在被用户不断地挖掘出新的用法和能力，不管它的长期影响是好是坏，我想没有人会否认它很能干这个事实。
&lt;/p&gt;

&lt;p&gt;
在受益于 ChatGPT 的同时，很多人也因此非常焦虑，我多少也有一点，这种焦虑的根源主要在于 ChatGPT 后续影响的不确定性。目前观察到的应对这种焦虑的方式主要有几种：
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;通过追踪新的资讯、动态来证明自己能跟上变化，但往往因为人的精力有限而使自己非常疲惫并造成进一步的焦虑；&lt;/li&gt;
&lt;li&gt;通过预测（或看别人预测）大语言模型普及背景下的行业和社会未来以减轻焦虑，但是真的了解专业知识又具有宏观视野的人还是比较少，大部分非专业人士之间的相关讨论往往落入玄谈范畴，或者索性变成个人世界观的输出；&lt;/li&gt;
&lt;li&gt;通过重度使用、开发相关工具或应用、推动相关社会治理规范来参与新生态的建设，但是由于目前尚处于新生态早期，工具和方法论都非常不完善，想象力也还是不够。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
作为一个工程师，我不认为自己具备预测未来的宏观视野，但我想我还是可以参与到新生态建设里去的。以 ChatGPT 为代表的大语言模型效果确实非常强，但它也还是有非常多问题的，和所有机器学习模型一样，这些问题在之后有可能会慢慢地得到缓解，但绝对不会消失，如果要将大语言模型作为一个基础设施来构建应用，那么这些问题必然要有相应的应对机制，我相信新的生态会在这个基础上生长出来。这些问题已经在大量的论文中被提出讨论了，我自己也有维护相应的笔记来追踪这些问题的研究进展，本来是想以各个问题作为出发点来写一些文章做一些讨论的，不过不少问题即使在研究上也还处在探索讨论的阶段，只是单纯整理出来作为科普觉得会有点枯燥，于是决定写一个项目，通过代码的方式来展示我对这些问题的应对方法的思考和尝试。
&lt;/p&gt;

&lt;p&gt;
对大语言模型，我们目前已经知道的问题有：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;模型偏差问题: 模型会表现出对特定领域的倾向性而不是在各种问题上完全中立客观，在有上下文时模型会表现出近期偏差和标签偏差；&lt;/li&gt;
&lt;li&gt;评估问题: 对输入和输出结果，我们缺乏足够有效的评估手段；&lt;/li&gt;
&lt;li&gt;知识幻觉问题: 有时候语言模型会输出一些与给定上下文或客观事实不符的内容，该问题是由训练数据噪声、表示学习的不充分、解码方法、记忆机制缺失等众多复杂因素导致的；&lt;/li&gt;
&lt;li&gt;记忆机制的缺失: 语言模型本身未设计任何记忆机制，以 ChatGPT 为代表的产品仅能将需要记忆的内容同其他内容一起输入给语言模型，需要模型自己对区分输入中哪部分是记忆、哪部分是指令及其他内容，也因此无法像人一样维护长期记忆；&lt;/li&gt;
&lt;li&gt;多轮对话状态管理: 在对话模式下，对话场景的开始、跳出、返回、结束，目前全依靠语言模型自身进行辨别但做得并不是特别好；&lt;/li&gt;
&lt;li&gt;复杂结构数据的处理: 对体量较大但内部结构简单的数据目前可以切片处理，但对内部结构复杂的数据（如完整的项目源代码）目前要处理还是比较麻烦；&lt;/li&gt;
&lt;li&gt;复杂操作的执行: 人类往往对自己给出的指令的复杂性不太敏感，有时候认为理所当然的简单要求实际上可能需要分解成复杂的步骤才能完成，分解后的步骤之间也可能存在复杂的关系。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
我准备写的这个项目，计划由易而难地推进，最开始应该就是实现一个简单的机器人，设定一个初始 Prompt，每次对话时带上之前的聊天历史，然后逐步实现记忆机制、加上对知识幻觉的处理、整合阅读网页和文档的能力、整合图像和音频理解能力、加上任务分解和执行能力、实现人设的一致性和连续性、模拟出自我意识、统治人类……这些都不难，多多少少也在很多其他项目中实现过了，大概率不会有特别突破性的东西，甚至有可能鸽掉……总之，我现在要去解决最困难的一个问题了，那就是，这个项目该叫什么名字？
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>2022.07.31 百花山</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2022/08/01/hiking.html"/>
    <category term="" scheme="http://www.zmonster.me/categories.html#"/>
    <id>http://www.zmonster.me/2022/08/01/hiking</id>
    <published>2022-08-01T00:00:00+00:00</published>
    <updated>2022-08-01T00:00:00+00:00</updated>
    <description>
    
      <p>
早上五点半起来了，地铁去了汇合点，简单吃了早饭后就出发了。天气多云，本来还担心今天看不到什么云，路上看到，开车窗拍了下。


</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
早上五点半起来了，地铁去了汇合点，简单吃了早饭后就出发了。天气多云，本来还担心今天看不到什么云，路上看到，开车窗拍了下。
&lt;/p&gt;


&lt;div id=&quot;orgddc1240&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_7945.webp&quot; alt=&quot;IMG_7945.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
到达山脚后，惯例和「禁止攀爬野山」的警示牌合影——左二是我，不过打码了应该相熟的人才能看出来。
&lt;/p&gt;


&lt;div id=&quot;org48fabab&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8078.webp&quot; alt=&quot;IMG_8078.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
到山里后天空情况不错，因为水汽足又有不少的云，我非常满意，不过看山顶似乎被云层笼罩了，有点担心。
&lt;/p&gt;


&lt;div id=&quot;orge254d37&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_7953.webp&quot; alt=&quot;IMG_7953.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
蕙花（by形色）
&lt;/p&gt;


&lt;div id=&quot;orge875465&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_7954.webp&quot; alt=&quot;IMG_7954.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
蓝盆花（by 形色）
&lt;/p&gt;


&lt;div id=&quot;orgc400275&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_7957.webp&quot; alt=&quot;IMG_7957.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
​棉花糖！
&lt;/p&gt;


&lt;div id=&quot;org4d75f88&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_7959.webp&quot; alt=&quot;IMG_7959.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
被云层笼罩的山顶
&lt;/p&gt;


&lt;div id=&quot;orgf08aec0&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_7964.webp&quot; alt=&quot;IMG_7964.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
糖芥（by 形色），花语是平凡中的甜蜜快乐，真好！
&lt;/p&gt;


&lt;div id=&quot;orga54d706&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_7966.webp&quot; alt=&quot;IMG_7966.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
败酱（by 形色）
&lt;/p&gt;


&lt;div id=&quot;orgef0da79&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_7970.webp&quot; alt=&quot;IMG_7970.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
不知道叫什么，形色识别出来好几种很像的。
&lt;/p&gt;


&lt;div id=&quot;org4cfff6b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_7972.webp&quot; alt=&quot;IMG_7972.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
弱鸡如我只能在队尾偷拍
&lt;/p&gt;


&lt;div id=&quot;org4890c81&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_7975.webp&quot; alt=&quot;IMG_7975.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
沙参，我吃它食物中毒过哈哈哈哈
&lt;/p&gt;


&lt;div id=&quot;org5e001f3&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_7978.webp&quot; alt=&quot;IMG_7978.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
优雅
&lt;/p&gt;


&lt;div id=&quot;orge565f6a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_7980.webp&quot; alt=&quot;IMG_7980.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
丰盛的午饭，背包里不小一部分重量都是食物
&lt;/p&gt;


&lt;div id=&quot;orge087c1e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_7985.webp&quot; alt=&quot;IMG_7985.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
云雾缭绕
&lt;/p&gt;


&lt;div id=&quot;org730a97a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_7987.webp&quot; alt=&quot;IMG_7987.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
天然加湿器
&lt;/p&gt;


&lt;div id=&quot;orga44b60d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_7988.webp&quot; alt=&quot;IMG_7988.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
柳兰（by 形色）
&lt;/p&gt;


&lt;div id=&quot;orgcf5eb98&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_7992.webp&quot; alt=&quot;IMG_7992.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
雾气非常重
&lt;/p&gt;


&lt;div id=&quot;orgdd82eae&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8002.webp&quot; alt=&quot;IMG_8002.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
远眺，但什么也看不见
&lt;/p&gt;


&lt;div id=&quot;org147a4c0&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8012.webp&quot; alt=&quot;IMG_8012.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
老鹤草（by 形色）
&lt;/p&gt;


&lt;div id=&quot;org0a7f4df&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8022.webp&quot; alt=&quot;IMG_8022.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
紫菀，或者狗娃花，我分不出来
&lt;/p&gt;


&lt;div id=&quot;orgc833922&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8023.webp&quot; alt=&quot;IMG_8023.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
其他fafa
&lt;/p&gt;


&lt;div id=&quot;org089e8cb&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8025.webp&quot; alt=&quot;IMG_8025.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgca56884&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8026.webp&quot; alt=&quot;IMG_8026.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orge2e8865&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8033.webp&quot; alt=&quot;IMG_8033.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
雾气偶尔散去，云彩很漂亮，我能看上一整天
&lt;/p&gt;


&lt;div id=&quot;org5887d68&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8039.webp&quot; alt=&quot;IMG_8039.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgc6489d4&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8047.webp&quot; alt=&quot;IMG_8047.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org4b2564c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8051.webp&quot; alt=&quot;IMG_8051.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org44bb4c2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8054.webp&quot; alt=&quot;IMG_8054.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org5d576da&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8057.webp&quot; alt=&quot;IMG_8057.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
到达山顶草甸后合了个影，iWatch 真好用，远程控制手机拍照
&lt;/p&gt;


&lt;div id=&quot;org005a264&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8080.webp&quot; alt=&quot;IMG_8080.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
山顶草甸开满了各式细碎的小花
&lt;/p&gt;


&lt;div id=&quot;orgb9d688e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8065.webp&quot; alt=&quot;IMG_8065.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org67811c5&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8066.webp&quot; alt=&quot;IMG_8066.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgb3f6855&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8073.webp&quot; alt=&quot;IMG_8073.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在凉亭吃瓜，挑衅嘲讽边上没瓜吃的小孩
&lt;/p&gt;


&lt;div id=&quot;orgf89128d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/IMG_8079.webp&quot; alt=&quot;IMG_8079.webp&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
​八点大家才下到山脚，感觉自己变强了，上次爬下山后腿完全没力气了，这次还有很多余力。租了个车回出发点停车场，师傅在弯弯绕绕的山道上飚到100，把我们吓得够呛。两个晚上没怎么睡好，回程的时候我特别困了，十点到门头沟吃小烧烤，我就吃了串烤烤豇豆、烤青椒，勉强吃了串肉。回到家已经过零点了。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>博客新增闲言碎语栏目实现类微博功能</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2022/05/14/setup-microblog.html"/>
    <category term="博客" scheme="http://www.zmonster.me/categories.html#博客"/>
    <id>http://www.zmonster.me/2022/05/14/setup-microblog</id>
    <published>2022-05-14T00:00:00+00:00</published>
    <updated>2022-05-14T00:00:00+00:00</updated>
    <description>
    
      <p>以后就统一在自己博客里写 microblog 然后再同步到其他平台了</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
从 2013 年建立这个博客后，这里一直是我主要甚至几乎可以说唯一的表达渠道，虽然我也有公众号、微博、豆瓣、Twitter 等各个平台的帐号，但我几乎不怎么在这些平台上表达，朋友圈也用得非常少。有的人很喜欢有反馈的表达或者说其表达的目的就是为了让别人看到、听到，我呢，只是把这里当作自己的一个小花园，我收拾它、布置它，我在这里自得其乐，渐渐地它也变成我的一部分，至于是不是有人来访问是不是热闹都是次要的，如果有人看到后觉得我这好玩我当然也表示欢迎，仅此而已。公众号、微博、豆瓣、Twitter 这些平台，它们更像是家外面的咖啡馆、茶馆、广场，拥挤得不行，大家都在说话，我在这些地方不自在，也不想说话，更多是当个打听消息的地方。
&lt;/p&gt;

&lt;p&gt;
今年以来我的生活状况有点乱，所以博客很久没更新了，二月之后有一篇闲言碎语只发在了公众号没发到博客，有网友也关注了我公众号，问我说是不在博客更新了。首先呢，就像开头说的那样，博客是我主要的表达渠道，我会好好维护的，更新可能会少但一定不会停掉的；其次，发了一年左右的被我叫做“闲言碎语”的个人日记汇总，和我对这个博客的规划是有点冲突的，博客里更想写一些相对系统的、篇幅长一点的内容，所以一直在想把这部分内容以类似微博/Twitter 的形式来呈现，并且自动同步到其他平台上，今天算是完成了这个修改，方法也很简单，见相关 &lt;a href=&quot;https://github.com/Linusp/Linusp.github.io/commit/166cd2892721d6420f0ad35b298eefbe6c463cc9&quot;&gt;commit&lt;/a&gt; 。
&lt;/p&gt;

&lt;p&gt;
新栏目地址是 &lt;a href=&quot;https://www.zmonster.me/microblog.html&quot;&gt;https://www.zmonster.me/microblog.html&lt;/a&gt; ，样式非常简陋，多条内容之间用一条分隔线分开，每条内容有一个标题，点击后可以前往详情页写或者看评论 —— 本来想做成在一个页面展示所有评论的，但是 disqus 好像不支持，所以先这样吧。
&lt;/p&gt;


&lt;div id=&quot;org4f35e20&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20220514_162946.png&quot; alt=&quot;20220514_162946.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
关注我的朋友如果不嫌弃我的碎碎念的话，可以订阅这个栏目的 &lt;a href=&quot;https://www.zmonster.me/microblog-feed.xml&quot;&gt;RSS&lt;/a&gt;，或者关注我的 &lt;a href=&quot;https://twitter.com/zmonster_nobody&quot;&gt;twitter&lt;/a&gt; ，至于之前那种一周或者好几周汇总成一篇的方式，容我考虑下是否还要保留。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2022/01/24-2022/02/06)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2022/02/06/lifelog.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2022/02/06/lifelog</id>
    <published>2022-02-06T00:00:00+00:00</published>
    <updated>2022-02-06T00:00:00+00:00</updated>
    <description>
    
      <p>近期生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org0adfe08&quot;&gt;2022-01-24 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org4f6c6db&quot;&gt;22:00 返家&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org049d02c&quot;&gt;22:00 电话&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org23ea19d&quot;&gt;2022-01-25 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgb09e850&quot;&gt;22:25 XX村之星&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd5bb55d&quot;&gt;22:29 魔术&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2078487&quot;&gt;2022-01-26 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgbf41b0c&quot;&gt;16:00 搞卫生&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf2561cb&quot;&gt;20:00 医药&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc9fa42a&quot;&gt;2022-01-28 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org2ef14e7&quot;&gt;14:00 拜访&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf2dd784&quot;&gt;20:00 新大楼&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgeadf0fd&quot;&gt;20:30 网友&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6cc0781&quot;&gt;21:00 《最爱》&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org0baa26c&quot;&gt;2022-01-29 周六&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org270e302&quot;&gt;2022-01-30 周日&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3d66d0c&quot;&gt;2022-01-31 周一&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org28e20c6&quot;&gt;2022-02-02 周三&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org935936f&quot;&gt;2022-02-04 周五&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgdf42267&quot;&gt;2022-02-05 周六&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0adfe08&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org0adfe08&quot;&gt;2022-01-24 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org0adfe08&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org4f6c6db&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4f6c6db&quot;&gt;22:00 返家&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4f6c6db&quot;&gt;
&lt;p&gt;
弟弟顺利下了车，没有隔离，就登记了下，八点左右到了家。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org049d02c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org049d02c&quot;&gt;22:00 电话&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org049d02c&quot;&gt;
&lt;p&gt;
ZYC打电话过来，问我回没回家，三年没联系了吧，不知道联系我干嘛，能还我钱吗，或者还想找我借钱？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org23ea19d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org23ea19d&quot;&gt;2022-01-25 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org23ea19d&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgb09e850&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb09e850&quot;&gt;22:25 XX村之星&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb09e850&quot;&gt;
&lt;p&gt;
我在洗碗，一个邻居过来打招呼，瞎聊了几句，最后他说了一句「你可是XX村之星啊」。大学、工作后，我和村里的同龄人打交道都很少了，回家少回来也是宅着，所以我其实不太清楚村里人是怎么看我的，对于这种夸赞，我也不知道该以什么方式去回应，只好打了个哈哈。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd5bb55d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd5bb55d&quot;&gt;22:29 魔术&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd5bb55d&quot;&gt;
&lt;p&gt;
弟弟喜欢魔术，这半年多自己练习了不少扑克魔术，就让他表演了几个，还挺像模像样的哈哈哈，不错不错。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2078487&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org2078487&quot;&gt;2022-01-26 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org2078487&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgbf41b0c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgbf41b0c&quot;&gt;16:00 搞卫生&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgbf41b0c&quot;&gt;
&lt;p&gt;
今天家里搞卫生，爸妈协作在打扫厨房，清洗橱柜，擦被烟熏得发黑的墙壁和天花板，擦大门什么的。搞完洗了个澡，清爽。下午出太阳了，暖和、敞亮。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf2561cb&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf2561cb&quot;&gt;20:00 医药&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgf2561cb&quot;&gt;
&lt;p&gt;
医药下跌很剧烈，忽悠弟弟买了 100 块全指医药联接基金。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc9fa42a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgc9fa42a&quot;&gt;2022-01-28 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgc9fa42a&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org2ef14e7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2ef14e7&quot;&gt;14:00 拜访&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2ef14e7&quot;&gt;
&lt;p&gt;
中午ZCH和他爸、姐夫来拜访，送了水果、酒、牛奶，特别隆重。接待有点尴尬，一来是对方太隆重了，二来最后ZCH他爸和姐夫去下坊了，为了表示礼节，我们就把ZCH留下来吃午饭了，然后我陪着在那尬聊了半天，吃完饭快一点了，我又约了上线，所以ZCH他爸过来接我就直接把他们送走了。年后有时间去拜访一次吧。
&lt;/p&gt;

&lt;p&gt;
送ZCH出去后，前面一位邻居看到我了，过去说了两句话，觉得她也老了很多了，岁月的痕迹。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf2dd784&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf2dd784&quot;&gt;20:00 新大楼&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgf2dd784&quot;&gt;
&lt;p&gt;
看老徐转发的朋友圈，说我校计院开始建自己的专属大楼了，非常不错。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgeadf0fd&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgeadf0fd&quot;&gt;20:30 网友&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgeadf0fd&quot;&gt;
&lt;p&gt;
一位网友在我的博客下好是评论了一大段，我感觉他是真的想和我交朋友，哈哈哈。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6cc0781&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6cc0781&quot;&gt;21:00 《最爱》&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6cc0781&quot;&gt;
&lt;p&gt;
泡脚的时候音乐频道听到这首歌，粤语的，觉得很好听。我猜应该是老歌，上网易云搜索了下原来是周慧敏的，电视上真不厚道，谁作词谁作曲谁原唱一概没提，就标了个演唱者的名字。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0baa26c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org0baa26c&quot;&gt;2022-01-29 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org0baa26c&quot;&gt;
&lt;p&gt;
给我爸买的鞋子他取回来了，看得出来我爸还是喜欢、高兴的。
&lt;/p&gt;

&lt;p&gt;
中午表弟、弟媳带着孩子来了，家里做了好些菜。吃完聊天，我让弟弟表演了几个魔术，把氛围炒热了一点点。然后前屋的邻居说杀了猪，做了猪血，叫我们过去吃，我爸不能吃，我妈要做事，于是我就去了。他家叫来了特别多人，非常热闹。我吃了一小碗，和桌上其他邻居聊了聊闲话，北京冷不冷啊、有没有谈好女朋友啊、在哪个公司上班啊之类的。见见这些村里的邻居也挺好的。虽然未必所有人都会对我抱以善意，但我确实也希望和这些人恢复最基本的沟通吧，毕竟，我小时候和这些人在一起生活长大，我的一部分是有受到他们影响的。
&lt;/p&gt;

&lt;p&gt;
晚饭后，堂哥带着嫂子下来了，我趁机了解了下堂哥的工作和生意情况，生意方面是开了一个定制衣服的小店我嫂子在打理，想做线上但现在还没空去做，工作方面我哥原来工作的厂子被大厂兼并了，但还会让我哥去做，说是填补了对方的业务/技术空白啥的，但是得去漳州那边上班了。
&lt;/p&gt;

&lt;p&gt;
和爸妈聊天，得知我堂哥的一个姐姐不是亲生的，亲生父母是云石山人，可能是被遗弃或者被卖掉的，说早年间和亲生父母没来往这后面开始有一些了，我之前就一直疑惑为什么我喊姐姐但是又嫁在了我们村。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org270e302&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org270e302&quot;&gt;2022-01-30 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org270e302&quot;&gt;
&lt;p&gt;
中午去一个要好的邻居家吃饺子，见到了一起长大上小学中学但早已嫁人的ZHH，聊了一些天，真的是好久不见了，然后聊天才知道邻居的儿媳是 87 年人，但是皮肤好人也漂亮看着像是很年轻的人呢，可惜嫁的人很混蛋，不知道以后会怎么样。
&lt;/p&gt;

&lt;p&gt;
下午和LYC聊了一些知识管理方面的想法，开心。
&lt;/p&gt;

&lt;p&gt;
晚上去伯母家吃饭，姐夫也来了但是姐姐没来，我先拍了一张饭包肉丸的照片给WJ和LWL看，馋一下她们哈哈哈哈。
&lt;/p&gt;

&lt;p&gt;
看微信群里，LY那边紧锣密鼓地在张罗年夜饭了，我蛮想和他们一起过的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3d66d0c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3d66d0c&quot;&gt;2022-01-31 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3d66d0c&quot;&gt;
&lt;p&gt;
早上起床吃完饭后先去敬神，按顺序分别是祠堂祖公堂两支大香烛五支线香、旁边土地一支小香烛一支线香、天井一支小香烛一支线香、祠堂门框一支小香烛一支线香、祠堂门口空地上两支大香烛五支线香、我家门口空地上两支大香烛五支线香、我家门口一支小香烛一支线香、我家祖公堂上两支大香烛五支线香，最后灶上两支大香烛五支线香，这个顺序大致意味着请神到家这个过程。敬神过程中遇到了几个长辈。
&lt;/p&gt;

&lt;p&gt;
敬神完毕后，和弟弟一起把前门墙壁下堆着柴搬到了杂物间，搬完后我爸拿水管冲洗墙壁和门口的空地、清理门口的水沟等等。我妈炖好鸡鸭后我和弟弟喝了点肉汤，然后我妈开始做饭包肉丸，我帮着拿点东西还切了菠菜，开蒸后，我和弟弟就去伯母家喊大家来吃，结果他们先做了好多菜，喊我和弟弟在那吃，我喝了点汤吃了点菜，然后等了一会催促大家下到我家去，由于大家都吃饱了，所以只是象征性地吃了点饭包肉丸，然后就进入了聊天打闹环节。我哥领着两个侄女和外甥女到我们后院看鸡鸭，然后摘了菜地里一些黄掉的菜叶子、杂草什么的扔给鸡鸭吃，玩得不亦乐乎。
&lt;/p&gt;

&lt;p&gt;
下午贴完春联后，三四点我和弟弟先后洗澡换了衣服，然后我妈做了年夜饭，再次把伯母一家喊下来一起吃，不过姐姐和姐夫年夜饭得在姐夫家吃所以下午已经走了，所以桌上就是我家四口人加上伯母一家五口人，也算是热闹了。吃完再聊了聊天伯母一家就回自家去了。然后我和弟弟去点岁火，流程和早上敬神一样，但不用提着祭品了，只用香烛和线香。点岁火遇到了一些同辈的邻居，回来路上遇到大眼带着他的小儿子，大的说有十一岁了哈哈哈。点完岁火到家，村里到处开始放烟花，特别特别吵闹，好看或许是好看，但真的是太吵了，两边隔壁家、屋前屋后邻居家都在放，距离不过十来米，震耳欲聋 —— 我们家嫌吵闹是从来不放烟花的，敬神和点岁火按规矩打串爆竹就好了。烟花这个东西，大概没人真的去欣赏它转瞬即逝的美，大家都在放无非是热闹、跟风、攀比，挺无聊的。
&lt;/p&gt;

&lt;p&gt;
晚上开始下雨了，我弟在春晚沈腾小品的背景下又表演了几个扑克魔术，然后洗脸泡脚，上床看魂圈拜年纪，和朋友聊天。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org28e20c6&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org28e20c6&quot;&gt;2022-02-02 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org28e20c6&quot;&gt;
&lt;p&gt;
今天依然在下雨，早上起来很冷，看着外面被我妈叫做「大泡子点」的雨，有点畏惧出门，但又很想见见WJ，就想着下雨的话该怎么去。不过到了下午雨小了，天气真是给面子。快两点的时候，LBL带着WJ从云石山过来，我走了一小段路到桥头，又遇到一个同学，后来加联系方式他发了自己的姓名我才想起来是LJ并且和以前记忆里的脸对上。等我走出路边LBL的车已经在等着了，我上了副驾，看到LBL和WJ的脸，觉得一点也不生份，就是老朋友相见的亲切感觉。WJ说话比我印象中要爽朗大气了，不知道是不是我的错觉。
&lt;/p&gt;

&lt;p&gt;
先去了QL家坐了一会，WJ的女儿和儿子马上就玩上了，一点都没有因为环境陌生就拘谨。QL的爸爸妈妈张罗零食酒水，我们就边聊边嗑瓜子喝水，聊了什么来着我都不太记得了，总之气氛是愉快、轻松的。没见到QL的哥哥姐姐，只见到他嫂子和三个侄子，三个侄子分别是三年级四年级五年级，感觉当年这位嫂子挺辛苦的……
&lt;/p&gt;

&lt;p&gt;
在QL家坐了一会后就上WJ家了。WJ家热热闹闹地来了许多客，就把靠门口的一张桌子收拾了下我们几个坐上开始聊天，还特别热情地上了很多吃的，我记得的就有菜头生、豆腐拌辣椒（没见过的做法）、酸菜、米粿（炒的但是放上了鸭肉，也是没见过的做法）、饭包肉丸，都挺好吃的，我吃个不停。后来四点多快五点去走亲戚的JS也骑摩托过来了，我们聊了各自的情况，还共同回忆各种初中的同学、老师及相关的事情，感觉WJ是和初中的人事关联最紧密的，QL甚至连同村距离不到 50 米的初中同学都记不得了，我也差不多，所以多数时候是WJ在帮忙补充，比如说初三我们一个班读过啦、JQ老师去统战部还是统战局了啊、FQ老师去光大银行了呀（还有啥想不起来了）……
&lt;/p&gt;

&lt;p&gt;
快六点我们就散了，QL走路回家，我蹭JS的车回去。JS车开到清溪，下来买了一大盒 18 块的摔炮和两把手持烟花给孩子玩，然后去对面超市买家里要用的白醋。我本来是在等着的，他买完东西回来说看到ZYH了，我就过去打了个招呼简单聊了两句，加上微信方便以后联系。JS骑车带着我从清溪走，送我到了家里，我喊他下来喝了点热水，知道他家里催着他回去吃饭所以就没怎么留他。
&lt;/p&gt;

&lt;p&gt;
我回到家后家里已经吃完饭了，不过我在QL和WJ家都吃了很多东西所以也不再需要吃什么，简单玩了玩就洗漱了。和LWL也聊了聊分享了下我今天的经历，聊着聊着开始聊小学同学，稍微共同回忆了下，我记得以前DHT说过LTT也在一中并且表达过我欺负过她的意思，我和LWL说这个，结果LWL告诉我说LTT初中后就没上学了，所以是我记错了还是怎么样？LWL还很自信说小学五年级每个同学坐哪个位置都记得清楚，确实能记得我坐第三组第三排，但我问我前后排是谁她就说不出来了，然后迅速认怂说确实记不起来了，笑死我了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org935936f&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org935936f&quot;&gt;2022-02-04 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org935936f&quot;&gt;
&lt;p&gt;
（略好多字）真是难过的一天，晚上拖着LWL和我聊天到零点，好歹是好受了一点。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgdf42267&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgdf42267&quot;&gt;2022-02-05 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgdf42267&quot;&gt;
&lt;p&gt;
可能两点才睡吧，五点多醒了，想再睡，脑子里翻来覆去的还是那些事情。
&lt;/p&gt;

&lt;p&gt;
本来定了今天去外婆家和ZCH家以及见CH他们，然后我决定都不去了，哪都不想去了。我妈本来也说不想去，但后来因为弟弟说想去，就还是一起去了，吃完饭收拾好各种东西我爸骑车把他们两送到了圩上搭公交车。
&lt;/p&gt;

&lt;p&gt;
这之后我持续地处于大脑迟钝的状态，什么都不想做，只想刷手机看小说新闻来分散注意力。
&lt;/p&gt;

&lt;p&gt;
下午五点多吧，伯母那边喊上去吃饭，我穿了鞋上去，坐了整整两桌的人，我都不认识，就坐在姐夫边上吃了碗饭喝了点汤，就回家了。我爸本来让我说他在打麻将不去吃，后来伯母下来喊，还是上去吃了点。
&lt;/p&gt;

&lt;p&gt;
我给锅上倒了水想着烧水洗漱，后来我爸就接手过去烧火了。坐着坐着，收到我哥的信息，说两个侄女（其实有一个是外甥女）觉得学习太累了，待会让她们下来和我聊聊，过了会两个小姑娘下来了，排排坐坐到了房间椅子上。我就觉得特尴尬，说这个咋聊啊，学习累太正常了嘛，先起了个头说自己没法说学习方法建议可以想想自己以后想做什么，从这个就展开讲了我为啥会选计算机啊（因为经常去网吧玩，所以真的非常运气），接着又讲了很多我的一些故事，比如我填志愿填了清华大学填着玩啦、不喜欢重点班的氛围（卷、同学嘲笑心理有问题的女生）最喜欢复读那一年的时光啦（六一节大家看葫芦娃）、我去做暑假工的事情啦（这个算是有说教意义）、不喜欢自己专业的人会痛苦啦（我的室友/同学）……最后点了几个题，一个是跟她们讲应当要去享受知识本身的乐趣，这个是比分数更长远的东西，聊了各个学科我知道的一些奇怪有趣的东西；后来进一步我也聊说还可以通过一些游戏化的方式来提高乐趣啊之类的。感觉聊完和两个小姑娘是有拉近一点距离的，希望我传达了正确的观念。
&lt;/p&gt;

&lt;p&gt;
上床后，十一点左右，舅舅打了电话过来，问怎么回事，我也不想说什么细节，就说我在处理。后来和LWL聊了会，我感觉她还挺喜欢和我聊的嘛。零点后，CH又打了过来，视频通话，CH和LH在CML家，CML说他 25 才回去，LH和CH都是明天回，开导了我一番。
&lt;/p&gt;

&lt;p&gt;
感谢大家的关心吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2022/01/10-2022/01/23)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2022/01/24/lifelog.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2022/01/24/lifelog</id>
    <published>2022-01-24T00:00:00+00:00</published>
    <updated>2022-01-24T00:00:00+00:00</updated>
    <description>
    
      <p>近期生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org09e383a&quot;&gt;2022-01-10 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org81c00c8&quot;&gt;23:20 芋芽芋荷芋子粥&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org23c9e4d&quot;&gt;2022-01-12 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orge2fc164&quot;&gt;22:05 明年&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3939f17&quot;&gt;22:40 残忍&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org128f940&quot;&gt;2022-01-13 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org54f066a&quot;&gt;08:58 可爱&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6297329&quot;&gt;2022-01-14 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgfe750dc&quot;&gt;21:42 清晰&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org36ae934&quot;&gt;2022-01-16 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orge95bc19&quot;&gt;15:51 独处&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org882ba96&quot;&gt;15:52 理想伴侣&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org9c4602a&quot;&gt;2022-01-17 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org2081e22&quot;&gt;12:01 史官&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org98f7336&quot;&gt;2022-01-18 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org2235566&quot;&gt;21:11 新增&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org870b2dc&quot;&gt;2022-01-19 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org9df5a27&quot;&gt;22:03 童年&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc168136&quot;&gt;22:26 柳比歇夫&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8f9f894&quot;&gt;2022-01-20 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgd0bab36&quot;&gt;09:14 幻听&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgebd716c&quot;&gt;21:54 小孩&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf87d3ac&quot;&gt;23:00 气候&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org9d49a05&quot;&gt;2022-01-21 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgd0d7374&quot;&gt;08:09 失眠&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge77411d&quot;&gt;2022-01-22 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org1f5c747&quot;&gt;22:52 堂姐&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3d78fb0&quot;&gt;22:56 拒绝&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb991dab&quot;&gt;23:12 送节&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc244db7&quot;&gt;23:01 八一南路&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org09e383a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org09e383a&quot;&gt;2022-01-10 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org09e383a&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org81c00c8&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org81c00c8&quot;&gt;23:20 芋芽芋荷芋子粥&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org81c00c8&quot;&gt;
&lt;p&gt;
芋芽还是第一次吃，挺新奇的；芋荷炒牛肉简直无敌；芋子粥，粥里的米没有煮烂，我爸说不能煮烂这样粥才能好吃有甜味，是这样吗，学到了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org23c9e4d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org23c9e4d&quot;&gt;2022-01-12 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org23c9e4d&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orge2fc164&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge2fc164&quot;&gt;22:05 明年&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge2fc164&quot;&gt;
&lt;p&gt;
午饭的时候，我爸笑着说「你可以在北京找，我们也不要求说多快结婚，但明年你起码要带一个回来看看吧」。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3939f17&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3939f17&quot;&gt;22:40 残忍&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org3939f17&quot;&gt;
&lt;p&gt;
有时候我会想，我如果真的遇到一个合适的人，却要她来和我一起分担面对我的痛苦，这不会太残忍了吗？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org128f940&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org128f940&quot;&gt;2022-01-13 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org128f940&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org54f066a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org54f066a&quot;&gt;08:58 可爱&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org54f066a&quot;&gt;
&lt;p&gt;
早上起来，看到 WJ 在最新一篇公众号的文章下评论「觉得你有时好可爱」，那当然了，我超可爱的，希望有更多人爱我。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6297329&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org6297329&quot;&gt;2022-01-14 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org6297329&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgfe750dc&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgfe750dc&quot;&gt;21:42 清晰&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgfe750dc&quot;&gt;
&lt;p&gt;
相亲也不是没有好处的，至少在这个过程中，对于我能和什么样的人聊得来、想和什么样的人共同相处有更清晰的想法了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org36ae934&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org36ae934&quot;&gt;2022-01-16 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org36ae934&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orge95bc19&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge95bc19&quot;&gt;15:51 独处&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge95bc19&quot;&gt;
&lt;p&gt;
在家里，没有太多独处的空间，我觉得这是最大的一个问题。倒也不是说我不能一个人待着，但是父母就在附近，我没有办法不去想他们的事情。周末这样的日子变得很难熬，倒是想到上班后觉得一阵轻松。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org882ba96&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org882ba96&quot;&gt;15:52 理想伴侣&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org882ba96&quot;&gt;
&lt;p&gt;
我想要什么样的伴侣呢？我这阵子想过一些，比如说互相理解啦、三观一致啦，可能这些都不是必要的，因为互相理解的状态是需要在双方共处的过程中逐步建立起来的，三观涉及的东西太多说一致完全就没意义。非要说的话，希望是一个独立自主且保持开放心态的人吧。
&lt;/p&gt;

&lt;p&gt;
等于没有说。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org9c4602a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org9c4602a&quot;&gt;2022-01-17 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org9c4602a&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org2081e22&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2081e22&quot;&gt;12:01 史官&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2081e22&quot;&gt;
&lt;p&gt;
我是我自己的史官。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org98f7336&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org98f7336&quot;&gt;2022-01-18 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org98f7336&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org2235566&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2235566&quot;&gt;21:11 新增&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2235566&quot;&gt;
&lt;p&gt;
北京和深圳都有新增病例，爸妈忧心忡忡，担心弟弟回不了家过年，我说担心也没办法，人平安就好。北京的一些朋友已经不打算回家了，有些人买好了车票但也在担心。如果这种情况还会维持几年，大概会有很多的社会习俗要被迫跟着改变吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org870b2dc&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org870b2dc&quot;&gt;2022-01-19 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org870b2dc&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org9df5a27&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org9df5a27&quot;&gt;22:03 童年&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org9df5a27&quot;&gt;
&lt;p&gt;
陪我妈聊了很多她童年的事情 —— 最开始是我在看电视，记录频道在讲徽派建筑，我说外婆家那里的屋子有点类似的味道，以这个为由头聊起了村里的建筑，我妈说她小时候就是在祠堂上的学，聊到我大外公（我外公的哥哥）是老师，然后聊起我大外公家，进而开始聊到我妈小时候和大外公家谁玩得好各种事情，还说我大舅小时候不知道为什么被大外婆嫌弃被她打特别厉害，说到大舅，我妈仍然是非常不解，反复在说「都是自己生的，不知道你大外婆为什么那么讨厌他」。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc168136&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc168136&quot;&gt;22:26 柳比歇夫&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc168136&quot;&gt;
&lt;p&gt;
微信群里认识的网友，说我是现代柳比歇夫，了解了一下，确实我现在做的事情有点像他呢，希望我也可以坚持几十年。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8f9f894&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org8f9f894&quot;&gt;2022-01-20 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org8f9f894&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgd0bab36&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd0bab36&quot;&gt;09:14 幻听&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd0bab36&quot;&gt;
&lt;p&gt;
七点多快八点的时候，我隐约听到父母的争吵声，但是仔细听，却又听不出具体的词汇，我轻轻起床来到楼梯口，楼下安安静静的，只有锅铲和锅碰撞的声音、排风扇的嗡鸣、门开合的吱呀声，并没有争吵声，我是幻听了吗？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgebd716c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgebd716c&quot;&gt;21:54 小孩&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgebd716c&quot;&gt;
&lt;pre class=&quot;example&quot; id=&quot;org49a9b5e&quot;&gt;
诶，我一直的印象中故作成熟有点臭屁的小孩，为嘛现在总感觉有点小抑郁。这么需要别人理解。
&lt;/pre&gt;

&lt;p&gt;
我小时候臭屁吗？没啥印象了哈哈哈哈。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf87d3ac&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf87d3ac&quot;&gt;23:00 气候&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgf87d3ac&quot;&gt;
&lt;p&gt;
我妈说，她小时候气候和现在相差很大，九十月的时候就会很冷了。这么一说确实是，我记得我小时候时，冬天到处是能见到冰的：田地里会结一层薄薄的冰，晾衣服的竹竿和屋檐都会挂上冰锥 —— 我们叫凌冰。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org9d49a05&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org9d49a05&quot;&gt;2022-01-21 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org9d49a05&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgd0d7374&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd0d7374&quot;&gt;08:09 失眠&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd0d7374&quot;&gt;
&lt;p&gt;
三点半醒了，之后好像断断续续都没怎么睡着。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge77411d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge77411d&quot;&gt;2022-01-22 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge77411d&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org1f5c747&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1f5c747&quot;&gt;22:52 堂姐&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1f5c747&quot;&gt;
&lt;p&gt;
堂姐和姐夫上门拜访，挺奇怪的，因为长辈的矛盾，几乎没见过她专门来走动的，我陪着聊了半天，他们主要是围绕他们高二的儿子在聊，说成绩不稳定，问我有没有什么考试方法、学习方法的建议。我妈后面说，估计是听说我回家了，专门为这个事来的。
&lt;/p&gt;

&lt;p&gt;
真的，我学习好不是因为学习方法，大家就不能承认我聪明这个事实吗？哈哈哈，中考后学校把前 20 名召集起来开会，我在那个会上说「我觉得读书还是要靠天分的」的事情了，想起来就好笑。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3d78fb0&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3d78fb0&quot;&gt;22:56 拒绝&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org3d78fb0&quot;&gt;
&lt;p&gt;
拒绝了朋友介绍的一位姑娘的见面请求，微信上聊了这些日子，觉得不太聊得来。其实早就觉得聊不来了，但之前想着是朋友介绍并且称赞的人，是不是应该还是见一见什么的，但现在我实在是心累，不想再浪费双方的精力了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb991dab&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb991dab&quot;&gt;23:12 送节&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb991dab&quot;&gt;
&lt;p&gt;
跟我妈去送节，先准备送点自家的东西给大姨，因为要去外婆家，我妈为了谢绝大姨邀请我们吃午饭，电话里除了说要去外婆家还拿我做借口撒谎说我有事要办，我听到后又好气又好笑，不想去就不去呗干嘛扯我啊，万一待会大姨问起来我有啥事，该咋回答？无奈，我就跟我妈对好口径，说如果问起就说我去找我同学了。
&lt;/p&gt;

&lt;p&gt;
我妈送东西给大姨就先下车了，我就到广场才下，去银行取钱，惯例又遇到 ATM 钱被取空，找到工商银行的 ATM 才完成取钱任务。然后在等我妈的过程中和高中同学聊了聊，不说恢复感情，起码恢复了微信沟通吧。
&lt;/p&gt;

&lt;p&gt;
去了外婆家，见到了表弟的妻子和刚出生不久的女儿，我还抱了会孩子。还见到了最小的三个表弟，两个大点的一个在一中读高一、一个初三，都很高大了，过得真快，最小的才 10 岁不过也很快的。
&lt;/p&gt;

&lt;p&gt;
在门口竹椅上坐着和外婆聊了一些天。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc244db7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc244db7&quot;&gt;23:01 八一南路&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc244db7&quot;&gt;
&lt;p&gt;
走完亲戚，陪我妈去八一南路买被套，人挤人热闹得不行。拥挤的人潮里，回忆不断涌出来：在文化馆打桌球，在一家已经不记得名字的店吃卤豆腐等小吃，在双清书院买小说，穿过有好多香烛店的解放路去向阳南路的租书店看小说和漫画……对于高中生活，脑子里清晰记得的只有几个印象深刻的片段，但其实也有很多很多开心平凡的日常，都模模糊糊了，只有像今天这样，在特定的地点触发之后才能勉强回想起来一点。
&lt;/p&gt;

&lt;p&gt;
我过去到底是怎么样一个人，我其实已经完全不清楚了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>我的2021</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2022/01/15/annual-summary-of-2021.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2022/01/15/annual-summary-of-2021</id>
    <published>2022-01-15T00:00:00+00:00</published>
    <updated>2022-01-15T00:00:00+00:00</updated>
    <description>
    
      <p>一次数据化分析总结的尝试</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;orge57be3b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2021_diaries_heatmap.png&quot; alt=&quot;2021_diaries_heatmap.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在 2021 年里，我写了 321 天日记，一共写下了 797 条记录，共计 138574 字，平均每天要写 432 字。我在 2021-06-14 写了 3107 个字的日记，是这一年中中最多的一天。797 条记录里，有 234 条是在做计划，有 95 条在做回顾，剩下的 468 条在记录生活细节。
&lt;/p&gt;


&lt;div id=&quot;org7e9b484&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2021_diary_words.png&quot; alt=&quot;2021_diary_words.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
日记里的关键词显示，我这一年关心得最多的，是父母和搞钱，也有很多的想法，不过并没有去付诸行动。虽然热衷于搞钱，但是全年的总收益率才 4% 左右，还是需要学习呀 —— 虽然没有在投资上赚到什么钱，但在财务上，我把我从 2016 年开始记的账都梳理清楚了，我现在能算出我所有资产的增长趋势了，搞清楚了这一点我很开心。
&lt;/p&gt;


&lt;div id=&quot;orgc186e25&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2021_diaries_sentiment_2.png&quot; alt=&quot;2021_diaries_sentiment_2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
日记显示，我这一年有较大的情绪变化，特别是年末的几个月，过得并不开心。
&lt;/p&gt;


&lt;div id=&quot;orgd1cf0c2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2021_diaries_sentiment_wordcloud.png&quot; alt=&quot;2021_diaries_sentiment_wordcloud.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
朋友们的陪伴给了我最多的正面情绪，帮助我对抗了各种各样的痛苦，感谢我的朋友们。分析了微信聊天记录后，我选出来十位和我聊得多的朋友，看看我都和他们聊了些什么：
&lt;/p&gt;


&lt;div id=&quot;orgcb1f84f&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2021_chathistory_top_person_1.png&quot; alt=&quot;2021_chathistory_top_person_1.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
我和 ZCB 聊了最多，这个是我弟弟，聊得多也正常，我也会比较唠叨，所以对他说的话是多过他对我说的话的；其次是 LY，他对我说的比我说的还多，看来他比我话痨；ZYP 是我表弟，2021 年刚上大学学计算机，三天两头来找我请教问题，所以聊的内容大多是一些计算机的内容；WJ 是我的多年老友，虽然多年未见了，但是我们始终在共同探讨心灵、自我方面的话题。
&lt;/p&gt;


&lt;div id=&quot;org98e9cef&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2021_chathistory_top_person_2.png&quot; alt=&quot;2021_chathistory_top_person_2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
我和 LY 在 200 多天里都有交流，积少成多，才有了他top2的地位。
&lt;/p&gt;


&lt;div id=&quot;org90795bd&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2021_chathistory_top_person_3.png&quot; alt=&quot;2021_chathistory_top_person_3.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
我和ZYP、ZCB以及WJ一聊就停不下来。
&lt;/p&gt;


&lt;div id=&quot;orgc9a25fa&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2021_chathistory_top_person_words.png&quot; alt=&quot;2021_chathistory_top_person_words.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
上图是我和这十位朋友聊天记录的关键词，相交的部分是我们共同提到的内容。
&lt;/p&gt;

&lt;p&gt;
人生不如意者十之八九，也许我该找个人聊聊？但是很多话题，实在是找不到人来聊，所以我去读了《也许你该找个人聊聊》和《蛤蟆先生去看心理医生》：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
前者说：
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;所有问题的根源都可以归结到自由、孤独、无意义和死亡这四个问题上&lt;/li&gt;
&lt;li&gt;我们真正的问题往往被我们回避着&lt;/li&gt;
&lt;li&gt;即使我们认识到了真正的问题以及解决方案，往往也会视而不见，因为与其从并未上锁的囚笼中走出来面对命运的无常，我们宁愿选择沉溺在已知的、确定的痛苦和自毁中&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
我在读这本书的时候，注视到了我一直视而不见的阴影，我知道我的自省已经做得够多了，时候已到，是时候作出改变了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;后者说：

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;人有三种心理状态：只会说「我要这个我要那个」的儿童自我、只会说「你应该这样你应该那样」的父母自我，以及「我要去做些什么来应对现在的问题」的成人自我&lt;/li&gt;
&lt;li&gt;当我们出问题时，往往是在儿童自我或父母自我中停留了过久，尝试让自己进入成人自我，是脱离痛苦的道路&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
除了朋友和书籍，B站也陪伴我度过了很多时间，可惜B站的观看历史只保留最近三个月的，所以我只能基于这三个多月的数据来做一些分析了。
&lt;/p&gt;


&lt;div id=&quot;org0dbaba1&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/bili_2021_times_1.png&quot; alt=&quot;bili_2021_times_1.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
每天的早上和深夜，是我使用B站的高峰期，深夜难眠，B站陪伴，早上看得多是因为我早上吃饭时用来下饭，坚持吃早饭的我真棒！
&lt;/p&gt;


&lt;div id=&quot;org2598577&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/bili_2021_times_2.png&quot; alt=&quot;bili_2021_times_2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
工作日只能早晚看，但周末就看得很多了。
&lt;/p&gt;


&lt;div id=&quot;orgbb3138a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/bili_tags.png&quot; alt=&quot;bili_tags.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在内容上，我喜欢看游戏、搞笑和日常类别的视频，没什么营养，但打发时间足够了。
&lt;/p&gt;


&lt;div id=&quot;org13bb1e0&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/bili_title_wordcloud.png&quot; alt=&quot;bili_title_wordcloud.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这三个多月里，我看了大量《黑暗之魂》和《血源诅咒》的视频，并和大家一样，期待着《艾尔登法环》的到来。
&lt;/p&gt;


&lt;div id=&quot;orgde705fc&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/bili_authors.png&quot; alt=&quot;bili_authors.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
我最喜欢的10位UP主见上图，其中四位都是黑暗之魂系列游戏的UP主，我对宫崎英高是真爱。
&lt;/p&gt;


&lt;div id=&quot;org5c9fc9c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2021_journal_heatmap.png&quot; alt=&quot;2021_journal_heatmap.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
工作方面，我写了 239 天的工作日志，一共写下 523 条记录，共计 233429 字，平均每天要写 977 字。以可复现工作为准则的我，除了文字，还在日记里记录了我实际的操作，记录了 5808 行操作用的代码，其中 Python 代码 3015 行，shell 1715 行，SQL 430 行，YAML 379 行。
&lt;/p&gt;


&lt;div id=&quot;org7815f8d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2021_journal_words.png&quot; alt=&quot;2021_journal_words.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
工作日志的关键词显示，这一年的工作内容里，我和数据、资讯、股票打交道很多，大量的时间是在做具体业务，我已经远离算法了。
&lt;/p&gt;

&lt;p&gt;
这是一次数据化分析总结的尝试，限于精力还有很多东西没有分析，争取在2022年多收集一些数据，做一个更全面的分析出来。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/12/02-2021/01/09)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2022/01/10/lifelog.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2022/01/10/lifelog</id>
    <published>2022-01-10T00:00:00+00:00</published>
    <updated>2022-01-10T00:00:00+00:00</updated>
    <description>
    
      <p>近期生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org68700e4&quot;&gt;2021-12-04 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgffd74de&quot;&gt;17:15 阴影&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org77ffd9d&quot;&gt;2021-12-05 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org4392f94&quot;&gt;09:45 导出&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgcdd360c&quot;&gt;18:39 改变&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org790d711&quot;&gt;20:44 想成为UP主&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org83068cf&quot;&gt;2021-12-06 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgc535859&quot;&gt;18:43 失望&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org709a412&quot;&gt;2021-12-07 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org7fe1611&quot;&gt;00:30 拆股和再投资&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd059c97&quot;&gt;13:05 降低要求&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6938883&quot;&gt;2021-12-08 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org752080e&quot;&gt;22:38 坠落&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga282ac4&quot;&gt;23:45 续&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org91368f7&quot;&gt;2021-12-13 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgbfd2da4&quot;&gt;22:45 泄漏&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org76654a7&quot;&gt;22:48 代际&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org47a5279&quot;&gt;2021-12-14 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgd5f9922&quot;&gt;08:52 梦&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org02ab6d3&quot;&gt;2021-12-15 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org829fabc&quot;&gt;08:30 无梦&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6436972&quot;&gt;23:30 畅谈&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org05c7d4d&quot;&gt;2021-12-17 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org50ea528&quot;&gt;19:30 回家&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6e4fe03&quot;&gt;23:06 记录&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc23801a&quot;&gt;23:14 香猪坊会议&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org964e380&quot;&gt;2021-12-19 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org9216dd9&quot;&gt;15:39 个人数据库&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb6597b0&quot;&gt;2021-12-21 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgc408579&quot;&gt;23:49 连手&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org091d4bc&quot;&gt;2021-12-22 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org7c7eabb&quot;&gt;14:12 二胎&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org93be1ec&quot;&gt;2021-12-24 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org79c79c6&quot;&gt;23:44 平安夜&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga4a9f9c&quot;&gt;2021-12-27 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgdd8e0e3&quot;&gt;22:26 关店&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org053bbdf&quot;&gt;22:29 裁员&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge2de828&quot;&gt;22:38 体检&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc186a90&quot;&gt;2021-12-28 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgddefcdc&quot;&gt;11:17 体检&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge4bfc09&quot;&gt;2021-12-30 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgd4c1100&quot;&gt;23:15 升21转&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf613402&quot;&gt;2022-01-01 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgbdf273d&quot;&gt;12:44 同理心&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4f37d34&quot;&gt;20:47 退货&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6795a12&quot;&gt;2022-01-02 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgb1b1eea&quot;&gt;06:17 停运&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org9b67a11&quot;&gt;11:50 九江农业号&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga1ad36b&quot;&gt;18:02 南昌&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc48b2c0&quot;&gt;20:13 陪伴&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org184cc7e&quot;&gt;23:00 接站&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org7851410&quot;&gt;2022-01-03 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga4ddf18&quot;&gt;10:00 核酸检测&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org066b10d&quot;&gt;22:00 家（补）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5c4c139&quot;&gt;2022-01-07 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org063f80b&quot;&gt;23:00 相亲（补）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgdf80847&quot;&gt;2022-01-08 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org9772a9b&quot;&gt;16:00 相亲（补）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6880170&quot;&gt;22:00 共鸣（补）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org91f649f&quot;&gt;22:00 畅谈（补）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb84a0d9&quot;&gt;22:00 理想伴侣（补）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org43465b4&quot;&gt;2022-01-09 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org3749b47&quot;&gt;21:52 遗忘&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3857d10&quot;&gt;23:55 畅谈&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org68700e4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org68700e4&quot;&gt;2021-12-04 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org68700e4&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgffd74de&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgffd74de&quot;&gt;17:15 阴影&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgffd74de&quot;&gt;
&lt;p&gt;
《也许你该找个人聊聊》这本讲心理治疗的故事的书，传达了一个观点，就是每个出现问题的人，大都有一个自己在回避的根源性问题。我想了一下，我有这样的问题吗，可能还真有，我以为我已经从中平复过来了，但也许那道阴影一直都在。即使现在这样一个瞬间我能看向它，但这种不敢面对、不想改变的症结才是最大的问题。
&lt;/p&gt;

&lt;p&gt;
我的阴影可能是：（略去104字）。因为这个，我不想发展什么亲近关系，因为一旦亲近，我就必然要告知他们这些状况，我害怕那时候他们的反应。
&lt;/p&gt;

&lt;p&gt;
当然，把所有问题归结到一个点上，可能又是一种把复杂问题简单化的自我欺骗，谁知道呢？我得承认，我对自己的了解还是非常的不够。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org77ffd9d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org77ffd9d&quot;&gt;2021-12-05 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org77ffd9d&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org4392f94&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4392f94&quot;&gt;09:45 导出&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4392f94&quot;&gt;
&lt;p&gt;
发现 Telegram 自带了聊天记录导出功能，非常友好！一口气备份好了多个群及好友的聊天记录，不过 EFB 我大概是 18 年才开始使用，更早的就没办法了。
&lt;/p&gt;


&lt;div id=&quot;orgb524dbe&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/telegram_chathistory_export.png&quot; alt=&quot;telegram_chathistory_export.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgcdd360c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgcdd360c&quot;&gt;18:39 改变&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgcdd360c&quot;&gt;
&lt;p&gt;
今天去 LY 家进行小饭桌活动，来回的路上我都继续在读《也许你该找个人聊聊》，里面有一段表达了这么一个观点：人们会积极会消极地走上自毁的道路，因为这样就可以给自己带来一种自己掌握了命运的错觉，而不用被不确定性困扰。
&lt;/p&gt;

&lt;p&gt;
我对此表示赞同，因为改变意味着丧失而丧失则带来痛苦，一个已经在困境里的人，同样可以用这个困境作为外壳来保护自己免受更多的痛苦，至少人的潜意识里是这样的。
&lt;/p&gt;

&lt;p&gt;
我昨天觉得，我发现了自己身上一个具体的更大的问题，但现在，我觉得更大的问题，是我也在抗拒改变、害怕改变。
&lt;/p&gt;

&lt;p&gt;
我想要一些改变。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org790d711&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org790d711&quot;&gt;20:44 想成为UP主&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org790d711&quot;&gt;
&lt;p&gt;
嗯，一个想法是，想用音频、视频的方式来记录自己的生活，就当视频日记来做，感觉也会很好，毕竟音视频能更好地还原生活的状态。
&lt;/p&gt;

&lt;p&gt;
大概了解了下，以我这种需求，拍摄的话买个手机支架就好了，录音方面可能需要声卡、话筒但也不是必需，然后就是电脑能跑得动一些常见的视频剪辑软件了，要不要试试呢？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org83068cf&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org83068cf&quot;&gt;2021-12-06 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org83068cf&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgc535859&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc535859&quot;&gt;18:43 失望&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc535859&quot;&gt;
&lt;p&gt;
写了段漂亮的代码，换来的却是一句「为什么要搞这么复杂啊」，对，从头到尾堆语句没有任何设计倒是简单了，输入输出稍微改一下也只要把原来的代码抄一抄糊一遍，确实简单。失望透顶。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org709a412&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org709a412&quot;&gt;2021-12-07 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org709a412&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org7fe1611&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org7fe1611&quot;&gt;00:30 拆股和再投资&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org7fe1611&quot;&gt;
&lt;p&gt;
发现在 beancount 里拆股可以这么写
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org4dbe0af&quot;&gt;
2021-09-13 * &quot;证券保险ETF拆分&quot;
  Assets:投资:证券账户:华宝证券:持仓                         -2000.00 SH512070 @ 2.3490 CNY
  Assets:投资:证券账户:华宝证券:持仓                          6000.00 SH512070 @ 0.7830 CNY
&lt;/pre&gt;

&lt;p&gt;
那分红再投资是不是也可以这么写呢？可以的话就不会造成大量的分红收入了 —— 原来的做法是先写一个分红的收入，然后再写一个买入，像下面这样
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;orgc9e183a&quot;&gt;
2021-10-20 * &quot;交银双轮动AB分红&quot;
  Assets:投资:且慢:稳健投资:CASH    101.03 CNY
  Income:分红

2021-10-20 * &quot;买入交银双轮动AB&quot;
  Assets:投资:且慢:稳健投资:持仓    95.15 OF519723 @@ 101.03 CNY
  Assets:投资:且慢:稳健投资:CASH    -101.03 CNY
&lt;/pre&gt;

&lt;p&gt;
分红再投资其实就是钱左手倒右手并没有变多，但这么一记就产生了一笔收入。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd059c97&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd059c97&quot;&gt;13:05 降低要求&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd059c97&quot;&gt;
&lt;p&gt;
日子总是还得过，就降低对别人的期望和要求呗，不然还能咋地。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6938883&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org6938883&quot;&gt;2021-12-08 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org6938883&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org752080e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org752080e&quot;&gt;22:38 坠落&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org752080e&quot;&gt;
&lt;p&gt;
（略去 707 字）
&lt;/p&gt;

&lt;p&gt;
打完电话是 19:40 多了，还好，不算太晚，LY 和 K 喊着去吃二哥，我本来想不去了，但是想着自己现在这样的状态，回去更危险，于是强撑着还是一起去了，吃了 345，觉得二哥的味道比以前差了好多，以后可能不去了。
&lt;/p&gt;

&lt;p&gt;
好绝望、好难过、好无助……
&lt;/p&gt;

&lt;p&gt;
（略去 445 字）
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga282ac4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga282ac4&quot;&gt;23:45 续&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga282ac4&quot;&gt;
&lt;p&gt;
洗了个澡，感觉好一点了。
&lt;/p&gt;

&lt;p&gt;
（略去 114 字）
&lt;/p&gt;

&lt;p&gt;
暂时不想睡，需要一些刺激多巴胺的东西，看看 B 站或许再玩玩游戏。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org91368f7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org91368f7&quot;&gt;2021-12-13 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org91368f7&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgbfd2da4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgbfd2da4&quot;&gt;22:45 泄漏&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgbfd2da4&quot;&gt;
&lt;p&gt;
上午我在写当日计划，然后接到中国电信升级套餐的电话，就停下来接电话，这个时候同事过来询问工作的事情，当时我的屏幕上正显示着「失望透顶」那一段，察觉到对方可能看到后，我把屏幕切到了浏览器上，然后继续聊工作。
&lt;/p&gt;

&lt;p&gt;
也许对方看到了，也许对方会一整天心情都不好，不过，那又怎么样呢。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org76654a7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org76654a7&quot;&gt;22:48 代际&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org76654a7&quot;&gt;
&lt;p&gt;
下班拉着 ZCH 去饭阿姨吃饭，聊了聊天，他说他想干个两年后就离开一线城市，到比如武汉、南昌这种地方。说真的，我毕业、刚工作的时候可完全没这种心态。不过，虽说是一个大的趋势吧，我感觉他并没有想清楚自己要的是什么生活，聊的过程中他说到他一个同学在军校学计算机出来后就分配工作「生活有希望」，到底是什么希望呢？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org47a5279&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org47a5279&quot;&gt;2021-12-14 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org47a5279&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgd5f9922&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd5f9922&quot;&gt;08:52 梦&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd5f9922&quot;&gt;
&lt;p&gt;
梦到（略去 30 字）。梦醒后无言对着深夜的黑沉，一边庆幸只是梦一边又想现实和梦也没啥区别。
&lt;/p&gt;

&lt;p&gt;
还梦到了（略），在世界发生巨大灾难快要毁灭的时候，（略）。是什么灾难来着？我记得有洪水，还有被雨水淋久了后身上会冒出黑色的丝线样事物这个事情。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org02ab6d3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org02ab6d3&quot;&gt;2021-12-15 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org02ab6d3&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org829fabc&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org829fabc&quot;&gt;08:30 无梦&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org829fabc&quot;&gt;
&lt;p&gt;
没有做什么噩梦，真好。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6436972&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6436972&quot;&gt;23:30 畅谈&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6436972&quot;&gt;
&lt;p&gt;
和 WJ 畅谈了一番大数据啊、世界观啊、痛苦啊、自我啊、命运啊之类的，特别开心。她在我心目中一直是感性、对生活很有感受力那种人，我还以为她不会被类似的问题困扰，看来是想多了，这个年纪的人，大概都差不多。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org05c7d4d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org05c7d4d&quot;&gt;2021-12-17 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org05c7d4d&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org50ea528&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org50ea528&quot;&gt;19:30 回家&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org50ea528&quot;&gt;
&lt;p&gt;
开完组会跟领导说了我想提前回家的事情，领导没怎么为难就说没问题，还说「你回家了也没事做对不对」，挺放心我的啊，大概是去年大家有过 remote 的经历吧。额，其实我是想着提一个月应该不会同意然后等着讨价还价的，目标是 14 天来着，防止到家后被隔离 14 天。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6e4fe03&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6e4fe03&quot;&gt;23:06 记录&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6e4fe03&quot;&gt;
&lt;p&gt;
看到 WJ 发了新公众号文章，说「我喜欢用文字记录生活的点点滴滴，喜欢捕捉稍纵即逝的每一份美好时刻」，不过她的记录好像都是通过朋友圈来做的，我就发微信提醒了她下，并且推荐了 flomo 这个应用给她。后来还陆续聊了不少记录方面的想法，并且把我的 org-roam 笔记展示给她看了，这个时候才知道我把她的学校记成「兰州大学」是搞错了，其实是「西北民族大学」，不过也在兰州啦。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc23801a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc23801a&quot;&gt;23:14 香猪坊会议&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc23801a&quot;&gt;
&lt;p&gt;
上午的时候，K 问了一个问题：如果你不能做现在的工作，你还能干啥？
&lt;/p&gt;

&lt;p&gt;
我就说如果可以的话我还是想在计算机领域做事，顺势聊了一些我对 NLP 的想法。最后回到「不使用第一技能如何挣钱」这个问题上又讨论了一番，XKL 说她想写科幻小说或者图书管理员，K 说他想 BFS 也就是说探索更多领域的知识和技能，LY 说他想玩现代农业。最后发展到怎么做些不那么累又能养活自己的小生意，聊得很热闹。
&lt;/p&gt;

&lt;p&gt;
下班后相约到了香猪坊吃烤肉，继续聊了这个话题。K 到了我们办公室，我和 XKL、K 一起走路先去香猪坊的，路上还开玩笑说是不是可以做「外卖技术专家」，像外卖一样供别人下单然后半小时到一小时内上门帮忙解决 bug 哈哈哈哈……去了香猪坊后继续聊，不过吃饭时间太短了，八点开始点菜的吧，八点半就吃得差不多了。期间 XKL 提到她自己有记录一些点子，给我们说了几个。LY 说了 TeXPage 这个小众产品。
&lt;/p&gt;

&lt;p&gt;
XKL 还有点奇怪，说她这个年纪想这个问题还好说，我们几个都还比较年轻为什么也在想这个。我倒觉得很正常啦。另外我问 XKL 是不是每年理财就够生活了，她说是，生活没问题，所以会想去写科幻小说、图书管理员。
&lt;/p&gt;

&lt;p&gt;
我们决定之后可以继续就这个话题展开讨论。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org964e380&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org964e380&quot;&gt;2021-12-19 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org964e380&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org9216dd9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org9216dd9&quot;&gt;15:39 个人数据库&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org9216dd9&quot;&gt;
&lt;p&gt;
我想简单设计一下数据库，把自己的一些数据存储起来，比如说和朋友的聊天记录啦之类的。
&lt;/p&gt;

&lt;p&gt;
在鱼塘和大家聊了聊，好像没有什么特别合适的、开箱即用的工具，所以还是自己来写点代码做处理了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb6597b0&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgb6597b0&quot;&gt;2021-12-21 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgb6597b0&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgc408579&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc408579&quot;&gt;23:49 连手&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc408579&quot;&gt;
&lt;p&gt;
今天 K 生日 —— 据他说身份证上是明天 —— 下班后四个人去了连手吃烤串。据说「连手」是兰州话「朋友」的意思。
&lt;/p&gt;

&lt;p&gt;
边吃边继续聊小生意的事情。
&lt;/p&gt;

&lt;p&gt;
LY 存款不多，XKL 有房所以肯定是不缺了，K 说他的存款也不少了，躺着的话在北京还会有一点焦虑但如果回兰州就够够的了。
&lt;/p&gt;

&lt;p&gt;
XKL 说她主要是想要躲起来以应付接下来可能发生的社会变化，以及生活上钱也够了所以可以找点自己想做的事情做。
&lt;/p&gt;

&lt;p&gt;
K 没说太多他的目的和想法，不过我们聊过多少钱才够自由这个事情，我当时比较想强调自由和钱关系不是那么大了抬了不少杠，被 K 说我是在使用稻草人谬误，哈哈，是得反思下，我讲话有时候也没啥逻辑，也会为了印证自己的观点而强行使用证据和说话方式。
&lt;/p&gt;

&lt;p&gt;
LY 的想法和我差不多，就是想做点有价值的事情。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org091d4bc&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org091d4bc&quot;&gt;2021-12-22 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org091d4bc&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org7c7eabb&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org7c7eabb&quot;&gt;14:12 二胎&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org7c7eabb&quot;&gt;
&lt;p&gt;
去贵凤凰吃饭，边上一男二女在聊二胎话题，男的说他媳妇想生二胎但他不想，因为之前陪产过觉得太痛苦了；二女中的一个说这个其实还好，虽然痛但也就很短一段时间，如果要生二胎她觉得自己是能忍受的，而她不想生二胎是担心两个孩子之间感情分配不均衡。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org93be1ec&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org93be1ec&quot;&gt;2021-12-24 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org93be1ec&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org79c79c6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org79c79c6&quot;&gt;23:44 平安夜&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org79c79c6&quot;&gt;
&lt;p&gt;
下了班，饭罪委员会加上姨夫一起去了零公里，车上姨夫给店里打电话问要不要等位，对方说今天店里人还比较少，因为吃西餐的人会比较多，哈哈。
&lt;/p&gt;

&lt;p&gt;
我们到了零公里后，点了酒都肥肠、李庄白肉、叙洲包浆豆腐、花生浆菜豆腐、酸豆角烧魔芋、燃面几个吃过的菜，还点了鲜锅兔、回锅排骨、腊味拼盘、猪鼻筋等几个新菜。由于有姨夫在，我们闲扯多聊了会，比往常吃完花了更多的时间，挺开心的。聊了点姨夫的感情生活，得知他已经和上海的那位分手了，说发愁之后去哪里，回家长期住着估计也不喜欢但出去住现在也没什么名目了之类的。
&lt;/p&gt;

&lt;p&gt;
话说，到店后注意到 XKL 涂了口红，头发也明显打理过，还戴了一条红白的围巾，美美的。
&lt;/p&gt;

&lt;p&gt;
吃完坐 XKL 的车到北土城，然后回家，见到一个姑娘拿着一支花和一个装在袋子里的苹果，不知道是朋友还是公司送的。路上看到表弟发给我的 C 语言问题的消息，我问他说平安夜有没有去玩，说学校不让过洋节，加上太冷了同学也不愿意出去，哈哈。
&lt;/p&gt;

&lt;p&gt;
23:22 的时候跟 WJ 简单说了声平安夜快乐，得到了回应。往常可能是她先说的，这次我抢个先吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga4a9f9c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga4a9f9c&quot;&gt;2021-12-27 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga4a9f9c&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgdd8e0e3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgdd8e0e3&quot;&gt;22:26 关店&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgdd8e0e3&quot;&gt;
&lt;p&gt;
得知简阳羊肉汤在年后就要关店了，老板说这种品类的店也就冬天生意稍好一点，其他季节不行，最近两年经济又不好，房租又涨，没有新客老客也在流失，实在是开不下去了。还挺遗憾的，一家开了 9 年的老店，就要这样没了。结帐的时候继续跟老板闲聊，老板说孩子现在 10 岁了，关店之后就回家照顾孩子，在家里咋生活没问，总是能找到路子吧，做点零工、小生意，总是能生活下去的。
&lt;/p&gt;

&lt;p&gt;
吃饭的过程中，隔壁桌抽烟被 LY 制止了，隔壁桌性格也还不错，后来问 LY 说想抽一口行不行，被 LY 和 XKL 严辞拒绝了，还挺有意思的，看 LY 扎了头发就问 LY 是不是做艺术的，笑死。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org053bbdf&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org053bbdf&quot;&gt;22:29 裁员&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org053bbdf&quot;&gt;
&lt;p&gt;
之前听 K 说过他们公司在缩减运营人员，没想到下午的时候 WR 和姨夫一起过来，说被裁掉了 —— 技术就剩了四个人，公司产品被认为是错误的方向，运营一直做不上去，因此不再做了，K 还留着继续做剩下一个业务线，同时公司会讨论新的方向之后继续吧。
&lt;/p&gt;

&lt;p&gt;
就挺突然的……
&lt;/p&gt;

&lt;p&gt;
WR 走前送了一个卡比兽和妙蛙种子的手办给我和 LY，一人一个。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge2de828&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge2de828&quot;&gt;22:38 体检&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge2de828&quot;&gt;
&lt;p&gt;
体验预约我一直拖延，今天一看各个地方都没号了，奇怪的是望京分院明天有号，于是只好约了明天望京分院的，得早起了哇……
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc186a90&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgc186a90&quot;&gt;2021-12-28 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgc186a90&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgddefcdc&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgddefcdc&quot;&gt;11:17 体检&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgddefcdc&quot;&gt;
&lt;p&gt;
七点半起来了，也没有想象的困难，甚至觉得有点精神。坐地铁到望京东C口出去，然后走了一公里多到了慈铭，到的时候是九点过几分。人并不多，先抽了血，然后检查耳鼻喉，先问我鼻子流不流鼻涕，我就说我有鼻炎，随便看了看说「有点鼻炎」这他妈不是废话嘛……做完耳鼻喉做内科，就用停诊器听了听心肺，完了医生说我有点紧张，我笑笑出门；然后排队做心电图，这种等待的感觉真好，就放心刷着手机，什么工作啊社会啊都不用想，做完后给隔壁医生看就扫了一眼说「正常」，嗯，挺好的；然后去做彩超，又一阵好等；做完彩超去做了胸部CT，然后做血压、身高、体重一般检查，最后是去卫生间留了半盒尿。剩下有一些项目我放弃了，下一楼还了钥匙领了鸡蛋走人。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge4bfc09&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge4bfc09&quot;&gt;2021-12-30 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge4bfc09&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgd4c1100&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd4c1100&quot;&gt;23:15 升21转&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd4c1100&quot;&gt;
&lt;p&gt;
这个可转债今天上市就涨 35% 导致停牌，快三点的时候差点忘了卖掉，还好 ZY 过来找我聊这个，才想起来把它卖掉了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf613402&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf613402&quot;&gt;2022-01-01 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf613402&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgbdf273d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgbdf273d&quot;&gt;12:44 同理心&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgbdf273d&quot;&gt;
&lt;p&gt;
老徐发了一条朋友圈，大意是宁波有疫情回不去了，我没想太多，发了一条「我明天回家」，然后被他怼了。看到他的回复我其实很不舒服，不过回头一想，他看到我的留言肯定也是不舒服的，以牙还牙把这种不舒服还给我，很合理。我开始自认为「没有想太多」，但仔细想想，我这条留言，不就是看到别人回不了家然后觉得自己回得了家，进而产生了一些优越感和窃喜吗？
&lt;/p&gt;

&lt;p&gt;
他人是一面镜子，可以很好地照出自己的样子。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4f37d34&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4f37d34&quot;&gt;20:47 退货&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4f37d34&quot;&gt;
&lt;p&gt;
前些天买的一件衣服，尺码不对，于是我发起退货了，京东说今天 15:00 到 21:00 会来取件，然后我一整天都在担心这个事情，就是那种一件事情没有完成的状态，很难受。
&lt;/p&gt;

&lt;p&gt;
就在刚才，给我打电话了，问我在不在家，我说在。过了没一会，敲门声响起来，我把装好的衣服递出去，问「要不要检查下什么」，京东小哥乐呵地说道「我还能不相信你嘛」，接着说「嘿嘿，我又回来了……取件还是我取」，我看他那么自来熟，但戴着毛茸茸的套头的帽子，实在是辨认不出来是哪位京东小哥，只好掩饰着尴尬说「我还以为你不来了呢，都八点多了」。「哪能不来呢，别人的件我都没取先来取你的了」，他这样说道，依然是乐乐呵呵的，然后拿着件走了。
&lt;/p&gt;

&lt;p&gt;
他好开心的样子，看得我也开心了起来。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6795a12&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org6795a12&quot;&gt;2022-01-02 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org6795a12&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgb1b1eea&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb1b1eea&quot;&gt;06:17 停运&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb1b1eea&quot;&gt;
&lt;p&gt;
四点十分起了床，洗漱收拾完毕，到五点左右出门，约的出租车就停在了小区门口，师傅放倒了椅子在睡觉，我敲窗户把他叫醒，出发往西站去。我昨天看地图说要一个小时到，师傅说只要半小时，大概是我昨天看的时候是按当时的路况来估计的。
&lt;/p&gt;

&lt;p&gt;
和师傅聊天，聊疫情，我先用最新的研究给师傅灌输了一波焦虑，感叹了一番。师傅问我是不是出差，我说怕回不去提前回家，于是就聊到过年的事情，师傅说现在过年没有年味，以前就拉客都能感受到，先是农民工大堆回家然后是学生们回家，都热热闹闹的。还说到他小时候过年的一些风俗：一个什么火，说是劈好柴在院子里像篝火一样点燃，火烧得越旺越高就意味着新年生活越好；说他父亲会拿个瓢盛着醋在家里转着洒来辟邪 —— 其实是能起到消毒作用吧；说他哥会拿锤子把砖头敲成球，不过这个没听太细，不知道是他们家普遍的风俗，还是小孩子的玩耍；还说他们用黄米（黄米是什么米不懂）做成面蒸馍吃，以前没东西吃这个就算好粮食了，现在这么做来吃的少了。我也讲了我们初一迎神和捣年糕的风俗。
&lt;/p&gt;

&lt;p&gt;
到西站五点半，验了健康码安检后进站，却在刷身份证进站时被告知我买的车已经停运，给我整懵了。工作人员让我去问售票处，我去了，售票处说列车已停运只能给我退钱了，然后说可以帮我看下有没其他车，最后找到一个在南昌中转的路线，中间就隔半个小时，要比原来的车便宜150、晚3个小时出发晚一个半小时到，反倒更快？不过更快也没啥意义，我这都已经在火车站了。生活真是充满了意外呀。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org9b67a11&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org9b67a11&quot;&gt;11:50 九江农业号&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org9b67a11&quot;&gt;
&lt;p&gt;
火车叫九江农业号，是收益不行所以开始出售广告位来赚钱吗？车厢人挺少的，一大半都是空的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga1ad36b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga1ad36b&quot;&gt;18:02 南昌&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga1ad36b&quot;&gt;
&lt;p&gt;
在南昌换乘，有便捷换乘路线，直接到候车大厅，不用出站，还挺好的。等了一会后进站，到站台后才明白工作人员强调蓝色地标是什么意思，车还没来，只能靠地上的标识确认哪里是门的位置以及是几号门，而这些位置上用不同颜色标着不同的数字，我是5号车厢，找到蓝色的数字5的地标就好了。上了车，我的位置是11A，靠窗，不过晚上了啥也看不见没啥好的，现在倒是觉得C和F这种靠过道的位置好，走动方便哇。B位上是一个姑娘，染了一头鲜艳的橘色头发，挺惹眼的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc48b2c0&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc48b2c0&quot;&gt;20:13 陪伴&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc48b2c0&quot;&gt;
&lt;p&gt;
旅途中又和 ZQL 聊了聊，得知他女朋友单位不让离京，我说那你不如不回家好了，陪陪妹子啊，然后他说奶奶身体不好之前还进了ICU，虽然现在转轻症了，但感觉老人时间不多了，还是想陪一陪。都不容易。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org184cc7e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org184cc7e&quot;&gt;23:00 接站&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org184cc7e&quot;&gt;
&lt;p&gt;
昨天和家里打电话的时候，姐姐和姐夫正好在我家，听到了电话，于是姐夫开了车来接站。一路上闲聊，发现姐夫还真是交游广泛，对于我初中时那些老师的去向都很清楚，我随口说了一句是不是哪个老师去了教育局，然后他连报了好几个我初中学校老师的名字，太厉害了。因为第二天还要去做核酸，就在我姐夫家过夜了，姐姐和孩子都在，我就陪着聊天聊到 10 点多，感觉我还挺能聊的了，不知道从哪学的。外甥女去一中补课了，现在孩子压力真大。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org7851410&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org7851410&quot;&gt;2022-01-03 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org7851410&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orga4ddf18&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga4ddf18&quot;&gt;10:00 核酸检测&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga4ddf18&quot;&gt;
&lt;p&gt;
在姐夫家吃完早饭 —— 米粿汤后，坐了会就出门去人民医院做核酸了，结果吧，江西搞的那个什么赣通码直接给我整个报错，还好国家平台健康码能用。进医院后挂了个号，出来在门口角落的检测亭里做了咽拭子检测，没几个人，后来一查，说是「愿检尽检」，也就是说我不做检测直接回家，问题也不大。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org066b10d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org066b10d&quot;&gt;22:00 家（补）&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org066b10d&quot;&gt;
&lt;p&gt;
做完核酸后，姐夫送我到家，坐着聊了挺久的天，但是没有及时记录，我已经记不清他是不是在我家吃午饭的了，以及午饭吃了啥，我也不记得了。
&lt;/p&gt;

&lt;p&gt;
天气很好，有太阳，很温暖，我站在门口晒太阳，一位邻居路过看到了我，就过来聊了会天，聊的什么我也忘记了。
&lt;/p&gt;

&lt;p&gt;
好几个邻居见到我都说我高了，30 岁的人了，还怎么长高啊？后来我妈说，可能是因为我瘦了所以看着显高了一点，似乎有点道理。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5c4c139&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org5c4c139&quot;&gt;2022-01-07 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org5c4c139&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org063f80b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org063f80b&quot;&gt;23:00 相亲（补）&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org063f80b&quot;&gt;
&lt;p&gt;
大概是之前和父母吐露过心结，他们觉得我终于开始积极思考感情问题了，回来后找到亲戚让介绍姑娘，下班后，跟我说了一个姑娘的状况，说对方说了，不用长辈安排，我们自己加联系方式去碰面。给了我一个手机号和姓名，我加微信加不上，于是发了一段长长的短信过去，作为第一次相亲活动，我决定记录一下留作纪念：
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;org8b99814&quot;&gt;
你好，我是你邻居XXX介绍来认识的，我叫XXX。按照安排，明天咱们得聊一面，不嫌弃的话找个地方我请你喝点东西，不过地方可能得麻烦你找一下了，我在家时间少各个地方都熟悉。不知道你对这种活动什么态度，我头次参加，有点忐忑，不过觉得能聊得来的话不管最后怎么样多个朋友也好。如果你比较没兴趣也可以先告诉我，我不介意；如果有兴趣多聊一点的话，可以加我微信，这个手机号就行。
&lt;/pre&gt;

&lt;p&gt;
过了会对方微信加了我，说「发短信也太复古了吧」，经我提醒，她才意识到自己把通过手机号添加好友的设置关掉了。简单聊了聊，约了第二天见面。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgdf80847&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgdf80847&quot;&gt;2022-01-08 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgdf80847&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org9772a9b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org9772a9b&quot;&gt;16:00 相亲（补）&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org9772a9b&quot;&gt;
&lt;p&gt;
吃完早饭收拾了一下就出门了，坐车去县城，车上的时候我觉得特别烦躁。我到了后，对方提议说在她家附近体育馆碰头，我到了后等了会，见到了对方。
&lt;/p&gt;

&lt;p&gt;
人挺好看的，也很健谈，我们就绕着体育馆外面的路边聊边说，她是学音乐教育的，然后也学了舞蹈，有编制，教小学的音乐和语文，聊了基本状况后就说一些学校的事情，边走还边给我介绍周围的建筑之类的；我的话就聊聊计算机和互联网，也被问到收入有多少的。回头一想，其实没有聊什么有价值的东西，基本就是了解各自的状况然后没话找话。到 12 点决定去吃个火锅，她地头熟，打了车去一个重庆火锅店，那重庆火锅点菜我可是当仁不让了，点上了炸腐皮、酥肉、贡菜等一些有特色的东西，其他的肉啊什么的也点了一些，不过最后很失望，贡菜软趴趴、酥肉里面全是肥肉、冰粉太甜了，最后吃了 248，这价钱我在壹圣元能吃得好得多啊。
&lt;/p&gt;

&lt;p&gt;
吃完饭我就不准备继续下去了，因为她现在是在家里当老师，想考到江西其他地方去，但并不愿意出江西省，而我一两年内是不太可能回江西的，这是个很实际的问题。于是告别然后去我姑妈家做了下汇报（因为是她介绍的），然后就回家了。
&lt;/p&gt;

&lt;p&gt;
回到家后，我和爸妈也摊开来聊了下，首先是表明了态度，我会去积极和人交往争取找到自己合适的人，但同时也希望他们不要急，因为我还是想先把心结解决。我觉得这个坦诚是有成果的，毕竟我这个心结，多多少少也有他们的原因在，说是我的心结，其实也是他们的心结。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6880170&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6880170&quot;&gt;22:00 共鸣（补）&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6880170&quot;&gt;
&lt;p&gt;
去相亲的路上特别烦闷，就直接在微信的订阅号助手上，把 2021 年总结编辑好发了出去，顺手还发到了 E 大粉丝群里，收获了不少赞扬和肯定，有一个人在我的一篇公众号文章下的留言最让我感动：
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;org7e8f67e&quot;&gt;
不知道为什么，看这些闲言碎语有一种世界上另一个我的感觉，莫名其妙的想哭想笑
&lt;/pre&gt;

&lt;p&gt;
我坚信平凡的生活点滴才是最能打动人的东西，我坚信将来的我也能被我曾经这些平凡的生活记录所打动，我还会继续记录下去。
&lt;/p&gt;

&lt;p&gt;
另外，文章发到群里后，又认识了几个新朋友，开心。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org91f649f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org91f649f&quot;&gt;22:00 畅谈（补）&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org91f649f&quot;&gt;
&lt;p&gt;
看到 LWL 关注了我的公众号，就去打了个招呼，没想到一下就聊了特别特别多，开心。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb84a0d9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb84a0d9&quot;&gt;22:00 理想伴侣（补）&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb84a0d9&quot;&gt;
&lt;p&gt;
WJ 问我：你憧憬爱情吗？有想过理想伴侣吗？
&lt;/p&gt;

&lt;p&gt;
我不假思索地回答到：我憧憬互相理解互相尊重互相促进的关系，是不是爱情倒没太在意。
&lt;/p&gt;

&lt;p&gt;
我所遭受过的痛苦，绝大部分都源于人和人之间互相不理解，所以我会这样想吧，也许我是错的，这些都是需要验证的。我疯狂地做记录分析自己，其实也有一部分动机是这个，因为对自己的不理解同样是痛苦的来源之一。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org43465b4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org43465b4&quot;&gt;2022-01-09 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org43465b4&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org3749b47&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3749b47&quot;&gt;21:52 遗忘&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org3749b47&quot;&gt;
&lt;p&gt;
开始整理这一周发生的事情，我记得我似乎和爸妈聊了很多很多，但到底聊了啥啊，完全不记得了。疏于记录就是这种下场。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3857d10&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3857d10&quot;&gt;23:55 畅谈&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org3857d10&quot;&gt;
&lt;p&gt;
又和 LWL 畅谈了一番，感觉很开心。她说「我们加微信这么久好像啥也没聊过。可昨天和你聊天，突然没了之前那种心态，感觉能聊的东西就多了」，我觉得这是因为，19 年加微信的时候有一个长辈介绍的因素在，就觉得不自然很奇怪，而这次我们开始聊上则是自然发生的，我并没有什么过多的想法，我只是想多个朋友，自然就能聊得开，反倒是这两天其他长辈、朋友介绍的人，大家都显得一副急匆匆的样子 —— 我们快点成为朋友吧、快点见见面吧、快点看看是否合适吧，我不喜欢这样。
&lt;/p&gt;

&lt;p&gt;
LWL 问：那你需要的是朋友？
&lt;/p&gt;

&lt;p&gt;
对，我想我需要的是朋友。也许我这种想法，还是有对亲密关系的恐惧？我不知道。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/11/15-2021/12/01)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/12/01/lifelog.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/12/01/lifelog</id>
    <published>2021-12-01T00:00:00+00:00</published>
    <updated>2021-12-01T00:00:00+00:00</updated>
    <description>
    
      <p>近期生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga22a028&quot;&gt;2021-11-15 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org2ebef16&quot;&gt;10:36 内推成功&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8f83890&quot;&gt;2021-11-18 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org74678b9&quot;&gt;22:41 误区&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4d38e69&quot;&gt;2021-11-19 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org5f44530&quot;&gt;23:00 零公里&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org38b2e3c&quot;&gt;2021-11-20 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgd948a6a&quot;&gt;18:00 表弟近况&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge5d4dc3&quot;&gt;2021-11-21 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org1ff7523&quot;&gt;11:42 ENS空投&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org90d8772&quot;&gt;16:20 GPT-3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org0212c67&quot;&gt;18:30 老同学&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org620e4ae&quot;&gt;2021-11-22 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org4b0a4bc&quot;&gt;21:53 再遇&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgeca34d4&quot;&gt;2021-11-23 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org56c350b&quot;&gt;08:28 噩梦&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf363bff&quot;&gt;2021-11-24 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org153c0f4&quot;&gt;08:30 排挤&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org20f349c&quot;&gt;12:05 失策&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgddff6a2&quot;&gt;21:30 WY&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org701a520&quot;&gt;2021-11-25 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org08e53a6&quot;&gt;21:00 光影&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga299dbe&quot;&gt;21:30 感情&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb735378&quot;&gt;23:30 历史&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org25ece03&quot;&gt;2021-11-26 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgf03d2da&quot;&gt;23:36 脆弱&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgcd83568&quot;&gt;2021-11-27 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgebb7cb4&quot;&gt;19:27 花钱&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgbc75cb0&quot;&gt;2021-11-30 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org829cd67&quot;&gt;23:00 图形与衬底&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org86b4acd&quot;&gt;2021-12-01 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgbab66a0&quot;&gt;22:20 杨平兄弟&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga22a028&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga22a028&quot;&gt;2021-11-15 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga22a028&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org2ebef16&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2ebef16&quot;&gt;10:36 内推成功&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2ebef16&quot;&gt;
&lt;p&gt;
之前一个 ZCH 说被裁了找我推荐，我看履历和我们公司的一个新业务方向还蛮契合的，就顺手给 HR 和领导了，上周接了 offer，这周就来报道了。这是我第一个成功的内推，就不知道奖励啥时候会下来。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8f83890&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org8f83890&quot;&gt;2021-11-18 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org8f83890&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org74678b9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org74678b9&quot;&gt;22:41 误区&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org74678b9&quot;&gt;
&lt;p&gt;
我觉得之前可能陷入了误区里，想着用 org-mode 完成结构化知识的存储、展示、编辑和使用，但其实没必要，存储完全可以放在 Neo4j 或者关系数据库里，org-mode 可以作为一个编辑和展示端就够了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4d38e69&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4d38e69&quot;&gt;2021-11-19 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org4d38e69&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org5f44530&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5f44530&quot;&gt;23:00 零公里&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5f44530&quot;&gt;
&lt;p&gt;
又去吃零公里啦，点了这些东西：筠连椒麻鸡、酒都肥肠、芙蓉鸡豆花、叙洲包浆豆腐、青笋烧肚条、油渣小白菜、缠丝肉、鱼香肉丝。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org38b2e3c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org38b2e3c&quot;&gt;2021-11-20 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org38b2e3c&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgd948a6a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd948a6a&quot;&gt;18:00 表弟近况&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd948a6a&quot;&gt;
&lt;p&gt;
表弟一个多月没来问我问题了，问了问近况，说是进了老师的实验室，在各种参加比赛，说了几个，我只知道蓝桥杯。看起来前途大好啊，真好。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge5d4dc3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge5d4dc3&quot;&gt;2021-11-21 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge5d4dc3&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org1ff7523&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1ff7523&quot;&gt;11:42 ENS空投&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1ff7523&quot;&gt;
&lt;p&gt;
才知道 ENS 在空投，但要求是 10.31 之前在 ENS 上注册过 .eth 域名，并且根据时间来发放，错过了哇。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org90d8772&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org90d8772&quot;&gt;16:20 GPT-3&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org90d8772&quot;&gt;
&lt;p&gt;
OpenAI 开放了 GPT-3 的 API，然而，不支持中国地区。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0212c67&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org0212c67&quot;&gt;18:30 老同学&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org0212c67&quot;&gt;
&lt;p&gt;
等理发的时候无聊找一位老同学聊了聊，得知他这周五刚答辩完，明年一月份拿到毕业证书，就正式博士毕业了，不容易啊。问他毕业后的打算，说是准备进公司赚点钱，挺好的，计算机的博士，出来的待遇会很不错的。最后我还开玩笑说看看明年六月份我这房子到期后有没有合租的机会，虽然是开玩笑，如果确实有机会的话也还不错。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org620e4ae&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org620e4ae&quot;&gt;2021-11-22 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org620e4ae&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org4b0a4bc&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4b0a4bc&quot;&gt;21:53 再遇&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4b0a4bc&quot;&gt;
&lt;p&gt;
下班，上地铁左下后看到对面就是 WY，约了周三吃饭。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgeca34d4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgeca34d4&quot;&gt;2021-11-23 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgeca34d4&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org56c350b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org56c350b&quot;&gt;08:28 噩梦&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org56c350b&quot;&gt;
&lt;p&gt;
做了一晚上噩梦，好累好烦啊。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf363bff&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf363bff&quot;&gt;2021-11-24 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf363bff&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org153c0f4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org153c0f4&quot;&gt;08:30 排挤&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org153c0f4&quot;&gt;
&lt;p&gt;
梦到全办公室的人联合起来排挤某个人，不知道这是大脑在快速眼动睡眠周期内拿我哪些记忆和想法加工出来的离奇故事。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org20f349c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org20f349c&quot;&gt;12:05 失策&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org20f349c&quot;&gt;
&lt;p&gt;
啊，发现 ZZ 是下午送餐，然后我以为是中午把和 WY 的饭约到了晚上七点……希望七点前能送到。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgddff6a2&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgddff6a2&quot;&gt;21:30 WY&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgddff6a2&quot;&gt;
&lt;p&gt;
和 WY 去管氏翅吧碰了头，聊了一个多钟头。互相聊了聊工作生活的近况，又七扯八扯聊了投资、算命、游戏、价值观，还给我介绍姑娘来着……挺久没见过的人这么聊一聊，感觉还挺好的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org701a520&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org701a520&quot;&gt;2021-11-25 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org701a520&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org08e53a6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org08e53a6&quot;&gt;21:00 光影&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org08e53a6&quot;&gt;
&lt;p&gt;
死去的、错过的那些人，就像身后的光，我看不到他们，但可以通过自己的影子感受到我仍然和他们联系在一起。带着这些影子活下去，也是意义之一。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga299dbe&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga299dbe&quot;&gt;21:30 感情&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga299dbe&quot;&gt;
&lt;p&gt;
下午 WY 来问我要照片，并问我「你现在有进入一段感情的打算没」。我真的没有认真想过，而且呀，我在维护关系（不管是亲密关系还是朋友关系）这件事情上真的很白痴，如何表达好感和关心、如何保持联系与距离、如何建立信任与尊重……光是想象就已经让我觉得很麻烦了……
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb735378&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb735378&quot;&gt;23:30 历史&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb735378&quot;&gt;
&lt;p&gt;
我从 2016 年 6 月开始手工记账直到今年年初，积攒了大量历史数据，这两周在尝试把这些历史数据也纳入到 beancount 的管理中来，今天总算初步完成了历史数据和今年数据的融合、校验，至少数字上没有什么差错了，当然在这个过程中不可避免地开始对支出做细分和分组，今年的新数据的收支类型还没完全调整好。现在看 2016 的时候我的钱真是少的可怜，不过那点少得可怜的钱也从那个时候一直再慢慢地变多，看着那条爬升的线感觉很开心。接下来就可以把这些数据放到 Keysersoze 里得到收益率的分析结果了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org25ece03&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org25ece03&quot;&gt;2021-11-26 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org25ece03&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgf03d2da&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf03d2da&quot;&gt;23:36 脆弱&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgf03d2da&quot;&gt;
&lt;p&gt;
人和人的关系真脆弱，不知道什么时候一两句话就会导致裂痕的出现。我无法揣测其他人的心思，但希望自己能做得好一些，比如说我现在还是会在某些时候表现出傲慢、冷漠的一面，有时候心情不好、压力过大也会把情绪带给别人。目前我起码能做到时时自省，在事后不久的时候觉察出自己的不对。
&lt;/p&gt;

&lt;p&gt;
不过话说回来，和我走散的人，好像都不是因为闹僵了，而是因为我不去保持联系。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgcd83568&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgcd83568&quot;&gt;2021-11-27 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgcd83568&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgebb7cb4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgebb7cb4&quot;&gt;19:27 花钱&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgebb7cb4&quot;&gt;
&lt;p&gt;
总算把 2016 年 6 月至今的历史账单都梳理清楚了，下面这张图是这些年的支出状况（略去了家庭支出和每年春节的长途往返支出）：
&lt;/p&gt;


&lt;div id=&quot;orge17f60c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/expenses_since_2016.png&quot; alt=&quot;expenses_since_2016.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;餐饮一共花了 10 万，平均每天 50，虽然我觉得自己吃得还不错，不过这个均值确实看着有点低，主要是我在吃饭之外很少有别的餐饮开销&lt;/li&gt;
&lt;li&gt;很少去医院，所以医药这块花销很少，不过我不怎么运动所以花销少完全是因为还年轻吧……&lt;/li&gt;
&lt;li&gt;发红包那个支出，一大半是份子钱，我好亏哦&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgbc75cb0&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgbc75cb0&quot;&gt;2021-11-30 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgbc75cb0&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org829cd67&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org829cd67&quot;&gt;23:00 图形与衬底&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org829cd67&quot;&gt;
&lt;p&gt;
被工作上的烦心事搞得心情很差，虽然我知道那些都是正常的、合理的事情。下班路上，随着这种厌烦情绪的滋生，仿佛为了对抗它一样，另外一种渴望也壮大了起来，想起了我想做的一些事情。正因为痛苦，欢乐才有意义，他们是一体两面的事物。
&lt;/p&gt;


&lt;div id=&quot;org86eeb42&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/escher_two_birds.jpg&quot; alt=&quot;escher_two_birds.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org86b4acd&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org86b4acd&quot;&gt;2021-12-01 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org86b4acd&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgbab66a0&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgbab66a0&quot;&gt;22:20 杨平兄弟&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgbab66a0&quot;&gt;

&lt;div id=&quot;org16886ac&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20211201_food.png&quot; alt=&quot;20211201_food.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
三位戴表人士和一名普通群众去了上周五没能吃上的杨平兄弟烤牛肠，再次在那老旧的大楼里迷路，错综复杂的大楼真的很有城市探险的感觉。点了一个三人套餐，量不太够，后面又加了一份牛大肠、一份嫩豆腐汤和一份海鲜饼。牛肠不差但并没有特别惊艳吧，主要是比较贵了，生拌牛肉和嫩豆腐汤非常赞。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/11/01-2021/11/14)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/11/14/lifelog.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/11/14/lifelog</id>
    <published>2021-11-14T00:00:00+00:00</published>
    <updated>2021-11-14T00:00:00+00:00</updated>
    <description>
    
      <p>近期生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga0716c5&quot;&gt;2021-11-01 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org170eb7f&quot;&gt;11:00 新衣服&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3a41dfe&quot;&gt;2021-11-02 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org883261f&quot;&gt;18:00 体检&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org82e7535&quot;&gt;22:31 陌生人&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org37bcea0&quot;&gt;22:42 美团买菜&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2ca1e6e&quot;&gt;2021-11-04 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org7ba01f1&quot;&gt;22:35 玉流馆&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgcad3102&quot;&gt;2021-11-06 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgf4156c9&quot;&gt;11:30 疫苗&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc28846d&quot;&gt;16:30 风控&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org51f3999&quot;&gt;18:30 雪&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org41c9d2d&quot;&gt;2021-11-09 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orge053da5&quot;&gt;17:30 拉新&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org26c102b&quot;&gt;18:52 第三历史决议&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgef20773&quot;&gt;23:27 工具&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf669188&quot;&gt;2021-11-11 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga9af2d7&quot;&gt;21:10 煎蛋&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3425d27&quot;&gt;21:20 危&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org637236c&quot;&gt;2021-11-12 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org1eb755a&quot;&gt;10:10 冷漠&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga8f70ee&quot;&gt;19:00 批评&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga6064c3&quot;&gt;23:50 陌生人&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga2eb481&quot;&gt;2021-11-13 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org64ea871&quot;&gt;20:45 外甥女&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org88448c3&quot;&gt;2021-11-14 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org686fef1&quot;&gt;17:33 日落&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga0716c5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga0716c5&quot;&gt;2021-11-01 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga0716c5&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org170eb7f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org170eb7f&quot;&gt;11:00 新衣服&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org170eb7f&quot;&gt;
&lt;p&gt;
咦，买新冲锋衣啦，这个颜色很合适哦 —— 上周也穿了新衣服啊，哼。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3a41dfe&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3a41dfe&quot;&gt;2021-11-02 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3a41dfe&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org883261f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org883261f&quot;&gt;18:00 体检&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org883261f&quot;&gt;
&lt;p&gt;
公司给我们发了导诊册，说我们可以开始预约体检了，说起来上次体检都不记得是哪年了，总之好几年没有体检过了。看了下体检项目，有点高端，除常规项目外，居然还有癌症筛查和基因检查。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org82e7535&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org82e7535&quot;&gt;22:31 陌生人&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org82e7535&quot;&gt;
&lt;p&gt;
下班回去换到 8 号线上后，习惯性的玩着手机把自己和其他人隔绝开来，冷不丁的对面一位四十到五十的大姐看着我问到「这趟车最晚到几点啊」，也许并不是问我而是看着车门上方的运行路线在自言自语，但我刚好位于对方的视线区域于是下意识地回答了下，她后面重复了几次这个问题，中间夹杂着几个我没听过的地名，也许是想去那个地方？一场莫名其妙的与陌生人的对话。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org37bcea0&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org37bcea0&quot;&gt;22:42 美团买菜&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org37bcea0&quot;&gt;
&lt;p&gt;
快到小区的时候，被路边美团买菜的推广人员叫住了，说他今天指标完不成，央求我扫个码，那会不赶时间，想着薅个新用户羊毛也不错，就帮他完成了一个指标，买了几个西红柿、一盒牛奶、一个柚子，然后送了四个鸡蛋接着一分钱换了一小箱水，回来看还有满 29 减12 的券，还行吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2ca1e6e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org2ca1e6e&quot;&gt;2021-11-04 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org2ca1e6e&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org7ba01f1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org7ba01f1&quot;&gt;22:35 玉流馆&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org7ba01f1&quot;&gt;
&lt;p&gt;
中午聚餐，吃了闻名已久的玉流馆，服务员果然都很漂亮，但是菜味道一般，至少是匹配不上价钱的。中午人比较少，据说晚上会有节目表演。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgcad3102&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgcad3102&quot;&gt;2021-11-06 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgcad3102&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgf4156c9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf4156c9&quot;&gt;11:30 疫苗&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgf4156c9&quot;&gt;
&lt;p&gt;
终于打了第一针新冠疫苗了。接种点就在我小区附近，走路 5 分钟就到了，排队排了半个多小时，打完 10:20 了，在留观区坐到 10:50 多没啥反应就回了。出来的时候外面已经在下着小雨了，没带伞，把羽绒服的帽子戴起来回去了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc28846d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc28846d&quot;&gt;16:30 风控&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc28846d&quot;&gt;
&lt;p&gt;
之前接到自称是火币客服的电话，说我的账户触发了风控，让我和他们风控部分的人对接解除风险后才能正常交易，当时在上班就没应付了两句说以后我再去看。下午又接到了这个电话，我还是想着年底才清退呢，我干嘛非得今天解决，就跟对方说行啦我知道了之后我再处理吧，结果对方说什么排号排到了我这里让我尽快处理最好就马上处理，让我下了个叫什么 TeamPro 的协作软件，我下完后开始觉得不对，这个软件明显和火币没什么关系啊，问对方对方也没正面回答就是翻来覆去说你赶快处理，我想着不是说不能交易嘛，马上打开火币提现了 100 个 USDT，告诉对方我能正常交易啊，对面很震惊说不可能啊，只能说演得真好吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org51f3999&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org51f3999&quot;&gt;18:30 雪&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org51f3999&quot;&gt;
&lt;p&gt;
到晚上六点多的时候，已经下起雪来了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org41c9d2d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org41c9d2d&quot;&gt;2021-11-09 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org41c9d2d&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orge053da5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge053da5&quot;&gt;17:30 拉新&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge053da5&quot;&gt;
&lt;p&gt;
接到一个电话让我加一个股票交流群，很直白就说是在完成拉新任务，让我在群里待两天就行，给我 3 块钱红包，爽快。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org26c102b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org26c102b&quot;&gt;18:52 第三历史决议&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org26c102b&quot;&gt;
&lt;p&gt;
百年党史革命、建设、改革的豹尾已经收官，全面建设社会主义现代化国家的龙头正在开启。中华民族迎来了从站起来、富起来到强起来的伟大飞跃，实现中华民族伟大复兴进入了不可逆转的历史进程。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgef20773&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgef20773&quot;&gt;23:27 工具&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgef20773&quot;&gt;
&lt;p&gt;
将自我看作工具的一个好处，是可以摈弃掉各种主观偏见，借用自己熟悉的领域知识（于我而言是计算机科学）来建立相对稳固、自洽的认知体系。比如说我目前是这样看待自己的：我是一个用庞大的编码量编制出来的智能系统，并经过了 30 年脏乱的数据训练，由于编码上有大量的不良设计和错误，加上训练数据质量不够好导致存在偏见，因此虽然勉强能够运作，但也经常出现 bug；这个系统的意义就在于处理接收到的数据，也因此这个系统的目标是能更好地处理数据 —— 至少要让 bug 越来越少；这个系统的优化方法，一个方向是在编码上着手以优化底层架构，另外一个方向则是用更多更丰富的数据训练来进行优化。如果我想，我完全可以把这套认知建立在数学、物理学、文学、中医、迷信、真香、下次一定等各种事物上，当然后面两个过于简单未必能撑起来一个自洽的系统，单纯是用来举例的，如果真有人用他们构建自我也不是不可能，不过大概率非疯即傻。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf669188&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf669188&quot;&gt;2021-11-11 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf669188&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orga9af2d7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga9af2d7&quot;&gt;21:10 煎蛋&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga9af2d7&quot;&gt;
&lt;p&gt;
买的绿帽子煎蛋卫衣到了，试穿了下还蛮合身的，好看。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3425d27&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3425d27&quot;&gt;21:20 危&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org3425d27&quot;&gt;
&lt;p&gt;
凌晨的消息，海淀有一个病例，离我住的地方也就五六公里，下午的时候 C 说他们附近小区开始组织测核酸了。我下班回去路上，小区后面空地上也看到了核酸检测的队伍，工作人员想凑够五个人，招呼我问我要不要做一下，还强调说免费的，不过后来里面说五个人凑够了，于是门口的小哥说让我想一下如果要测的话还得等四个人，那我就算了。简单聊了两句，说主要是在给商超里的人做检测。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org637236c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org637236c&quot;&gt;2021-11-12 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org637236c&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org1eb755a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1eb755a&quot;&gt;10:10 冷漠&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1eb755a&quot;&gt;
&lt;p&gt;
上班，到站的时候被比较暴力地挤出了车厢，觉得没太大必要啊，那个站好多人下的，着急那几秒钟干啥呢，不过还好，大部分时间大家还是平和有序下车的。这种上班路上匆忙的状态，人是会变得冷漠甚至暴躁，但我时常会想起几年前一次不知道去哪里时坐着的一个姑娘大概是看我比较累把座位让给我这件事情。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga8f70ee&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga8f70ee&quot;&gt;19:00 批评&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga8f70ee&quot;&gt;
&lt;p&gt;
开组会，领导（比较温和地）批评一个同事的工作没有规划没有产出，同事也有点委屈有点情绪，我大概也可以理解，纯做算法工作而无业务项目，是很容易陷入到一种长久没成果的状态里。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga6064c3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga6064c3&quot;&gt;23:50 陌生人&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga6064c3&quot;&gt;
&lt;p&gt;
晚上去吃南门涮肉安定门店，还来了 XKL 的两个朋友，都住在 XKL 附近。吃饭吃得有点紧张和尴尬，三个女性聊得很多，其他人偶尔能接一两句话吧。虽然有些紧张不自在，但观察到自己面对陌生人时的心理状态和反应，也挺有意思的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga2eb481&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga2eb481&quot;&gt;2021-11-13 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga2eb481&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org64ea871&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org64ea871&quot;&gt;20:45 外甥女&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org64ea871&quot;&gt;
&lt;p&gt;
堂姐跟我说她女儿上高一后考得很差还哭了，请我去和她聊一聊。我和这个堂姐感情很好，但这个外甥女小时候比较怕生见得也不多，开始还担心会不会不愿意和我聊，加了微信后斟酌了许久写了一大段近千字的内容发过去，没想到她还看得下去聊了一会，可能是因为我理解学生时代的那种压力和心情，也表示出了尊重的姿态吧。她说她爸妈给她很多负能量，感觉我们那能当好家长的就没几个，这也是我们的命了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org88448c3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org88448c3&quot;&gt;2021-11-14 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org88448c3&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org686fef1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org686fef1&quot;&gt;17:33 日落&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org686fef1&quot;&gt;
&lt;p&gt;
去河边走了走，行人从身边流过，年轻的妈妈拿着两片大叶子逗弄儿童车上的孩子，一只萨摩耶领着短发的女主人在跑步，被家长拽着后领防止掉下河的两个小孩趴在栏杆上看着水里的鱼儿乐不可支，两位阿姨一人站在路边一人站在干涸的水沟里讨论摄影技巧，两位男子谈着国家大事严肃地路过……夕阳从天边慢慢落下去，感觉很难过。
&lt;/p&gt;


&lt;div id=&quot;org43ac7e8&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/sunset.jpg&quot; alt=&quot;sunset.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/10/25-2021/10/31)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/11/01/lifelog.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/11/01/lifelog</id>
    <published>2021-11-01T00:00:00+00:00</published>
    <updated>2021-11-01T00:00:00+00:00</updated>
    <description>
    
      <p>近期生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgbe537e6&quot;&gt;2021-10-25 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgbd5c44b&quot;&gt;10:10 关怀模式&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org26998dd&quot;&gt;12:35 贝果&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4848238&quot;&gt;23:57 冰冷&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org96f82fd&quot;&gt;2021-10-26 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org17e17ed&quot;&gt;08:50 壳聚糖&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6f8beb2&quot;&gt;10:33 做T&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge42e416&quot;&gt;13:38 度小满&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org25259be&quot;&gt;21:00 偶遇&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf113fcb&quot;&gt;2021-10-28 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org78e0317&quot;&gt;14:37 吐司&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc16c600&quot;&gt;20:30 照片&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2e86e4b&quot;&gt;2021-10-29 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgee97c57&quot;&gt;22:05 失控玩家&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org307afe9&quot;&gt;22:20 元宇宙&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org388eb5a&quot;&gt;2021-10-30 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org5dd160c&quot;&gt;17:30 No Time To Die&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1abef31&quot;&gt;2021-10-31 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org73f9e78&quot;&gt;11:11 DAO: 分布式自治组织&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org9d8824d&quot;&gt;22:28 分类&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgab992fa&quot;&gt;23:00 十月总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgbe537e6&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgbe537e6&quot;&gt;2021-10-25 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgbe537e6&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgbd5c44b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgbd5c44b&quot;&gt;10:10 关怀模式&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgbd5c44b&quot;&gt;
&lt;p&gt;
微信也有关怀模式了，就是文字、图标和按钮都更大的那种。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org26998dd&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org26998dd&quot;&gt;12:35 贝果&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org26998dd&quot;&gt;
&lt;p&gt;
从 ZZ 那订的五个贝果（原味/黑芝麻/花生酱各一个及肉桂葡萄干两个）到了，查了下，贝果之所以叫贝果是因为英文名叫 bagel，是个音译，其实没有贝也没有果，看到非音译的中文名叫硬面包圈，这个就很好理解了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4848238&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4848238&quot;&gt;23:57 冰冷&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4848238&quot;&gt;
&lt;p&gt;
周末和朋友聊天，她说：
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;org1890828&quot;&gt;
你内心太冰冷了，老是给人一种拒人于千里之外的感觉。
&lt;/pre&gt;

&lt;p&gt;
我是有察觉这点，但还是第一次有别人说出来，今天在想这个事情。首先，是不是呢？不太好说，我内心戏其实还蛮多的，但是确实会下意识地克制自己不怎么去表现出来吧，而且确实在一些至今仍然印象深刻的事件中表现出极大的冷漠；其次，这种状况我是否想要改变呢？确实是想的，因为这会阻碍我和环境的交互不利于自我的改进；然后可能的阻碍主要是是惯性和试错成本吧，具体的实践方法我目前并没有什么很好的思路，不过多感受、多表达，应该不会错。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org96f82fd&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org96f82fd&quot;&gt;2021-10-26 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org96f82fd&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org17e17ed&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org17e17ed&quot;&gt;08:50 壳聚糖&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org17e17ed&quot;&gt;
&lt;p&gt;
早上吃饭把口腔内部右侧咬破了，当时只是觉得有点疼，刷牙的时候吐了一口血出来吓了自己一跳，赶紧翻出来去年口腔溃疡时买的贴片贴到伤口上。看了下说明书，是一种壳聚糖成分，可以由几丁质（甲壳素）经脱乙酰化作用来制备，没有药物作用，在我这个事情上就是单纯帮助止血、防止口腔粘膜进一步损伤。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6f8beb2&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6f8beb2&quot;&gt;10:33 做T&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6f8beb2&quot;&gt;
&lt;p&gt;
上班路上做了个 T，赚了 300，还不错。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge42e416&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge42e416&quot;&gt;13:38 度小满&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge42e416&quot;&gt;
&lt;p&gt;
从微众银行转了点钱到度小满里，薅点新用户羊毛。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org25259be&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org25259be&quot;&gt;21:00 偶遇&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org25259be&quot;&gt;
&lt;p&gt;
在 15 号线遇到了前同事 WY，他说现在在一起作业网，教育公司嘛现在比较惨，说正在找下家准备跑路。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf113fcb&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf113fcb&quot;&gt;2021-10-28 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf113fcb&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org78e0317&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org78e0317&quot;&gt;14:37 吐司&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org78e0317&quot;&gt;
&lt;p&gt;
ZZ 提供吐司预订了，之前试吃过柠檬乳酪吐司挺好吃的，这次我本想预订一个柠檬的一个牛奶吐司，但是数量有限我只能订一个了，就订了个牛奶吐司。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc16c600&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc16c600&quot;&gt;20:30 照片&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc16c600&quot;&gt;
&lt;p&gt;
姑父又打来了电话，还是说上次那位介绍的学姐的事情，说让我发张照片给他他给对方看看，搞得还挺正式的，要我说要是双方都不抗拒先加个微信聊聊呗，这才哪到哪啊。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2e86e4b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org2e86e4b&quot;&gt;2021-10-29 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org2e86e4b&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgee97c57&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgee97c57&quot;&gt;22:05 失控玩家&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgee97c57&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Buddy: So what do we do&lt;/li&gt;
&lt;li&gt;Guy: Whatever we want&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
以前我们在《异次元骇客》和《黑客帝国》里讨论何为自我、何为真实和虚假，《失控玩家》虽然借助了类似的概念，但更像是一个成年人的童话，借着 Buddy 和 Guy 的问答，想像一个自由自在想做什么都可以的乐土，这可能是人类自古以来一直都有的共同愿望，新瓶装旧酒，看着乐呵就好了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org307afe9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org307afe9&quot;&gt;22:20 元宇宙&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org307afe9&quot;&gt;
&lt;p&gt;
Facebook 改名 Meta 了，可以预见元宇宙这个概念还会继续火下去，感觉现在这样的态势，如果黑客帝国的世界真的降临了，自愿插上管子进到矩阵里的人怕是不会少。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org388eb5a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org388eb5a&quot;&gt;2021-10-30 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org388eb5a&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org5dd160c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5dd160c&quot;&gt;17:30 No Time To Die&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5dd160c&quot;&gt;
&lt;p&gt;
下午去看了新上映的《007》，挺好看的，主题曲部分很好听，回来后查了下原来歌手是 2020 年格莱美奖五项大奖得主，嗯，我喜欢她的声音。
&lt;/p&gt;

&lt;p&gt;
看完电影慢悠悠骑车回去，一片半黄半绿的银杏叶过早地落了下来，打了几个旋落在了车框里。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1abef31&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1abef31&quot;&gt;2021-10-31 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org1abef31&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org73f9e78&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org73f9e78&quot;&gt;11:11 DAO: 分布式自治组织&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org73f9e78&quot;&gt;
&lt;p&gt;
在区块链技术上衍生出来的一种组织管理模式，挺有意思的。由于技术普及程度、法规等个方面的限制，短期内大概不能替代现代公司，但是用来作为一个开放社区的管理模式感觉还挺不错的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org9d8824d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org9d8824d&quot;&gt;22:28 分类&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org9d8824d&quot;&gt;
&lt;p&gt;
梳理了下自己的知识管理体系，把内容分成了资料、笔记、知识体系三大块：资料是指用 Zotero 统一管理的文档，本地化存储，每个资料都具有唯一 URI，可以方便地引用；笔记是对资料的解读、理解、感受以及在学习、建立某个知识体系时所做的记录、产生的理解，准备统一用 org-roam 管理；知识体系目前还没个谱，期望是一个精心维护的、严格结构化的数据。以前的笔记往往三者混杂，这两年逐步形成了 Zotero 和 org-mode 配合的习惯，前两者其实已经区分得比较好了，主要是在笔记和知识体系之间摇摆不定，还是分开来想好一点。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgab992fa&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgab992fa&quot;&gt;23:00 十月总结&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgab992fa&quot;&gt;
&lt;p&gt;
时间使用情况：
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;休息时间 263 小时，平均睡眠时间不算低，不过我看了下，基本上都是周末多睡导致的，工作日的平均睡眠时间还是不够 8 小时，而且我的睡眠质量还比较差&lt;/li&gt;
&lt;li&gt;日常行为 139 小时，比前几个月多出来十几二十个小时，因为这个月我还是花了一点时间去处理 RSS 的&lt;/li&gt;
&lt;li&gt;休闲时间 106 小时，没什么好说的&lt;/li&gt;
&lt;li&gt;工作时间 116 小时，一共 15 个工作日（我 10.11 才回去工作），所以日均工作时间是 7.73 小时，感觉挺累的，我负责的项目基本上就是我一个人在推进&lt;/li&gt;
&lt;li&gt;社交（聚餐/电话/网上聊天）时间 9.5 小时，显著低于过往几个月，这个时间的减少大概也是因为工作&lt;/li&gt;
&lt;li&gt;花了 20 个小时来记账，简直离谱，主要是 8 月和 9 月有一个多月没有及时记账，国庆第一天就花了 7 个小时来记账，其实说是 20 个小时，但中间有大量的记着记着就走神了去看视频看 RSS 的时间&lt;/li&gt;
&lt;li&gt;在写作上只用了 3 个小时，因为只写了三篇文章，两篇“闲言碎语”，另外一篇也没花什么时间&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
工作上主要在推进项目，彻底沦为后端开发哈哈哈 —— 不过也学到不少东西，比如说 K8S、Django 我都比以前熟练很多了，所以我并不讨厌这样的事情。一个人做项目，虽然累，但也不用被效率不行的队友拖后腿，有什么想法马上就能去做，还蛮爽的。
&lt;/p&gt;

&lt;p&gt;
投资方面，本月收益率跑赢了所有市场指标，本月累计收益金额在 10 月 26 日这天达到最高点，但离 9 月 13 日的今年最高点还是有一点距离。如果把证券账户从统计中剔除的话，会发现我的当月收益率和今年累计收益金额都大大下降，因为这个把月来大部分的指数走势都不怎么好，相反我场内重仓的招商银行，在三季报发布之后股价开始迅速地逼近了历史高点，为此带来了更高的收益，招商银行的股票我还会继续持有下去。
&lt;/p&gt;


&lt;div id=&quot;orgc668acf&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20211101_230617.png&quot; alt=&quot;20211101_230617.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
生活上没有太大的波澜，希望十一月也能继续平淡，平淡的、日常的每一天是最难得的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>北青深一度和谷雨实验室全文RSS</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/10/31/two-new-feeds.html"/>
    <category term="数字生活" scheme="http://www.zmonster.me/categories.html#数字生活"/>
    <id>http://www.zmonster.me/2021/10/31/two-new-feeds</id>
    <published>2021-10-31T00:00:00+00:00</published>
    <updated>2021-10-31T00:00:00+00:00</updated>
    <description>
    
      <p>应网友要求制作了北青深一度和谷雨实验室的全文RSS</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org2a1f31a&quot;&gt;北青深一度&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgfb1bc37&quot;&gt;谷雨实验室&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
之前《&lt;a href=&quot;https://www.zmonster.me/2020/03/10/wx-article-rss.html&quot;&gt;我制作的微信公众号RSS&lt;/a&gt;》这篇文章的评论里，有网友反馈了一些希望输出 RSS 的信息源，捡了两个看着顺眼的做了下。
&lt;/p&gt;

&lt;div id=&quot;outline-container-org2a1f31a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org2a1f31a&quot;&gt;北青深一度&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org2a1f31a&quot;&gt;
&lt;p&gt;
地址：&lt;a href=&quot;https://feedpress.me/bqs&quot;&gt;https://feedpress.me/bqs&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
制作步骤：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;找到北青深一度的网易号页面：&lt;a href=&quot;https://c.m.163.com/news/sub/T1477387792079.html&quot;&gt;https://c.m.163.com/news/sub/T1477387792079.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
在 Inoreader 中添加订阅源，输入这个地址，会显示这不是一个有效的 Feed，然后点击「创建 Rss 订阅源」，按照提示创建
&lt;/p&gt;


&lt;div id=&quot;org9085b7a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20211031_132837.png&quot; alt=&quot;20211031_132837.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
不知道为什么，我今天想重现这个过程，老是显示「我们无法抓取远程网站」，所以无法给出后续步骤示例了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
由于这种方式创建的订阅没有公开的 RSS 地址，要给别人用的话不太方便，好在 Inoreader 提供了对目录输出 RSS 的功能（限 Pro 用户），因此在 Inoreader 里新建了一个同名目录，把这个订阅移动到这个目录里，右键选择获取 RSS 订阅源就可以得到可以公开使用的 RSS 地址了
&lt;/p&gt;


&lt;div id=&quot;org934f0ef&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20211031_133912.png&quot; alt=&quot;20211031_133912.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgfb1bc37&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgfb1bc37&quot;&gt;谷雨实验室&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgfb1bc37&quot;&gt;
&lt;p&gt;
地址：&lt;a href=&quot;https://feedpress.me/wx-guyulab&quot;&gt;https://feedpress.me/wx-guyulab&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
制作步骤
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;用我的个人微信订阅「谷雨实验室-腾讯新闻」这个公众号，并记住公众号 guyulab&lt;/li&gt;
&lt;li&gt;在 Telegram 上将这个公众号关联到我专门的群组里&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
用 &lt;a href=&quot;https://github.com/Linusp/zs&quot;&gt;zs&lt;/a&gt; 生成 Huginn Scenario
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;zs-rss gen-wx-scenario -n &amp;#35895;&amp;#38632;&amp;#23454;&amp;#39564;&amp;#23460; -i guyulab -o wx-guyulab.json
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;登录 Huginn 导入创建好的 Scenario&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/10/11-2021/10/24)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/10/24/lifelog.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/10/24/lifelog</id>
    <published>2021-10-24T00:00:00+00:00</published>
    <updated>2021-10-24T00:00:00+00:00</updated>
    <description>
    
      <p>近期生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org26c7f9d&quot;&gt;2021-10-11 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org56ec14a&quot;&gt;17:37 Firefox Relay&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org17a1b50&quot;&gt;2021-10-12 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org3a53f66&quot;&gt;13:57 调仓考虑&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgeb776a1&quot;&gt;22:33 对话&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org22e7117&quot;&gt;2021-10-13 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org655995d&quot;&gt;17:17 留言&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgfb36e1a&quot;&gt;22:35 消息&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb93f6ee&quot;&gt;2021-10-14 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga612968&quot;&gt;22:29 执念&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgcd5936c&quot;&gt;23:51 现金&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2e7c875&quot;&gt;2021-10-17 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org5fb04ce&quot;&gt;09:28 梦&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge3077e1&quot;&gt;09:48 港美股入金&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org763e5c0&quot;&gt;17:27 豆瓣&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgbb15ef5&quot;&gt;19:52 传记&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org46c5672&quot;&gt;20:05 改变&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org04db11d&quot;&gt;21:46 链接&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgcfe88af&quot;&gt;2021-10-19 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga435385&quot;&gt;10:01 寒冷&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org70ef820&quot;&gt;23:57 时机&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgaef9afa&quot;&gt;2021-10-21 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org5b30942&quot;&gt;23:49 零公里&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org03c8843&quot;&gt;2021-10-22 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org5cc17a6&quot;&gt;23:08 二刷零公里&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6e19bea&quot;&gt;2021-10-23 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org526e186&quot;&gt;22:00 克苏鲁&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc108ad0&quot;&gt;2021-10-24 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org3940962&quot;&gt;21:30 沙丘&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org26c7f9d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org26c7f9d&quot;&gt;2021-10-11 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org26c7f9d&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org56ec14a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org56ec14a&quot;&gt;17:37 Firefox Relay&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org56ec14a&quot;&gt;
&lt;p&gt;
Firefox 提供的一个服务，可以生成一个邮箱地址，所有发到这个邮箱的邮件会转发到用户指定的邮箱里，这样就可以避免用户真实的邮箱地址被泄漏了。我以前注销了 Facebook，今天用 Firefox Relay 生成的邮箱重新注册了一个。
&lt;/p&gt;


&lt;div id=&quot;orgfab3969&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/firefox_relay.png&quot; alt=&quot;firefox_relay.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org17a1b50&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org17a1b50&quot;&gt;2021-10-12 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org17a1b50&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org3a53f66&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3a53f66&quot;&gt;13:57 调仓考虑&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org3a53f66&quot;&gt;
&lt;p&gt;
看 18 年到现在天宏中证银行ETF联接A和华夏中证500ETF联接A的比值，已经过了一个低点开始往上走，一方面是中证500今年持续涨了很久了，另外一方面是中证银行一直出于低估有估值修复的可能性，所以我在想，要不要把一部分中证500卖了换成中证银行？不过今天看场内500ETF在跌而银行ETF在上涨（虽然涨得不多），今天调感觉有点吃亏，到周四或者周五再做一下决定吧。
&lt;/p&gt;

&lt;p&gt;
嗯，场外买卖不要太频繁，可以考虑以周为单位在每周的固定时间进行交易，这也算是一种交易纪律了，能建立起来这个习惯应该会不错。
&lt;/p&gt;


&lt;div id=&quot;orge1af97f&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/compare_fund_001594_007994.png&quot; alt=&quot;compare_fund_001594_007994.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-orgeb776a1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgeb776a1&quot;&gt;22:33 对话&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgeb776a1&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;来啦！还有酸菜、豆角的，其他的没了&lt;/li&gt;
&lt;li&gt;酸菜来两个，豆角来两个，粉条的还有吗？&lt;/li&gt;
&lt;li&gt;哦对，粉条的还有 —— 你好些天没来了&lt;/li&gt;
&lt;li&gt;假期就自己做着吃啦&lt;/li&gt;
&lt;li&gt;自己还会做啊&lt;/li&gt;
&lt;li&gt;嗯，那可不得自己做，不能天天吃外卖啊&lt;/li&gt;
&lt;li&gt;那是不能&lt;/li&gt;
&lt;li&gt;多少钱&lt;/li&gt;
&lt;li&gt;10 块 5，好几天没来价钱你都不记得了&lt;/li&gt;
&lt;li&gt;哈哈，以前也不记得，就记得大概&lt;/li&gt;
&lt;li&gt;下次得记得哈，要有点默契&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org22e7117&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org22e7117&quot;&gt;2021-10-13 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org22e7117&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org655995d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org655995d&quot;&gt;17:17 留言&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org655995d&quot;&gt;
&lt;p&gt;
接到联合国儿童基金会的电话，聊完了让我填写一个问卷调查，结尾问：对于孩子们和联合国基金儿童基金会的工作人员，您有那些期待、鼓励或想说的话？请留下您的心声吧（这对我们很重要！）
&lt;/p&gt;

&lt;p&gt;
花了点时间想了想，最后写了这么一段话：人类的未来这种话对孩子们来说是过于沉重的责任，我觉得爱、真、善、美才是让世界变好的希望，希望孩子们能感受到善意并也以善意回报身边的人，健康但普通地成长就好。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgfb36e1a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgfb36e1a&quot;&gt;22:35 消息&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgfb36e1a&quot;&gt;
&lt;p&gt;
今天得知 ZF 要离职了，说是是心理状态、情绪很差，之前大家其实也有所察觉毕竟他一直都表现得很丧嘛，加上我和他聊过几次知道一点他的价值观和想法，得知这个消息也不算很震惊，毕竟一个钱也赚了不少了又没法从赚钱中得到满足感的人，如果工作内容本身不够有吸引力，那么离开也是迟早的，或许我也会有这么一天？开完会和 DS 一起去和合谷吃午饭也聊了一会这个问题，DS 是很有责任心的人，觉得 ZF 不应该影响到工作或者说至少应该在影响到工作前及时表达出来，各有各的道理吧。今天工作内容很饱满，没有别的事情，平淡的一天。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb93f6ee&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgb93f6ee&quot;&gt;2021-10-14 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgb93f6ee&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orga612968&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga612968&quot;&gt;22:29 执念&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga612968&quot;&gt;
&lt;p&gt;
今天发现我又放下了一个执念，就是「希望能有一个人非常理解我」，一来这极其困难，二来自己都还没有足够理解自己呢。不过这并不是悲观的想法，只是一个观念的转变吧，而且因为预期降低了，有时候和人在一些非常非常微小的点上能共通时，也会非常地开心。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgcd5936c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgcd5936c&quot;&gt;23:51 现金&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgcd5936c&quot;&gt;
&lt;p&gt;
把现金部分也纳入到 keysersoze 的管理范围里了，这样我就能看到我除了加密货币和公积金外所有其他资产的总体增长状况了。
&lt;/p&gt;


&lt;div id=&quot;orgc4d8698&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/keysersoze_cash.png&quot; alt=&quot;keysersoze_cash.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2e7c875&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org2e7c875&quot;&gt;2021-10-17 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org2e7c875&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org5fb04ce&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5fb04ce&quot;&gt;09:28 梦&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5fb04ce&quot;&gt;
&lt;p&gt;
梦到几个大学同学开了公众号，在朋友圈分享来着。工作后因为自己的性格就渐渐地和别的城市的同学少了联系，偶尔还是会想念上学时和同学们的关系的，会做这个梦，可能和昨晚看了一个视频有关系，一位 97 岁的哲学家讲述临近死亡时的恐惧和孤独感。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge3077e1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge3077e1&quot;&gt;09:48 港美股入金&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge3077e1&quot;&gt;
&lt;p&gt;
华美银行可以轻松网上申请开户，Google Pay 可以绑定华美银行进行支付和收款，Coinbase 可以使用 Google Pay —— 所以有加密货币的话，可以转移到 Coinbase 里然后卖出到 Google Pay，然后通过华美银行给港美股账户入金。不过我试了下，Google Pay 注册的时候不认 Google Voice 号码，Coinbase 一进入到交易页面就显示「我们遇到连接问题」，我猜 Coinbase 和 Google Pay 都有别的可用替代品。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org763e5c0&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org763e5c0&quot;&gt;17:27 豆瓣&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org763e5c0&quot;&gt;
&lt;p&gt;
豆瓣帐号原来关联的自己的 Gmail，今天给解绑了，想着反正都绑定了手机号，要不绑个微信看看，结果发现 2018 年的时候我用现在这个微信号创建过一个豆瓣帐号，只好注销掉再绑定了。想把各个绑定了 Gmail 的国内平台帐号都解绑，不过也不是什么着急的事情，看心情来吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgbb15ef5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgbb15ef5&quot;&gt;19:52 传记&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgbb15ef5&quot;&gt;
&lt;p&gt;
最近有看点传记的想法，不是看某个人，就是找很多个人，都看看，最好是和我专业无关的、不熟悉的那种人，看看别人是怎么应对生活的，比起天天自己在想可能会有意思得多。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org46c5672&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org46c5672&quot;&gt;20:05 改变&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org46c5672&quot;&gt;
&lt;p&gt;
发现我已经不太容易看得进去 NLP/DL 的东西 —— 一方面是挺久没有直接做相关的工作了，另外一方面是从事多年工作之后对结构工程、模型翻新已经开始有点厌恶。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org04db11d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org04db11d&quot;&gt;21:46 链接&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org04db11d&quot;&gt;
&lt;p&gt;
在 Youtube 上看到《互联网体检》这个小品，太有意思了。看完突然想，Youtube 不知道有没有提供链接到视频特定时间点的方法，一查果然是有的，具体来说，在需要的时间点暂停，在视频上右键，然后点击「Copy video URL at current time」就可以，比如下图中我得到的链接是 &lt;a href=&quot;https://youtu.be/kOYrj2wG63E?t=88&quot;&gt;https://youtu.be/kOYrj2wG63E?t=88&lt;/a&gt; —— 仔细观察，这个链接其实是在原链接上加了 t=88 这样一个后缀，对应着视频第 88s，很好理解
&lt;/p&gt;



&lt;div id=&quot;orgafd2236&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/youtube_position_link.png&quot; alt=&quot;youtube_position_link.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
嗯，接下来发现 Bilibili 也支持这个特性，比如 &lt;a href=&quot;https://www.bilibili.com/video/BV1Px411c7RM?t=100&quot;&gt;https://www.bilibili.com/video/BV1Px411c7RM?t=100&lt;/a&gt; 这个链接会跳转到视频的第 100s。
&lt;/p&gt;


&lt;div id=&quot;org829d03f&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/bilibili_position_link.png&quot; alt=&quot;bilibili_position_link.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
其他视频平台的话，简单试了下：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
优酷：能获得这样的链接 &lt;a href=&quot;https://v.youku.com/v_show/id_XNDY5MDkzMjAxMg==.html?_time=100&quot;&gt;https://v.youku.com/v_show/id_XNDY5MDkzMjAxMg==.html?_time=100&lt;/a&gt; ，但是我在浏览器访问这个链接并不能跳转到对应的时间
&lt;/p&gt;


&lt;div id=&quot;org328a100&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/youku_position_link.png&quot; alt=&quot;youku_position_link.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;爱奇艺：能获得这样的链接 &lt;a href=&quot;http://www.iqiyi.com/v_19rwfzg07o.html?share_sTime=33&quot;&gt;http://www.iqiyi.com/v_19rwfzg07o.html?share_sTime=33&lt;/a&gt; ，但和优酷的问题是一样的&lt;/li&gt;
&lt;li&gt;抖音网页版：不支持&lt;/li&gt;
&lt;li&gt;快手网页版：不支持&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
国内平台除了 Bilibili 可能都不支持这个功能，不过无所谓了，Youtube 和 Bilibili 能覆盖我看的绝大多数视频了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgcfe88af&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgcfe88af&quot;&gt;2021-10-19 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgcfe88af&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orga435385&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga435385&quot;&gt;10:01 寒冷&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga435385&quot;&gt;
&lt;p&gt;
我喜欢秋冬寒冷的天气，会让我冷静下来更好地思考问题，今天上班路上就久违地开始思考一些事情了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org70ef820&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org70ef820&quot;&gt;23:57 时机&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org70ef820&quot;&gt;
&lt;p&gt;
午饭吃饭，LY 好是抱怨了一通工作内容，我们各自也觉得方向太多人太少，多少有点抱怨。晚上和 LY、K 去吃烤肉和烤鳗鱼，LY 又稍微抱怨了两句，看得出来他心理压力很大。我也没什么可说的，但这半年多来，也确实感觉有各种问题吧，就像我之前写过的一样，是很充实，但如果自己并没有变得更好，那么这种忙碌就没有太多意义。早上我就在想，我想变得更好，那我就需要更丰富的环境（以及环境的反应）来激发、训练和检验自己，这个问题我也会持续思考并且进行自我观察，时机到了的话就顺其自然吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgaef9afa&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgaef9afa&quot;&gt;2021-10-21 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgaef9afa&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org5b30942&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5b30942&quot;&gt;23:49 零公里&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5b30942&quot;&gt;
&lt;p&gt;
和 LY、K 下班后去了炎黄艺术馆新开的一家叫做「零公里」店，点了 TOP3 的宜宾燃面、李庄白肉、酒都肥肠以及三江豆腐脑花和一个老妈蹄花，燃面比常去的望花路燃面扁平很多，也不像望花路燃面那么湿，好像是 7 块钱一两很便宜，我们点了二两；白肉一片片都超大，夹上一片铺在盘子上看着就很有满足感，再自由发挥一下把肥肠、脑花放上去卷起来吃 —— 额会稍微有点腻，如果有点蔬菜什么的搭配一下会更好；酒都肥肠非常好，和去年百花山奔走 25 公里后在百花人家吃的肥肠一样毫无缺点；豆腐脑花很下饭但前面我一直在对付白肉和非常，导致我的米饭居然吃剩了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org03c8843&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org03c8843&quot;&gt;2021-10-22 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org03c8843&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org5cc17a6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5cc17a6&quot;&gt;23:08 二刷零公里&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5cc17a6&quot;&gt;
&lt;p&gt;
今天二刷零公里，相比昨晚，多喊到两个人凑上了五个人，点了昨晚吃过的李庄白肉、酒都肥肠和宜宾燃面，还点了小院跳水菜、花生浆菜豆腐、宫保脆皮肉、富油黄粑、陈皮兔、乡味腊肉和鲜椒热窝鸡。花生浆菜豆腐是一道汤菜，顾名思义，它的汤可能是加了花生打成的浆，花生的香气非常浓郁，喝汤的时候也能尝到细细的花生碎末，非常有特色；宫保脆皮肉外观色泽上有点像东北的锅包肉但口感完全不一样，很薄（相比锅包肉）又特别酥脆，轻轻一口下去就能咬断，里层肉的味道和油脂就出来了，咬断口能明显看到分层，但口感上却毫无感觉，很神奇；富油黄粑就是粽子的口感，没啥特别的；陈皮兔陈皮味道很淡，没啥特别的；热窝鸡是先煮熟再炒的做法，这种形式和我家里的做法是一样的，很家常亲切的味道。昨晚三个人半小时吃完，今晚也特地看了下时间，20:42 上的第一道菜，吃完用时 31 分钟，不愧是我们！
&lt;/p&gt;

&lt;p&gt;
吃完结帐，一个经理还是店长之类的男子过来表示抱歉，但我没听到前面实在没搞明白是抱歉什么，大概是说我们吃的时候服务员也在吃饭了服务不周之类的吧，但我其实还蛮喜欢看到饭店员工们一起热热闹闹吃饭的，因为这种店的饭菜一般都好吃。完了他还送我们到店门口，豪气地说要以北京为起点辐射全国，能跟仅仅是顾客的我们讲这种话，不管信不信，但还是挺开心的。
&lt;/p&gt;

&lt;p&gt;
他们家菜单特别厚，有很多在北京川菜馆没见过的特色的菜，所以准备多去几次都尝试一下，希望他们能经营下去～
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6e19bea&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org6e19bea&quot;&gt;2021-10-23 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org6e19bea&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org526e186&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org526e186&quot;&gt;22:00 克苏鲁&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org526e186&quot;&gt;
&lt;p&gt;
开始看《克苏鲁神话》！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc108ad0&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgc108ad0&quot;&gt;2021-10-24 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgc108ad0&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org3940962&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3940962&quot;&gt;21:30 沙丘&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org3940962&quot;&gt;
&lt;p&gt;
昨天买了《沙丘》的票，于是三点多出了门往小米总部附近的五彩城购物中心去，早些年住上地的时候也会去，所以还蛮熟悉的，只不过这会是从另外一个方向过去。16:20 的场，16:11 到了电影院，取完票就检票进去了。电影还是不错的，剧情基本尊重了原著，大概是小说第一卷的内容，虽然搞什么先知、预言不是我比较喜欢的故事，但也是合格的；画面很美，沙虫和一些巨大建筑很有感觉，在一些细节上展现了书里的设定，比如收集呼吸中的水蒸汽、汗水、泪水（甚至还有那啥）来循环用水的服装和帐篷、竖起大耳朵来收集露水的沙鼠，还有哈克南男爵因为过度肥胖无法行走只能给自己加了个便携式浮空器能让自己飘起来这个事情，电影完全没解释，我听到旁边的人说妖怪笑死了；音乐太吵了，大量的画面明明安安静静就好了，非得加上节奏特别急促的 BGM，我明白想要渲染紧张感，但是太刻意太吵了。
&lt;/p&gt;

&lt;p&gt;
看完电影出来去优衣库买了两件衣服，犹豫了下要不要在商场吃饭，不过看了下都不太适合一个人吃就算了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/09/06-2021/10/10)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/10/10/lifelog.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/10/10/lifelog</id>
    <published>2021-10-10T00:00:00+00:00</published>
    <updated>2021-10-10T00:00:00+00:00</updated>
    <description>
    
      <p>近期生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org687c75c&quot;&gt;2021-09-10 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org3739eec&quot;&gt;09:01 R.I.P&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3cd1c92&quot;&gt;2021-09-11 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org41f2234&quot;&gt;21:34 仓位&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org553eef8&quot;&gt;2021-09-12 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org17ccf3d&quot;&gt;09:34 无根之草&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8ca8854&quot;&gt;22:23 今日回顾&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org66c67f7&quot;&gt;2021-09-13 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgc86fa98&quot;&gt;10:13 早饭&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5ff0195&quot;&gt;2021-09-17 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org2609e67&quot;&gt;08:02 噩梦&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5258493&quot;&gt;08:11 桌角&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org80a4180&quot;&gt;08:45 锚&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org59efc26&quot;&gt;2021-09-18 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org13a675f&quot;&gt;20:00 学姐&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org7c49877&quot;&gt;2021-09-20 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org8e4caba&quot;&gt;22:56 今日回顾&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgdcb7110&quot;&gt;2021-09-21 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga373f06&quot;&gt;22:44 今日回顾&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org14b98ab&quot;&gt;2021-09-23 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org245ac3c&quot;&gt;21:28 二建&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge0b6b5b&quot;&gt;2021-09-24 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgde78324&quot;&gt;22:31 秩序&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org199ace5&quot;&gt;2021-09-25 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgff092d9&quot;&gt;08:18 无眠&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgac9f6eb&quot;&gt;10:48 生活&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgbb2a48f&quot;&gt;19:15 平静&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgacae578&quot;&gt;2021-09-26 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org67d5ec7&quot;&gt;08:33 梦&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd2034bc&quot;&gt;22:34 降温&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8e7629a&quot;&gt;2021-09-27 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgb7e4630&quot;&gt;23:42 今日回顾&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge8a9a19&quot;&gt;2021-09-29 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org6e5037b&quot;&gt;22:19 熟悉&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga37424c&quot;&gt;2021-09-30 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgfe72dad&quot;&gt;13:33 景点&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org84fbd1f&quot;&gt;2021-10-01 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orge5e8658&quot;&gt;22:16 记账&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org28b1ced&quot;&gt;2021-10-03 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgf84e336&quot;&gt;20:01 公益&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org81adba1&quot;&gt;22:10 明天&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge99dbc4&quot;&gt;2021-10-05 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgf16cd9a&quot;&gt;23:48 接站&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd2b4d3b&quot;&gt;2021-10-06 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org2960093&quot;&gt;19:54 第一天&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga87e0b2&quot;&gt;2021-10-07 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga2f1ca8&quot;&gt;20:00 第二天&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgda80cdf&quot;&gt;2021-10-08 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org9e13327&quot;&gt;20:14 第三天&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org687c75c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org687c75c&quot;&gt;2021-09-10 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org687c75c&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org3739eec&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3739eec&quot;&gt;09:01 R.I.P&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org3739eec&quot;&gt;
&lt;p&gt;
得知关注的那位推友已经去世。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3cd1c92&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3cd1c92&quot;&gt;2021-09-11 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3cd1c92&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org41f2234&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org41f2234&quot;&gt;21:34 仓位&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org41f2234&quot;&gt;
&lt;p&gt;
今天又给 keysersoze 写了点代码，一个是加上了仓位变化曲线（下图右侧是仓位的坐标）：
&lt;/p&gt;


&lt;div id=&quot;org84e40f1&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/keysersoze_return_with_position.png&quot; alt=&quot;keysersoze_return_with_position.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
今年以来收益还可以，我一直觉得是我把仓位提高的原因，从上图来看累计收益和仓位是正相关的，算是验证了我这个想法吧。
&lt;/p&gt;

&lt;p&gt;
然后就是在首页加上了各个账户的柱状图，这下写总结的时候可以直接截图而不是临时写代码去绘图了。
&lt;/p&gt;


&lt;div id=&quot;orgffdf250&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/keysersoze_return_bars.png&quot; alt=&quot;keysersoze_return_bars.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org553eef8&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org553eef8&quot;&gt;2021-09-12 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org553eef8&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org17ccf3d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org17ccf3d&quot;&gt;09:34 无根之草&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org17ccf3d&quot;&gt;
&lt;p&gt;
从龙崎那知道的，想玩，发现豆瓣上没有对应条目呢，索性去创建了一个，这还是我第一次在豆瓣上创建条目。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8ca8854&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8ca8854&quot;&gt;22:23 今日回顾&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8ca8854&quot;&gt;
&lt;p&gt;
今天久违地做了一次饭啦，上午在叮咚买了点菜，中午做了个蒜蓉蚝油红薯叶和青椒炒鸡腿肉，并把昨天剩的那块鳗鱼蒸了，中午吃了个肚皮饱饱，照例剩了菜在晚上吃。明天早上的话准备炒个西红柿鸡蛋再搞个水煮西兰花，主食的话打算空气炸锅扔个红薯进去。工作虽然很忙，但偶尔过得好一点还是可以的。
&lt;/p&gt;

&lt;p&gt;
今天一整天都是在玩，除了花了半小时把要写的一篇博客的思路捋了下外，没做什么其他正经事情。开始玩血源诅咒了，不过第一个 BOSS 都还没见着哈哈。
&lt;/p&gt;

&lt;p&gt;
明天又要开始工作了，心累，早点休息吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org66c67f7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org66c67f7&quot;&gt;2021-09-13 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org66c67f7&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgc86fa98&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc86fa98&quot;&gt;10:13 早饭&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc86fa98&quot;&gt;
&lt;p&gt;
昨晚还兴致勃勃地准备今天早饭的东西来着，结果 7 点闹钟响了后再眯了会就 9 点了……
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org5ff0195&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org5ff0195&quot;&gt;2021-09-17 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org5ff0195&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org2609e67&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2609e67&quot;&gt;08:02 噩梦&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2609e67&quot;&gt;
&lt;p&gt;
梦到有两个不熟的朋友带一个他们的朋友突然上门玩，有一个朋友要玩我的电脑，我不让但他偏要玩，我发火了让他们滚，他们起身穿鞋有一个人找不到第二只鞋。我和他们一起出了门，回的时候却找不到路了，在饭店大堂、阴森的小巷、熟悉但就是没有我的门牌号的楼道组成的迷宫里徘徊寻找。找没找到不知道，反正醒过来了，看到早晨鲜红的阳光从阳台透过来，听到忘了关的空调吵闹的嗡嗡声，手一伸摸到了手机，顿时安心下来。
&lt;/p&gt;

&lt;p&gt;
做了噩梦，有时候会很害怕、很难过，有时候也会庆幸那些恐怖的事情只是在梦里发生。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5258493&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5258493&quot;&gt;08:11 桌角&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5258493&quot;&gt;
&lt;p&gt;
左腿大腿外侧撞到了桌角，又要带着淤青好一阵子了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org80a4180&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org80a4180&quot;&gt;08:45 锚&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org80a4180&quot;&gt;
&lt;p&gt;
变化和混乱永恒存在，每个人都像是汪洋大海里的孤舟，除了组成船队互助，另外一个办法是备好船锚，在风浪到来的时候能够牢牢地固定住自己。伟大的理想、稳定的工作、钱……有很多东西可以成为锚，但除了这些大的、表面很有用的东西外，还有很多东西也可以，比如清晨的阳光、书页的芳香、夏天的风、冬天的雪、山巅壮阔的风景、熟悉的老店……越多越好。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org59efc26&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org59efc26&quot;&gt;2021-09-18 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org59efc26&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org13a675f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org13a675f&quot;&gt;20:00 学姐&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org13a675f&quot;&gt;
&lt;p&gt;
下午开着会的时候姑妈打电话过来说要找我聊点事，因为正在开会和工作没有办法抽出大段时间，就简单聊了两句约下班后再聊，下班后刚到地铁站又接到了电话，和我猜的一样，说是觉得有个合适的姑娘看我们要不要聊一聊，还是高中时候的学姐。以前我对这种事情是比较抗拒的，现在觉得只是聊聊无所谓嘛。当然，说还要去看一下对方愿不愿意聊，兴许就没有后续了也说不定。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org7c49877&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org7c49877&quot;&gt;2021-09-20 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org7c49877&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org8e4caba&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8e4caba&quot;&gt;22:56 今日回顾&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8e4caba&quot;&gt;
&lt;p&gt;
昨天约了 ZCH 见面吃饭，结果上午一直在下雨，有那么一会还犹豫了下要不要改时间，但想着还是今天把各种事情处理了比较好，就作罢了。出门被风一吹觉得冷，看了下气温才 16，于是把垃圾扔了后回屋换了厚点的外套，坐 8 号线往南到鼓楼大街站转 2 号线到了安定门，从 A 口出去后往左一直走就到了。
&lt;/p&gt;

&lt;p&gt;
他比我先到，不知道是因为雨天还是什么，壹圣元人特别冷清，我一口气点了鲜鸭血、嫩牛肉、小酥肉、黄喉、毛肚、鲜豆腐、平菇、白萝卜、土豆，点多了最后没吃完，就把剩的平菇、土豆、小酥肉还有个什么打包了。两个人都是那种宅、内向的人，聊天没有很热烈，我主要聊了我做记录、做金钱预算的事情，感觉是有点用的东西，技术上的东西没啥可聊的。最后花了 350，果然是点多了。
&lt;/p&gt;

&lt;p&gt;
吃完饭他坐公交我坐地铁，同走了一小段，他先到公交站，我继续走到了地铁站。2 号线转 8 号线的换乘路上，又遇到讨厌的辅警查身份证，我掉头去了另外一个换乘口，果然没人查，哼。回到家后又玩了会血源，然后开始准备给表弟要讲的东西，到七点的时候特别饿，可能是因为中午没吃什么主食，于是把包子热了两个吃了。八点半的时候表弟还没回我消息，后来说临时有事在处理，所以我继续等到八点四十多开始讲，到九点十几二十的时候就讲完了，并且录了视频。
&lt;/p&gt;

&lt;p&gt;
今天就是这样啦。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgdcb7110&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgdcb7110&quot;&gt;2021-09-21 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgdcb7110&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orga373f06&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga373f06&quot;&gt;22:44 今日回顾&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga373f06&quot;&gt;
&lt;p&gt;
问了下弟弟这三天的去向，去理了发，和爸妈打了电话。
&lt;/p&gt;

&lt;p&gt;
明天又要开始上班啦，不开心，早点睡觉吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org14b98ab&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org14b98ab&quot;&gt;2021-09-23 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org14b98ab&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org245ac3c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org245ac3c&quot;&gt;21:28 二建&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org245ac3c&quot;&gt;
&lt;p&gt;
我爸打电话过来，说在手机上看视频小说的时候看到了二级建造师的广告，加上周围有一些朋友也在说这个事情，有点心动，让我查一下相关的信息看靠不靠谱。我反正觉得挺不靠谱的，还好能来问我。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge0b6b5b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge0b6b5b&quot;&gt;2021-09-24 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge0b6b5b&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgde78324&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgde78324&quot;&gt;22:31 秩序&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgde78324&quot;&gt;
&lt;p&gt;
不管发生什么事情，保持生活的秩序，就能保证稳定住自己。但如果连生活的常态都无法维持了呢？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org199ace5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org199ace5&quot;&gt;2021-09-25 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org199ace5&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgff092d9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgff092d9&quot;&gt;08:18 无眠&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgff092d9&quot;&gt;
&lt;p&gt;
昨晚翻来覆去到很晚 —— 三点多才睡着吧，醒来后仍然觉得难受。虽然糟糕的事情现在未必能说发生了，但是有很多问题，我过去确实是在故意回避视而不见吧。有时候会想，为什么要让我来到这个世界承受这些呢？分外无助的时候，偶尔会觉得如果有个人互相支撑确实会比较好，双活容错负载均衡嘛。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgac9f6eb&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgac9f6eb&quot;&gt;10:48 生活&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgac9f6eb&quot;&gt;
&lt;p&gt;
读到和菜头的&lt;a href=&quot;https://mp.weixin.qq.com/s?__biz=MjM5MjAzODU2MA==&amp;amp;mid=2652786474&amp;amp;idx=1&amp;amp;sn=abd28c0480d9e03c476e56fe7e4a0c33&quot;&gt;《看完两边走中间》&lt;/a&gt;，心情稍微平静一些了，坦然接受自己的无知无力、生活的无常，这是这两年来我在努力做的事情，迄今为止我做得很好，保持下去就好了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgbb2a48f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgbb2a48f&quot;&gt;19:15 平静&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgbb2a48f&quot;&gt;
&lt;p&gt;
写了篇博客，和朋友见了面吃了饭，终于感觉平静下来了。真要有事，也不是我在这急这一会有什么用的，没事的话我就更是干着急了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgacae578&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgacae578&quot;&gt;2021-09-26 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgacae578&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org67d5ec7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org67d5ec7&quot;&gt;08:33 梦&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org67d5ec7&quot;&gt;
&lt;p&gt;
梦见我飞过山岗，地面有一堆奇形怪状生物的群落，他们飞上来要抢飞行器，被我不知道在哪里的友军击毁了。我飞进了一栋建筑里，熟练地穿过一间房子进入楼梯区域，然后在楼梯回环的空隙中直接垂直向下飞了几层到达一个有很多人的房间，穿过众人背后的小门到了一个狭窄的过道，然后进了电梯，电梯里有两个人，我和其中一个隐晦地聊了几句互相威胁对方，一起出电梯的时候，剩下那个没出电梯的人在电梯门合拢时的缝隙瞥了我们一眼，按下了录音笔的结束录制按钮，我和一起出电梯那个人打了起来。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd2034bc&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd2034bc&quot;&gt;22:34 降温&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd2034bc&quot;&gt;
&lt;p&gt;
和爸妈打电话游说他们来北京，感觉是接近成功了，然后最近两天的焦虑也降下来了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8e7629a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org8e7629a&quot;&gt;2021-09-27 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org8e7629a&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgb7e4630&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb7e4630&quot;&gt;23:42 今日回顾&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb7e4630&quot;&gt;
&lt;p&gt;
中午去探新店吃了裕兴记，平平无奇还吃出了 52 的人均，这价钱能在红京鱼吃到撑哇。
&lt;/p&gt;

&lt;p&gt;
下班路上在 Inoreader 上读 RSS 来着，看到 hankcs 昨天发了一篇新博客，说自己不开心，点开想看全文却 404 了，当时还在路上没法去追溯，也没想太多。到家后打电话给我爸，询问来北京玩的事情，我爸说和妈聊过后都愿意来北京玩，但是前阵子我妈被狗咬到 4 号要打第二针狂犬疫苗，不知道该如何安排，说准备明天去询问下医生看能不能提前一两天打或者不打（觉得可以不打是因为伤口很浅几乎只有牙印）。打完电话想起 hankcs 的事情来，想着他的文章虽然删掉了，但作为一个还比较知名的网站应该 Google 有生成网页快照，去搜了下果然搜到了，看了内容顿觉不妙，觉得整篇文章都在发送求救信号，但是找了一圈都找不到对方的直接联系方式（邮件/电话/社交网络私信渠道），着急之下到 NLP 群来了个群发，直到有人发了一个疑似他团队的人的联系方式，我犹豫了下加了微信，但没有得到回应，干脆打了个电话过去说明情况，还好对方确实能联系上 hankcs，并告知我对方人没事。之后 hankcs 给我发了一篇简单的感谢邮件，说自己「已经完全恢复了」，但我觉得，一个昨天还通篇宣泄绝望情绪的人，怎么可能就「完全恢复」了呢？于是又啰啰嗦嗦写了一大堆话，也许我是反应过度了吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge8a9a19&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge8a9a19&quot;&gt;2021-09-29 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge8a9a19&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org6e5037b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6e5037b&quot;&gt;22:19 熟悉&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6e5037b&quot;&gt;
&lt;p&gt;
包子铺的老板已经记得我不吃茴香了，希望她的店铺可以一直开下去。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga37424c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga37424c&quot;&gt;2021-09-30 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga37424c&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgfe72dad&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgfe72dad&quot;&gt;13:33 景点&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgfe72dad&quot;&gt;
&lt;p&gt;
故宫只能买到 7 号的票了，颐和园、圆明园、恭王府倒是还都有票，不过向来人都会很多。这些都是从北京本地宝看到的，然后从各个地方进出京是否要做核酸检测这些，在北京本地宝上都能查到，还是很方便的呀。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org84fbd1f&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org84fbd1f&quot;&gt;2021-10-01 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org84fbd1f&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orge5e8658&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge5e8658&quot;&gt;22:16 记账&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge5e8658&quot;&gt;
&lt;p&gt;
有一个多月没有整理日常开支的账单了，有点混乱，今天花了大半天时间来整理他们，算是基本上记录、校验完了，但是信用卡账单部分因为支出和还款的时间间隔比较大而有点乱，还需要进一步梳理细节。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org28b1ced&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org28b1ced&quot;&gt;2021-10-03 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org28b1ced&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgf84e336&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf84e336&quot;&gt;20:01 公益&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgf84e336&quot;&gt;
&lt;p&gt;
B站看到一个支教的姑娘的视频，就去给联合国儿童基金会开了个每月定期捐助，只用出钱可以，真是偷懒啊。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org81adba1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org81adba1&quot;&gt;22:10 明天&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org81adba1&quot;&gt;
&lt;p&gt;
明天准备早起，开始全力为父母来北京的事情准备，希望能把这个国庆过好！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge99dbc4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge99dbc4&quot;&gt;2021-10-05 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge99dbc4&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgf16cd9a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf16cd9a&quot;&gt;23:48 接站&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgf16cd9a&quot;&gt;
&lt;p&gt;
火车晚点了十几分钟，接到爸妈的时候已经快十点了，然后发现我爸提着一箱带给我的东西，我拎了下挺沉的，就挺无语的，电话里反复说不要带太多东西了……接下来没啥好说的，9 号线转 6 号线转 8 号线，我爸赞叹地铁通风和光线很舒服，我妈则感叹地铁生意好，然后跟我念叨说玩个两天就回去，听到我酒店订了五天两人纷纷表示可以住你那为啥要订酒店还一订五天啊 —— 他们不想待太久，一方面是不想花太多钱外，但他们大概不知道酒店的钱也就和一个人过来的车票钱差不多；另一方面是，因为怕家里东西没人照顾把我外婆叫到了我家，就担心年岁已大的外婆一个人在家能不能照顾好自己。出了地铁后发现下着不小的雨，还好酒店就在边上，办完入住我爸拎着东西和我一起到了我住的地方，因为里面有肉必需得放冰箱，一路走来把鞋也弄湿了，如果少带点我自己就能拎过来就不会这样了。火车上我爸没吃，我从冰箱拿了香蕉和苹果让我爸对付一下，拆了箱把肉类都放进速冻，就下楼把我爸送到了小区门口。
&lt;/p&gt;

&lt;p&gt;
挺折腾的一天，后面还有四五天，加油吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd2b4d3b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgd2b4d3b&quot;&gt;2021-10-06 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgd2b4d3b&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org2960093&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2960093&quot;&gt;19:54 第一天&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2960093&quot;&gt;
&lt;p&gt;
今天爸妈到我住处，一起做饭吃饭聊天，早饭做了米粉，中午炒了野猪肉（啊吃野味不好但超好吃耶）、芥兰，做了芋子粥（超香），晚上炒了鸭杂。聊了一整天的家常，感觉好累，今天早点睡吧，明天去天安门和恭王府。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga87e0b2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga87e0b2&quot;&gt;2021-10-07 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga87e0b2&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orga2f1ca8&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga2f1ca8&quot;&gt;20:00 第二天&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga2f1ca8&quot;&gt;
&lt;p&gt;
今天带父母去了天安门，走在对面路上的时候，我父母都有点失望地说「感觉天安门不像电视上那么雄伟壮观」，不过到了金水桥上还是开心地各种拍照。本来是打算去了天安门后再去南边的毛主席纪念馆，结果天安门的路线是单向的，不允许原路返回，绕回去的话时间就不够了，就把预约取消了，走去了北海公园散步，教了他们怎么拍全景，拍了鸳鸯、坐了轮渡。从北海公园出来后去德胜门内大街的峨嵋酒家吃了午饭，然后由于我爸兴致勃勃地说想看看胡同，就走兴华胡同去了恭王府，其实胡同也就那么回事啦……恭王府是挺豪华的，我们在里面迷路了几次，到后花园又迷路了几次，某个展厅里说大观园原型可能是恭王府或者至少参考了恭王府，这个我以前不知道，算是有收获啦。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgda80cdf&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgda80cdf&quot;&gt;2021-10-08 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgda80cdf&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org9e13327&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org9e13327&quot;&gt;20:14 第三天&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org9e13327&quot;&gt;
&lt;p&gt;
父母昨天表示还是想看看毛主席，于是再次预约了今天，比昨天方便的是今天天安门东站和天安门西站都开放了，就在天安门西站下车，得以少走一点路，因为时间还没到就在天安门广场上闲逛，看大花篮、人民英雄纪念碑和站岗时偷偷玩手机的武警小哥哥，顺便找一个好心、时髦且对拍照质量要求比较高的阿姨给我们拍了个三人合照。时间快到的时候去问了下工作人员，才知道要去毛主席纪念馆瞻仰，必须先到东边马路对面国博那里把包都存了，让父母在广场上等着，我一个人过去把包存了，存包处要求游客展示预约单才能进去存包但很多游客要么没预约要么预约了找不到，各种原因交织下工作人员火气很大，我当然是做了很多准备工作顺利完成各项手续，然后回去排队飞速完成瞻仰仪式。完了去前门小吃街廉价便捷地让我父母了解北京的一些基本元素，非常凑合地在东来顺让我父母了解了下铜锅涮肉，并被 LY 强烈谴责，但也没办法啊，带着两个在北京没啥自理能力的孩子，实在是没有精力去精心挑选吃食，更何况昨天人均 70 的峨嵋酒家还被我妈念叨了一路直到晚上。下午去了故宫，很明显刚进门后父母被宽阔的大广场、宫殿群震撼到了，但是看完三大殿到后面乾清宫、交泰殿、坤宁宫的时候就有点审美疲劳了，不过钟表馆和珍宝馆还是让他们惊叹连连，虽然到后面也麻木了，只是在出来后多次表示「皇帝的生活真是无法想像」。回程路上我妈突然蹦出来一句说想找个地方买北京特产带给亲戚，我血管都要爆了，中午逛前门的时候我都问了几次要不要买点特产带给亲戚那个时候明明说不要，想一出是一出真的和小孩没两样，于是我在 8 号线到鼓楼大街的时候说要不干脆下车我去找个店买吧，大概是觉得太麻烦我了又忙表示说不要了就是看看我住处附近超市有没有有就买没有就算了，我爸开始数落我妈，我赶紧阻止他习惯性讲各种大道理长篇大论以免形势进一步恶化，要我说我爸那些官场小说真的是白看了，当我责备我妈的时候，他应该声援我妈来达成平衡啊，两个人处不来真的是两个人自己都有一大堆毛病偏偏还都觉得是对方的问题。
&lt;/p&gt;

&lt;p&gt;
回到住处后，为了解决问题，就去附近永辉超市带我妈逛了一圈，买了明天火车上吃的东西，顺便看了一下确实没有什么烤鸭之类的卖。然后在附近湘菜馆点了菜，并被父母大加赞赏表示好吃和家里味道差不多，最后珍珠丸子剩了三个我打包带回来了。累啊，不过明天就能送走他们了，我可以休息了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>我的生活记录经验及个人工具与方法</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/09/25/record-life-with-org.html"/>
    <category term="Emacs" scheme="http://www.zmonster.me/categories.html#Emacs"/>
    <id>http://www.zmonster.me/2021/09/25/record-life-with-org</id>
    <published>2021-09-25T00:00:00+00:00</published>
    <updated>2021-09-25T00:00:00+00:00</updated>
    <description>
    
      <p>
中学的时候，我开始写日记，记录琐事和当时再正常不过的一些小心情，就这么一写一直写纸质日记到 2020 年。工作之后，我把上学时候写的日记也带在了身边，不过中学时候的只剩了高三复读时候那一本，早...</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
中学的时候，我开始写日记，记录琐事和当时再正常不过的一些小心情，就这么一写一直写纸质日记到 2020 年。工作之后，我把上学时候写的日记也带在了身边，不过中学时候的只剩了高三复读时候那一本，早先的记得应该是被我以一些现在看来蠢蠢的理由烧掉了。偶尔兴起会翻一翻自己的日记，重温当时的一些感动，记得有一年翻日记翻到和大学同学的事情，觉得特别感动，没头没脑地给同学发了条信息说「想起当时的XXX觉得好温暖啊」，对方大概会觉得莫名其妙吧。
&lt;/p&gt;


&lt;div id=&quot;org052f4b7&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/diary.png&quot; alt=&quot;diary.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;1&amp;nbsp; &lt;/span&gt;我的纸质日记&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
我经常想起曾经朋友见到后会说的两句话，一句是“你变了”另外一句则是“你一点都没变”，每次听到这两句话，都特别想问问，对方看到我没变的东西是什么、变了的东西又是什么呢？当然，有些人我可能永远也没有机会去问这个问题了，但幸好我还能从我的日记里，大致地知道自己发生了怎么样的变化，而不是只靠回忆里那些印象深刻但寥寥无几的事件来知道自己是个怎么样的人。当然，在开始写日记的那些年里，我并未意识到这些价值，只是惯性和表达欲使然，再加上潜意识里觉得记忆不靠谱产生了把一些有价值的事情记录下来的想法吧。真正发现记录的深刻价值是在我工作后。开始工作后，我发现自己有很多东西要学、有很多事情要做，每件事情又充满了不确定性和意外，且有时候极其复杂，于是开始在本子上写工作日志 —— 说是工作日志，其实也没有什么章法，写得也很潦草。据说招我进去的领导特别喜欢我学习和记录时候的认真劲，不过工资太少了最后我还是跳槽了。
&lt;/p&gt;


&lt;div id=&quot;org35dbd04&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/pachira_journal.jpg&quot; alt=&quot;pachira_journal.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;2&amp;nbsp; &lt;/span&gt;一篇调试错误的工作日志&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
从 2015 年第二份工作起，我便开始在电脑上记工作日志，简单做了下统计，去掉空行和空格后，从 2015 年 3 月 10 日到今天（2021 年 9 月 25 日），累计写了 15.3 万行共 734 万字，平均每天写 64 行共 3070 字，也不算很多，但是能一做就是这么多年，我还是挺自得的。我的工作日志按日期来顺序记录，都是尽量追求把处理问题的完整过程（包括思考和执行）都记录下来，可复现性还是比较高的，现在同事如果问一个几年前我经手过的事情，我基本上都能在日志中找到过程，如果有必要的环境把当时做的事情重做一遍基本也可以做到 —— 事实上我自己在工作中隔了半个月甚至几个月要重新做一件事情也并不少见，这种情况下工作日志也帮到我很多。
&lt;/p&gt;


&lt;div id=&quot;org3e33509&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2017_work_journal_sample.png&quot; alt=&quot;2017_work_journal_sample.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;3&amp;nbsp; &lt;/span&gt;2017年工作日志片段&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
到 2018 年下半年的时候，我开始关注自己的时间使用情况，用 &lt;a href=&quot;https://apps.apple.com/us/app/life-cycle-track-your-time/id1064955217&quot;&gt;Life Cycle&lt;/a&gt; 这款 iOS 软件对自己的日常时间开销做一些粗粒度的自动记录，并且在年终总结（见&lt;a href=&quot;https://www.zmonster.me/2019/01/01/annual-summary-of-2018.html&quot;&gt;2018年总结&lt;/a&gt;和&lt;a href=&quot;https://www.zmonster.me/2020/01/04/annual-summary-of-2019.html&quot;&gt;2019年总结&lt;/a&gt;）的时候用来做一些简单统计和分析。说实在的，这个记录的粒度非常粗，大概就是根据我的位置之类的，判断我在什么场所做什么事情，如果我在一个场所做了两类不同的事情，就需要我自己去手工修正类别，但因为它自动记录和分类的特性，作为一个初步的尝试还是不错的，用了几年后，至少对自己的时间使用情况有了一个数字上的认识。
&lt;/p&gt;


&lt;div id=&quot;org19779ad&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/life_cycle.jpg&quot; alt=&quot;life_cycle.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;4&amp;nbsp; &lt;/span&gt;&quot;Life Cycle 记录&quot;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
如果说写工作日志是为了更好的工作，那么写个人日记和做时间记录则是为了更好地认识自己，而 Life Cycle 这样粗粒度的记录并不能满足我的要求，于是在 2019 年下半年开始，我开始摸索更适合自己的时间记录方式，并在 2020 年逐步进行完善后开始正式使用，目前基本上能把我每天的时间使用情况按事情精确到分钟级进行记录，虽然不是自动化的，但也不会耗费太多精力，写今年的&lt;a href=&quot;https://www.zmonster.me/2021/07/04/semi-annual-summary.html&quot;&gt;半年总结&lt;/a&gt;的时候就用到了这个方法产生的数据。
&lt;/p&gt;

&lt;p&gt;
对于我的记录方法，有若干网友在我的数篇文章的评论里表示感兴趣，所以在这里简单说一下，其实并没有什么很复杂的东西，就是用 org-mode 的 org-agenda 功能，下面是我的 agenda 视图：
&lt;/p&gt;


&lt;div id=&quot;org69c2c73&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/my_agenda_view.png&quot; alt=&quot;my_agenda_view.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;5&amp;nbsp; &lt;/span&gt;我的 agenda 视图&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在这个视图里，我可以按一下 I(大写) 开始某项任务的计时，按一下 O(大写) 则结束任务的计时，操作是很简单的，我要做的是调整一些短期任务让他们显示到「今日事项」这个区域里，这种短期任务一天不会超过十件，只需要在每天做梳理和计划的时候处理即可，而这个梳理和计划我又是通过图上「写今日计划」来进行的，所以这个梳理和计划的耗时也可以得到记录。用 org-mode 来管理任务，这个对 org-mode 用户是很自然的事情，我做的一点点微小创新（其实是不是创新都不好说），就是把一些日常的事情作为“纯计时任务”纳入到这个体系里面了，就这么简单。公司有同事看到我这个方法后有和我讨论，他不用 Emacs 更别说 org-mode 了，但其实是可以借鉴思路的，要能把这个记录过程进行下去，最根本的一点就是操作要尽量的简单和快捷：（1）任务的查找和定位要快，org-agenda 的好处就是提供了一个统一的视图来展示不同来源的任务，其他工具如果也能做到这点的话也会很棒；（2）任务的计时操作要简单便捷，最好是按一个键就能完成。基于这个共识，我们讨论了几种可能的方案：（1）使用 Alfred，自己写点 Apple Script 来定位任务、进行计时；（2）使用 zsh，通过自动补全功能来迅速定位任务并进行计时。
&lt;/p&gt;

&lt;p&gt;
如果对我用 org-agenda 进行时间记录的方法有兴趣，可以看看我准备的示例配置：&lt;a href=&quot;https://github.com/Linusp/org-agenda-example&quot;&gt;https://github.com/Linusp/org-agenda-example&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
需要强调的是，对我来说，自我记录和自我管理，是两个完全不同的事情，我绝对不会想要把这两个事情混到一起去 —— 记录强调时序、强调过去、强调忠于事实，而管理则尝试控制未来的走向，这对我来说太难了，而且我也不认为人能要求事情的未来按照自己的要求或期望进行。我们没有办法减少未来的不确定性，只能去应对它们，但通过记录来减少对过去的记忆的模糊，是每一个人都能去做的。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/08/02-2021/09/05)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/09/05/2021-august.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/09/05/2021-august</id>
    <published>2021-09-05T00:00:00+00:00</published>
    <updated>2021-09-05T00:00:00+00:00</updated>
    <description>
    
      <p>近期生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org91e0e9a&quot;&gt;2021-08-02 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgcb19752&quot;&gt;22:00 打断&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb8e56fd&quot;&gt;22:00 幽邃&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org880661e&quot;&gt;2021-08-03 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org0b2a6ee&quot;&gt;12:06 复利&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd0a7ba7&quot;&gt;2021-08-04 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orge0fde36&quot;&gt;08:28 鼻炎&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb0bc6f5&quot;&gt;2021-08-06 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org2e94c62&quot;&gt;07:59 充实&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org63dab25&quot;&gt;2021-08-08 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgddaec24&quot;&gt;09:14 梦&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6d60f74&quot;&gt;16:06 断电&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2e76c14&quot;&gt;2021-08-09 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org1b43f35&quot;&gt;08:16 断电原因&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8b626ea&quot;&gt;21:30 disqus&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb42e663&quot;&gt;2021-08-10 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgecdad56&quot;&gt;22:58 中签&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org942abc2&quot;&gt;2021-08-11 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org5600d69&quot;&gt;12:22 蛋卷基金&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org371abe2&quot;&gt;14:00 倒三轮&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgccb928d&quot;&gt;22:32 咸甜&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga3e1505&quot;&gt;2021-08-12 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org1b73698&quot;&gt;10:28 感动&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc260d4a&quot;&gt;23:35 链接&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1f94a74&quot;&gt;2021-08-13 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org0815a59&quot;&gt;08:47 图片&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org66309c4&quot;&gt;2021-08-18 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga01bcfb&quot;&gt;13:30 一次对话&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf798b89&quot;&gt;2021-08-20 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgb3041b8&quot;&gt;20:00 损失厌恶&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org9b5f9fa&quot;&gt;2021-08-22 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org70bd6a4&quot;&gt;22:00 小饭桌&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org47cafa0&quot;&gt;22:42 中元&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org93b16c1&quot;&gt;23:53 模糊&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc05e776&quot;&gt;2021-08-23 周一&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org21a024b&quot;&gt;2021-08-24 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgc4a73a1&quot;&gt;14:00 两元甜筒&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1b2b214&quot;&gt;17:14 压力&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgff5e607&quot;&gt;23:33 日记&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgbfb0571&quot;&gt;2021-08-25 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org66ef0ad&quot;&gt;21:03 臃肿&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1d3dbc8&quot;&gt;2021-08-27 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgbe0ebad&quot;&gt;10:06 呆&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6b19419&quot;&gt;21:09 Fight or Flight&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4cbd970&quot;&gt;2021-08-28 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgd827b22&quot;&gt;11:53 洛斯里克&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga717daf&quot;&gt;2021-08-29 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org769c731&quot;&gt;23:52 实习&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgfd4812d&quot;&gt;2021-08-31 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org1dfd49e&quot;&gt;10:06 音游&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org614c033&quot;&gt;10:34 算法推荐管理规定意见稿&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org9a8eba7&quot;&gt;2021-09-01 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgda84728&quot;&gt;07:58 噩梦&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org875b8af&quot;&gt;2021-09-02 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org5f59cf1&quot;&gt;08:00 秋意&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org25aff0b&quot;&gt;21:56 新高&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5ffdc97&quot;&gt;2021-09-05 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org5acf40c&quot;&gt;21:04 三十周岁&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org91e0e9a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org91e0e9a&quot;&gt;2021-08-02 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org91e0e9a&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgcb19752&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgcb19752&quot;&gt;22:00 打断&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgcb19752&quot;&gt;
&lt;p&gt;
我不喜欢别人打断我，但我其实也经常打断同事来着，这个其实也不太好……
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb8e56fd&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb8e56fd&quot;&gt;22:00 幽邃&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb8e56fd&quot;&gt;
&lt;p&gt;
《黑暗之魂》：发现幽邃教堂可以直接从顶上走去罗莎莉雅的篝火，这样可以跳过被帕奇坑的阶段，让他直接回传火祭祀场，然后买装备在净身小教会救洋葱。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org880661e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org880661e&quot;&gt;2021-08-03 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org880661e&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org0b2a6ee&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org0b2a6ee&quot;&gt;12:06 复利&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org0b2a6ee&quot;&gt;
&lt;p&gt;
其实，从表面来看，基金是没什么复利的，净值型产品，所有盈利都是纸面上的，分红一般也不多。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd0a7ba7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgd0a7ba7&quot;&gt;2021-08-04 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgd0a7ba7&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orge0fde36&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge0fde36&quot;&gt;08:28 鼻炎&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge0fde36&quot;&gt;
&lt;p&gt;
半夜两点醒过来了，鼻炎导致呼吸不畅 —— 还不是堵住那种不畅，就是不舒服……
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb0bc6f5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgb0bc6f5&quot;&gt;2021-08-06 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgb0bc6f5&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org2e94c62&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2e94c62&quot;&gt;07:59 充实&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2e94c62&quot;&gt;
&lt;p&gt;
因为忙碌而感到充实，但这忙碌并没有让我变得更好，充实我的是什么呢？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org63dab25&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org63dab25&quot;&gt;2021-08-08 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org63dab25&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgddaec24&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgddaec24&quot;&gt;09:14 梦&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgddaec24&quot;&gt;
&lt;p&gt;
醒了，朦胧间摸到枕边的手机，看到两条朋友在 8 点多发过来的消息，说梦到和我在家里的小酒馆吃饭聊天。
&lt;/p&gt;

&lt;p&gt;
我好久没有梦到过什么人了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6d60f74&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6d60f74&quot;&gt;16:06 断电&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6d60f74&quot;&gt;
&lt;p&gt;
半夜断了一次电，有一些设备因为断电发出了短促的蜂鸣声把我吵醒了一会，没想到下午又断电，半小时内断了三次吧，不知道在干嘛。
&lt;/p&gt;

&lt;p&gt;
&lt;span class=&quot;timestamp-wrapper&quot;&gt;&lt;span class=&quot;timestamp&quot;&gt;[2021-08-08 日 19:00] &lt;/span&gt;&lt;/span&gt; 有病啊，七八次了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2e76c14&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org2e76c14&quot;&gt;2021-08-09 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org2e76c14&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org1b43f35&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1b43f35&quot;&gt;08:16 断电原因&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1b43f35&quot;&gt;
&lt;p&gt;
昨天下午到晚上断电十几次吧……今早物业上门了，问家里有没有什么电器一开就跳闸，说他们昨天排查了一天并没有发现具体的故障，只能猜测是谁家里的电器有问题，正在挨个上门问。能是啥问题啊，电器短路了，还是功率过大？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8b626ea&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8b626ea&quot;&gt;21:30 disqus&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8b626ea&quot;&gt;
&lt;p&gt;
通过朋友在我博客的评论，我才知道原来现在 disqus 强制展示广告了，我可能因为是老用户才可以自己选择是否开启广告。虽然不太喜欢，但是人家也是需要生存的，只能说可以理解吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb42e663&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgb42e663&quot;&gt;2021-08-10 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgb42e663&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgecdad56&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgecdad56&quot;&gt;22:58 中签&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgecdad56&quot;&gt;
&lt;p&gt;
第一次新股中签！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org942abc2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org942abc2&quot;&gt;2021-08-11 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org942abc2&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org5600d69&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5600d69&quot;&gt;12:22 蛋卷基金&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5600d69&quot;&gt;
&lt;p&gt;
发现蛋卷基金是有网页版的，简单试了下导出交易记录成功了，其他的应该也可以。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org371abe2&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org371abe2&quot;&gt;14:00 倒三轮&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org371abe2&quot;&gt;
&lt;p&gt;
在公司门口看到一辆倒三轮的车，挺好玩的，大概是下面这个样子。
&lt;/p&gt;


&lt;div id=&quot;org4618d16&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/tricycle.jpg&quot; alt=&quot;tricycle.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgccb928d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgccb928d&quot;&gt;22:32 咸甜&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgccb928d&quot;&gt;
&lt;p&gt;
饭罪吃重庆火锅，发现椰奶冰沙和红锅中捞出来热乎的鲜鸭血特别的搭，鸭血的滑嫩和冰沙的绵密特别般配，前者轻微的咸辣味和后者的甜腻以及奶香交织在一起产生有层次的、丰富的味道，冰沙的冰爽又极好地压下了刚从锅中捞出的鸭血的热辣，于是连着这样吃了好几块鸭血。这种吃法让我想起小时候在潮汕吃过的西瓜，老板用漂亮的手法将西瓜切成小块，和刨冰一起装进塑料袋，然后浇上辣椒油，好吃极了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga3e1505&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga3e1505&quot;&gt;2021-08-12 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga3e1505&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org1b73698&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1b73698&quot;&gt;10:28 感动&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1b73698&quot;&gt;
&lt;p&gt;
又用上 lain 啦！用了半年 kubectl 和 helm 了，还是 lain 好用。
&lt;/p&gt;


&lt;div id=&quot;orgb4403f5&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/lain.jpg&quot; alt=&quot;lain.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc260d4a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc260d4a&quot;&gt;23:35 链接&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc260d4a&quot;&gt;
&lt;p&gt;
Telegram 里每条消息都有对应的链接，Slack 也是，这非常好。之前在思考自己的知识管理系统的时候，发现会有部分信息是从朋友那里来的，通常是在Telegram/Slack/微信这些地方聊天的时候产生的，虽然我能把元信息尽量记录下来，但能追溯到发生时的场景当然会更好一些，这个发现算是解决了我这个问题吧。我的微信消息大部分都转发到 Telegram 了，所以微信消息的问题也相当于解决了；飞书作为协同工具和 Slack 算是一类工具，就去看了一下飞书是否有类似的功能，结果当然是我想多了。
&lt;/p&gt;


&lt;div id=&quot;org8c1f890&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/telegram_message_link.png&quot; alt=&quot;telegram_message_link.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org38ef547&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/slack_message_link.png&quot; alt=&quot;slack_message_link.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1f94a74&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1f94a74&quot;&gt;2021-08-13 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org1f94a74&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org0815a59&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org0815a59&quot;&gt;08:47 图片&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org0815a59&quot;&gt;
&lt;p&gt;
想要一个本地存储的、开源的图片管理工具，希望它在基本的图片管理功能基础上，还能像 Zotero 一样能生成文献引用数据库，提供 URI 供外部程序进行链接，找了一圈并没有找到 Linux 上能用的，看到一些直接用 Zotero 来做图片管理的，但 Zotero 连预览图像都做不到，也没法提取图片的各种元信息，如果有插件能解决这些问题的话或许可以试试。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org66309c4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org66309c4&quot;&gt;2021-08-18 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org66309c4&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orga01bcfb&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga01bcfb&quot;&gt;13:30 一次对话&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga01bcfb&quot;&gt;
&lt;p&gt;
记不太清，略去很多细节
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;X: 可能和我的家庭和性格有关系，我就想找个小城市，不想干互联网了。&lt;/li&gt;
&lt;li&gt;我: 不想工作这个念头大家都有，我和其他朋友或多或少都聊过这个话题。&lt;/li&gt;
&lt;li&gt;X: 看大家工作很有热情，我还以为是我的问题，现在就后悔从前司离职后没有好好玩一段时间。&lt;/li&gt;
&lt;li&gt;我: 我就有一个疑问没法得到解答，如果不工作了该干嘛呢？岁数小点的时候，会有一个大的目标或者说理想，认为那个是自己的方向，但现在没有了，可能不工作的头两年各种玩，会觉得很开心，但可能过了头两年，就会不知道该干嘛了。&lt;/li&gt;
&lt;li&gt;X: 嗯，我懂你的意思，就是没有了那种很强的生活的驱动力。对于你这个问题，我能想到这几种情况，一个是人生进入一个新的阶段，另外一个可以结合自己的能力做一些小的能赚钱的事情，而不是像互联网玩流量（举了一个例子）。&lt;/li&gt;
&lt;li&gt;我: 人生进入一个新的阶段，比如说结婚、买房、生孩子？&lt;/li&gt;
&lt;li&gt;X: 对。&lt;/li&gt;
&lt;li&gt;我: 第二个，我最近也有类似的想法，我觉得再做一个对所有人或者说大部分人都有价值的东西，在现在的互联网环境下，可能不太现实了，但是还是有很多小的群体，为他们专门提供一些服务，还是有价值的。&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf798b89&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf798b89&quot;&gt;2021-08-20 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf798b89&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgb3041b8&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb3041b8&quot;&gt;20:00 损失厌恶&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb3041b8&quot;&gt;
&lt;p&gt;
今天中国电信上市，集合竞价阶段涨 20%，但我不知道那个阶段能卖，等 09:30 开盘后涨幅迅速收窄至 3%~5%，我怕还会继续跌，就以 4.68 的价格卖了，扣掉手续费后只赚了 140，结果中午价格又涨回去了，仔细一算我原来能赚近 1000，但最终赚了 140 就跑了，虽然实际上行还是赚了钱，但心理上还是认为自己遭受了损失。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org9b5f9fa&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org9b5f9fa&quot;&gt;2021-08-22 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org9b5f9fa&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org70bd6a4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org70bd6a4&quot;&gt;22:00 小饭桌&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org70bd6a4&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;参与者：ZZ、YS、我、K&lt;/li&gt;
&lt;li&gt;食物

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;K 从家里带来的羊肉，做成的红焖羊排&lt;/li&gt;
&lt;li&gt;K 带来的酱牛肉，LY 淋了点红油&lt;/li&gt;
&lt;li&gt;鲜椒跳水鲈鱼&lt;/li&gt;
&lt;li&gt;拌三丝&lt;/li&gt;
&lt;li&gt;ZZ 和 YS 带来的柚子醋鸡皮、酱油麴烤鸡排、热炉月饼、绿茶酥&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;饭后活动: 打《双人成行》最后两章，顺利通关&lt;/li&gt;
&lt;li&gt;去 LY 家附近吃晚饭，点了一个尖椒焖蛋、油渣炒油菜和一大碗的面炕肉，吃撑，第三个菜没吃完，打包我带走了&lt;/li&gt;
&lt;li&gt;饭后 LY 骑电动车送我到地铁站&lt;/li&gt;
&lt;/ul&gt;


&lt;div id=&quot;org5797abb&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20210822_food.jpg&quot; alt=&quot;20210822_food.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org47cafa0&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org47cafa0&quot;&gt;22:42 中元&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org47cafa0&quot;&gt;
&lt;p&gt;
从地铁回去的路上，在一个小区的出入口附近看到十几堆灰烬，晚风吹过，火星四散，烟雾在地面弥漫。死者已逝，只是活人想要记住死者，并在这种祭祀中强化那些自己挑选过的回忆，以便使自己得到慰藉。我父亲有时候会说，如果我祖父还在世就好了，能看到我考上了大学会很欣慰，但我记得他在世时苦难繁多，只是因我欣慰那么一两回就要继续承受那些，我觉得那对他不公平，说到底也不过是我父亲的一厢情愿罢了，但毕竟那是他的父亲，他有更强烈的执念也理所当然 —— 我印象中的祖父就只是那个在墙边端着水杯晒太阳看报纸的沉默老人罢了，年少时的记忆缺乏记录，早已不记得除此以外的大部分细节。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org93b16c1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org93b16c1&quot;&gt;23:53 模糊&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org93b16c1&quot;&gt;
&lt;p&gt;
只是一周之内的事情，当时忘了记录，就已然模糊。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc05e776&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgc05e776&quot;&gt;2021-08-23 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgc05e776&quot;&gt;
&lt;p&gt;
早上没吃早饭，最近这种状况挺多，久了对身体不好。
&lt;/p&gt;

&lt;p&gt;
在去公司的地铁上，把闻泰转债卖掉了，并卖出了周五买入的招行 —— 目的是把招行从华宝证券上转到银河证券上，所以并没有赚太多。
&lt;/p&gt;

&lt;p&gt;
刚到公司，表弟又来没头没脑地问域名和网站的事情，说也说不清楚，还说什么「你操作一个论坛应该难度不高吧 实在不行我去北京找下学习」可真是吓到我了。多聊了会后得知他虽然在做运营，但对技术有兴趣所以自己在学，最终目标是能自己开发和维护论坛一类的网站，估计报了一些培训班或者网课学了点皮毛表面的东西，学这点当然解决不了他所有疑惑就来问我，但也问不到点上。我确定他有兴趣后，承诺给他打点基础，约了这周日先和他讲下基础的东西，所以这周也要准备一下资料了。
&lt;/p&gt;

&lt;p&gt;
（此处略去工作相关的事情 430 字）
&lt;/p&gt;

&lt;p&gt;
这阵子一个同事对我的反应让我有点不太适应，今天惊叹我「有这个项目的代码，好厉害」（大意是原来以为我作为算法工程师只会做一些研究性质的事情结果我居然真的会写工程代码所以感到震惊），然后聊需求的时候在边上看到我的编辑器问我是不是用的 Emacs 并在我给予肯定回复后惊叹「终于见到用 Emacs 的了」。我对他了解尚浅，不知道他是单纯的惊叹还是捎带了猎奇的心态，所以对于他这些惊叹，我都以自嘲或者无视的态度应付过去了。
&lt;/p&gt;

&lt;p&gt;
晚上回来后，把昨天打包的肉热了吃了点就当晚饭了，非常不讲究。然后又花了一个多小时梳理我的证券账户，这一个多月没记账带来的混乱后遗症，估计还得花点时间处理掉。
&lt;/p&gt;

&lt;p&gt;
写了连续的、较长的日记，体验和写碎片化的一些事情还挺不一样的，能让我把混沌的记忆确定下来，我挺喜欢的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org21a024b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org21a024b&quot;&gt;2021-08-24 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org21a024b&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgc4a73a1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc4a73a1&quot;&gt;14:00 两元甜筒&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc4a73a1&quot;&gt;
&lt;p&gt;
吃完午饭路过蜜雪冰城，得知两元甜筒不再卖了，不开心。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1b2b214&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1b2b214&quot;&gt;17:14 压力&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1b2b214&quot;&gt;
&lt;p&gt;
会议室突然传出来一个人大声说话的声音，带着点快要哭泣时的那种沙哑，大意是在说自己很累压力很大，应该是运营或者销售团队的人。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgff5e607&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgff5e607&quot;&gt;23:33 日记&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgff5e607&quot;&gt;
&lt;p&gt;
今天天气特别的舒服，有秋天那个味道了，被电动车俘虏的 LY 今天午饭的时候也为了享受凉爽的天气而放弃了电动车改成骑车去吃午饭了。除了凉爽，照例是忙碌的一天。
&lt;/p&gt;

&lt;p&gt;
晚上回来总算把证券账户的账理得比较清楚了，至少银河证券已经能完全对上了，华宝证券明天看看。然后开了黑魂3把绘画世界的图跑了跑，点了所有篝火，尝试打了下丹涅尔和舞娘但都失败了。
&lt;/p&gt;

&lt;p&gt;
剩的那点面炕肉我晚上都吃了，好吃是好吃，但是肥肉太多了，后面好多我就把外面裹着的面吃了，里面的肥肉丢掉了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgbfb0571&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgbfb0571&quot;&gt;2021-08-25 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgbfb0571&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org66ef0ad&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org66ef0ad&quot;&gt;21:03 臃肿&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org66ef0ad&quot;&gt;
&lt;p&gt;
今天是被 pytorch 以及附带库折磨的一天，产生了把 pytorch 从我主导的每个项目的依赖里删掉的冲动。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1d3dbc8&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1d3dbc8&quot;&gt;2021-08-27 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org1d3dbc8&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgbe0ebad&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgbe0ebad&quot;&gt;10:06 呆&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgbe0ebad&quot;&gt;
&lt;p&gt;
出门去上班，坐电梯下楼，电梯门一开看到楼栋里那两只大型但比较乖的狗，还以为到了六楼还是七楼，傻乎乎地跟狗主人说「你进来吧我不怕的」，狗主人无奈地说了句「一楼」，我才反应过来，尴尬，于是夺门而逃。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6b19419&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6b19419&quot;&gt;21:09 Fight or Flight&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6b19419&quot;&gt;
&lt;p&gt;
我的下意识行为应该是逃走，感觉在工作中遇到过很多次了，遇到工作压力比较大的时候，会下意识夸大难度或者摆出放弃姿态，「你们定就好我随便，让我做什么就做什么」，大概这样。事后当然也会反省自己，但是再怎么反省，压力也不会消失。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4cbd970&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4cbd970&quot;&gt;2021-08-28 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org4cbd970&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgd827b22&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd827b22&quot;&gt;11:53 洛斯里克&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd827b22&quot;&gt;
&lt;p&gt;
早上爬起来又玩了下黑魂，居然两遍打过了舞娘，二阶段躲着大风车就好，其他的招式还是能翻滚躲一躲的，太怂反而不容易打过。打过舞娘后一路推到猎龙铠甲那，把伊果和希里斯都召唤了出来一起打，虽然猎龙铠甲血量多了很多，但在这个孤独的游戏里能有叫上朋友（虽然是 NPC）一起并肩作战的机会，当然是要用一下了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga717daf&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga717daf&quot;&gt;2021-08-29 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga717daf&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org769c731&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org769c731&quot;&gt;23:52 实习&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org769c731&quot;&gt;
&lt;p&gt;
到开学了，弟弟为实习的事情大概有点着急，投了十几家了只有两家有回应，又觉得一直待在家里待不住。除了帮忙改改简历指导一下方向，我目前也做不了什么事情，还是得看他自己呢。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgfd4812d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgfd4812d&quot;&gt;2021-08-31 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgfd4812d&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org1dfd49e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1dfd49e&quot;&gt;10:06 音游&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1dfd49e&quot;&gt;
&lt;p&gt;
地铁里看到一个姑娘在手机上横屏玩音游，手速飞快，我看着都眼花。音游我还是不擅长呀，好像也就玩过一个 QQ 音速，看了下，这游戏国服 19 年停止运营了哈哈。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org614c033&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org614c033&quot;&gt;10:34 算法推荐管理规定意见稿&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org614c033&quot;&gt;
&lt;p&gt;
&lt;a href=&quot;http://www.cac.gov.cn/2021-08/27/c_1631652502874117.htm&quot;&gt;http://www.cac.gov.cn/2021-08/27/c_1631652502874117.htm&lt;/a&gt;
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
用户自主权，举双手赞成
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;org894cabe&quot;&gt;
第十五条 算法推荐服务提供者应当向用户提供不针对其个人特征的选项，或者向用户提供便捷的关闭算法推荐服务的选项。用户选择关闭算法推荐服务的，算法推荐服务提供者应当立即停止提供相关服务。

算法推荐服务提供者应当向用户提供选择、修改或者删除用于算法推荐服务的用户标签的功能。
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
要求存档六个月的日志及相关信息，应该是指给用户推荐了什么之类的记录？
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;org521b0f1&quot;&gt;
第二十三条 具有舆论属性或者社会动员能力的算法推荐服务提供者应当按照国家有关规定开展安全评估。

算法推荐服务提供者应当完善算法推荐服务管理机制，对算法推荐服务日志等信息进行留存，留存期限不少于六个月，并在相关执法部门依法查询时予以提供。
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
订单分配应保障劳动者权益，具体不知道该怎么执行
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;orge8e6650&quot;&gt;
第十七条 算法推荐服务提供者向劳动者提供工作调度服务的，应当建立完善平台订单分配、报酬构成及支付、工作时间、奖惩等相关算法，履行劳动者权益保障义务。
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
禁止大数据杀熟
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;orgddfe281&quot;&gt;
第十八条 算法推荐服务提供者向消费者销售商品或者提供服务的，应当保护消费者合法权益，不得根据消费者的偏好、交易习惯等特征，利用算法在交易价格等交易条件上实行不合理的差别待遇等违法行为。
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
互联网信息服务算法备案系统
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;orgbbdcee3&quot;&gt;
第二十条 具有舆论属性或者社会动员能力的算法推荐服务提供者应当在提供服务之日起十个工作日内通过互联网信息服务算法备案系统填报服务提供者的名称、服务形式、应用领域、算法类型、算法自评估报告、拟公示内容等信息，履行备案手续。
&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org9a8eba7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org9a8eba7&quot;&gt;2021-09-01 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org9a8eba7&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgda84728&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgda84728&quot;&gt;07:58 噩梦&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgda84728&quot;&gt;
&lt;p&gt;
梦到现实中可能发生的糟糕事情，没有比这更恐怖的了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org875b8af&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org875b8af&quot;&gt;2021-09-02 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org875b8af&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org5f59cf1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5f59cf1&quot;&gt;08:00 秋意&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5f59cf1&quot;&gt;
&lt;p&gt;
晚上不盖东西睡觉已经会觉得冷了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org25aff0b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org25aff0b&quot;&gt;21:56 新高&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org25aff0b&quot;&gt;
&lt;p&gt;
经过了一个多月的低谷期，我的投资的累计收益终于回来并且新高了，不容易啊。
&lt;/p&gt;


&lt;div id=&quot;org9e1ea7b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20210902_keysersoze.png&quot; alt=&quot;20210902_keysersoze.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
注：上图显示的是收益金额不是收益率，由于我不想把我真的赚了多少钱展示出来，就把所有数据除以最大值相当于做了一个隐私保护，所以图上的 1.0 并不是说我有了 100% 的收益。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5ffdc97&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org5ffdc97&quot;&gt;2021-09-05 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org5ffdc97&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org5acf40c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5acf40c&quot;&gt;21:04 三十周岁&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5acf40c&quot;&gt;
&lt;p&gt;
（生日在工作日，本来 ZZ 提议周末去吃湘彬萱和她做的蛋糕，但我忽然很想吃珍滋味，就提议去珍滋味请大家吃顿饭，最后变成了在 ZZ 家六人聚餐，ZZ 安排外卖了珍滋味的火锅、采买了各类海鲜肉类，我就只用安心出钱了）
&lt;/p&gt;

&lt;p&gt;
昨晚三点多才睡着，醒来仍然头疼，吃了点东西玩了会后洗了个热水澡精神才好起来。天气阴凉，出门后还能看到夜里下雨的痕迹，等我坐地铁到 ZZ 家的时候 K 已经到了，随后 XKL 也到了，LY 惯例晚到。珍滋味的外卖到的稍迟了一些，先吃了 ZZ 做的提拉米苏 —— 我对甜点没什么研究和鉴赏能力，嘴里只能蹦出来甜和好吃两个词，不过其他人评价都很高啦，说不比外面店里卖的还好，因为用料很好嘛。等珍滋味的瑶柱粥锅底和佛跳墙锅底到了后就正式开吃了，两份锅底都分别用六个较大的外卖用塑料碗装着，大概两碗能盛满一锅的样子，所以锅底其实并不贵。瑶柱粥煮开后滚烫，夹肉的时候溅到两滴到手背和手指上疼得我直咧嘴。吃饭过程就没啥好说的啦，吃了小象拔蚌、基围虾、雪花牛肉、吊龙、牛五花、肥牛、五花趾、海螺、赤贝、鲍鱼、扇贝、松茸、竹荪、猴头菇、炸响铃，都很好吃啦，粥里下牛肉特别有潮汕牛肉粥的感觉，快收尾的时候还敲了几个鸡蛋到粥里。吃完肉后大家还一起分吃了 ZZ 做的水果芝士蛋糕，然后在逗渔总、闲聊中度过了一个下午。
&lt;/p&gt;


&lt;div id=&quot;orga005577&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20210905_food.jpg&quot; alt=&quot;20210905_food.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
水果芝士蛋糕
&lt;img src=&quot;/assets/img/20210905_cake.jpg&quot; alt=&quot;20210905_cake.jpg&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;
寿星吃面图和饭后葛优瘫
&lt;img src=&quot;/assets/img/20210905_person.jpg&quot; alt=&quot;20210905_person.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/07/01-2021/08/01)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/08/01/2021-july.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/08/01/2021-july</id>
    <published>2021-08-01T00:00:00+00:00</published>
    <updated>2021-08-01T00:00:00+00:00</updated>
    <description>
    
      <p>7月生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org76494b5&quot;&gt;2021-07-01 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org83b73e8&quot;&gt;08:04 触发&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb72a92b&quot;&gt;10:43 无心工作&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org12ce33b&quot;&gt;18:34 个人特点&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgdd8bf7c&quot;&gt;2021-07-11 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org6769435&quot;&gt;18:31 优化&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org7e7d1aa&quot;&gt;22:01 电话&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc87b140&quot;&gt;2021-07-12 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org4c69439&quot;&gt;23:44 蛍&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2c535b1&quot;&gt;23:48 数字墓地&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org68c2a84&quot;&gt;23:53 死亡&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3062e25&quot;&gt;2021-07-13 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgd06a1cc&quot;&gt;23:13 酒&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6118003&quot;&gt;2021-07-14 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org60216ba&quot;&gt;23:02 再见&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2c34e72&quot;&gt;2021-07-18 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgfc90591&quot;&gt;21:43 扫码登录&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org189616d&quot;&gt;2021-07-19 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org5b5228f&quot;&gt;00:03 发愁&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgbd984ef&quot;&gt;08:01 吵&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd38a1a1&quot;&gt;15:39 电话推销&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgced94f9&quot;&gt;2021-07-21 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org8967fde&quot;&gt;20:46 犬吠&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf6ef46b&quot;&gt;2021-07-22 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org68b0792&quot;&gt;10:17 可爱&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5e1e1d3&quot;&gt;10:18 引路人&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2d03e79&quot;&gt;13:53 华宝证券&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org7f1ede3&quot;&gt;2021-07-24 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgd80defd&quot;&gt;17:08 疫苗接种&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgaa4e927&quot;&gt;23:09 重来&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org932ed80&quot;&gt;2021-07-25 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org8e8e727&quot;&gt;20:31 杀死自己&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc19a7df&quot;&gt;2021-07-27 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org297c68e&quot;&gt;23:04 离开&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgefec444&quot;&gt;2021-08-01 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgc580cf9&quot;&gt;10:00 疲惫&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga4de898&quot;&gt;21:00 七月总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-org76494b5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org76494b5&quot;&gt;2021-07-01 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org76494b5&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org83b73e8&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org83b73e8&quot;&gt;08:04 触发&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org83b73e8&quot;&gt;
&lt;p&gt;
我自己的一个小项目，今天有个人给我提 PR 修了一个低级错误，虽然并不是多大的事情，但让很久都没去管这个项目的我又想把这个项目捡起来了，看今年能不能发个 1.0 吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb72a92b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb72a92b&quot;&gt;10:43 无心工作&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb72a92b&quot;&gt;
&lt;p&gt;
百年党庆，无心工作。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org12ce33b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org12ce33b&quot;&gt;18:34 个人特点&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org12ce33b&quot;&gt;
&lt;p&gt;
我同时是 Emacs 用户、RSS 爱好者、NLP 从业人员、游戏爱好者，如果能结合我自身的这几个特点来做一些事情，想必会非常有意思。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgdd8bf7c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgdd8bf7c&quot;&gt;2021-07-11 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgdd8bf7c&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org6769435&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6769435&quot;&gt;18:31 优化&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6769435&quot;&gt;
&lt;p&gt;
为 org-agenda 写的过滤函数特别慢，今天想着优化了一下重写了一版，结果更慢了，尴尬……
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org7e7d1aa&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org7e7d1aa&quot;&gt;22:01 电话&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org7e7d1aa&quot;&gt;
&lt;p&gt;
和爸妈分别聊了电话，得知
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;今年高考的那位表弟执意选计算机，和他爸妈希望他当医生、老师意愿强烈冲突，有一些矛盾，可能我得和姨妈打个电话，避免对方认为是我让他选的；等他入学了我还是帮一帮吧，我们其实都一样，如果不能证明自己比父母强，那么他们就会以爱的名义要求我们按照他们的意愿来生活&lt;/li&gt;
&lt;li&gt;今年毕业的一位表弟没有回家，好像在上海那边找了什么事情做&lt;/li&gt;
&lt;li&gt;在家做公务员的一位高中同学升职调走了 —— 我其实不太在意他是什么级别也不想通过他获得什么便利，我想这是我能和他保持还算友好关系的原因吧&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc87b140&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgc87b140&quot;&gt;2021-07-12 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgc87b140&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org4c69439&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4c69439&quot;&gt;23:44 蛍&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4c69439&quot;&gt;
&lt;p&gt;
我不认识他，也不知道该说些什么，只是觉得难过。想起我一个伯父。
&lt;/p&gt;


&lt;div id=&quot;orgb61faa8&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/uekawakuyuurei_1.png&quot; alt=&quot;uekawakuyuurei_1.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2c535b1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2c535b1&quot;&gt;23:48 数字墓地&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2c535b1&quot;&gt;
&lt;p&gt;
有没有什么办法可以把一个过世的人的信息收集归档起来呢？我怕有一天，李文亮微博下一百万的评论会消失，像蛍这样的人的痛苦呼喊和其他人拼命但或许徒劳的安慰会消失。
&lt;/p&gt;

&lt;p&gt;
失落的信息和知识都可以被重新发现，每一个鲜活的人却不能。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org68c2a84&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org68c2a84&quot;&gt;23:53 死亡&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org68c2a84&quot;&gt;
&lt;p&gt;
我们终将迎来死亡，如果都能以一种体面而舒适的形式就好了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org3062e25&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3062e25&quot;&gt;2021-07-13 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3062e25&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgd06a1cc&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd06a1cc&quot;&gt;23:13 酒&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd06a1cc&quot;&gt;
&lt;p&gt;
劝阻了一位想买招商中证白酒的朋友，希望酒厂不要打我的脸。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6118003&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org6118003&quot;&gt;2021-07-14 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org6118003&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org60216ba&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org60216ba&quot;&gt;23:02 再见&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org60216ba&quot;&gt;
&lt;p&gt;
和当初公司的一位实习生一起吃了个饭，他现在在阿里，说觉得以前在我们那实习的时候氛围特别的好，氛围好也没用哇。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2c34e72&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org2c34e72&quot;&gt;2021-07-18 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org2c34e72&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgfc90591&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgfc90591&quot;&gt;21:43 扫码登录&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgfc90591&quot;&gt;
&lt;p&gt;
网易云音乐的网页版去掉了帐号密码登录，只允许通过手机 APP 扫码登录了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org189616d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org189616d&quot;&gt;2021-07-19 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org189616d&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org5b5228f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5b5228f&quot;&gt;00:03 发愁&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5b5228f&quot;&gt;
&lt;p&gt;
突然觉得自己很不专业，突然觉得事情很匆忙。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgbd984ef&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgbd984ef&quot;&gt;08:01 吵&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgbd984ef&quot;&gt;
&lt;p&gt;
一大早上的，小区里有一个电摩的警报声一直在响，令人无法睡着。突然就产生了换房子的想法。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd38a1a1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd38a1a1&quot;&gt;15:39 电话推销&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd38a1a1&quot;&gt;
&lt;p&gt;
接到中信银行的贷款之类的推销，这种电话接太多了，我开玩笑说了一句「不用了我很有钱」，说完自己都觉得好笑，又笑着说「不好意思开玩笑的不需要」，对面可能也是觉得是个能开玩笑的人，语气马上生动起来了，缠着让我加微信啥的又聊了几句。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgced94f9&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgced94f9&quot;&gt;2021-07-21 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgced94f9&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org8967fde&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8967fde&quot;&gt;20:46 犬吠&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8967fde&quot;&gt;
&lt;p&gt;
邻居又在楼道里溜那只极其胆小怕人的狗，不知道又嗅着了哪位陌生人的气息在那狂吠不止。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf6ef46b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf6ef46b&quot;&gt;2021-07-22 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf6ef46b&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org68b0792&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org68b0792&quot;&gt;10:17 可爱&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org68b0792&quot;&gt;
&lt;p&gt;
我可爱在哪里哇？我当然明白自己身上的优点和缺点，不过不太清楚触动别人的点是什么，或许只是「呆到深处自然萌」也说不定。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5e1e1d3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5e1e1d3&quot;&gt;10:18 引路人&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5e1e1d3&quot;&gt;
&lt;p&gt;
在集智的群里讨论救灾互助的手段，我反复在说信息的自由流通，提到 RSS，有朋友说我是他的 RSS 引路人，开心！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2d03e79&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2d03e79&quot;&gt;13:53 华宝证券&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2d03e79&quot;&gt;
&lt;p&gt;
到网站上登录可以按月导出交易对账单： &lt;a href=&quot;https://wsyyt.touker.com:7070&quot;&gt;https://wsyyt.touker.com:7070&lt;/a&gt;
&lt;/p&gt;


&lt;div id=&quot;org8d2c53a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/huabao_web_bill.png&quot; alt=&quot;huabao_web_bill.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org7f1ede3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org7f1ede3&quot;&gt;2021-07-24 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org7f1ede3&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgd80defd&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd80defd&quot;&gt;17:08 疫苗接种&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd80defd&quot;&gt;
&lt;p&gt;
加上今天我妈给我的电话，已经是这两周第三次地方政府通过家里催促我打疫苗了，我妈说隔一两天就登记一次，挺烦人的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgaa4e927&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgaa4e927&quot;&gt;23:09 重来&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgaa4e927&quot;&gt;
&lt;p&gt;
看了《重制人生》的前几集，有点感慨。
&lt;/p&gt;

&lt;p&gt;
如果时光倒流的话，该犯的错大概率还是会犯，要经历的痛苦还是要经历，会有不同但也不会有太大的不同。
&lt;/p&gt;

&lt;p&gt;
什么时候开始这种近似宿命论想法的呢？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org932ed80&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org932ed80&quot;&gt;2021-07-25 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org932ed80&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org8e8e727&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8e8e727&quot;&gt;20:31 杀死自己&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8e8e727&quot;&gt;
&lt;p&gt;
今天在小说里看到一个有趣的说法：过去的和现在的自己差距如此之大，如果在某种神秘力量作用下，现在的自己直接占据了过去自己的身体（或者未来的自己占据了现在的身体），无异于直接杀死了过去的自己，把这个过程拉长并不改变这件事情的性质。觉得这个说法很有意思，但它其实只是特修斯之船的一个变形罢了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc19a7df&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgc19a7df&quot;&gt;2021-07-27 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgc19a7df&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org297c68e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org297c68e&quot;&gt;23:04 离开&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org297c68e&quot;&gt;
&lt;p&gt;
晚上吃烤串，K 说 YS 要离职回豆瓣了，已经开始休假。我觉得挺好的，这样他有更多的时间陪 ZZ 和渔总啦。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgefec444&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgefec444&quot;&gt;2021-08-01 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgefec444&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgc580cf9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc580cf9&quot;&gt;10:00 疲惫&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc580cf9&quot;&gt;
&lt;p&gt;
昨天又去 LY 家蹭饭了，钵钵糍粑（啊并没有这道菜是我把糍粑扔钵钵鸡的汤汁里）意外的不错。
&lt;/p&gt;


&lt;div id=&quot;org7b3fb1a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/0731_food.jpg&quot; alt=&quot;0731_food.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
见到了以前的一位实习生，他要从腾讯研究院跑路去留学了，硕博连读要 5 年。吃完饭他还有事就离开了，我们剩下四个人玩 &lt;a href=&quot;http://picoparkgame.com/en/&quot;&gt;PICO PARK&lt;/a&gt; 到晚上，特别欢乐，但是最后有一关容错率太低始终过不了。
&lt;/p&gt;


&lt;div id=&quot;org9c8c4bb&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/pico_park.png&quot; alt=&quot;pico_park.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
打完游戏去吃了&lt;a href=&quot;http://www.dianping.com/shop/H4GJ1dosmNRhLiWz&quot;&gt;1998小树林烧烤&lt;/a&gt;，没拍照，不过我还是比较喜欢，本来特别困了的，最后还是吃了不少。吃完回到家已经很晚了，睡了一觉起来还是觉得挺累的，这就是快乐的代价吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga4de898&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga4de898&quot;&gt;21:00 七月总结&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga4de898&quot;&gt;
&lt;p&gt;
月度总结就随便一点不画图了。
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;休息时间 252 小时，包含了在公司午睡的时间和周末赖床的时间，总之 8.14 小时这个平均值是有水分啦……&lt;/li&gt;
&lt;li&gt;日常行为耗时 121 个小时，大头在通勤和吃饭上，并没有什么大变化&lt;/li&gt;
&lt;li&gt;休闲时间 112 小时……基本上就是下班回来后打开 B 站看《黑暗之魂》的视频，偶尔看点番；以及，开始玩《只狼》了，目前卡在火牛那里&lt;/li&gt;
&lt;li&gt;进行了 10 个小时的个人项目开发，主要是在优化我的 &lt;a href=&quot;https://github.com/Linusp/python-inoreader&quot;&gt;python-inoreader&lt;/a&gt; 项目，目前已经有比较完整的规划了，计划在国庆前发个 1.0 吧&lt;/li&gt;
&lt;li&gt;写作花了 11 个小时，其中 7 个小时是用在写半年总结上，还有 4 个小时花在一篇未完成的 org-mode 相关的文章上&lt;/li&gt;
&lt;li&gt;工作时间 167.5 个小时，7 月一共 22 个工作日，所以日均工作时间是 7.6 个小时，还行哦&lt;/li&gt;
&lt;li&gt;7 月份大项目推进很快，我这边事情也开始多起来了，工作量吧也不能说大，但事情多有时候就会觉得烦躁。&lt;/li&gt;
&lt;li&gt;投资方面这个月亏损严重，主要原因是没有仓位控制的意识，下跌的时候没有节奏地进行频繁加仓 —— 很多道理以前都知道，但还是要挨了打才会长记性&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>半年总结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/07/04/semi-annual-summary.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2021/07/04/semi-annual-summary</id>
    <published>2021-07-04T00:00:00+00:00</published>
    <updated>2021-07-04T00:00:00+00:00</updated>
    <description>
    
      <p>2021年上半年的收获和感悟。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;org3666bf0&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2021_semi_annual_stats.png&quot; alt=&quot;2021_semi_annual_stats.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
从 2019 年开始，我对自己每天在各项事情上的时间消耗进行跟踪和记录，上图是根据这些记录画出来的 2021 年上半年时间开销统计图，181 天中未被记录的时间开销放到了「其他」部分，约为 2% 左右。从统计结果来看，我个人最大的时间开销分别为：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;休息：包含晚间的睡眠、午睡等，主要组成部分还是晚间的睡眠&lt;/li&gt;
&lt;li&gt;工作：包含了在公司工作以及在家处理工作的时间&lt;/li&gt;
&lt;li&gt;日常：包含做饭、吃饭、通勤、洗漱、打扫卫生、购物、非工作目的的交通、上厕所、购物等日常行为的用时&lt;/li&gt;
&lt;li&gt;休闲：逛社交网站、看视频、看小说、玩游戏所花费的时间&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
这四部分内容占据了我所有时间的 84%，剩下 16% 的时间里我虽然进行了学习、运动、（个人的）开发、写作、自我管理等有益于个人成长的事情，但花费的时间都远远小于 TOP4 的内容。我曾经对自己的时间开销作过分析，首先工作和休息的时间是固定开销无法削减；日常时间开销中的 TOP5 分别是吃饭（239 小时）、通勤（204 小时）、洗漱（102 小时）、做饭（69 小时）和上厕所（55 小时），除了通勤可以（以搬家到公司附近作为代价）削减外，其他的时间开销也很难削减；倒是第四大块内容即休闲时间，其实是可以削减的。学习、运动、开发、写作这些有益事情我做得却很少，我不认为这是自制力的问题，而是目前我在这几类事情上都还没有建立起正反馈机制，无法从中获得足够的满足感，再加上工作带来的精力耗尽，自然就往娱乐方面投入了更多的注意力 —— 相比之下，记账和记录生活这两个事情我却做得非常好，这是因为我能从这两个行为中获得满足感，而不是因为所谓的自制力。
&lt;/p&gt;

&lt;p&gt;
基于上述分析，下半年我的行动方向就是削减休闲娱乐时间获得更多的个人成长。
&lt;/p&gt;

&lt;p&gt;
抛开统计数据来说一下上半年的概况：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
工作上：
&lt;/p&gt;

&lt;p&gt;
一月换了工作，收入有较大提升，工作内容是分析金融领域的资讯并用于推荐，不过苦于人手不足大部分时间在做一些工程向、业务向的事情，这半年来在 NLP 方面可谓毫无建树，不过学到挺多金融知识，也还不错。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
生活上：
&lt;/p&gt;

&lt;p&gt;
生活上还是以宅为主，除了玩游戏和看番之外，因为公司在望京所以体验到了许多新的美食。
&lt;/p&gt;

&lt;p&gt;
游戏一直在玩《黑暗之魂3》，还差修女芙莉德、无名之王、奴隶骑士盖尔三个 BOSS 没有打过，剧情已经走完了。下半年应该会玩《&lt;a href=&quot;https://www.douban.com/game/30245105/&quot;&gt;只狼&lt;/a&gt;》和《&lt;a href=&quot;https://www.douban.com/game/26142568/&quot;&gt;血源诅咒&lt;/a&gt;》。
&lt;/p&gt;


&lt;div id=&quot;org1a3b9fe&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2021_animes.jpg&quot; alt=&quot;2021_animes.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
动画方面，看了上面这些：《&lt;a href=&quot;https://movie.douban.com/subject/35332568/&quot;&gt;ODD TAXI&lt;/a&gt;》的故事超级棒，甚至连角色的动物形象也是叙事的一部分，这点是没有想到的，我给第一名；《&lt;a href=&quot;https://movie.douban.com/subject/35332489/&quot;&gt;Vivy&lt;/a&gt;》也非常棒，我觉得并不逊色于《ODD TAXI》，但由于是两种不同的类型而目前我偏爱《ODD TAXI》一点，就给个第二好了；《&lt;a href=&quot;https://movie.douban.com/subject/34941837/&quot;&gt;致不灭的你&lt;/a&gt;》故事催泪感人，《&lt;a href=&quot;https://movie.douban.com/subject/35225512/&quot;&gt;影宅&lt;/a&gt;》设定有趣富有深意，《&lt;a href=&quot;https://movie.douban.com/subject/33443015/&quot;&gt;悠哉日常大王&lt;/a&gt;》童趣日常，共同排列第三好了；《&lt;a href=&quot;https://movie.douban.com/subject/34990943/&quot;&gt;里世界郊游&lt;/a&gt;》新怪谈的故事挺喜欢，《&lt;a href=&quot;https://movie.douban.com/subject/34959193/&quot;&gt;记录的地平线&lt;/a&gt;》故事发挥稳定但没什么惊喜，《&lt;a href=&quot;https://movie.douban.com/subject/30267273/&quot;&gt;转生成蜘蛛又怎样&lt;/a&gt;》看个乐呵不用费脑子，这三个排在第四档好了；剩下的《&lt;a href=&quot;https://movie.douban.com/subject/35216228/&quot;&gt;奇蛋物语&lt;/a&gt;》、《&lt;a href=&quot;https://movie.douban.com/subject/34937800/&quot;&gt;动物狂想曲&lt;/a&gt;》我还没看完，不做评论。
&lt;/p&gt;

&lt;p&gt;
为了达成分工合作，社会要求我们一定程度上了解和理解他人，但更进一步地深入理解却并非必需，大家的悲喜并不相通，故事在传达情感方面却没有这个限制，正因如此，游戏、动画、小说都是我重要的情感源泉，虽然那些故事是虚假的甚至荒诞的，但他们能表达和传递的情感都可以很真实，甚至能比现实中更浓烈，我爱它们。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
投资上：
&lt;/p&gt;

&lt;p&gt;
今年我大幅调高了个人风险偏好，将绝大部分钱都投入各种投资品种中了，在个人投资水平并无明显提高的情况下获得的收益已经接近 2020 年一整年的收益，对此我还是比较满意的。我给自己的投资定的第一个阶段目标是年收益能满足在北京的一年日常开支，以上半年的情况来看，今年是有可能完成这个目标的，当然我也知道这些收益并非源自我的个人能力，绝大部分都是市场本身带来的，我还有很多东西要学习。
&lt;/p&gt;


&lt;div id=&quot;org50ce558&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2021_semi_annual_invest.png&quot; alt=&quot;2021_semi_annual_invest.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
学习投资之外，苦于没有一个工具来对不同平台上的多个投资账户进行分析，我自己写了 &lt;a href=&quot;https://github.com/Linusp/keysersoze&quot;&gt;Keysersoze&lt;/a&gt; 这个工具，虽然目前还远远谈不上完善，但自用已然足够，希望下半年能完善这个项目让别人也能使用。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
写作上：
&lt;/p&gt;

&lt;p&gt;
两个多月里每周写一篇当周的想法和生活记录，这种写作产出的内容价值不高，但也有收获一些交流，所以我还会继续坚持下去，希望以后能提供更有价值的内容吧。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
下半年的计划里，除了前面提到的投资目标、完善 Keysersoze 项目、写作，我还有一些其他的想法：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;在 NLP 方面，准备正式启动「棱镜计划（暂命名）」，事实上这个计划的最初想法是 2019 年年末产生的，它会是一个庞大的项目，今年肯定是没有办法完成的，但我希望下半年能切实地开始一些准备工作 —— 包括想一个更贴切、好听又有内涵的名字，毕竟现在这个名字和美国的网络监听计划同名了……&lt;/li&gt;
&lt;li&gt;希望能为 Emacs 社区和 RSS 社区做点事情 —— 以前我主要是通过写一些相关的文章来参与到社区讨论里，今后我希望能为相关的开源项目做一点事情，有可能的话自己写一些项目就更好了。&lt;/li&gt;
&lt;/ul&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/06/21-2021/06/27)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/06/27/2021-w25.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/06/27/2021-w25</id>
    <published>2021-06-27T00:00:00+00:00</published>
    <updated>2021-06-27T00:00:00+00:00</updated>
    <description>
    
      <p>本周想法和生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgf205454&quot;&gt;2021-06-21 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org95d0138&quot;&gt;23:33 故地&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgfd23f9b&quot;&gt;23:37 无知&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3f206a9&quot;&gt;2021-06-24 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org2fd9ffe&quot;&gt;21:31 志愿&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org9563a47&quot;&gt;2021-06-27 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgc959322&quot;&gt;09:21 分析&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1e44ef0&quot;&gt;10:25 歧视&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgde1d077&quot;&gt;17:33 蹭吃蹭喝&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge8e1e53&quot;&gt;17:44 分数&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgde6ac7c&quot;&gt;20:50 带宽&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf205454&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf205454&quot;&gt;2021-06-21 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf205454&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org95d0138&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org95d0138&quot;&gt;23:33 故地&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org95d0138&quot;&gt;
&lt;p&gt;
下班后去圆明园附近进行饭罪活动，吃完后我走去圆明园地铁站，一路看着住过两年的地方附近熟悉的夜景，城市太大我又太宅，以至于我搬离北河沿小区后再也没回去过，其实我还是挺喜欢这一片的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgfd23f9b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgfd23f9b&quot;&gt;23:37 无知&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgfd23f9b&quot;&gt;
&lt;p&gt;
看盗月社新的视频，发现我对南昌了解很少，不过我了解少的何止是南昌呢，我的家乡、我的亲朋我所知也不多 —— 除了人际、社会和周遭的环境，即使是赖以为生的专业知识我也仅仅是掌握到勉强够用的程度。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3f206a9&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3f206a9&quot;&gt;2021-06-24 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3f206a9&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org2fd9ffe&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2fd9ffe&quot;&gt;21:31 志愿&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2fd9ffe&quot;&gt;
&lt;p&gt;
表弟勉强过了一本线，在看计算机专业；表妹差一点，决定复读。表弟既然对计算机感兴趣，我就和他多聊了一点。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org9563a47&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org9563a47&quot;&gt;2021-06-27 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org9563a47&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgc959322&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc959322&quot;&gt;09:21 分析&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc959322&quot;&gt;
&lt;p&gt;
这两天把持仓分析和相关性分析加上了。
&lt;/p&gt;

&lt;p&gt;
持仓分析是根据上季度披露的基金持仓数据来估算我的投资组合里都包含了什么股票、债券，效果如下：
&lt;/p&gt;


&lt;div id=&quot;org860e73a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/keysersoze_holdings_analysis.png&quot; alt=&quot;keysersoze_holdings_analysis.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;p&gt;
相关性分析用来把组合里高相关性的基金、股票找出来，方便后续优化组合，效果如下：
&lt;/p&gt;


&lt;div id=&quot;org647ba6b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/keysersoze_corr.png&quot; alt=&quot;keysersoze_corr.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
当然，这些功能所需的数据都是从公开渠道获取的，小问题还挺多，以及展示样式也还需要优化，但总之有个东西了，慢慢调整好了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1e44ef0&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1e44ef0&quot;&gt;10:25 歧视&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1e44ef0&quot;&gt;
&lt;p&gt;
讨厌被叫中年人被叫叔叔阿姨，是不是一种年龄歧视？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgde1d077&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgde1d077&quot;&gt;17:33 蹭吃蹭喝&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgde1d077&quot;&gt;
&lt;p&gt;
又是蹭吃蹭喝的一天，感谢渔总，感谢 ZZ！
&lt;/p&gt;


&lt;div id=&quot;orgaf1bace&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20210627_foods.jpg&quot; alt=&quot;20210627_foods.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge8e1e53&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge8e1e53&quot;&gt;17:44 分数&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge8e1e53&quot;&gt;
&lt;p&gt;
今年江西理科一本线 518，我当年是 519，非常接近，然而我校计算机当年在江西的录取线是 570 多（具体记不清了），今年是 654，真是恐怖……
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgde6ac7c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgde6ac7c&quot;&gt;20:50 带宽&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgde6ac7c&quot;&gt;
&lt;p&gt;
月底电信宽带到期，之前接到过几次电话来着，我想着手机上也能办，晚上一看，原来 200M 的套餐续费最低只能选 300M 的，得多花 400 块钱，问题是我也用不上那么高的带宽啊！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/06/14-2021/06/20)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/06/20/2021-w24.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/06/20/2021-w24</id>
    <published>2021-06-20T00:00:00+00:00</published>
    <updated>2021-06-20T00:00:00+00:00</updated>
    <description>
    
      <p>本周想法和生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org2378b75&quot;&gt;2021-06-14 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org9b62519&quot;&gt;17:15 灰羽&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org436834f&quot;&gt;18:27 新机&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4efdd21&quot;&gt;19:14 不胖秘诀&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1a00711&quot;&gt;2021-06-15 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgfeb2292&quot;&gt;21:46 醉&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4384d22&quot;&gt;22:00 环&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgad580a6&quot;&gt;23:09 工具&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5dac638&quot;&gt;2021-06-16 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orge3fb21f&quot;&gt;10:14 RSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgfddc4cc&quot;&gt;22:00 事件抽取&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga3dfedf&quot;&gt;22:00 野炊2！&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org7468801&quot;&gt;2021-06-17 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org8a84dad&quot;&gt;17:51 鸟&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1459c2c&quot;&gt;2021-06-18 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org3477e6d&quot;&gt;14:23 躺平&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org84d3c65&quot;&gt;22:00 异常&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6891587&quot;&gt;2021-06-19 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org5f9da5a&quot;&gt;12:50 新旧手机&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc2d488c&quot;&gt;18:20 世界尽头&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd0ce135&quot;&gt;19:49 涨价&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org7777fd7&quot;&gt;2021-06-20 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org7e19a1e&quot;&gt;08:53 喜加一&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2378b75&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org2378b75&quot;&gt;2021-06-14 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org2378b75&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org9b62519&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org9b62519&quot;&gt;17:15 灰羽&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org9b62519&quot;&gt;
&lt;p&gt;
心血来潮看了看《灰羽联盟》的评论，看到有人说故事可能借鉴了村上春树的《世界尽头与冷酷仙境》，于是找来开始看了，挺有意思的。说起来，他的书我都没看过。
&lt;/p&gt;


&lt;div id=&quot;orgef4896d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/haibane_renmei.jpg&quot; alt=&quot;haibane_renmei.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org436834f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org436834f&quot;&gt;18:27 新机&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org436834f&quot;&gt;
&lt;p&gt;
之前想换手机纠结了挺长时间不知道该选啥，最后决定买了个二手 iPhone SE2，毕竟我不想花太多时间在适应新系统上，也不想花太多钱在手机上。我这台 iPhone 6s 用了五年多快六年了，别人会觉得我节省其实我只是懒。手机刚刚送到了，成色很好。不得不说苹果在用户体验方面做得还是不错的，开机后自动检测到旧手机，直接就提示让我把手机拿到旁边同步数据，按照提示一步步来非常友好。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4efdd21&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4efdd21&quot;&gt;19:14 不胖秘诀&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4efdd21&quot;&gt;
&lt;p&gt;
写上周总结的时候瞄了一眼，发现上厕所的时间接近两个小时，平均下来每天有 15 分钟以上在上厕所，我可能找到我能吃不（那么快）胖的秘诀了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1a00711&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1a00711&quot;&gt;2021-06-15 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org1a00711&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgfeb2292&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgfeb2292&quot;&gt;21:46 醉&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgfeb2292&quot;&gt;
&lt;p&gt;
回家路上，路旁一个男子趴在车上，嚎着歌，边上两个男子在旁边看护着，应该是喝醉了酒。有些人需要靠着酒醉或者别的什么东西才能说出所谓的真心话，其实人和人都有可能真切地传达自己的情感，只不过语言经常会把这一切都扭曲掉，或者说，不是语言而是所谓的语境、语用、上下文这堆东西会把语言的所指卷入一个无穷的嵌套里，所谓的酒后吐真言，无非是用来把自己身上的语境锁链破坏掉的一种手段而已，通过对自己进行降智来告诉别人「我所有的话都是本能没有别的任何用意所以请单纯地相信我语言的字面含义吧」，但一个不理智的人说出来的话里，真的有多少信息吗？语言是这个世界上最复杂的游戏之一了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4384d22&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4384d22&quot;&gt;22:00 环&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4384d22&quot;&gt;
&lt;p&gt;
《Elden Ring》后面又爆出老贼的采访内容，信息量超大，恨不得一下快进到 2022 年呀！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgad580a6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgad580a6&quot;&gt;23:09 工具&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgad580a6&quot;&gt;
&lt;p&gt;
不断有新的笔记工具出来，但问题根本不在工具上，而在人本身的复杂性、语言的不精确性以及世界的多样性上。总之，我对新工具已经没什么热情。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5dac638&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org5dac638&quot;&gt;2021-06-16 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org5dac638&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orge3fb21f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge3fb21f&quot;&gt;10:14 RSS&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge3fb21f&quot;&gt;
&lt;p&gt;
RSS 已死、古典互联网已死的感慨不差我们这一两句，不用过于悲观。小宇宙、Spotify 要跑马圈地又怎么样，Google Reader 倒了 RSS 也照样好好的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgfddc4cc&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgfddc4cc&quot;&gt;22:00 事件抽取&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgfddc4cc&quot;&gt;
&lt;p&gt;
看了一天事件抽取方面的东西，大体上搞明白了，感觉可以和知识图谱构建共用一套框架。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga3dfedf&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga3dfedf&quot;&gt;22:00 野炊2！&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga3dfedf&quot;&gt;
&lt;p&gt;
《塞尔达传说·旷野之息》续作发布新预告片了，信息量很大，不过公主又被抓走了，还以为可以和塞尔达一起冒险来着，哼！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org7468801&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org7468801&quot;&gt;2021-06-17 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org7468801&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org8a84dad&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8a84dad&quot;&gt;17:51 鸟&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8a84dad&quot;&gt;
&lt;p&gt;
敞开心扉！你不是犯人，你是空中逐梦飞翔的鸟！  —— 《世界尽头与冷酷仙境》
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1459c2c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1459c2c&quot;&gt;2021-06-18 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org1459c2c&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org3477e6d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3477e6d&quot;&gt;14:23 躺平&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org3477e6d&quot;&gt;
&lt;p&gt;
六月以来的这一波回调，让我的整体收益直接回到了一个月前的水平，也没有钱加仓了 —— 备用的流动资金是不会去动的，索性躺平了。
&lt;/p&gt;


&lt;div id=&quot;org58e5c44&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/june_drawdown.png&quot; alt=&quot;june_drawdown.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org84d3c65&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org84d3c65&quot;&gt;22:00 异常&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org84d3c65&quot;&gt;
&lt;p&gt;
想起来一个奇怪的地方，端午节前我每天早上出门上班，小区门口都还有很多共享单车，端午过后同样的时间一辆都没有了，发生了什么呢？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6891587&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org6891587&quot;&gt;2021-06-19 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org6891587&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org5f9da5a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5f9da5a&quot;&gt;12:50 新旧手机&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5f9da5a&quot;&gt;
&lt;p&gt;
旧手机换个电池然后卸载掉一堆国产应用（比如说微信）的话应该还是挺好用的，所以还是想利用起来，不过暂时没有比较明确的想法。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc2d488c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc2d488c&quot;&gt;18:20 世界尽头&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc2d488c&quot;&gt;
&lt;p&gt;
把《世界尽头与冷酷仙境》读完了，第一人称视角、双线叙事、满溢的表达欲望，是个复杂的故事，不好简单评价。看完后发现《灰羽联盟》确实有非常多受这本书影响的痕迹，但有很大不同的一点是，《灰羽》里只有“世界尽头”这一部分而缺失了“冷酷仙境”。
&lt;/p&gt;


&lt;div id=&quot;orge2bc1c1&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/haibane_renmei2.png&quot; alt=&quot;haibane_renmei2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd0ce135&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd0ce135&quot;&gt;19:49 涨价&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd0ce135&quot;&gt;
&lt;p&gt;
生气，FeedPress 涨价到 60 欧一年，之前是 50 刀一年，这就太过份了吧！考虑换个别的 RSS 烧录平台了 —— 我其实都不在乎他那些分析功能，只是想要一个稳定的 RSS 地址而已，大不了像以前一样直接输出 Huginn 的地址好了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org7777fd7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org7777fd7&quot;&gt;2021-06-20 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org7777fd7&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org7e19a1e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org7e19a1e&quot;&gt;08:53 喜加一&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org7e19a1e&quot;&gt;
&lt;p&gt;
Steam 上黑魂2和黑魂3史低，果断入手，就等显卡降价了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/06/07-2021/06/13)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/06/13/2021-w23.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/06/13/2021-w23</id>
    <published>2021-06-13T00:00:00+00:00</published>
    <updated>2021-06-13T00:00:00+00:00</updated>
    <description>
    
      <p>本周想法和生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org93a8201&quot;&gt;2021-06-07 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org28847e9&quot;&gt;14:05 信用卡&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org7a66e5a&quot;&gt;21:53 公积金&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org0498956&quot;&gt;2021-06-08 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgb2708cb&quot;&gt;08:10 头疼&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org24006b0&quot;&gt;08:32 京豆和京东E卡&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org298b85c&quot;&gt;2021-06-10 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org6d6c2fb&quot;&gt;16:12 神清气爽&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc74fddb&quot;&gt;08:38 如何选择&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org94c75cd&quot;&gt;2021-06-11 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgb4e2b42&quot;&gt;09:21 老头环！&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga9ef920&quot;&gt;09:47 盐！&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3be4ec5&quot;&gt;12:15 西瓜&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgaed2550&quot;&gt;2021-06-12 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org24b2c1f&quot;&gt;10:47 黑魂&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5ec50dc&quot;&gt;17:37 发呆&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgfe07404&quot;&gt;2021-06-13 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org7245372&quot;&gt;15:29 新玩具&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge895e93&quot;&gt;19:04 跨模态搜索&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-org93a8201&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org93a8201&quot;&gt;2021-06-07 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org93a8201&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org28847e9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org28847e9&quot;&gt;14:05 信用卡&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org28847e9&quot;&gt;
&lt;p&gt;
信用卡 7/16 到期，之前我看到过直接寄送到指定地点的功能，想着去操作一下直接寄到公司来，结果发现找不到这个功能了，然后信用卡还变成了「未开卡」的状态，大惊，以为新卡已经寄出，犹豫了下联系人工客服询问，告知新卡还没寄出，只是提前更新一下卡的状态而已。松了口气但也有点疑惑，按照流程还有一周才会寄新卡，干嘛这么早就改卡的状态呢？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org7a66e5a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org7a66e5a&quot;&gt;21:53 公积金&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org7a66e5a&quot;&gt;
&lt;p&gt;
把住房公积金也纳入到我的资产统计里了，这样我的总资产数字又涨了一截！逐渐完善记账体系也是一个逐渐完善自我认知的过程，虽然这笔钱暂时不怎么用得到，但是感觉很好。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0498956&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org0498956&quot;&gt;2021-06-08 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org0498956&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgb2708cb&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb2708cb&quot;&gt;08:10 头疼&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb2708cb&quot;&gt;
&lt;p&gt;
连续两天没睡好了，头疼欲裂。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org24006b0&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org24006b0&quot;&gt;08:32 京豆和京东E卡&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org24006b0&quot;&gt;
&lt;p&gt;
把京豆和京东E卡也用 beancount 记起来了。京东E卡就是上周公司发的端午节福利啦；京豆是开通了京东 PLUS 会员后按 10 倍付款金额奖励的，100 个京豆可以在购物的时候抵扣 1 块钱，积少成多也挺不错的。
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;org0f41f4e&quot;&gt;
2021-06-08 * &quot;记录京豆&quot;
  Assets:积分卡券                                               4851.00 JDB
  Equity:Opening-Balances

2021-06-08 * &quot;添加京东E卡&quot;
  Assets:积分卡券                                                200.00 JDE
  Equity:Opening-Balances
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org298b85c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org298b85c&quot;&gt;2021-06-10 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org298b85c&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org6d6c2fb&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6d6c2fb&quot;&gt;16:12 神清气爽&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6d6c2fb&quot;&gt;
&lt;p&gt;
经过两晚的恢复，今天的状态非常好。周一周二那两天吧，一来是没睡好，二来颈椎也很不舒服，睡好睡不好这个主要靠自己，颈椎的话公司准备换好点的椅子了，应该也会有改善。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc74fddb&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc74fddb&quot;&gt;08:38 如何选择&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc74fddb&quot;&gt;
&lt;p&gt;
我个人的习惯，是先把可能（而不只是当下可以）的选项列举出来，然后用排除法去掉一些特别离谱或不喜欢的，最后根据不同的维度进行相对客观的比较选出少量的候选，可以的话全都要，不可以全要的话看心情吧。和机器学习的优化过程有共通之处，尽力找全局最优或次优，如果只凭感觉或有限的信息，是很容易落到局部最优里的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org94c75cd&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org94c75cd&quot;&gt;2021-06-11 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org94c75cd&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgb4e2b42&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb4e2b42&quot;&gt;09:21 老头环！&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb4e2b42&quot;&gt;
&lt;p&gt;
出新预告片和发售日期了！明年 1 月份发售，虽然不是原来想的今年发售，但也没差多久，开心！在此之前可以去看看凯尔特神话故事，嘿嘿。
&lt;/p&gt;


&lt;div id=&quot;orgce9412b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/elden_ring.jpg&quot; alt=&quot;elden_ring.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga9ef920&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga9ef920&quot;&gt;09:47 盐！&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga9ef920&quot;&gt;
&lt;p&gt;
《盐与避难所》也公布续作了 ——《盐与牺牲》，今天是什么好日子啊，就缺《丝之歌》了！
&lt;/p&gt;


&lt;div id=&quot;org6db99b9&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/salt_and_sacrifice.jpg&quot; alt=&quot;salt_and_sacrifice.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3be4ec5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3be4ec5&quot;&gt;12:15 西瓜&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org3be4ec5&quot;&gt;
&lt;p&gt;
上周日买了个西瓜，吃了一半，剩下一半拿保鲜膜盖起来放冰箱了，之后一直没空吃，还以为坏了结果没有，开心。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgaed2550&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgaed2550&quot;&gt;2021-06-12 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgaed2550&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org24b2c1f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org24b2c1f&quot;&gt;10:47 黑魂&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org24b2c1f&quot;&gt;
&lt;p&gt;
把守墓大狼打过了，然后去试了试修女小姐姐，好歹是打到第三阶段了……
&lt;/p&gt;


&lt;div id=&quot;org415cdb8&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/friede.jpg&quot; alt=&quot;friede.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5ec50dc&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5ec50dc&quot;&gt;17:37 发呆&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5ec50dc&quot;&gt;
&lt;p&gt;
靠在沙发上两个小时啥也没干，戴上耳机听着老歌，随意遐想，看着自己的念头从这边涌到那边，然后逐渐平静下来。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgfe07404&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgfe07404&quot;&gt;2021-06-13 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgfe07404&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org7245372&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org7245372&quot;&gt;15:29 新玩具&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org7245372&quot;&gt;
&lt;p&gt;
昨天买的新玩具到啦，海信 Touch 墨水屏阅读器，128G 存储、1440x720 276ppi 的分辨率，1599 的价格相比手机来说可能不太划算，但和 Kindle 比起来就太棒了：Android 11，能自由安装微信读书等 APP；5.8 寸的屏幕，单手操作自如；128G 的存储空间可以放下更多的书，之前我的 Kindle 才塞了几部高清动漫进去空间就用完了。
&lt;/p&gt;

&lt;p&gt;
简单开箱
&lt;/p&gt;


&lt;div id=&quot;org99323fb&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/hisense_touch_1.jpg&quot; alt=&quot;hisense_touch_1.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org7cb8751&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/hisense_touch_2.jpg&quot; alt=&quot;hisense_touch_2.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgfb20718&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/hisense_touch_3.jpg&quot; alt=&quot;hisense_touch_3.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org8b25e51&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/hisense_touch_4.jpg&quot; alt=&quot;hisense_touch_4.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge895e93&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge895e93&quot;&gt;19:04 跨模态搜索&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge895e93&quot;&gt;
&lt;p&gt;
看到一个网站，能通过台词来搜索电影甚至给出对应的电影截图，感觉这种跨模态的搜索还有进一步的想象空间，比如说视频的搜索，如果能根据视频里人说的话、展示的文字来搜索，应该会很有意思 —— 技术上来说是可行的，搜了下大厂也有在做，但都是作为内容平台的一个普通工具，我说的有意思是指在产品形态上应该会有一些有意思的点，比如说自动生成鬼畜视频哈哈哈哈。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>关闭部分公众号RSS的全文输出</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/06/08/close-wxrss-fulltext.html"/>
    <category term="数字生活" scheme="http://www.zmonster.me/categories.html#数字生活"/>
    <id>http://www.zmonster.me/2021/06/08/close-wxrss-fulltext</id>
    <published>2021-06-08T00:00:00+00:00</published>
    <updated>2021-06-08T00:00:00+00:00</updated>
    <description>
    
      <p>为减轻服务器的压力，我选出了一批公众号RSS，关闭了他们的全文输出</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
出于服务器压力、对微信反爬的担忧等多方面考虑，我决定关闭一些我制作的微信公众号 RSS 的全文输出，选择的标准如下：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Inoreader 上订阅数少于 3 的，考虑关闭全文输出；&lt;/li&gt;
&lt;li&gt;每日发表文章在 3 篇以上的，考虑关闭全文输出；&lt;/li&gt;
&lt;li&gt;作者（或写作团队）有在其他平台发布内容且提供 RSS 输出的，考虑关闭全文输出；&lt;/li&gt;
&lt;li&gt;内容很简短的，考虑关闭全文输出；&lt;/li&gt;
&lt;li&gt;我个人对内容已经不感兴趣的，考虑关闭全文输出。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
按照上述标准，筛讯出来了 8 个公众号 RSS，在昨晚做调整把它们的全文输出关闭了，这 8 个公众号及关闭全文理由如下：
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://feedpress.me/wx-ainlp&quot;&gt;AINLP&lt;/a&gt;： 更新频率过高&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://feedpress.me/wx-aigechibaole&quot;&gt;艾格吃饱了&lt;/a&gt;： 美食类公众号，我个人不是很有兴趣，订阅数 4 人也比较少&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://feedpress.me/wx-foodfile-111010&quot;&gt;碗丸食事&lt;/a&gt;：同上&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://feedpress.me/wx-yetanmoney&quot;&gt;也谈钱&lt;/a&gt;：作为投资理财类公众号，内容比较水（个人观点），我不太想看了，且订阅数少于 3&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://feedpress.me/wx-msrasia&quot;&gt;微软研究院AI头条&lt;/a&gt;：其内容同样被发布在 MSRA 的官方博客上，并提供&lt;a href=&quot;https://www.msra.cn/feed&quot;&gt;全文RSS&lt;/a&gt;输出，所以这个公众号 RSS 其实就没必要了&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://feedpress.me/wx-iwatch1024&quot;&gt;观人看世界&lt;/a&gt;：虽然订阅者有 17 人，但是其主要内容是引用其他文章并发表简短评论&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://feedpress.me/wx-folklore-forum&quot;&gt;民俗学论坛&lt;/a&gt;：订阅数少于 3 人&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://feedpress.me/wx-hsinfect&quot;&gt;华山感染&lt;/a&gt;：订阅数 4 人，且内容我不是很有兴趣&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
如果对上述公众号有全文需求，有如下解决办法：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;使用 Inoreader，打开文章后，按下 w 键来载入全文，经测试对微信公众号的抓取效果还不错&lt;/li&gt;
&lt;li&gt;我提供的 RSS 输出的都是文章原始链接，所以可以使用我提供的 RSS 抓取全文&lt;/li&gt;
&lt;/ol&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/05/31-2021/06/06)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/06/06/2021-w22.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/06/06/2021-w22</id>
    <published>2021-06-06T00:00:00+00:00</published>
    <updated>2021-06-06T00:00:00+00:00</updated>
    <description>
    
      <p>本周想法和生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org5fce72f&quot;&gt;2021-05-31 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org79ab46e&quot;&gt;11:54 端午福利&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8d102c9&quot;&gt;23:33 伞&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org186f80e&quot;&gt;2021-06-01 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org144f7d3&quot;&gt;20:07 无意义&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4eb74e7&quot;&gt;2021-06-02 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org6246aea&quot;&gt;10:43 心态&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org08ff8da&quot;&gt;2021-06-03 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org8d531ba&quot;&gt;15:16 专利&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga48dc7f&quot;&gt;17:39 少不是目标&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org429a850&quot;&gt;22:00 定投&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgda964e7&quot;&gt;2021-06-04 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org8bd0c85&quot;&gt;08:10 念头&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga7d43da&quot;&gt;2021-06-05 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgfe34fa6&quot;&gt;22:35 忙碌&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge9de533&quot;&gt;2021-06-06 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org0e58c9c&quot;&gt;12:40 记账&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org432f547&quot;&gt;14:41 做饭&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org862a79f&quot;&gt;15:47 道路&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org605f92c&quot;&gt;16:06 道理和故事&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5fce72f&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org5fce72f&quot;&gt;2021-05-31 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org5fce72f&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org79ab46e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org79ab46e&quot;&gt;11:54 端午福利&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org79ab46e&quot;&gt;
&lt;p&gt;
今年这回发的是京东卡，比以前发粽子好啦。还没想好用来买什么。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8d102c9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8d102c9&quot;&gt;23:33 伞&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8d102c9&quot;&gt;
&lt;p&gt;
痛失 kumamon 图案的折叠伞，想必会有需要它的人成为它的新主人的。这伞还是去招行驻场开发时买的，就让这回忆和它一起随风而去吧！
&lt;/p&gt;


&lt;div id=&quot;orga34cf56&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/kumamon.jpg&quot; alt=&quot;kumamon.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org186f80e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org186f80e&quot;&gt;2021-06-01 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org186f80e&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org144f7d3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org144f7d3&quot;&gt;20:07 无意义&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org144f7d3&quot;&gt;
&lt;p&gt;
三家供应商，其实算是内定了一家，那我这几周在做的各种指标评测有啥意义呀？领导回曰「没有意义」。嗯，我倒没觉得这几周白干了，毕竟公司付我钱了，只是想起了以前做乙方的日子，各种中不了标，除了自己产品的问题，可能也遇到过类似的状况吧？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4eb74e7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4eb74e7&quot;&gt;2021-06-02 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org4eb74e7&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org6246aea&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6246aea&quot;&gt;10:43 心态&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6246aea&quot;&gt;
&lt;p&gt;
在金融相关的行业能看到各种（看似能）暴富的机会，要保持平稳的心态真的挺难的。不过我还好，大部分资金还是在场外的指数基金里，场内的部分，是用来释放交易欲望和磨练投资操作的，在有足够的自信前，我应该不会再追加投入。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org08ff8da&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org08ff8da&quot;&gt;2021-06-03 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org08ff8da&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org8d531ba&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8d531ba&quot;&gt;15:16 专利&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8d531ba&quot;&gt;
&lt;p&gt;
听说我有两个专利通过了耶！老实说专利感觉没啥用，又不是多先进的东西，而且相比申请专利，我更想把它们给开源了给有需要的人。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga48dc7f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga48dc7f&quot;&gt;17:39 少不是目标&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga48dc7f&quot;&gt;
&lt;p&gt;
工作头两年会觉得代码写少一点很酷，现在不刻意追求这个了，整体结构上的合理性、模块化以及代码的可读性，远远比绞尽脑汁在某个局部把代码从 20 行优化到 10 行有价值。同样的，变量名写个完整的单词也不长，但非要按不知道什么样的标准拿其中两三个字母出来拼凑成一个缩写的行为，我也是很讨厌的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org429a850&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org429a850&quot;&gt;22:00 定投&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org429a850&quot;&gt;
&lt;p&gt;
让我弟每月定投 100 块钱到中证 500 里，前天触发的，今天在我的投资管理小工具里给他建了个账户来进行追踪。
&lt;/p&gt;


&lt;div id=&quot;org889caa6&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/keysersoze_new_account.png&quot; alt=&quot;keysersoze_new_account.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgda964e7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgda964e7&quot;&gt;2021-06-04 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgda964e7&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org8bd0c85&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8bd0c85&quot;&gt;08:10 念头&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8bd0c85&quot;&gt;
&lt;p&gt;
脑子里翻滚着好多又好乱的念头，好累，需要花点时间做一场大扫除。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga7d43da&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga7d43da&quot;&gt;2021-06-05 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga7d43da&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgfe34fa6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgfe34fa6&quot;&gt;22:35 忙碌&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgfe34fa6&quot;&gt;
&lt;p&gt;
哎呀呀，本来还想放空一下的，又忙碌了一天，真是闲不住。嗯，主要是把 keysersoze 的代码整理了下提交到了 github 上，顺便把几年前买的阿里云 VPS 废物利用了下。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge9de533&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge9de533&quot;&gt;2021-06-06 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge9de533&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org0e58c9c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org0e58c9c&quot;&gt;12:40 记账&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org0e58c9c&quot;&gt;
&lt;p&gt;
两周没记账了，花了一上午才梳理完，看到一丝不差的数字以及总资产的增长曲线，还是很满足的。记账和打扫收纳很像，它不能帮助我产生更多的钱，就像打扫收纳不能让房子从 50 平变成 100 平，但都能获得更整洁的环境，感受到自己对生活的掌控感。
&lt;/p&gt;

&lt;p&gt;
从某个神秘的角度来说，记账和追求永生都是一样的呀，相比起永生来说，记账简单多啦。
&lt;/p&gt;


&lt;div id=&quot;org142d664&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20210606_balance_sheet.png&quot; alt=&quot;20210606_balance_sheet.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org432f547&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org432f547&quot;&gt;14:41 做饭&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org432f547&quot;&gt;
&lt;p&gt;
久违的做了个饭，荷兰豆焯水简单炒炒调味也很好吃。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org862a79f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org862a79f&quot;&gt;15:47 道路&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org862a79f&quot;&gt;
&lt;p&gt;
推上看到一位应该刚进大学不久的人在抱怨学校生活，说了很多事情，但不免天真和简单，就像曾经的自己。本想说点什么，但想想还是作罢了，认识自我和世界并建立起在两者之间适当的相处模式，是每个人必经的过程。少数幸运或卓越的人能在很早的时候就发现自己的价值所在，但大部分人普通人可能得花一辈子去追逐答案，我不过也是这样一个普通人而已，没啥可讲的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org605f92c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org605f92c&quot;&gt;16:06 道理和故事&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org605f92c&quot;&gt;
&lt;p&gt;
道理可能简单，没有相关经历却很难切身体会，但故事人人能懂。想给别人讲道理时，想想自己有没有相关的故事可讲，如果没有，可能自己懂得这个道理也只是一个幻觉。
&lt;/p&gt;

&lt;p&gt;
是不是这个道理呢？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/05/24-2021/05/30)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/05/30/2021-w21.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/05/30/2021-w21</id>
    <published>2021-05-30T00:00:00+00:00</published>
    <updated>2021-05-30T00:00:00+00:00</updated>
    <description>
    
      <p>本周想法和生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org4e2d171&quot;&gt;2021-05-24 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgba70890&quot;&gt;08:24 失眠&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org64c682f&quot;&gt;14:00 表演&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6e3ace4&quot;&gt;23:08 自由&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org76872d3&quot;&gt;2021-05-25 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org02117cb&quot;&gt;16:46 偏差&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org72a3894&quot;&gt;21:40 圆月&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org0098f06&quot;&gt;22:00 今日交易&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org120d815&quot;&gt;2021-05-26 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org45c4f17&quot;&gt;21:53 月食&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf20c5ef&quot;&gt;22:04 今日交易&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org27e1dcb&quot;&gt;22:53 微博API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org644064c&quot;&gt;2021-05-27 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga1ac656&quot;&gt;10:09 不理解&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1279fcc&quot;&gt;2021-05-28 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgf432b61&quot;&gt;00:07 早睡个屁啊&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org77c99f9&quot;&gt;11:07 过程和结果&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4494a56&quot;&gt;14:00 惯性&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org13732e0&quot;&gt;18:00 留言&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgbb724a5&quot;&gt;2021-05-29 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org97ea5d3&quot;&gt;10:58 演戏&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org31c125e&quot;&gt;20:00 真实和虚假&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6c4ab6b&quot;&gt;2021-05-30 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orge05be27&quot;&gt;17:33 催婚&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2567acb&quot;&gt;17:35 疫苗&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4cdaa28&quot;&gt;22:00 进化&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4e2d171&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4e2d171&quot;&gt;2021-05-24 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org4e2d171&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgba70890&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgba70890&quot;&gt;08:24 失眠&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgba70890&quot;&gt;
&lt;p&gt;
三点多还没睡着，今天精神又好不了了……
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org64c682f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org64c682f&quot;&gt;14:00 表演&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org64c682f&quot;&gt;
&lt;p&gt;
前公司同事聚餐，和 WR 聊新番，我说《ODD TAXI》挺好看来着，WR 觉得这个动画的表演没太多看点，简单来说就是人物的肢体语言都很朴实，镜头也特别简单，基本上只靠对话在推动剧情 —— 这个确实，不过我确实更喜欢故事性比较强的动画（其实游戏和电影也是），反倒因为故事内容过于单薄而并不喜欢一些很知名、表演很好的动画。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6e3ace4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6e3ace4&quot;&gt;23:08 自由&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6e3ace4&quot;&gt;
&lt;p&gt;
某同事说，要是能回到上学那会就好了，想干嘛干嘛。先不说上课和作业的问题，说这种话的人有想过自己有空闲了后要做什么事情么？完全没想过就只想吃喝玩乐那自然没问题，如果有想做的事情却完全没有实际去做过，那么即使有空闲了大概率也不会去做的。当然了，同事只是觉得现在事情繁杂感叹一下而已，不用太认真，就自己这么想一想，毕竟这种想法我也有过。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org76872d3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org76872d3&quot;&gt;2021-05-25 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org76872d3&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org02117cb&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org02117cb&quot;&gt;16:46 偏差&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org02117cb&quot;&gt;
&lt;p&gt;
公司要采购一些数据，出了一份评估列表，最近两周我都在根据评估列表上的需求做数据分析和统计，今天和采购相关的人讲评估结果，聊完发现有偏差，还得和供应商继续沟通然后我们再做处理。这里面的问题很多啦，比如供应商给了采购负责人他们能提供什么数据，但这个信息并没有给到我，这就导致我给的一部分分析结果其实是没有意义的；再比如说评估需求是我们这边的人写的而采购负责人并没有在开始就提出来哪些不合理，然后我开始接手后也觉得有些地方不清楚但也犯了懒就觉得给我这样我就这样做好了。这种涉及很多方的事情，可能先进行大量沟通把问题说得透透的再来执行会好很多吧，我是不太擅长应付这种场景，跟不熟的人对接往往我会在那为了写个说明文档纠结个半天的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org72a3894&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org72a3894&quot;&gt;21:40 圆月&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org72a3894&quot;&gt;
&lt;p&gt;
今晚月亮好圆哦，而且没什么云看得很清楚。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0098f06&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org0098f06&quot;&gt;22:00 今日交易&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org0098f06&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;证券ETF上涨，网格触发卖出&lt;/li&gt;
&lt;li&gt;红利ETF上涨，网格触发卖出&lt;/li&gt;
&lt;li&gt;传媒ETF上涨，网格触发卖出&lt;/li&gt;
&lt;li&gt;银行ETF上涨，网格触发卖出&lt;/li&gt;
&lt;li&gt;卖出若干招行，买入若干格力电器&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
今天市场大涨，我场内和场外收益都很不错，总资产又新高啦，开心！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org120d815&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org120d815&quot;&gt;2021-05-26 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org120d815&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org45c4f17&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org45c4f17&quot;&gt;21:53 月食&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org45c4f17&quot;&gt;
&lt;p&gt;
走到地铁口的时候，很多人对着对面拍照，仔细一看，月亮缺了一块，低低地挂在对面小区楼顶上，显得特别的近。我还是第一次看见月食耶，有趣，可惜没看到全过程。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf20c5ef&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf20c5ef&quot;&gt;22:04 今日交易&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgf20c5ef&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;清仓军工ETF&lt;/li&gt;
&lt;li&gt;通信ETF上涨，网格触发卖出&lt;/li&gt;
&lt;li&gt;恒生ETF上涨，网格触发卖出&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org27e1dcb&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org27e1dcb&quot;&gt;22:53 微博API&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org27e1dcb&quot;&gt;
&lt;p&gt;
发现微博有 API 可以获得指定微博的所有评论，不过访问稍微多一点就会要认证，不知道该咋解决。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org644064c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org644064c&quot;&gt;2021-05-27 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org644064c&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orga1ac656&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga1ac656&quot;&gt;10:09 不理解&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga1ac656&quot;&gt;
&lt;p&gt;
不理解是怎么来的呢？我能想到这几点：信息的不对称、信任的缺失，还有语言模式的问题。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1279fcc&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1279fcc&quot;&gt;2021-05-28 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org1279fcc&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgf432b61&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf432b61&quot;&gt;00:07 早睡个屁啊&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgf432b61&quot;&gt;
&lt;p&gt;
写自己的小项目，看了两集《Legal High》，又折腾到零点了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org77c99f9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org77c99f9&quot;&gt;11:07 过程和结果&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org77c99f9&quot;&gt;
&lt;p&gt;
想做的事情别人已经做了，而且做得比自己想得还完善，那还要不要做呢？我还是想做的，因为觉得有意思，至于结果，本来也没想获得什么利益，又有什么关系呢？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4494a56&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4494a56&quot;&gt;14:00 惯性&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4494a56&quot;&gt;
&lt;p&gt;
「我们已经不是在XX」了，确实啊，不过，是不是每个人都能意识到这个事实，并且把自己的行事方式调整过来呢？承认变化，可能并不是那么容易的事情，人的惯性是很强的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org13732e0&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org13732e0&quot;&gt;18:00 留言&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org13732e0&quot;&gt;
&lt;p&gt;
博客新文章下有一条新留言「来个一个推特的联系方式」，我觉得吧，如果有问题想要交流，直接在留言区交流就好了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgbb724a5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgbb724a5&quot;&gt;2021-05-29 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgbb724a5&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org97ea5d3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org97ea5d3&quot;&gt;10:58 演戏&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org97ea5d3&quot;&gt;
&lt;p&gt;
在戏里演戏，太有意思了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org31c125e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org31c125e&quot;&gt;20:00 真实和虚假&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org31c125e&quot;&gt;
&lt;p&gt;
对我来说，虚构世界里并不比物理世界虚假。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6c4ab6b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org6c4ab6b&quot;&gt;2021-05-30 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org6c4ab6b&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orge05be27&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge05be27&quot;&gt;17:33 催婚&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge05be27&quot;&gt;
&lt;p&gt;
我爸又拿几个人试探了下：一个在北京做编辑的，一个在老家当法官的。还问了下去年加的那位小学同学。唔，没太多想法。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2567acb&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2567acb&quot;&gt;17:35 疫苗&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2567acb&quot;&gt;
&lt;p&gt;
我爸和我妈都打完第一针疫苗了，近期我也在考虑这个事情。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4cdaa28&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4cdaa28&quot;&gt;22:00 进化&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4cdaa28&quot;&gt;
&lt;p&gt;
这两天又把自己的投资管理小工具打磨了下，现在很像那么一回事了呢！
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
除了总资产走势和累计收益率走势外，还可以查看累计收益（金额）走势和日收益历史了
&lt;/p&gt;


&lt;div id=&quot;org62861f1&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/keysersoze_day_return.png&quot; alt=&quot;keysersoze_day_return.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
累计收益率走势图里加上了最大回撤的显示
&lt;/p&gt;


&lt;div id=&quot;org21faf12&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/keysersoze_max_drawdown.png&quot; alt=&quot;keysersoze_max_drawdown.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
持仓列表的展示方式表格改成了卡片，还加上了品种的十日走势图
&lt;/p&gt;


&lt;div id=&quot;org12756fe&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/keysersoze_holdings.png&quot; alt=&quot;keysersoze_holdings.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
交易记录列表的展示方式也从表格改成了卡片
&lt;/p&gt;


&lt;div id=&quot;orgb49268a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/keysersoze_deals.png&quot; alt=&quot;keysersoze_deals.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
可视化方面我觉得已经挺舒服的了，下一步准备加上一些有用的分析功能，比如持仓的相关性分析之类的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>（已修复）对微信公众号 RSS 停止更新的说明</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/05/23/fix-huginn-rss.html"/>
    <category term="数字生活" scheme="http://www.zmonster.me/categories.html#数字生活"/>
    <id>http://www.zmonster.me/2021/05/23/fix-huginn-rss</id>
    <published>2021-05-23T00:00:00+00:00</published>
    <updated>2021-05-23T00:00:00+00:00</updated>
    <description>
    
      <p>今天发现我用 Huginn 制作的微信公众号全部没有更新了，持续了大概三到四周，对各位订阅者表示歉意。</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
年初换了新工作后，变得更忙了一点，看 RSS 的习惯也逐渐荒废了，今天上去看看，才发现我之前制作的微信公众号 RSS （见&lt;a href=&quot;https://www.zmonster.me/2020/03/10/wx-article-rss.html&quot;&gt;文章1&lt;/a&gt;和&lt;a href=&quot;https://www.zmonster.me/2020/04/11/wx-article-rss-2.html&quot;&gt;文章2&lt;/a&gt;）全部停止更新了，故障发生的时间点大概是三到四周前，赶紧去看下到底是怎么回事。
&lt;/p&gt;

&lt;p&gt;
由于 RSS 最终是由 &lt;a href=&quot;https://feedpress.com&quot;&gt;FeedPress&lt;/a&gt; 输出的，所以我先登录到 FeedPress 上看了下，确认 FeedPress 自己没有出问题，只是输出的数据都是三到四周前的了；接着去看 Huginn，也是一样，工作正常，但接收到的原始数据就缺失了，而这些原始数据是我在一台国外 VPS 上的定时任务产出的，通过 Telegram API 获取 EFB 同步过来的微信公众号文章消息（详见我的&lt;a href=&quot;https://www.zmonster.me/2020/04/17/wechat-articles-rss-solution.html&quot;&gt;另一篇文章&lt;/a&gt;），看了下日志，确认是这个定时任务出问题了。
&lt;/p&gt;

&lt;p&gt;
手工执行了下定时任务，得到了这么一条错误输出：
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;orgd865196&quot;&gt;
The authorization key (session file) was used under two different IP addresses simultaneously, and can no longer be used. Use the same session exclusively, or use different sessions'
&lt;/pre&gt;

&lt;p&gt;
出错的代码见 &lt;a href=&quot;https://github.com/Linusp/zs/blob/master/zs/telegram.py#L366&quot;&gt;Github&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
至此明白原因了：大概三周前，我在本地使用相同的 token 跑了自己写的脚本，用来导出聊天记录，当时我本地也报了这个错，但没太在意，就是从那个时候起 VPS 上的 token 就失效了，然后加上没有做什么监控也没有用户反馈，导致到今天我才发现这个问题。
&lt;/p&gt;

&lt;p&gt;
明确问题后，按照如下过程修复问题：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;删除 VPS 上的 token，并重新认证&lt;/li&gt;
&lt;li&gt;获取 2021.04.30 后的微信公众号更新消息&lt;/li&gt;
&lt;li&gt;对每个有输出 RSS 的公众号，取最近 10 篇文章发送到 Huginn，生成相应的 RSS&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
这样处理后问题暂时就解决了，FeedPress 应该会在之后陆续更新相应的 RSS 源了。
&lt;/p&gt;

&lt;p&gt;
在此对订阅这些 RSS 源的朋友表示歉意！
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/05/17-2021/05/23)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/05/23/2021-w20.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/05/23/2021-w20</id>
    <published>2021-05-23T00:00:00+00:00</published>
    <updated>2021-05-23T00:00:00+00:00</updated>
    <description>
    
      <p>本周想法和生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orge99abb3&quot;&gt;2021-05-18 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org0632035&quot;&gt;23:00 面试&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org743f8c3&quot;&gt;23:04 新高&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org49ab03b&quot;&gt;23:09 今日交易&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org650829a&quot;&gt;2021-05-19 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org97fc01e&quot;&gt;08:50 图谱&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga5b72af&quot;&gt;17:04 gakki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6f08d94&quot;&gt;18:00 愧疚&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2db445f&quot;&gt;20:00 大屠杀&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org9bee9ec&quot;&gt;2021-05-20 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orge03282f&quot;&gt;10:19 死工资&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1ddf924&quot;&gt;19:00 面试&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4f9082f&quot;&gt;21:01 剑风&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org45dbc30&quot;&gt;23:00 今日交易&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org0a87256&quot;&gt;2021-05-22 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org7f5a193&quot;&gt;12:30 视频&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge0cf5f4&quot;&gt;23:00 且慢&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgdf10b5f&quot;&gt;23:00 手机&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-orge99abb3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge99abb3&quot;&gt;2021-05-18 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge99abb3&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org0632035&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org0632035&quot;&gt;23:00 面试&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org0632035&quot;&gt;
&lt;p&gt;
依然是简历看着不错最后不通过，不过今天这个还挺积极的，最后请教我该如何提升啥的，不会是拿我们公司来练习面试了吧？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org743f8c3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org743f8c3&quot;&gt;23:04 新高&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org743f8c3&quot;&gt;
&lt;p&gt;
总资产连续三天新高，开心开心。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org49ab03b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org49ab03b&quot;&gt;23:09 今日交易&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org49ab03b&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;军工ETF上涨，条件单触发卖出若干&lt;/li&gt;
&lt;li&gt;恒生ETF上涨，小网格触发卖出若干&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org650829a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org650829a&quot;&gt;2021-05-19 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org650829a&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org97fc01e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org97fc01e&quot;&gt;08:50 图谱&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org97fc01e&quot;&gt;
&lt;p&gt;
早上起来把某个聊天群里的消息做了下分析，画了个花里胡哨但没啥用的图。
&lt;/p&gt;


&lt;div id=&quot;org236717a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/chatgraph.png&quot; alt=&quot;chatgraph.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga5b72af&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga5b72af&quot;&gt;17:04 gakki&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga5b72af&quot;&gt;
&lt;p&gt;
听说 gakki 结婚了，对我当然是没什么影响，很多人说伤心其实也是一种玩梗的心态，或许真的有倾注感情的人，但因为自己喜欢就不允许别人做一个正常人，这是不好的。
&lt;/p&gt;

&lt;p&gt;
逃避可耻但是可以结婚。
&lt;/p&gt;


&lt;div id=&quot;orgc28f0de&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gakki.jpg&quot; alt=&quot;gakki.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6f08d94&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6f08d94&quot;&gt;18:00 愧疚&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6f08d94&quot;&gt;
&lt;p&gt;
供应商给的数据有一些小问题，我提出来要求修正，感觉会打乱对面的技术同学的工作节奏，虽然说是他的工作失误，但如果我能及早发现及早告知就好了。当过乙方，我知道对面现在是怎么一个焦头烂额的状态，愧疚。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2db445f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2db445f&quot;&gt;20:00 大屠杀&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2db445f&quot;&gt;
&lt;p&gt;
币圈今日大跌，最近一两周因为下跌加了不少仓，仓位从过去的 50% 不到飙升到 90%，所以这波下跌我吃得很结实，直接把最近两三个月的收益都跌没了，没有纪律还是很容易出问题的，尤其是在币圈这种波动巨大的场子里。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org9bee9ec&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org9bee9ec&quot;&gt;2021-05-20 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org9bee9ec&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orge03282f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge03282f&quot;&gt;10:19 死工资&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge03282f&quot;&gt;
&lt;p&gt;
上班路上听到一个路人在打电话，说「我最近也在想，就我这点死工资……」，好像是对面有什么商机，然后这位路人在考虑要不要参与啥的。一方面担心这个人会不会陷入到什么骗局里，一方面也觉得死工资这个贬义的称呼没有必要。问题其实不在死工资上，而是工资少吧。我就觉得死工资很好，为我提供了源源不断的现金流，至于其他的什么个人成长、零食、住房补助之类的福利，都是次要的，我就这么俗。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1ddf924&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1ddf924&quot;&gt;19:00 面试&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1ddf924&quot;&gt;
&lt;p&gt;
看简历准备面试思路一小时，远程面试一小时，我生命中宝贵的两个小时又被浪费了。话说，我现在看简历挺有感觉的了，最近若干次面试前的感觉都被验证了，比如说这次面试前我就写了这么一个简历总结：看起来擅长的东西和我是很接近的，但我的感觉是一些细节描述的不清楚，简历中有「推动xxx」的字样，有点担心在相关的项目中是不是更偏重于规划和管理而非技术执行。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4f9082f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4f9082f&quot;&gt;21:01 剑风&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4f9082f&quot;&gt;
&lt;p&gt;
震惊地得知《剑风传奇》作者三浦健太郎在月初去世了，我以为我可以到四十岁继续骂着三浦老贼追着一年更新几次的漫画的，真是太遗憾了。
&lt;/p&gt;


&lt;div id=&quot;org21dbf3b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/guts.jpg&quot; alt=&quot;guts.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org45dbc30&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org45dbc30&quot;&gt;23:00 今日交易&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org45dbc30&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;买入太阳纸业若干&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0a87256&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org0a87256&quot;&gt;2021-05-22 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org0a87256&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org7f5a193&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org7f5a193&quot;&gt;12:30 视频&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org7f5a193&quot;&gt;
&lt;p&gt;
一个朋友找我帮忙下载学习强国上的视频，说找了不少工具都没法下载下来，我浏览器打开开发者工具一看这不视频链接直接就给了嘛……被喊一声大佬受之有愧，真的不是什么有门槛的东西。
&lt;/p&gt;


&lt;div id=&quot;orgf5783c0&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/zhihu_video_questions.png&quot; alt=&quot;zhihu_video_questions.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge0cf5f4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge0cf5f4&quot;&gt;23:00 且慢&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge0cf5f4&quot;&gt;
&lt;p&gt;
写了个能把且慢上各项资产的日收益数据导出的脚本，主要是用来导出货币三佳的数据，其他的能用净值算出来倒不用这个。货币三佳选择三个比较好的货币基金来保证收益，产品是好的，但是这三个基金会变来变去，如果是去解析交易记录跟踪份额和净值就太麻烦了，我就只当现金，把收益当再投资来记就好了。
&lt;/p&gt;


&lt;div id=&quot;orgf7b98e2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/qieman_profits.png&quot; alt=&quot;qieman_profits.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
其实货币三佳的收益很一般，但是为了管理方便，在想出更好的办法前还是保持现状好了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgdf10b5f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgdf10b5f&quot;&gt;23:00 手机&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgdf10b5f&quot;&gt;
&lt;p&gt;
想换手机，网上看了看，又选择困难了，算了，再说。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/05/10-2021/05/16)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/05/17/2021-w19.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/05/17/2021-w19</id>
    <published>2021-05-17T00:00:00+00:00</published>
    <updated>2021-05-17T00:00:00+00:00</updated>
    <description>
    
      <p>本周想法和生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgb7de73e&quot;&gt;2021-05-10 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org229c811&quot;&gt;08:59 甲方&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1bfd014&quot;&gt;21:43 今日交易&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org39c87e5&quot;&gt;23:33 面试&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6ec1657&quot;&gt;2021-05-11 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgc095421&quot;&gt;10:24 说话&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb74bba9&quot;&gt;23:07 合并&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org05d74bf&quot;&gt;2021-05-13 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgfebe6f7&quot;&gt;22:12 创造力&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf7a1ffa&quot;&gt;2021-05-14 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgd78b0eb&quot;&gt;22:27 海鲜&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgdadfd1e&quot;&gt;23:00 不灭&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc9eabc6&quot;&gt;23:00 今日交易&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org61563cc&quot;&gt;2021-05-15 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgf94a67d&quot;&gt;20:00 ODD TAXI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf3e0009&quot;&gt;20:00 影宅&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgdb22e75&quot;&gt;22:00 今日交易&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org9aaf282&quot;&gt;2021-05-16 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgd8ca9d9&quot;&gt;22:00 今日交易&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org99f292a&quot;&gt;22:00 Vivy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-orgb7de73e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgb7de73e&quot;&gt;2021-05-10 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgb7de73e&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org229c811&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org229c811&quot;&gt;08:59 甲方&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org229c811&quot;&gt;
&lt;p&gt;
做甲方也不好做啊，感觉没有做甲方的命。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1bfd014&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1bfd014&quot;&gt;21:43 今日交易&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1bfd014&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
卖出平安证券上的所有华宝油气，正式清仓，从 2019.09 开始到现在历时 612 天，算交易日的话是 402 天，累计收益约 2600，最开始那段时间的下跌的时候在平安证券上自己手工做网格，跌傻了，后来用华宝智投自动做，才逐渐恢复正收益
&lt;/p&gt;


&lt;div id=&quot;org6ce2124&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/trading_162411.png&quot; alt=&quot;trading_162411.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;证券ETF下跌触发网格买入若干&lt;/li&gt;
&lt;li&gt;卖出有色ETF若干&lt;/li&gt;
&lt;li&gt;中概互联下跌，条件单触发买入若干&lt;/li&gt;
&lt;li&gt;SHIB 暴涨 90%，把昨天买的 SHIB 出了一部分，赚了 150$ 的样子&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org39c87e5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org39c87e5&quot;&gt;23:33 面试&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org39c87e5&quot;&gt;
&lt;p&gt;
今天又面试了一个小伙，简历写一年工作经验但代码能力完全不像，反倒像刚毕业的，还是那种平时大作业和班里同学抄来抄去那种。我有点怀疑最近两份简历是不是被专门的人包装过，因为最近两份简历有非常雷同的一个项目经历，并且同样在被问及这个项目中非深度学习的部分时啥也回答不了的状况。培训班也好、见深度学习火（实际上现在已经没几年前火了）转行也好，咱至少把基础功打好吧，简历上写了熟悉 Python 那 Python 的基础语法至少过一遍吧，写熟悉数据库那最最简单的查询语句要能写出来吧，写熟悉 Linux 不能除了 ls/cd 啥都不知道吧，就只会 BERT 一把梭，太难了。
&lt;/p&gt;

&lt;p&gt;
另外，讲个笑话，BERT 可以用来做天气预测。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6ec1657&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org6ec1657&quot;&gt;2021-05-11 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org6ec1657&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgc095421&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc095421&quot;&gt;10:24 说话&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc095421&quot;&gt;
&lt;p&gt;
在朋友的公众号文章里留言，她说「你初中时可是很爱说话的，后来越来越少」，为什么呢，大概是因为一系列事件导致的性格变化吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb74bba9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb74bba9&quot;&gt;23:07 合并&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb74bba9&quot;&gt;
&lt;p&gt;
清仓华宝油气后，把平安证券上的钱全部挪到华宝证券里了，然后在自己写的应用里把两个账户的统计合并到了一起。合并后可以看到，今年以来我在证券账户里的投入翻了三倍多,但在投入增加的同时还是获得了 6% 的收益，还是不错的。
&lt;/p&gt;


&lt;div id=&quot;org5c5db0c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/exchange_sofar.png&quot; alt=&quot;exchange_sofar.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-org05d74bf&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org05d74bf&quot;&gt;2021-05-13 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org05d74bf&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgfebe6f7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgfebe6f7&quot;&gt;22:12 创造力&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgfebe6f7&quot;&gt;
&lt;p&gt;
被琐事缠身还能发挥创造力吗？我不知道，但我过往比较自得的一些产出，都是在比较悠闲的时候做出来的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf7a1ffa&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf7a1ffa&quot;&gt;2021-05-14 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf7a1ffa&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgd78b0eb&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd78b0eb&quot;&gt;22:27 海鲜&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd78b0eb&quot;&gt;
&lt;p&gt;
下了班和 LY、K 去吃了海鲜锅，我果然对海鲜还是欣赏不来，或许也和食材新鲜程度有关吧，不是太懂。
&lt;/p&gt;


&lt;div id=&quot;org2583659&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/seafood.jpg&quot; alt=&quot;seafood.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgdadfd1e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgdadfd1e&quot;&gt;23:00 不灭&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgdadfd1e&quot;&gt;
&lt;p&gt;
看了最新一集《致不灭的你》，有点冲击，怕不是每一两集就要死一两个人……有点想去看漫画，不过漫画看完后往往就会对动画失去兴趣，所以不妨先看完动画再看漫画把。
&lt;/p&gt;


&lt;div id=&quot;orgaa4fed5&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/to_you_eternity.png&quot; alt=&quot;to_you_eternity.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc9eabc6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc9eabc6&quot;&gt;23:00 今日交易&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc9eabc6&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;证券ETF上涨超过 7%，卖出若干&lt;/li&gt;
&lt;li&gt;BTC 下跌，以 49000$ 的价格买入若干&lt;/li&gt;
&lt;li&gt;DOGE 上涨，以 0.52$ 的价格卖出若干&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org61563cc&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org61563cc&quot;&gt;2021-05-15 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org61563cc&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgf94a67d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf94a67d&quot;&gt;20:00 ODD TAXI&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgf94a67d&quot;&gt;
&lt;p&gt;
新番里的《ODD TAXI》非常不错呀，看海报的话很容易被这个画风骗过去，实际故事非常出色，人物也挺饱满的，一口气看了好几集。
&lt;/p&gt;


&lt;div id=&quot;orgeb37926&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/odd_taxi.png&quot; alt=&quot;odd_taxi.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf3e0009&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf3e0009&quot;&gt;20:00 影宅&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgf3e0009&quot;&gt;
&lt;p&gt;
另一部新番《影宅》也很不错，设定有意思，若隐若现地暗示着什么，等之后谜题逐渐揭晓应该会很有意思。另外，音乐也很好听。
&lt;/p&gt;


&lt;div id=&quot;org715bb33&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/shadow_house.jpg&quot; alt=&quot;shadow_house.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgdb22e75&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgdb22e75&quot;&gt;22:00 今日交易&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgdb22e75&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;SHIB 下跌，以 0.000019$ 的价格买入若干&lt;/li&gt;
&lt;li&gt;BTC 下跌，以 48974.05$ 的价格买入若干&lt;/li&gt;
&lt;li&gt;ATOM 上涨，以 27.5$ 的价格卖出若干&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org9aaf282&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org9aaf282&quot;&gt;2021-05-16 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org9aaf282&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgd8ca9d9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd8ca9d9&quot;&gt;22:00 今日交易&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd8ca9d9&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;BTC 下跌，以 48000$ 的价格买入若干&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org99f292a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org99f292a&quot;&gt;22:00 Vivy&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org99f292a&quot;&gt;
&lt;p&gt;
又一部好看的动画《Vivy》，讲得是一个使命被设定为「用歌声让人类获得幸福」的机器人阻止人类和 AI 发生战争的故事，算是比较典型的科幻设定。差不多每集相当于一个小单元，女主机器人在（从未来返回的）搭档的提示下去阻止或推动一些事件的发生，但往往这个事件和搭档给出来的资料有一些不一致的地方，这样的故事结构还是挺吸引人的。
&lt;/p&gt;


&lt;div id=&quot;orgc7f2baa&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/vivy.jpg&quot; alt=&quot;vivy.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/05/03-2021/05/09)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/05/09/2021-w18.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/05/09/2021-w18</id>
    <published>2021-05-09T00:00:00+00:00</published>
    <updated>2021-05-09T00:00:00+00:00</updated>
    <description>
    
      <p>本周想法和生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org0d5cbe3&quot;&gt;2021-05-03 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org8ac6a1a&quot;&gt;22:56 电影&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8dc3086&quot;&gt;2021-05-04 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org4bd5e13&quot;&gt;12:16 HT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org93c2e5a&quot;&gt;17:51 安心&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1d63f25&quot;&gt;19:40 加密货币&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgcf7f76e&quot;&gt;21:30 黑暗之魂&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8266ffa&quot;&gt;2021-05-05 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org01727c6&quot;&gt;23:25 假期结束&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf1684ca&quot;&gt;2021-05-06 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgd563cd7&quot;&gt;18:00 表弟&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge16dda2&quot;&gt;22:00 今日交易&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5d80cd6&quot;&gt;2021-05-07 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org6329ad4&quot;&gt;15:12 面试&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org850e200&quot;&gt;20:00 今日交易&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3c71f95&quot;&gt;23:30 吃肉&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org97abe73&quot;&gt;2021-05-08 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga0af3a4&quot;&gt;08:34 币都疯了&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org483af85&quot;&gt;23:30 又吃肉&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga8a7ad8&quot;&gt;2021-05-09 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org628dcf3&quot;&gt;12:28 资产走势&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0d5cbe3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org0d5cbe3&quot;&gt;2021-05-03 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org0d5cbe3&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org8ac6a1a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8ac6a1a&quot;&gt;22:56 电影&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8ac6a1a&quot;&gt;
&lt;p&gt;
下午看了《指环王》前两部，发现故事细节我基本记不清了，就像看了两部新电影一样，挺好的。美中不足的是看第二场的时候，左边两个人一直在聊天，我说了两次才消停，气死。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8dc3086&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org8dc3086&quot;&gt;2021-05-04 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org8dc3086&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org4bd5e13&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4bd5e13&quot;&gt;12:16 HT&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4bd5e13&quot;&gt;
&lt;p&gt;
整理火币上的交易记录的时候，发现火币自己发的 HT 币从 2 月初到现在涨了三倍多，当时买 HT 是为了购买用来抵扣手续费的点卡的，还挺好玩的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org93c2e5a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org93c2e5a&quot;&gt;17:51 安心&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org93c2e5a&quot;&gt;
&lt;p&gt;
一个月前，清理关注的公众号的时候，发现一个公众号自 2020 年 8 月后再没有更新过，记得在知乎上看到作者过去受到过巨大的伤害，去看知乎个人页上面也贴着一张不太正式的寻人启事，当时就担心这个人会不会出什么事，犹豫再三在公众号上留了个言。这个留言一直没有得到回复，但今天发现这个人的 B 站帐号（和公众号、知乎用户名相同）有给一个 2021-04-10 发布的视频点投过币，所以人应该是没事，松了一口气。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1d63f25&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1d63f25&quot;&gt;19:40 加密货币&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1d63f25&quot;&gt;
&lt;p&gt;
花了半天时间，把火币上今年以来的交易记录导出来，做完整理和校验后转成 beancount 格式纳入到我的资产记录里了。不知道是不是因为浮点数精度问题，有些币种按照交易记录算出来的资产额和火币上给出来的会差一点点，懒得去管了直接抹掉这个差额。
&lt;/p&gt;


&lt;div id=&quot;orgf3b2b3d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/huobi_beancount.png&quot; alt=&quot;huobi_beancount.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgcf7f76e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgcf7f76e&quot;&gt;21:30 黑暗之魂&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgcf7f76e&quot;&gt;
&lt;p&gt;
黑魂3的故事相比黑魂1更加令人绝望，虽然整个系列的故事背景都比较灰暗，但在1代起码所有人都还有希望，“神明”和他们的追随者基本也还存在，但到3代就是整个世界都衰败了，1代的神明被囚禁、被吃掉、被诅咒还有疯掉的，传火派和灭火派激烈对抗，篡火派在旁边潜伏着，随时准备着把初火的掌控权从没落的神族拿到自己手里 —— 都在进行权力斗争，世界到底怎样才能变得更好其实没多少人关心，虽然关心也没用，毕竟初火的熄灭已经是注定的命运，黑暗终将降临。
&lt;/p&gt;

&lt;p&gt;
我选择灭火，是真的看不下去整个世界苟延残喘的样子，并且相信这可以加快下一个纪元的到来；但也有人选择传火，是因为这样能让主角认识的朋友还能过完相对正常的一生 —— 但按照游戏设定，主角作为一个对初火有病态般渴望的人，最终必然是会选择篡火或者夺火的。没有谁是正确的或者错误的，至少我们都按照自己的心情做出了选择。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8266ffa&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org8266ffa&quot;&gt;2021-05-05 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org8266ffa&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org01727c6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org01727c6&quot;&gt;23:25 假期结束&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org01727c6&quot;&gt;
&lt;p&gt;
感觉这五天时间完全不够啊，前后又要调休，实际只放一天假，真没意思。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf1684ca&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf1684ca&quot;&gt;2021-05-06 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf1684ca&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgd563cd7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd563cd7&quot;&gt;18:00 表弟&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd563cd7&quot;&gt;
&lt;p&gt;
5.1 那位给我打电话姨妈的儿子，加了我微信，闲聊了两句，语言还算活泼，有空再慢慢聊吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge16dda2&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge16dda2&quot;&gt;22:00 今日交易&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge16dda2&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;中概互联下跌触发买入&lt;/li&gt;
&lt;li&gt;招行涨到 54 以上，卖出若干&lt;/li&gt;
&lt;li&gt;恒生ETF网格触发买入&lt;/li&gt;
&lt;li&gt;把平安证券上的华宝油气卖了一半，由于手续费太高，准备在将来的一段时间内把在平安证券上的东西卖完然后注销平安证券的账户&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5d80cd6&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org5d80cd6&quot;&gt;2021-05-07 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org5d80cd6&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org6329ad4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6329ad4&quot;&gt;15:12 面试&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6329ad4&quot;&gt;
&lt;p&gt;
远程面试一个 97 年的小伙，聊项目虽然没亮点，但也没觉得有多不好，但在我共享屏幕把根据他简历准备的一些基础问题展示给他后，不一会他就表示放弃，还一个劲说对不起。都是非常基础的一些问题，答不出来那也没办法。
&lt;/p&gt;

&lt;p&gt;
简历上糊个深度学习项目是不是有点太容易了，估计准备了一些深度学习模型方面的知识以应对面试，但却没想到我不问算法只问计算机和编程基础？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org850e200&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org850e200&quot;&gt;20:00 今日交易&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org850e200&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;证券ETF下跌，条件单触发买入&lt;/li&gt;
&lt;li&gt;通信ETF下跌，条件单触发买入&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3c71f95&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3c71f95&quot;&gt;23:30 吃肉&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org3c71f95&quot;&gt;
&lt;p&gt;
下班后去附近吃烤肉吃了两小时，肥肠干净没有异味，一共点了四份，金砖五花肉一大块在那烤看着就很满足了，牛五花的油脂特别的香。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org97abe73&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org97abe73&quot;&gt;2021-05-08 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org97abe73&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orga0af3a4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga0af3a4&quot;&gt;08:34 币都疯了&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga0af3a4&quot;&gt;
&lt;p&gt;
ATOM 窜到了 30$，网格彻底没法做了；DOGE 突破 0.7$，和五一前比直接翻了一番。7x24 的赌场真可怕。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org483af85&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org483af85&quot;&gt;23:30 又吃肉&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org483af85&quot;&gt;
&lt;p&gt;
今天吃的是壹圣元，鲜鸭血不行，鳝片超大块吃起来很满足，泥鳅这次没什么精神没在锅里蹦达有点失望，其他的肉维持了水准。吃得很饱，毫无睡意。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga8a7ad8&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga8a7ad8&quot;&gt;2021-05-09 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga8a7ad8&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org628dcf3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org628dcf3&quot;&gt;12:28 资产走势&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org628dcf3&quot;&gt;
&lt;p&gt;
上午给自己写的投资管理小工具加上了资产走势图，看起来更直观了。
&lt;/p&gt;


&lt;div id=&quot;org3fe71e4&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/assets_history.png&quot; alt=&quot;assets_history.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/04/26 - 2021/05/02)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/05/02/2021-w17.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/05/02/2021-w17</id>
    <published>2021-05-02T00:00:00+00:00</published>
    <updated>2021-05-02T00:00:00+00:00</updated>
    <description>
    
      <p>本周想法和生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org9fcafec&quot;&gt;2021-04-26 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org5d46253&quot;&gt;20:34 疲惫&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1f3a45b&quot;&gt;22:00 今日交易&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org514a8bd&quot;&gt;2021-04-27 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org3b3dfe1&quot;&gt;21:15 时间&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc3c9792&quot;&gt;21:19 重复工作&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc9106fd&quot;&gt;2021-04-28 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org90efdfa&quot;&gt;21:14 尴尬&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb35cfa7&quot;&gt;21:20 计划&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga3a48be&quot;&gt;21:59 今日交易&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgaf5565b&quot;&gt;22:57 投资建议&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org23ad1ee&quot;&gt;23:36 新浪博客&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge248df0&quot;&gt;2021-04-29 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org154cab8&quot;&gt;13:41 泸州幺妹&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc09285e&quot;&gt;22:00 今日交易&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org669bda9&quot;&gt;2021-04-30 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org014ec6d&quot;&gt;22:00 表弟&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org90bdb2a&quot;&gt;23:05 今日交易&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb6e6e65&quot;&gt;2021-05-01 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org5784e1a&quot;&gt;16:30 和表弟聊天&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb7e167f&quot;&gt;21:30 另外的表弟&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org0cee8d9&quot;&gt;2021-05-02 周日&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgec09c0d&quot;&gt;18:10 小饭桌&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2a5265c&quot;&gt;18:10 清风&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge2186c8&quot;&gt;18:10 指环王&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org9fcafec&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org9fcafec&quot;&gt;2021-04-26 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org9fcafec&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org5d46253&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5d46253&quot;&gt;20:34 疲惫&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5d46253&quot;&gt;
&lt;p&gt;
团建完只觉得疲惫，所谓的开会就是听老板讲了两个多小时不知道重点在哪里的话，没睡好没吃好没玩好。
&lt;/p&gt;

&lt;p&gt;
下班路上和 C 讨论，再次感叹教授这样的人的珍稀程度。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1f3a45b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1f3a45b&quot;&gt;22:00 今日交易&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1f3a45b&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;卖出若干1000ETF&lt;/li&gt;
&lt;li&gt;卖出若干宁波银行&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org514a8bd&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org514a8bd&quot;&gt;2021-04-27 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org514a8bd&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org3b3dfe1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3b3dfe1&quot;&gt;21:15 时间&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org3b3dfe1&quot;&gt;
&lt;p&gt;
想做点有意思的事情，但是没有大块的时间可用，所以大概率五一我又要闭门不出了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc3c9792&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc3c9792&quot;&gt;21:19 重复工作&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc3c9792&quot;&gt;
&lt;p&gt;
每次新业务都要把分词、实体识别、文本这些东西重新做一遍，好无聊啊。人工标数据很麻烦，但也是因为初始效果不好导致的。
&lt;/p&gt;

&lt;p&gt;
如果各个行业各个公司能把自己的标注数据、模型都共享出来就好了，能减少多少重复工作啊。
&lt;/p&gt;

&lt;p&gt;
我不是想偷懒，就觉得无聊，想启动我拖延一年多的棱镜计划（暂命名）。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc9106fd&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgc9106fd&quot;&gt;2021-04-28 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgc9106fd&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org90efdfa&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org90efdfa&quot;&gt;21:14 尴尬&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org90efdfa&quot;&gt;
&lt;p&gt;
今天面试了一个人，全是偏学术而且偏图像的经历，开场特尴尬不知道聊啥，后来聊了聊 NLP，出了道编程题让他做，然后我出去等了，期间和同事稍微讨论了下这个面试，感觉有可能有被他听到（会议室几乎不隔音），感觉好尴尬。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb35cfa7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb35cfa7&quot;&gt;21:20 计划&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb35cfa7&quot;&gt;
&lt;p&gt;
下班路上和 XY 聊了聊我的棱镜计划（暂命名）的一些想法，嗯，感觉我想得还不清楚，可以再捋一捋。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga3a48be&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga3a48be&quot;&gt;21:59 今日交易&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga3a48be&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;顶格申购了正川发债&lt;/li&gt;
&lt;li&gt;卖出若干生物医药ETF，也没什么计划，就是感觉涨够了想卖一卖&lt;/li&gt;
&lt;li&gt;卖出若干宁波银行，一个是涨得不错了卖一点，另外就是腾点钱出来好捡捡垃圾&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgaf5565b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgaf5565b&quot;&gt;22:57 投资建议&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgaf5565b&quot;&gt;
&lt;p&gt;
怂恿一个朋友买了中证500ETF联接基金（定投）和兴全低波动小确幸。
&lt;/p&gt;

&lt;p&gt;
如果能帮助别人赚到钱，那会很开心的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org23ad1ee&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org23ad1ee&quot;&gt;23:36 新浪博客&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org23ad1ee&quot;&gt;
&lt;p&gt;
朋友说她的新浪博客登录不了了，我去瞅了下，无意中看到了自己新浪博客上 10 年前的留言，那是些美好的记忆，虽然再也回不去了。
&lt;/p&gt;

&lt;p&gt;
新浪博客上的文章我都备份到本地后删掉了，除了这个留言也没别的痕迹了。
&lt;/p&gt;


&lt;div id=&quot;org0decff2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/sina-blog-comment-1.png&quot; alt=&quot;sina-blog-comment-1.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orga4152ac&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/sina-blog-comment-2.png&quot; alt=&quot;sina-blog-comment-2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgb23f592&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/sina-blog-comment-3.png&quot; alt=&quot;sina-blog-comment-3.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org573eac2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/sina-blog-comment-4.png&quot; alt=&quot;sina-blog-comment-4.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge248df0&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge248df0&quot;&gt;2021-04-29 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge248df0&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org154cab8&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org154cab8&quot;&gt;13:41 泸州幺妹&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org154cab8&quot;&gt;
&lt;p&gt;
多多要离职了，大家一起去泸州幺妹吃了个饭，大家都吃了个撑，也就人均 60，实惠又好吃。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc09285e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc09285e&quot;&gt;22:00 今日交易&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc09285e&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;卖出温氏转债&lt;/li&gt;
&lt;li&gt;卖出若干招行&lt;/li&gt;
&lt;li&gt;长赢150份发车，跟车买入一份中证传媒、一份全指信息技术，卖出一份德国DAX30&lt;/li&gt;
&lt;li&gt;长赢S发车，跟车买入一份中证传媒，卖出 0.5 份 德国DAX30&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org669bda9&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org669bda9&quot;&gt;2021-04-30 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org669bda9&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org014ec6d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org014ec6d&quot;&gt;22:00 表弟&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org014ec6d&quot;&gt;
&lt;p&gt;
表弟今年高考，今天加了我微信准备聊一聊 —— 去年本来准备过年回去了解一下情况的，但因为疫情没回家，能网上聊一聊还挺好的吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org90bdb2a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org90bdb2a&quot;&gt;23:05 今日交易&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org90bdb2a&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;中证军工ETF的网格触发买入&lt;/li&gt;
&lt;li&gt;买入若干信息技术ETF&lt;/li&gt;
&lt;li&gt;买入若干建设银行&lt;/li&gt;
&lt;li&gt;卖出若干生物医药ETF&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb6e6e65&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgb6e6e65&quot;&gt;2021-05-01 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgb6e6e65&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org5784e1a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5784e1a&quot;&gt;16:30 和表弟聊天&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5784e1a&quot;&gt;
&lt;p&gt;
说现在高考外语可以不学英语，他选择了学日语，学得比英语好。令我吃惊的是谈到专业的时候他说也对计算机有点兴趣，不知道有没有受到我这个大表哥的间接影响。
&lt;/p&gt;

&lt;p&gt;
这个表弟和我还是比较亲近的，能聊不少天，还有一个大四的表弟虽然也学计算机但从来没有主动找我说过话。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb7e167f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb7e167f&quot;&gt;21:30 另外的表弟&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb7e167f&quot;&gt;
&lt;p&gt;
另外一个姨妈给我打电话，她儿子也是我表弟刚工作，她好像不太满意儿子的工作，就想让我帮忙给点意见之类的。
&lt;/p&gt;

&lt;p&gt;
我能给啥意见啊，他又不学计算机，计算机之外的其他行业我两眼一抹黑。姨妈又问让学计算机怎么样，我是觉得还是要看个人兴趣。
&lt;/p&gt;

&lt;p&gt;
最后就还是和表弟加微信再聊呗。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0cee8d9&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org0cee8d9&quot;&gt;2021-05-02 周日&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org0cee8d9&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgec09c0d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgec09c0d&quot;&gt;18:10 小饭桌&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgec09c0d&quot;&gt;
&lt;p&gt;
LY 的小饭桌今天又开张了，今天的参与者除了我还有 XKL、XX 和多多。小饭桌每次都很丰盛。
&lt;/p&gt;


&lt;div id=&quot;org1f86316&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/0502-food.jpg&quot; alt=&quot;0502-food.jpg&quot; width=&quot;600&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2a5265c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2a5265c&quot;&gt;18:10 清风&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2a5265c&quot;&gt;
&lt;p&gt;
在 LY 家吃完饭一起去了附近的公园，找了个地方铺了地垫、挂好吊床，几个人悠闲地在小树林里看书闲聊，非常惬意。
&lt;/p&gt;


&lt;div id=&quot;org440262f&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/0502-park.png&quot; alt=&quot;0502-park.png&quot; width=&quot;800&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
躺在吊床上吹着风半睡半醒的时候，小学时在外婆家吊楼地板上铺席子午睡的记忆浮现了出来，感觉挺接近的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge2186c8&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge2186c8&quot;&gt;18:10 指环王&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge2186c8&quot;&gt;
&lt;p&gt;
预订了明天两部《指环王》的 IMAX2D，在大屏幕上重温一下经典。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/04/19 - 2021/04/24)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/04/24/2021-w16.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/04/24/2021-w16</id>
    <published>2021-04-24T00:00:00+00:00</published>
    <updated>2021-04-24T00:00:00+00:00</updated>
    <description>
    
      <p>本周想法和生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgcd4edc3&quot;&gt;2021-04-19 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orge5a16f7&quot;&gt;08:18 ATOM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org774a6bc&quot;&gt;08:32 zlibrary 的捐赠策略&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgfd26b64&quot;&gt;11:15 恒生ETF大小两个网格都触发卖出&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc63475d&quot;&gt;14:04 清仓5GETF&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgbb34d03&quot;&gt;2021-04-20 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org3248b5e&quot;&gt;10:53 ATOM网格浮亏&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org02a0277&quot;&gt;21:00 哭泣的人&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb60d348&quot;&gt;2021-04-21 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga8ad793&quot;&gt;22:06 情绪&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org63f1ccb&quot;&gt;2021-04-22 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgb6f5cb3&quot;&gt;08:54 阴天&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgacffd89&quot;&gt;2021-04-23 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org3e87536&quot;&gt;14:39 茂盛&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org49429a6&quot;&gt;21:33 降噪耳机&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc361b93&quot;&gt;2021-04-24 周六&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org5700fe7&quot;&gt;16:42 绝望&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd3833d9&quot;&gt;17:19 锚&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-orgcd4edc3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgcd4edc3&quot;&gt;2021-04-19 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgcd4edc3&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orge5a16f7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge5a16f7&quot;&gt;08:18 ATOM&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge5a16f7&quot;&gt;
&lt;p&gt;
一觉醒来，ATOM（一种加密货币） 的网格已经赚了 80$ 了，大佬们吃肉我们喝喝汤也不错。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org774a6bc&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org774a6bc&quot;&gt;08:32 zlibrary 的捐赠策略&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org774a6bc&quot;&gt;
&lt;p&gt;
收到邮件，说捐赠带来的权限提升改成了持续 31 天，原来好良心的，捐赠任意金额后就能一直使用所有功能，看来是有支出压力了。既然这样，我考虑每月给捐点呗。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgfd26b64&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgfd26b64&quot;&gt;11:15 恒生ETF大小两个网格都触发卖出&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgfd26b64&quot;&gt;
&lt;p&gt;
卖完成本变成了负数，持仓还剩下 100 份，赶紧再跌下去让我买回来吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc63475d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc63475d&quot;&gt;14:04 清仓5GETF&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc63475d&quot;&gt;
&lt;p&gt;
今天看 5GETF 浮盈了，就全部卖出了。5GETF 现在应该还是很低估的，长期拿着应该不会亏，但我已经持有和 5GETF 相关性很高的通信ETF了，两个留一个就好了，而且也可以腾点资金出来用来买别的更好的品种。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgbb34d03&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgbb34d03&quot;&gt;2021-04-20 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgbb34d03&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org3248b5e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3248b5e&quot;&gt;10:53 ATOM网格浮亏&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org3248b5e&quot;&gt;
&lt;p&gt;
价格跌到网格下限之下了，导致所有网格利润都被吃掉了。
&lt;/p&gt;

&lt;p&gt;
所以，应该如何判断网格策略的设置需要做调整呢？我想到的是设置止盈线，结合价格走势，或许还可以结合短时风险评估来做判断。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org02a0277&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org02a0277&quot;&gt;21:00 哭泣的人&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org02a0277&quot;&gt;
&lt;p&gt;
出地铁站的时候，看到一个姑娘坐上电动车时摔了，并且在哭（感觉不光是因为摔了还有别的原因），犹豫要不要上前询问一下，但最终还是走开了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb60d348&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgb60d348&quot;&gt;2021-04-21 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgb60d348&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orga8ad793&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga8ad793&quot;&gt;22:06 情绪&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga8ad793&quot;&gt;
&lt;p&gt;
吃完饭 K 打了个车回家，我和 LY 蹭一段，我打算到望京西站就下车换地铁站，因为之后就是熟悉、确定的路线，而且因为吃得撑想要站一站走一走，然后 LY 觉得我可以一直蹭到底甚至让司机送到奥林匹克公园站，这样我会方便很多。到望京西站 LY 下车时我依然表示我也要下车，LY 对我说「你不用下车啊」，当时有点恼火，回了句「我要下你管我呢」。
&lt;/p&gt;

&lt;p&gt;
这当然是个小插曲，并不影响我下车后和 LY 一起聊天走到地铁站，但我这种情绪反应和语言表现是很有问题的，这些年来这种表现反反复复出现过很多次了，其实不带情绪解释一下就好了。反省过好多次，但好像也没什么改善。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org63f1ccb&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org63f1ccb&quot;&gt;2021-04-22 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org63f1ccb&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgb6f5cb3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb6f5cb3&quot;&gt;08:54 阴天&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb6f5cb3&quot;&gt;
&lt;p&gt;
天阴沉沉的，下着小雨，不喜欢这样的天气。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-orgacffd89&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgacffd89&quot;&gt;2021-04-23 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgacffd89&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org3e87536&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3e87536&quot;&gt;14:39 茂盛&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org3e87536&quot;&gt;
&lt;p&gt;
路旁树木的叶子开始茂盛起来了，隐约有点夏天的感觉呢。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org49429a6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org49429a6&quot;&gt;21:33 降噪耳机&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org49429a6&quot;&gt;
&lt;p&gt;
回到小区，进电梯按完楼层按钮后一转身发现身后有一个人，把我吓了一跳。戴着降噪耳机完全没注意到身后还有一个人，这效果也太好了吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc361b93&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgc361b93&quot;&gt;2021-04-24 周六&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgc361b93&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org5700fe7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5700fe7&quot;&gt;16:42 绝望&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5700fe7&quot;&gt;
&lt;p&gt;
和我妈电话，她跟我说到的情况，令人绝望。
&lt;/p&gt;

&lt;p&gt;
我曾经预感到我将会迎接越来越大的风浪，这预感每一年都在变成现实，暂时我还能承受下去。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd3833d9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd3833d9&quot;&gt;17:19 锚&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd3833d9&quot;&gt;
&lt;p&gt;
想念二十多年前的夏天，白色的房子，静谧的傍晚。
&lt;/p&gt;

&lt;p&gt;
可以用来锚定自己的东西有点少，得去多创造一点。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>闲言碎语(2021/04/12 - 2021/04/18)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/04/18/2021-w15.html"/>
    <category term="闲言碎语" scheme="http://www.zmonster.me/categories.html#闲言碎语"/>
    <id>http://www.zmonster.me/2021/04/18/2021-w15</id>
    <published>2021-04-18T00:00:00+00:00</published>
    <updated>2021-04-18T00:00:00+00:00</updated>
    <description>
    
      <p>本周想法和生活记录</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org4847665&quot;&gt;2021-04-12 周一&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org1d39178&quot;&gt;13:44 午饭燃面&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6631d86&quot;&gt;13:52 恒生ETF网格启动&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb44454e&quot;&gt;14:09 仓位&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org7e18f66&quot;&gt;21:04 理中客&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgda0ab98&quot;&gt;21:13 理解&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd51ac94&quot;&gt;21:14 风&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd8403ae&quot;&gt;2021-04-13 周二&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org98031a2&quot;&gt;10:06 李文亮&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgaff76c1&quot;&gt;10:22 贪婪&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org32af353&quot;&gt;13:39 又建了一个中证500的网格&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org08ecb51&quot;&gt;21:00 意识网&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga546cad&quot;&gt;2021-04-14 周三&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org4e97d8c&quot;&gt;08:33 睡眠&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8467d88&quot;&gt;08:42 离线&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4f6c39d&quot;&gt;08:52 再想 NeuralLink&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5b24672&quot;&gt;10:36 招行触发买入&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org84d223e&quot;&gt;15:54 写博客的乐趣&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5801166&quot;&gt;23:29 千秋梦&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd1cfc1f&quot;&gt;23:32 读《离线·共生》&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2bd4130&quot;&gt;23:53 少一点概念，少一点抽象&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4aebfe5&quot;&gt;2021-04-15 周四&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org03e1e68&quot;&gt;11:00 银行股继续下跌&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgeb7c73a&quot;&gt;18:06 MagicMirror&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org72869f5&quot;&gt;2021-04-16 周五&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org33f2603&quot;&gt;14:00 三刷&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5925ffd&quot;&gt;14:16 赞美的语言&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4a09630&quot;&gt;21:07 语言&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
年纪大了，微博、twitter、朋友圈这些都不玩了，但还是想有个地方能公开记录一些简单的想法和琐事。本来的想法是像搭这个博客一样，整个静态站点，像微博一样自己能写东西，还能输出 RSS，想法挺好的，但一直拖延着，索性以博客文章的形式发出来吧，大概会每周一次。
&lt;/p&gt;

&lt;p&gt;
我之前写博客喜欢在自己把事情、想法都进行了系统性梳理后再写长文，这个每周一篇的闲言碎语，就会比较碎片化、个人化了。
&lt;/p&gt;

&lt;p&gt;
每一条内容的时间只是我写下这个内容时的时间，都是在描述事件发生的时间之后，滞后多久也并不一定。
&lt;/p&gt;

&lt;div id=&quot;outline-container-org4847665&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4847665&quot;&gt;2021-04-12 周一&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org4847665&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org1d39178&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1d39178&quot;&gt;13:44 午饭燃面&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1d39178&quot;&gt;
&lt;p&gt;
和 LY、XKL 骑车去悠乐汇，我们的目标望花路燃面在二楼，之前 LY 和 K 去吃过说很好吃。我和 XKL 各要了一份 17 的大份荤燃面， LY 点了一份小份的什么面，另外点了一份蒜泥白肉、一份口水鸡和一份豆花，都挺不错。燃面第一筷子入口辣到我了，用了不少猪油，香。我没吃过多少次燃面，不太清楚什么是正宗不正宗的，但是口感和味道都不错，据说是北京做燃面最好的几家店之一了。
&lt;/p&gt;

&lt;p&gt;
回程时风大了一点，路边的花落了不少，感觉要下雨。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6631d86&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6631d86&quot;&gt;13:52 恒生ETF网格启动&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6631d86&quot;&gt;
&lt;p&gt;
上周新建了恒生ETF的网格交易，格子比较小，打算跑一跑看能不能吃点小波动的肉，原来的网格当然也还在跑着。新建的网格在一点整的时候触发了第一次买入，看看之后表现如何吧。
&lt;/p&gt;

&lt;p&gt;
要严肃一点的话，应该从关注的品种里找一个近期比如说一个月内整体涨跌幅不大，然后日收益率波动率稍微大一点的品种来去做网格，目前只是凭感觉选了恒生，之后可以考虑做个工具来自动筛选适合做网格交易的品种吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb44454e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb44454e&quot;&gt;14:09 仓位&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb44454e&quot;&gt;
&lt;p&gt;
今天开盘后招商银行和宁波银行都下跌了一点，想加仓，但证券账户里的钱已经没多少了，于是又从银行卡转了点到里面。我目前并没有什么仓位控制的概念，春节前上涨行情中因为没太多可买的，焦虑更多的是适合买入的机会不知道什么时候才会出现，春节后这几个月的下跌给了买入机会，但我并没有什么计划性，大部分时候就看心情觉得够低了就买一点点，结果买到证券账户内没什么现金了，这样还是不太好的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org7e18f66&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org7e18f66&quot;&gt;21:04 理中客&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org7e18f66&quot;&gt;
&lt;p&gt;
在鱼塘讨论新闻源可信度，我表现出了理中客的嘴脸，就是认为媒体都有立场所以看新闻不用那么认真这种态度，XKL 有点生气，蹭她车下班的时候聊了聊，她觉得理中客这种貌似理性客观的态度是抹杀了那些那些在为美好事物奋斗的人（如有操守的记者等）的价值，所以生气，她这么说的话我是能理解的。
&lt;/p&gt;

&lt;p&gt;
转念一想，我觉得美好的人事物，如果被别人否定，我好像也不会在意，可能我在心里并没有真的多么认可这些美好吧。现在就觉得一切都没什么意义，有点虚无主义的倾向。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgda0ab98&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgda0ab98&quot;&gt;21:13 理解&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgda0ab98&quot;&gt;
&lt;p&gt;
人和人互相理解是非常困难的，所以在合适的时候，我也应该努力去理解别人，同时也尽量让自己容易被理解。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd51ac94&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd51ac94&quot;&gt;21:14 风&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd51ac94&quot;&gt;
&lt;p&gt;
出了地铁往回走，风超大，有一点点冷，但是很舒服，开心。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd8403ae&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgd8403ae&quot;&gt;2021-04-13 周二&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgd8403ae&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org98031a2&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org98031a2&quot;&gt;10:06 李文亮&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org98031a2&quot;&gt;
&lt;p&gt;
走去地铁站的路上在想他的事情，去年疫情对我心理和情绪的影响仍然在持续。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgaff76c1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgaff76c1&quot;&gt;10:22 贪婪&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgaff76c1&quot;&gt;
&lt;p&gt;
昨天招行和波行下跌，我设置了一个接近当时最低价的加仓条件单，最后当然是没有成交，今天又涨回来了，就会有一点点懊悔。我这样的行为和情绪，还是买卖没有一个成型的原则，感觉有一天会吃亏的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org32af353&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org32af353&quot;&gt;13:39 又建了一个中证500的网格&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org32af353&quot;&gt;
&lt;p&gt;
看了下 2020 年 7 月后，中证500ETF一直在 6.7-7.4 之间震荡，感觉合适做网格
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org08ecb51&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org08ecb51&quot;&gt;21:00 意识网&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org08ecb51&quot;&gt;
&lt;p&gt;
这两天有人讨论 Neuralink 猴子用意念玩电子乒乓球游戏的新闻，自媒体重复着以意驭物、记忆存储、记忆移植这些词，我倒是希望这个可以成为意识网的基础。直接获取别人的感受，《奇诺之旅》认为这只会带来痛苦，那是因为奇诺只在一个地方停留三天吧，我相信人和人更多、跟深地互相理解后，是可以带来翻天覆地的变化的。
&lt;/p&gt;

&lt;p&gt;
可惜，我们没有意识网，有生之年可能也不会有什么希望，目前只有语言可用。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga546cad&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga546cad&quot;&gt;2021-04-14 周三&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga546cad&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org4e97d8c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4e97d8c&quot;&gt;08:33 睡眠&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4e97d8c&quot;&gt;
&lt;p&gt;
六点多就醒了，七点多爬了起来，虽然还想睡。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8467d88&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8467d88&quot;&gt;08:42 离线&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8467d88&quot;&gt;
&lt;p&gt;
收到短信，购买的《离线》杂志回归后的第一本新刊到了快递柜，开心。不过暂时不想去取，下班回来再取，然后好好读一读吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4f6c39d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4f6c39d&quot;&gt;08:52 再想 NeuralLink&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4f6c39d&quot;&gt;
&lt;p&gt;
我并不是觉得记忆存储、记忆移植、意识上传这些东西不好，但如果新技术不能修补人和人之间的裂缝，那么大概率会成为新的剥削工具。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5b24672&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5b24672&quot;&gt;10:36 招行触发买入&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5b24672&quot;&gt;
&lt;p&gt;
触发价 49.8，成交价 49.79，成交后看到价格一路下到 49.71，不过接着又回来了。前两天刚转入的钱又快没了，感觉被掏空。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org84d223e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org84d223e&quot;&gt;15:54 写博客的乐趣&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org84d223e&quot;&gt;
&lt;p&gt;
一篇多年前写的文章，因为搜索引擎的存在，还能帮到新的朋友，真开心呀。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5801166&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5801166&quot;&gt;23:29 千秋梦&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5801166&quot;&gt;
&lt;p&gt;
K 发了一个视频，一个通过歌曲《千秋梦》讲中古汉语的，没多大兴趣，不过是龚琳娜老师的歌，就去听了听，嗓音一如既往的好听！发现龚琳娜老师还有 B 站帐号了，火速关注，顺便又听了一些歌，开心。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd1cfc1f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd1cfc1f&quot;&gt;23:32 读《离线·共生》&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd1cfc1f&quot;&gt;
&lt;p&gt;
看了 50 页，大部分内容都是知道的东西，不过还是很满足，除了阅读本身，还有那种四年后和朋友重逢的感觉。美好的东西还能继续，这就让人很开心。
&lt;/p&gt;

&lt;p&gt;
如果好奇心日报以及其他一些东西也能回来就好了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2bd4130&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2bd4130&quot;&gt;23:53 少一点概念，少一点抽象&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2bd4130&quot;&gt;
&lt;p&gt;
交流前还要先对一遍术语表就让人很头疼，要是都是个人化而非标准化的术语表，那就更是鸡同鸭讲。
&lt;/p&gt;

&lt;p&gt;
潜水某微信群有感。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4aebfe5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4aebfe5&quot;&gt;2021-04-15 周四&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org4aebfe5&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org03e1e68&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org03e1e68&quot;&gt;11:00 银行股继续下跌&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org03e1e68&quot;&gt;
&lt;p&gt;
招行跌到 49 以下，波行和建行微跌（不到 1%），关注的银行也都是绿的，看看今天能不能触发银行ETF网格的买入。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgeb7c73a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgeb7c73a&quot;&gt;18:06 MagicMirror&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgeb7c73a&quot;&gt;
&lt;p&gt;
推上看到的，一个开源的智能镜子方案，看起看很酷！
&lt;/p&gt;


&lt;div id=&quot;orgc860ee4&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/magicmirror.png&quot; alt=&quot;magicmirror.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
项目主页: &lt;a href=&quot;https://magicmirror.builders/&quot;&gt;https://magicmirror.builders/&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org72869f5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org72869f5&quot;&gt;2021-04-16 周五&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org72869f5&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org33f2603&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org33f2603&quot;&gt;14:00 三刷&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org33f2603&quot;&gt;
&lt;p&gt;
这周吃了三次枣庄人家了，风味茄子的口感真的超赞。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5925ffd&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5925ffd&quot;&gt;14:16 赞美的语言&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5925ffd&quot;&gt;
&lt;p&gt;
产生了赞美的心情，却羞于用语言表达出来。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4a09630&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4a09630&quot;&gt;21:07 语言&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4a09630&quot;&gt;
&lt;p&gt;
是不是因为在用语言表达自己的感受这件事情上很糟糕，才会渴望意识网这种东西呢？大部分互相理解上的困境，也许通过合理运用语言就足够了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>我的 2020</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2021/01/03/annual-summary-of-2020.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2021/01/03/annual-summary-of-2020</id>
    <published>2021-01-03T00:00:00+00:00</published>
    <updated>2021-01-03T00:00:00+00:00</updated>
    <description>
    
      <p>梳理一下 2020 年的一些收获、得失，为新的一年做点准备</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org22d53d6&quot;&gt;投资&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8cbf96e&quot;&gt;知识管理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5b778fe&quot;&gt;技术&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org49944c0&quot;&gt;阅读&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org496f042&quot;&gt;动画&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgef78264&quot;&gt;其他&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
2020 年终于过去了，回想起这一年真是五味杂陈，心情复杂，这年终总结一时不知道从哪里说起。相对来说，我在这一年里受社会形势的冲击很少很少，没有因为疫情被隔离，也没有因为疫情和贸易战导致收入减少或丢失工作，之所以能这样，都是因为我所处的行业和我所在的公司，与我的个人能力并没有太大关系，真的是幸运啊。除了感到幸运，这些巨大的社会事件也让我深深地感受到个体的渺小，我一度因为疫情的资讯情绪低落难以入睡，也曾想象自己所处的行业、公司一夜之间倒闭后的惨淡情形，思考自己能为他人做些什么最后只能捐钱安心了事，而对困境加身时该如何自救却全然没有头绪，只能承认自己的无能、渺小。
&lt;/p&gt;

&lt;p&gt;
感叹完了，当然还是需要梳理一下 2020 年的一些收获、得失，为新的一年做点准备。2020 年我主要在知识管理、投资上主动做了一些尝试，但效果都一般；技术上则几乎没什么进展，绝大部分工作都在做业务、工程，业余时间虽然也看了不少论文，但学术研究能落地的毕竟有限；此外，由于这一年在家工作居多，休闲娱乐方面的时间大幅上升，虽说大部分都是打发时间，但也有几本书和一些影视作品可以聊一聊。
&lt;/p&gt;

&lt;p&gt;
接下来就分开讲一讲吧。
&lt;/p&gt;

&lt;div id=&quot;outline-container-org22d53d6&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org22d53d6&quot;&gt;投资&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org22d53d6&quot;&gt;
&lt;p&gt;
投资是我 2020 年相对来说做得还好的一个事情，主要的成果是完善了投资体系并开始尝试一些新的投资方式。
&lt;/p&gt;

&lt;p&gt;
我现在的投资方式，严格来说，还远远算不上“形成体系”，所谓“完善”是相比 2019 年而言。2019 年的时候我主要是在跟投别人的投资组合，收益虽然很不错，但有两个问题：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;我在跟投的投资组合上投入的钱不多，这导致我的储蓄大部分都在货币基金里&lt;/li&gt;
&lt;li&gt;我跟投的是&lt;a href=&quot;https://qieman.com/longwin/index/LONG_WIN&quot;&gt;长赢指数投资计划-150份&lt;/a&gt;和&lt;a href=&quot;https://qieman.com/longwin/index/LONG_WIN_S&quot;&gt;长赢指数投资计划-S定投&lt;/a&gt;，前者已经将投入上限规划好了不需要额外增加投入，后者的买入频率很低，这导致我每月的工资结余没有规划，最终绝大部分也买了货币基金&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
这两个问题就导致我的总体收益并不高，2019 年没有做很详细的记录，但估算我投资的总体年收益在 5% 到 6% 左右。另外就是大笔闲钱放在货币基金里带来了比较大的负担，一看到这笔钱就会想要不要买点啥，但因为没有规划最后又不了了之。高峰时期，我的总资产里货币基金所占的比例高达 40%，但以我这几年的生活状态是不需要这么多流动资金的，放在货币基金里真的是浪费。
&lt;/p&gt;

&lt;p&gt;
这个问题我一直都明白，但一直没有去行动，上半年的话主要是疫情导致情绪混乱而没有心情想这个事情，最终拖到 10 月份才开始重新规划资产配置，然后又磨蹭到 11 月才做完调整，留下一小笔流动资金继续放在货币基金里，剩下的钱买入债基组合，同时增加了更多的定投计划。把流动资金和投资资金彻底分开后，以后统计收益、分析资产成分等事情都更方便了 —— 原来一大笔钱放在货币基金里，虽说收益率低吧，但投入大导致收益金额也不少，如果不纳入统计也不好，纳入统计的话，它的投入一直在不规律地变化，投入金额还不是一个整数，看着特别烦。
&lt;/p&gt;

&lt;p&gt;
这样做完调整后，我已有的钱都清楚整齐了，然后我每月收入，扣完房租以及日常支出预算（2020 年每月 2500），剩下的一部分以定投的形式进入投资组合，再剩余一部分则作为流动资金依然放到货币基金里，也不用管它的收益了，爱多少多少。
&lt;/p&gt;

&lt;p&gt;
新的投资方式方面，都是 10 月份以后才开始尝试的，主要有这些：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;可转债打新，从 11 月 20 才开始的，到现在中签 3 支，大概能赚 300 多点，为了提高收益，还是要多开几个账户才行&lt;/li&gt;
&lt;li&gt;购买主动基金，目前买了谢治宇、张坤等明星基金经理的一些基金，了解的应该知道是哪几支，不了解的话本文不构成推荐意见，后果自负&lt;/li&gt;
&lt;li&gt;了解下港美股投资，但我没有境外银行卡，出入金太麻烦，放弃了，就通过购买 ETF 少量持有了一些港美股的资产，2021 年打算加大这方面的投入&lt;/li&gt;
&lt;li&gt;自动网格交易 —— 2019 年就有自己做网格，但代价是要比较频繁地盯着价格，对生活工作都有不小影响，2020 年用上了华宝智投，它支持设定网格规则后自动执行，非常省心，目前正在逐步把其他地方的网格挪到华宝智投上&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
到 2020/12/31 为止，我的投资组合表现如下图所示：
&lt;/p&gt;


&lt;div id=&quot;orgc0e014f&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2020_investment.png&quot; alt=&quot;2020_investment.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;1&amp;nbsp; &lt;/span&gt;2020投资收益&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这一年里绝大部分的收益都是长赢指数投资计划和U定投贡献的；基金网格因为重仓了华宝油气导致整体收益很低，但其他成分的收益还是不错的；债基组合和主动基金都刚买不久，算出来的年化收益率有点虚高，但看起来势头不错，希望他们能保持下去。
&lt;/p&gt;

&lt;p&gt;
2021 年的话，我打算继续调整资产配置，追求更高的整体收益，目标 10% —— 截止 2020/12/31，增加的收益除以总投入得到的结果是 9.66%（实际的年收益率计算应该没这么简单），这样一看 10% 的目标似乎很容易，但其实不然，一来 2020/12/31 这天市场表现比较好，往前一周的 2020/12/25 那天我的年收益才 8.71%，所以这个 9.66% 看看就好；二来在 2021 年我还会有稳定的工作收入，如果新增加的投入没有接近收益的话，估计很难达到 10% 的年收益了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8cbf96e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org8cbf96e&quot;&gt;知识管理&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org8cbf96e&quot;&gt;
&lt;p&gt;
我一直都想摸索出一套符合自己使用习惯（基于 org-mode）和理念（形成知识图谱）的知识管理体系出来，但一直没有什么很合适的工具，2019 年的时候，自己结合 org-mode 和 Neo4j 做了一个简单原型，但使用起来不是太方便，很多地方感觉也没有想清楚，还是没有用起来。比较惊喜的是 org-roam 的出现，让我学习到了不少新东西，也成为了我这一年主要的笔记管理方式，为此我还专门写了一篇&lt;a href=&quot;https://www.zmonster.me/2020/06/27/org-roam-introduction.html&quot;&gt;文章&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
org-roam 里我觉得对我来说很有启发的点有这么一些
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;基于 org-capture 来实现快速新建笔记的功能&lt;/li&gt;
&lt;li&gt;使用 &lt;a href=&quot;https://github.com/visjs/vis-network&quot;&gt;vis-network&lt;/a&gt; 来进行知识网络的绘制，其效果比 Neo4j 自带的好，而且更容易自己定制&lt;/li&gt;
&lt;li&gt;使用 helm 来快速查询笔记、选中笔记中的词语或短语直接将其转变为链接等友好的交互设计&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
不过对我来说它和我理想中的工具还是有一定的差距，在我看来有以下一些缺点
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;数据存储使用 sqlite3，想要进行更复杂的图操作会非常麻烦&lt;/li&gt;
&lt;li&gt;可视化知识网络的 web server 在 Emacs 中运行，当笔记数量较多时严重影响 Emacs 的性能&lt;/li&gt;
&lt;li&gt;web server 只能做知识网络的可视化，欠缺更灵活的查询和分析功能&lt;/li&gt;
&lt;li&gt;它本身并没有设计成为适合表示知识图谱的结构，如果自己想要在笔记中维护一些 schema 信息将会很麻烦&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
然后，我理想中的知识管理系统大概是这个样子的
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;使用 Emacs org-mode 编辑和维护，并存储结构化数据至 Neo4j 或其他图数据库，支持 web 端的显示、查询和分析&lt;/li&gt;
&lt;li&gt;每则笔记内容分成 meta 信息、普通笔记、任务、卡片四块：

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;meta 信息包括创建时的上下文以及预先定义的 schema 所要求的一些数据字段；&lt;/li&gt;
&lt;li&gt;普通笔记用来记录这则笔记的详细内容，不做内容和格式的限制；&lt;/li&gt;
&lt;li&gt;考虑加一个任务部分，主要是有些时候在学习、了解某些知识点的时候需要查阅资料进行理解，如果将这些行为在另外的 org 文件里作为任务管理的话会造成一定的数据和操作冗余；&lt;/li&gt;
&lt;li&gt;卡片部分是想用来撰写或自动生成一些细粒度的知识卡片，然后可以通过 &lt;a href=&quot;https://ankiweb.net/shared/info/2055492159&quot;&gt;AnkiConnect&lt;/a&gt; 将这些知识卡片同步到 &lt;a href=&quot;https://apps.ankiweb.net/&quot;&gt;Anki&lt;/a&gt; 中用于加强记忆和理解。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
上面两点是比较核心的想法，此外还有一些零碎的想法就不展开了。我准备在 2021 年把我设想的这个系统开发出来，涉及前后端和 Emacs 的插件开发，对我来说也是一个挑战呢。
&lt;/p&gt;

&lt;p&gt;
当然，除了工具本身，对信息源的控制也非常重要，我在 2020 年就深受其扰，因为想要关注学术研究动态，通过 RSS 订阅了 Arxiv 的论文更新，导致每天得花上近一个小时去清理更新的论文，但其实大部分论文都是我并不感兴趣或者灌水的论文，投入产出比非常糟糕，后来我干脆启用了白名单过滤，总算减轻了一些压力。再就是作为一个重度 RSS 用户，看到感兴趣的东西下意识地会去寻找 RSS 源，于是订阅也在慢慢增加，这种习性一时半会难以扭转，只能定期做一下清理了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5b778fe&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org5b778fe&quot;&gt;技术&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org5b778fe&quot;&gt;
&lt;p&gt;
上半年一直在做抽取类的业务项目，顺手写了个文本抽取的框架，但混杂了很多业务逻辑在里面，然后这种项目做完后一般都不会有人主动去推优化的事情，因此我也没有去做进一步的抽象和设计；下半年的话一大半精力放在项目重构上，重构做得很好，但已经是一个边缘项目了，所以算是我的自娱自乐吧；除此之外还还工作中做了点 metric learning、机器阅读理解和文本复述的工作，不过因为一些原因落地的都不多；最后工作之外的业余时间我也没有学什么新东西，倒是花了大力气去梳理我在 NLP 领域积累的笔记，只是对已有的东西做了更好的理解，并没有什么新的收获。总而言之 2020 年我在技术方面没什么建树。
&lt;/p&gt;

&lt;p&gt;
NLP 方面我这两年其实都没有太多新的认识，不过 2020 年的时候，有想到几个将 NLP 和我熟悉的一些其他东西比如 Emacs、RSS、知识管理做结合的点子，不过目前也仅仅是点子而已，也许以后会拎出来折腾一番。预计在 2021 年，我在 NLP 方面的工作并不会有太多很新鲜的东西，老实说问答和文本抽取做得已经有点腻了，自己会重点关注 few-shot learning、文本复述、text-based games 这些方向。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org49944c0&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org49944c0&quot;&gt;阅读&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org49944c0&quot;&gt;

&lt;div id=&quot;org3ffee25&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2020_books.jpg&quot; alt=&quot;2020_books.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;2&amp;nbsp; &lt;/span&gt;2020阅读记录&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
2020 年主要看了上面这些书，大部分都是上半年在家的时候看的，其中&lt;a href=&quot;https://book.douban.com/subject/26712353/&quot;&gt;《血疫》&lt;/a&gt;、&lt;a href=&quot;https://book.douban.com/subject/30164677/&quot;&gt;《我们为什么会生病》&lt;/a&gt;、&lt;a href=&quot;https://book.douban.com/subject/33408247/&quot;&gt;《病毒星球》&lt;/a&gt;这三本都是受疫情刺激而看的相关书籍，《血疫》描绘了埃博拉病毒爆发时的惨烈场景，《病毒星球》展示了我们对病毒是有多么的不了解，《我们为什么会生病》介绍了演化医学并揭露了我们对疾病的一些错误认识。对于以前不怎么关心相关知识的我来说，这几本书还是让我得到了一些新知的。
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;https://book.douban.com/subject/34672176/&quot;&gt;《呼吸》&lt;/a&gt;、&lt;a href=&quot;https://book.douban.com/subject/30284023/&quot;&gt;《城市与群星》&lt;/a&gt;、&lt;a href=&quot;https://book.douban.com/subject/30284022/&quot;&gt;《月海沉船》&lt;/a&gt;、&lt;a href=&quot;https://book.douban.com/subject/30324808/&quot;&gt;《变化的位面》&lt;/a&gt;和&lt;a href=&quot;https://book.douban.com/subject/34464618/&quot;&gt;《圣天秤星》&lt;/a&gt;这五本书是科幻小说，其中《呼吸》是特德·姜的短篇小说集，我很喜欢里面的同名短篇；《城市与群星》和《月海沉船》是克拉克的长篇，前者有点像一个科幻版的《美丽新世界》，后者则是一出月球上的沉船救援行动故事，无论是细节的描写还是故事的讲述都非常棒，我真是太喜欢克拉克了；《圣天秤星》嘛，本质就是一个刑侦+野外探险故事，感觉一般；《变化的位面》是厄休拉·勒古恩的作品，虽然所有故事都在同一个前提（可以穿越到其他世界的机场）来展开的，但本质上就是作者放飞想象力在写各种稀奇古怪的异世界，同时把作者对社会、人性的一些看法夹杂在故事里，不乏一些辛辣的讽刺，在读这本书的时候会有一种错乱感，毕竟语言的运用也非常放飞自我，和《地海传奇》里那种文风差异太大了。
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;https://book.douban.com/subject/25955474/&quot;&gt;《坏小孩》&lt;/a&gt;是&lt;a href=&quot;https://movie.douban.com/subject/33404425/&quot;&gt;《隐秘的角落》&lt;/a&gt;的原著，电视剧我没看，但去跟风读了原著小说。我对推理小说不是很懂，故事反正是不错啦。
&lt;/p&gt;

&lt;p&gt;
剩下的书种类各异，就不再一一写感想了，只聊一下&lt;a href=&quot;https://book.douban.com/subject/30379527/&quot;&gt;《世界观》&lt;/a&gt;和&lt;a href=&quot;https://www.goodreads.com/book/show/56343842&quot;&gt;《欲望的美学》&lt;/a&gt;这两本我最喜欢的书。
&lt;/p&gt;

&lt;p&gt;
《世界观》这本书是讲科学哲学和科学史的，把一个个观点体系类比成拼图来分析科学史上的世界观体系及其转变，这些分析让我认识到，这个世界上，并没有一种绝对普适的世界观可以让所有人都接受，甚至「世界观」可以推广到更广泛层面的观念体系上 —— 看起来这似乎是一个很简单的道理，但是随随便便就能找出一些反例出来，比如说受过高等教育的人对信奉中医的人不屑一顾难以理解、无神论者觉得神压根就不存在怎么会有人信仰神明呢 —— 这两种看法在我周围的人身上都不少见，甚至有人说如果面试发现应聘者信中医的话立即拒绝掉。看完《世界观》这本书就会明白，这种以为自己正确而别人错误的想法下面潜藏着多少思维和认知的陷阱，而且这些自大和盲目又是怎样在历史中一次次上演，包括现在 —— 举个例子，重力其实是不存在的，广义相对论已经给出了新的解释，我们所谓的重力，其实是质量使空间发生弯曲后造成的效应，但是重力这个概念在现代教育的推动下已经变成了一个基本常识，我想数百年后的人们看待我们认为重力存在的感受，大概和我们现在看待亚里士多德认为存在以太时候的感受差不多。这本书虽然是讲科学史的，但直到第三部分才开始讲相对论和量子力学，前两部分也就讲到牛顿世界观，阅读门槛并不高，强烈推荐。
&lt;/p&gt;

&lt;p&gt;
《欲望的美学》是 2020 年台湾出版的一本书，副标题是“心灵世界的陷阱与门径”，对于这两年来在艰难地进行自我认知和重建的我来说非常有帮助，书的第二部分通过分析历史上许多著名的哲学家、思想家的一些思想如柏拉图的洞穴之喻、康德的纯粹理性、中国的宋明理学，来揭露人类在探索心灵世界时所遭遇的种种陷阱，和《世界观》这本书正好可以相互印证，非常有意思。在此之前，我还读了项飙的《把自己作为方法》，老实说非常不满意，读完以后就觉得项彪说得很有智慧但在各种问题上都含糊不清并没有给读者任何确切的答案，在读过《欲望的美学》以后才大致理解了项飙想表达的是什么，本质上来说项飙的思想和《欲望的美学》这本书中表达的思想是很接近的，但《欲望的美学》胜在结构清晰层层递进，正如作者所说像是一本“心灵使用手册”，而《把自己作为方法》这本书受限于谈话的体裁，受提问者本身认知的限制，想到哪说到哪，比较随意，自然就会带来理解上的障碍了，当然如果读者本身已经有在思考项飙想传达的那些观点，读项飙的这本书的时候感觉可能会更好一些吧。
&lt;/p&gt;

&lt;p&gt;
《欲望的美学》这本书目前在京东上有卖，感兴趣的可以自己去了解一下。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org496f042&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org496f042&quot;&gt;动画&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org496f042&quot;&gt;

&lt;div id=&quot;org568841e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2020_animes.jpg&quot; alt=&quot;2020_animes.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;3&amp;nbsp; &lt;/span&gt;2020动漫记录&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
2020 年看过的评价尚可的动画如上图所示。
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;https://movie.douban.com/subject/25821673/&quot;&gt;《阿薇尔的虚构世界》&lt;/a&gt;、&lt;a href=&quot;https://movie.douban.com/subject/1302770/&quot;&gt;《阿基拉》&lt;/a&gt;、&lt;a href=&quot;https://movie.douban.com/subject/2347138/&quot;&gt;《横滨购物纪行》&lt;/a&gt;都是比较老的动画了，都是偏科幻体裁的。《阿薇尔》是蒸汽朋克类的故事，科幻要素丰富，画风和宫崎骏很接近，又充满了对科技发展的反思，各方面都是喜欢的元素，所以感觉非常棒；《阿基拉》是一部影响了后来很多作品的动画，被视为日本动画的一个里程碑，我很早就知道但一直没看，趁疫情在家给补完了，对它的评价和分析在网上都可以找到，我这里就不做什么评价了；《横滨购物纪行》是很小众的动画，其原作漫画获得 2007 年日本科幻奖项“星云奖”，我是在 2019 年通过《电脑线圈》找到这部动画的，故事的背景是全球海平面上升人类近乎绝迹的末世，虽然是末世，但故事整体却非常平静、乐观，我还蛮喜欢的。
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;https://movie.douban.com/subject/4848701/&quot;&gt;《日常》&lt;/a&gt;、&lt;a href=&quot;https://movie.douban.com/subject/26940008/&quot;&gt;《来自深渊》&lt;/a&gt;、&lt;a href=&quot;https://movie.douban.com/subject/26692622/&quot;&gt;《剑风传奇》&lt;/a&gt;和《犬夜叉》也都是老动画了，不过没有前面三个老，《日常》自不必说，轻松搞笑充满各种脑洞的日常番（指没有明确主线，以单元剧形式描绘日常生活的动画），大家都喜欢；《犬夜叉》是因为 B 站上线了就去重温了一遍，没太多好说的；《来自深渊》Q 萌的画风和残酷的剧情形成了强烈的对比，看完致郁那种，不过我挺喜欢的，大概因为这种故事里的人物会显得特别有张力和真实吧，当然得是合理、自洽地虐，为虐而虐的就算了；《剑风传奇》的话，主要是漫画没有更新来重温下动画吧。
&lt;/p&gt;

&lt;p&gt;
剩余的就是 2020 年新出的动画了，这一年因为&lt;a href=&quot;https://zh.wikipedia.org/wiki/%E4%BA%AC%E9%83%BD%E5%8A%A8%E7%94%BB%E7%BA%B5%E7%81%AB%E6%A1%88&quot;&gt;京都动画纵火案&lt;/a&gt;和疫情，导致很多动画延期或取消，所以总体质量比往年稍差一些，但是也不乏高品质的动画。
&lt;/p&gt;

&lt;p&gt;
最喜欢的就是汤浅政明的&lt;a href=&quot;https://movie.douban.com/subject/33438250/&quot;&gt;《别对映像研出手》&lt;/a&gt;了，我的豆瓣友邻也纷纷给出满分评价，它讲的是三个高中生共同制作动画的故事，故事中表达出来的对动画制作的热爱和执着大概也是汤浅政明这些从业人员自己的心态，至于传达出来的对于生活的热爱和细致观察、天马行空的想象力则是非动画行业的人也能产生共鸣的，总之，这是一部能让人想起自己的理想、产生热情拥抱生活冲动的作品。《映像研》之后我把&lt;a href=&quot;https://movie.douban.com/subject/34456027/&quot;&gt;《异度侵入》&lt;/a&gt;排在第二位，这两部动画在我看来是在一个梯队上，但相比之下我还是更偏爱《映像研》。
&lt;/p&gt;

&lt;p&gt;
剩下的动画里：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://movie.douban.com/subject/34458962/&quot;&gt;《动物新世代》&lt;/a&gt;的结尾觉得有点强行大团圆，主角的形象很有&lt;a href=&quot;https://movie.douban.com/subject/26826078/&quot;&gt;《小魔女学园》&lt;/a&gt;中亚可的既视感，就是那种活力爆棚我想做的事情一定做得成的形象，虽说也不讨厌，但稍微有点没新意；&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://movie.douban.com/subject/34456099/&quot;&gt;《没落要塞》&lt;/a&gt;的是一个科幻世界观设定的故事，设定上我觉得挺有意思的，但并没有过多展开，然后女主角的性格和《动物新世代》又雷同，有点审美疲劳；&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://movie.douban.com/subject/30174417/&quot;&gt;《思维覆写》&lt;/a&gt;的故事是以若干能操纵修改他人记忆的角色为中心展开的争斗，故事讲的真的是太好了，但格局稍微小一点，里面“中国人”的塑料普通话也有点违和；&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://movie.douban.com/subject/34982902/&quot;&gt;《神之塔》&lt;/a&gt;是韩国漫画改编，据说已有故事已经非常长了，这次动画化的内容其实只是一个开篇，人物还在成长、塑造阶段，期待后续吧；&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://movie.douban.com/subject/34966406/&quot;&gt;《小书痴第二季》&lt;/a&gt;的世界观和故事我还是满意的，但是制作组有点贫穷，画面制作没有跟上去；&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://movie.douban.com/subject/33413811/&quot;&gt;《放学后海堤日记》&lt;/a&gt;和&lt;a href=&quot;https://movie.douban.com/subject/35132768/&quot;&gt;《阿松》&lt;/a&gt;都是日常番，通过前者能学习到钓鱼知识但我并不会去钓鱼呢，后者更无厘头更搞笑一点，看起来都很轻松愉快；&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://movie.douban.com/subject/34895145/&quot;&gt;《咒术回战》&lt;/a&gt;是很典型的正反派争斗的热血故事，制作精良，如果人物能再真实丰满一点不要正邪二元分立的话我会给高一点的评价。&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgef78264&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgef78264&quot;&gt;其他&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgef78264&quot;&gt;
&lt;p&gt;
因为疫情，2020 年我在老家待到五月份，过完五一后才返京，而之后公司一直采用两天现场办公+三天远程办公的形式，于是这一年省下了大量原来用于通勤的时间，可以自己做饭，也有了更多的独处时间，在这一点上非常感谢我的公司。由于自己做饭控制了油盐碳水，我的体重从 65kg 一路下降到了 60kg，还挺开心的，不过除了体重降低并没有其他方面的改善，因为大部分时间都宅着并没有去运动，这也是理所当然的。此外自己做饭还帮我很好地控制住了每月支出，除房租外，我努力把每月支出控制在了 2500 左右，如果不是远程工作，每天上班吃饭可能就得花掉六七十，一个月下来光餐饮支出就能超出 2000，周末偶尔聚个餐再加上水电交通日常用品，2500 基本是不够的。
&lt;/p&gt;

&lt;p&gt;
2020 年我一如既往的宅，但这一年在同事们爱上了爬山，我也跟着爬了五回 —— 他们总共组织了十一次爬山，还有两位国庆去走了长线。五次爬山分别是五月份的灵山、六月份的京西古道、八月份的百花山、九月份的马栏林场和十月份再次登顶灵山。爬山的过程还是很愉快的，特别是爬野山，比走景区路线有意思太多了。当然了，不怎么运动的我体力是弱项，往往上山前半段走得飞起，后半段就没力气迈不动腿了，虽然慢慢变强了一点点，但总体上还是很弱。
&lt;/p&gt;


&lt;div id=&quot;org2e49b12&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/灵山天梯.png&quot; alt=&quot;灵山天梯.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;4&amp;nbsp; &lt;/span&gt;灵山天梯&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org275413f&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/灵山山顶风光.jpg&quot; alt=&quot;灵山山顶风光.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;5&amp;nbsp; &lt;/span&gt;灵山山顶风光&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgb4fe64e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/灵山狐狸.jpeg&quot; alt=&quot;灵山狐狸.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;6&amp;nbsp; &lt;/span&gt;灵山上完全不怕人的狐狸&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org16acfda&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/迷雾森林.jpg&quot; alt=&quot;迷雾森林.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;7&amp;nbsp; &lt;/span&gt;百花山之迷雾森林&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgd2be20e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/指点江山.jpg&quot; alt=&quot;指点江山.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;8&amp;nbsp; &lt;/span&gt;百花山之指点江山&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org96f1708&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/百花山顶.jpeg&quot; alt=&quot;百花山顶.jpeg&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;9&amp;nbsp; &lt;/span&gt;百花山山顶草甸&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
期待 2021 年的爬山活动！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>本周每日写作尝试总结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2020/11/22/review-of-thisweek.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2020/11/22/review-of-thisweek</id>
    <published>2020-11-22T00:00:00+00:00</published>
    <updated>2020-11-22T00:00:00+00:00</updated>
    <description>
    
      <p>尝试了在本周连续五天输出当日摘要到博客上，这里是一点总结</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
尝试了在本周（周一到周五）每天写一个当日摘要发到博客上，想确认一下我每天可以输出什么东西，也看一下自己是否能坚持这种写作方式，下面这五篇文章就是成果：
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2020/11/16/daily-post-of-20201116.html&quot;&gt;ZMonster's 每日摘要 2020-11-16 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2020/11/17/daily-post-of-20201117.html&quot;&gt;ZMonster's 每日摘要 2020-11-17 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2020/11/18/daily-post-of-20201118.html&quot;&gt;ZMonster's 每日摘要 2020-11-18 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2020/11/19/daily-post-of-20201119.html&quot;&gt;2020-11-19: Neo4j 多 DB, 笔记的目的 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2020/11/20/daily-post-of-20201120.html&quot;&gt;2020-11-20: 柏拉图立体 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
经过一周的尝试后，我有了以下体会或收获
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;对于仍然在全职工作的我，每天写作这件事情很有挑战性、很困难，即使我每天只是贴了一点干巴巴的笔记上去 —— 这当然有多方面的原因了，一方面在写作上我缺乏练习，另外一方面我的知识和见解也不足以支撑起我每天的表达，比较关键的一点是，我可能有点缺乏表达欲&lt;/li&gt;
&lt;li&gt;在 11 月 19 日这篇博客里，我有提到这个短期写作计划的主要目的之一是想尝试用输出的行为去倒逼我完善自己的知识管理系统，经过一周的尝试后我也确认了这个方式对改进我的系统帮助并不大，因为我的知识管理系统的主要问题并不在这里。我反思了下，我主要的问题是（通过 RSS）接收碎片信息过多 —— 虽然目前我的 RSS 里数量最大的部分是 Arxiv 上的论文更新，但是大多数论文我都是扫一眼就略过，真正会去看的并不多，这种情况下它们和碎片化信息的价值无异&lt;/li&gt;
&lt;li&gt;通过这几天的写作，我意识到我目前的 org-roam 笔记结构中的一些问题，比如说对写作不友好、链接过于集中在某些点上之类的&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
我决定停止这个写作计划，改为每周写一篇，这样可以做到言之有物，同时对我来说负担也不算重。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>2020-11-20: 柏拉图立体</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2020/11/20/daily-post-of-20201120.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2020/11/20/daily-post-of-20201120</id>
    <published>2020-11-20T00:00:00+00:00</published>
    <updated>2020-11-20T00:00:00+00:00</updated>
    <description>
    
      <p>尝试在本周每天写一个当日摘要发到博客上，对于当日摘要要写些什么东西，暂定会有「笔记」和「时间」两块，不过我的想法随时可能会变，也许会在之后的几天产生新的想法，这一周时间一来是想确认一下我每天可以输出什么东西，然后也看一下自己是否能坚持这种写作方式吧。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgd9cd9ca&quot;&gt;想法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb814a14&quot;&gt;笔记&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org20c29e1&quot;&gt;时间&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
尝试在本周每天写一个当日摘要发到博客上，对于当日摘要要写些什么东西，暂定会有「笔记」和「时间」两块，不过我的想法随时可能会变，也许会在之后的几天产生新的想法，这一周时间一来是想确认一下我每天可以输出什么东西，然后也看一下自己是否能坚持这种写作方式吧。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgd9cd9ca&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgd9cd9ca&quot;&gt;想法&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgd9cd9ca&quot;&gt;
&lt;p&gt;
最近都在重构一个项目的代码，遇到一个问题是，梳理完旧代码中的各种问题后，想出来一个更理想的设计，但在真正开始实现后，就会发现这个理想的设计的假设是有问题的，一般都是某个具体的问题没有考虑到。不过我并不想讨论编码问题，我只是觉得，这种问题还蛮常见的，就是自己设计一个理想的流程、工具、系统，但总是会遇到各种问题，而我们都会在这个「提出理想设计-&amp;gt;发现问题-&amp;gt;修正设计」的过程中积累一些经验，这些经验（遇到的问题、修正的思路）是不是有共性的呢？
&lt;/p&gt;

&lt;p&gt;
我觉得这是一个有意思的问题。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb814a14&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgb814a14&quot;&gt;笔记&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgb814a14&quot;&gt;

&lt;div id=&quot;orgab2dd51&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20201120-daily-notes.png&quot; alt=&quot;20201120-daily-notes.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
著作: 蒂迈欧篇
&lt;/p&gt;

&lt;p&gt;
柏拉图晚年的一部对话录作品，以苏格拉底等哲学家对话的形式试图去阐明宇宙万物的真理。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
术语: 柏拉图立体
&lt;/p&gt;

&lt;p&gt;
几何学中凸正多面体的另一个称呼，由于柏拉图对它们的记录而得名。凸正多面体有且仅有五个，分别是正四面体、立方体、正八面体、正十二面体和正二十面体，柏拉图在对话录《蒂迈欧篇》中将这五个正多面体和宇宙的构成联系起来，认为四大基础元素中火是正四面体、土是正六面体、气是正八面体、水是正二十面体，而正十二面体代表宇宙。
&lt;/p&gt;


&lt;div id=&quot;org6cb3ea4&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/platonic-solid.jpg&quot; alt=&quot;platonic-solid.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
看到一篇科研文章&lt;sup&gt;&lt;a id=&quot;fnr.1&quot; class=&quot;footref&quot; href=&quot;#fn.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;说到这么一个事情，从几何学上，可以证明把一个三维物体反复二分割后得到的碎片，最后它的形状会趋近于六面体，并且该理论通过地质学研究得到了一定程度的验证，这和柏拉图认为土元素是正六面体的说法似乎就对上了。
&lt;/p&gt;

&lt;p&gt;
当然，大可不必因此就觉得柏拉图代表了真理。我比较感兴趣的是上面这个研究的几何部分，似乎可以用程序来去模拟，找了下就发现了 sympy 这个 Python 库可以用来做相关的几何计算。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
软件: sympy
&lt;/p&gt;

&lt;p&gt;
一个 Python 的符号计算库，能用来进行包括微积分、代数、几何、方程求解等多种数学问题的计算。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org20c29e1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org20c29e1&quot;&gt;时间&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org20c29e1&quot;&gt;

&lt;div id=&quot;org45e1ecd&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20201120-time-usage.png&quot; alt=&quot;20201120-time-usage.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;&amp;#33050;&amp;#27880;: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.1&quot; class=&quot;footnum&quot; href=&quot;#fnr.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
&lt;a href=&quot;https://www.quantamagazine.org/geometry-reveals-how-the-world-is-assembled-from-cubes-20201119/&quot;&gt;Geometry Reveals How the World Is Assembled From Cubes | Quanta Magazine&lt;/a&gt;
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>2020-11-19: Neo4j 多 DB, 笔记的目的</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2020/11/19/daily-post-of-20201119.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2020/11/19/daily-post-of-20201119</id>
    <published>2020-11-19T00:00:00+00:00</published>
    <updated>2020-11-19T00:00:00+00:00</updated>
    <description>
    
      <p>尝试在本周每天写一个当日摘要发到博客上，对于当日摘要要写些什么东西，暂定会有「笔记」和「时间」两块，不过我的想法随时可能会变，也许会在之后的几天产生新的想法，这一周时间一来是想确认一下我每天可以输出什么东西，然后也看一下自己是否能坚持这种写作方式吧。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org62dee57&quot;&gt;想法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgfe4eb9b&quot;&gt;笔记&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org7262d9d&quot;&gt;时间&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
尝试在本周每天写一个当日摘要发到博客上，对于当日摘要要写些什么东西，暂定会有「笔记」和「时间」两块，不过我的想法随时可能会变，也许会在之后的几天产生新的想法，这一周时间一来是想确认一下我每天可以输出什么东西，然后也看一下自己是否能坚持这种写作方式吧。
&lt;/p&gt;

&lt;p&gt;
今天加了一节「想法」，改了一下标题。
&lt;/p&gt;

&lt;div id=&quot;outline-container-org62dee57&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org62dee57&quot;&gt;想法&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org62dee57&quot;&gt;
&lt;p&gt;
写当日摘要第四天了，老实说感觉挺困难的，因为不是每天都能学到新的有价值的知识分享出来，像今天展示的笔记内容，其实没有一条是今天才创建的，十点多的时候我就在发愁今天写些什么好，想不出来，干脆去整理自己的笔记（因为存在不少笔记的层次混乱或者没有填充具体内容），在这个过程中想到今天得知的 Neo4j 新版变化，然后才整理了点东西出来。
&lt;/p&gt;

&lt;p&gt;
我开始这个博客写作的短期计划，其主要目的之一是想尝试用输出的行为去倒逼我完善自己的知识管理系统，因为我发现我最近一段时间陷入了一个机械式学习东西然后往笔记库里填充材料的不良状态，除了看到笔记越来越多，得到的其他反馈很少。那么这个写作的计划有没有效果呢？确实是有的，现在我每天在扫资料的时候，开始会自发地询问自己看的这些东西是否有分享出去的价值、是否能和我已有的知识关联起来。
&lt;/p&gt;

&lt;p&gt;
不过一天一篇还是感到有点累了，好在今天是周四了，周五熬过去，周末会有更多的时间用来做学习和写作的事情。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgfe4eb9b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgfe4eb9b&quot;&gt;笔记&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgfe4eb9b&quot;&gt;

&lt;div id=&quot;org17de90d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20201119-daily-notes.png&quot; alt=&quot;20201119-daily-notes.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
术语: 知识图谱
&lt;/p&gt;

&lt;p&gt;
知识图谱并没有一个非常清晰的定义，大致可以用来泛指以图的结构存储实体以及实体之间关系，并以此来表示人类知识的一种知识库。其实通过结构化数据来表示并应用人类的知识，这是人工智能这一领域最早的时候符号主义学派的主张，自动定理证明、棋类 AI、游戏 AI 都和这个思想有关，这一条路子的发展在上世纪 80 年代左右的时候随着专家系统的商用达到顶峰。
&lt;/p&gt;

&lt;p&gt;
我做过一段时间知识图谱相关的工作，这一方向的主要问题是，构建图谱很困难 —— 先不说应用阶段是否有足够强的推理算法能力，因为如果真的要在知识图谱上建立起丰富强大的应用，一个大前提是要有一个足够大的、细节足够完善的知识图谱，而构建知识图谱是一个系统性工程，不是一个不可分割的原子问题，这就决定了没有一个单独的工具或流程能解决它，但目前也并没有成套的、成熟的、易用的解决方案。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
术语: 图数据库
&lt;/p&gt;

&lt;p&gt;
所谓图数据库是一种 NoSQL 数据库，相比于 MySQL 之类的关系数据库(RDBMS)，能更灵活地表示数据，这种灵活性体现在多方面：
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;像所有 NoSQL 数据库一样可以灵活地设计、扩展 schema&lt;/li&gt;
&lt;li&gt;更适合表示实体之间的关系，特别是当实体之间存在大量的、复杂的关系的时候&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
图数据库强调实体和关系两个基本概念，虽然说在关系数据库中也可以表示实体和关系，但如果关系的种类繁多且实体之间通过关系构成复杂的结构的时候，用图数据库可能会更合适一些。此外，图数据库会对一些常见的图操作进行支持，典型的比如查询最短路径，如果用关系数据库来做就会比较麻烦。
&lt;/p&gt;

&lt;p&gt;
知识图谱数据是比较典型的图数据。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
软件: Neo4j
&lt;/p&gt;

&lt;p&gt;
Neo4j 是一个流行的、Java 编写的图数据库，有比较易用的查询语句和可视化操作界面，我在之前写过一篇相关的&lt;a href=&quot;https://www.zmonster.me/2019/04/30/neo4j-introduction.html&quot;&gt;介绍文章&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
今年二月份 Neo4j 发布了 4.0 版，终于支持多 database 了 —— 多 database 这种在关系数据库中非常基本的功能，Neo4j 4.0 之前的版本是不支持的，这就导致当我们想要隔离数据时不得不部署多个 Neo4j 应用，管理起来非常的麻烦。
&lt;/p&gt;

&lt;p&gt;
为什么二月份发布的我现在才知道呢？因为很久没碰知识图谱这块了，但这周我司升级狂魔 SA 在迁移集群资源的时候发现了这个更新并告知了我。有多 database 功能的话，我构想中的基于 org-mode 和 Neo4j 的知识管理工具就更有吸引力了啊（然而挖坑半年了）。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
插件: ob-cypher
&lt;/p&gt;

&lt;p&gt;
主页: &lt;a href=&quot;https://github.com/zweifisch/ob-cypher&quot;&gt;https://github.com/zweifisch/ob-cypher&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
一个让 Emacs 用户能在 org-mode 的代码块中写 Neo4j 的查询语言并执行得到结果的插件，如下图所示：
&lt;/p&gt;


&lt;div id=&quot;org2a0bcb2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/ob-cypher.png&quot; alt=&quot;ob-cypher.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org7262d9d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org7262d9d&quot;&gt;时间&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org7262d9d&quot;&gt;

&lt;div id=&quot;orgfae90ae&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20201119-time-usage.png&quot; alt=&quot;20201119-time-usage.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>ZMonster's 每日摘要 2020-11-18</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2020/11/18/daily-post-of-20201118.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2020/11/18/daily-post-of-20201118</id>
    <published>2020-11-18T00:00:00+00:00</published>
    <updated>2020-11-18T00:00:00+00:00</updated>
    <description>
    
      <p>尝试在本周每天写一个当日摘要发到博客上，对于当日摘要要写些什么东西，暂定会有「笔记」和「时间」两块，不过我的想法随时可能会变，也许会在之后的几天产生新的想法，这一周时间一来是想确认一下我每天可以输出什么东西，然后也看一下自己是否能坚持这种写作方式吧。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org35325b7&quot;&gt;笔记&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org72b043c&quot;&gt;时间&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
尝试在本周每天写一个当日摘要发到博客上，对于当日摘要要写些什么东西，暂定会有「笔记」和「时间」两块，不过我的想法随时可能会变，也许会在之后的几天产生新的想法，这一周时间一来是想确认一下我每天可以输出什么东西，然后也看一下自己是否能坚持这种写作方式吧。
&lt;/p&gt;

&lt;div id=&quot;outline-container-org35325b7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org35325b7&quot;&gt;笔记&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org35325b7&quot;&gt;

&lt;div id=&quot;org943b0e2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20201118-daily-notes.png&quot; alt=&quot;20201118-daily-notes.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
机构: 北京智源人工智能研究院
&lt;/p&gt;

&lt;p&gt;
主页: &lt;a href=&quot;https://www.baai.ac.cn/&quot;&gt;https://www.baai.ac.cn/&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
北京智源人工智能研究院（简称“智源研究院”）是落实“北京智源行动计划”的重要举措，是在科技部和北京市委市政府的指导和支持下，由北京市科委和海淀区政府于2018年11月推动成立的新型研发机构。其组织架构中的成员有旷视、百度、小米、美团各大公司的高管以及清华、北大、中科院、加州大学、普林斯顿大学、康奈尔大学的学术研究者。
&lt;/p&gt;

&lt;p&gt;
看起来是一个重量级的机构，可以保持关注。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
术语: 清源CPM
&lt;/p&gt;


&lt;div id=&quot;orgcf5bbfb&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cpm.png&quot; alt=&quot;cpm.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
主页: &lt;a href=&quot;https://cpm.baai.ac.cn/&quot;&gt;https://cpm.baai.ac.cn/&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
智源研究院清华大学合作开展的大规模预训练模型开源计划，首期开源内容包括预训练中文语言模型和预训练知识表示模型，可广泛应用于中文自然语言理解、生成任务以及知识计算应用，所有模型免费向学术界和产业界开放下载，供研究使用。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
术语: CPM-LM
&lt;/p&gt;

&lt;p&gt;
清源CPM 推出的 26 亿参数的中文预训练语言模型，是至 2020 年 10 月为止最大的中文预训练语言模型，从宣传上来看是在对标 GPT3 模型。
&lt;/p&gt;


&lt;div id=&quot;org2c46314&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cpm-lm-example1.png&quot; alt=&quot;cpm-lm-example1.png&quot; width=&quot;600px&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgf2c5d8c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cpm-lm-example2.png&quot; alt=&quot;cpm-lm-example2.png&quot; width=&quot;600px&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;模型下载链接: &lt;a href=&quot;https://work-assets.baai.ac.cn/cpm/model-v1.tar.gz&quot;&gt;https://work-assets.baai.ac.cn/cpm/model-v1.tar.gz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
相关源码:
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;官方 Pytorch 版: &lt;a href=&quot;https://github.com/TsinghuaAI/CPM-Generate&quot;&gt;https://github.com/TsinghuaAI/CPM-Generate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;网友 TensorFlow 版: &lt;a href=&quot;https://github.com/qhduan/CPM-LM-TF2&quot;&gt;https://github.com/qhduan/CPM-LM-TF2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
官方 Pytorch 版是 float16 格式的模型，需要安装 APEX 并且在两张显卡上分布式运行，目前使用起来不是很方便，而非官方的 Tensorflow 版本则不受这些限制。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
详细介绍见智源研究院公众号的文章&lt;sup&gt;&lt;a id=&quot;fnr.1&quot; class=&quot;footref&quot; href=&quot;#fn.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
术语: 预训练语言模型
&lt;/p&gt;


&lt;div id=&quot;orgb88cbdf&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/PLMfamily.jpg&quot; alt=&quot;PLMfamily.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
指用大量文本数据训练出来的语言模型，这种模型可以在之后后用做各种各样的 NLP 任务的基础设施，在这些 NLP 任务上只需要对模型结构做微小修改（通常是输出层）然后用该特定任务的数据进行少量继续训练（这种训练一般称之为「微调」）后，通常就能取得不错的效果。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
术语: ERNIE
&lt;/p&gt;


&lt;div id=&quot;org855fd10&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/baidu-ernie.png&quot; alt=&quot;baidu-ernie.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
百度提出的使用知识图谱进行增强的预训练语言模型。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
平台: EasyDL
&lt;/p&gt;

&lt;p&gt;
主页: &lt;a href=&quot;https://ai.baidu.com/easydl/&quot;&gt;https://ai.baidu.com/easydl/&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
百度的 AI 平台，和以前那些提供 API 的功能不一样，这个平台可以让用户管理数据、选择和训练模型、发布模型，有点对标 AWS SageMaker 的感觉。EasyDL 对非 AI 技术人员很友好。
&lt;/p&gt;

&lt;p&gt;
提供三种不同的模式：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
经典版&lt;sup&gt;&lt;a id=&quot;fnr.2&quot; class=&quot;footref&quot; href=&quot;#fn.2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;：用户不需要关心（也不让关心）模型细节，只需要上传数据后触发训练然后发布模型即可使用，非技术人员也可以轻松上手
&lt;/p&gt;

&lt;p&gt;
经典版可处理的任务类型有：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;图像领域：图像分类、物体检测、图像分割&lt;/li&gt;
&lt;li&gt;文本领域：文本分类（单标签）、文本分类（多标签）、情感倾向分析、文本相似度&lt;/li&gt;
&lt;li&gt;视频分类&lt;/li&gt;
&lt;li&gt;声音分类&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
我比较关心文本方面的，以文本分类（单标签）为例，其操作如下：
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
创建模型
&lt;/p&gt;


&lt;div id=&quot;orgdbd9cfb&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/easydl-1.png&quot; alt=&quot;easydl-1.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
训练模型
&lt;/p&gt;


&lt;div id=&quot;org8a39b8c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/easydl-2.png&quot; alt=&quot;easydl-2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org0dc202b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/easydl-3.png&quot; alt=&quot;easydl-3.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org994e6da&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/easydl-4.png&quot; alt=&quot;easydl-4.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org5843eae&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/easydl-5.png&quot; alt=&quot;easydl-5.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
「训练中」后面那个感叹号点击后有一个选项，开启后可以在训练完成后发送短信通知用户。我用 cnsenticorp 情感分类数据 8249 条数据进行训练，用时 8 分钟，应该是用到了预训练模型（很有可能就是 ERNIE），不然不可能这么慢的。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
整体的使用体验还挺好的。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
专业版&lt;sup&gt;&lt;a id=&quot;fnr.3&quot; class=&quot;footref&quot; href=&quot;#fn.3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;：面向算法工程师的服务，让用户可以自主选择使用什么深度学习模型（CNN/BiLSTM 等）并进行参数调整
&lt;/p&gt;

&lt;p&gt;
专业版可处理的任务类型有
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;图像领域：图像分类、物体检测&lt;/li&gt;
&lt;li&gt;文本领域：文本分类（单标签）、文本分类（多标签）、短文本匹配、序列标注&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
以短文本匹配为例来看下其使用过程：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
创建项目
&lt;/p&gt;


&lt;div id=&quot;orgae84319&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/easydl-6.png&quot; alt=&quot;easydl-6.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
创建任务
&lt;/p&gt;


&lt;div id=&quot;org25bfa4c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/easydl-7.png&quot; alt=&quot;easydl-7.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这里会确定模型结构，同时直接生成代码，需要的话用户可以编辑这个代码。如果使用预训练语言模型 ERNIE 的话，选择网络那里就只有 FC（全连接层） 可选了。如果想对模型做一些自定义修改的话，可以且仅可以在这个时候编辑模型的代码。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
训练
&lt;/p&gt;

&lt;p&gt;
运行环境居然有 GPU V100，16G 显存，56G12U，可以啊……
&lt;/p&gt;


&lt;div id=&quot;orgf39d1ee&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/easydl-8.png&quot; alt=&quot;easydl-8.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
完成前面的设置后即可提交训练任务。我选择了 LCQMC 数据集用于训练，共 23w 条数据，耗时 55 分钟，也还行哦。
&lt;/p&gt;

&lt;p&gt;
可以看到训练过程产生的日志
&lt;/p&gt;


&lt;div id=&quot;org6e8a627&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/easydl-9.png&quot; alt=&quot;easydl-9.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
训练完成后可以看到模型评估报告
&lt;/p&gt;


&lt;div id=&quot;org20dbe95&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/easydl-10.png&quot; alt=&quot;easydl-10.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;零售版&lt;sup&gt;&lt;a id=&quot;fnr.4&quot; class=&quot;footref&quot; href=&quot;#fn.4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;：面向零售行业，提供商品检测、货架拼接及其他零售方面的 AI 能力&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org72b043c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org72b043c&quot;&gt;时间&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org72b043c&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;虽然昨晚也睡了近 8 个小时，但睡得晚起得晚，中间还醒过几次，导致今天精神不太好。&lt;/li&gt;
&lt;/ul&gt;


&lt;div id=&quot;orgb56d209&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20201118-time-usage.png&quot; alt=&quot;20201118-time-usage.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;&amp;#33050;&amp;#27880;: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.1&quot; class=&quot;footnum&quot; href=&quot;#fnr.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
&lt;a href=&quot;https://mp.weixin.qq.com/s/oI2Ak-M57MSuycLVpVEiHw&quot;&gt;中文版GPT-3来了？智源研究院发布清源 CPM —— 以中文为核心的大规模预训练模型&lt;/a&gt;
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.2&quot; class=&quot;footnum&quot; href=&quot;#fnr.2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
&lt;a href=&quot;https://ai.baidu.com/easydl/pro&quot;&gt;https://ai.baidu.com/easydl/pro&lt;/a&gt;
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.3&quot; class=&quot;footnum&quot; href=&quot;#fnr.3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
&lt;a href=&quot;https://ai.baidu.com/easydl/lite&quot;&gt;https://ai.baidu.com/easydl/lite&lt;/a&gt;
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.4&quot; class=&quot;footnum&quot; href=&quot;#fnr.4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
&lt;a href=&quot;https://ai.baidu.com/easydl/retail&quot;&gt;https://ai.baidu.com/easydl/retail&lt;/a&gt;
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>ZMonster's 每日摘要 2020-11-17</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2020/11/17/daily-post-of-20201117.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2020/11/17/daily-post-of-20201117</id>
    <published>2020-11-17T00:00:00+00:00</published>
    <updated>2020-11-17T00:00:00+00:00</updated>
    <description>
    
      <p>尝试在本周每天写一个当日摘要发到博客上，对于当日摘要要写些什么东西，暂定会有「笔记」和「时间」两块，不过我的想法随时可能会变，也许会在之后的几天产生新的想法，这一周时间一来是想确认一下我每天可以输出什么东西，然后也看一下自己是否能坚持这种写作方式吧。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org12bc254&quot;&gt;笔记&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd155b4e&quot;&gt;时间&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
尝试在本周每天写一个当日摘要发到博客上，对于当日摘要要写些什么东西，暂定会有「笔记」和「时间」两块，不过我的想法随时可能会变，也许会在之后的几天产生新的想法，这一周时间一来是想确认一下我每天可以输出什么东西，然后也看一下自己是否能坚持这种写作方式吧。
&lt;/p&gt;

&lt;div id=&quot;outline-container-org12bc254&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org12bc254&quot;&gt;笔记&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org12bc254&quot;&gt;

&lt;div id=&quot;org916df13&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20201117-daily-notes.png&quot; alt=&quot;20201117-daily-notes.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
术语: transclusion
&lt;/p&gt;


&lt;div id=&quot;org9df2b4e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/transclusion-multiple-foo.png&quot; alt=&quot;transclusion-multiple-foo.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
一种通过模板语法的形式将其他文档的内容嵌入到当前文档，并支持将嵌入文档的内容和当前文档的内容共同渲染展示甚至一起编辑的功能，从维基百科&lt;sup&gt;&lt;a id=&quot;fnr.1&quot; class=&quot;footref&quot; href=&quot;#fn.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;来看该功能是 &lt;a href=&quot;20201117225000-mediawiki.html&quot;&gt;MediaWiki&lt;/a&gt; 提出的，该功能在知名的个人 wiki 软件 &lt;a href=&quot;20201117225608-tiddlywiki.html&quot;&gt;TiddlyWiki&lt;/a&gt; 中也有实现。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
软件: &lt;a href=&quot;https://www.mediawiki.org/wiki/MediaWiki&quot;&gt;MediaWiki&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
MediaWiki 是一款开源的百科引擎软件，&lt;a href=&quot;20201117230220-维基百科.html&quot;&gt;维基百科&lt;/a&gt;和很多百科类网站都是使用它来构建的。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
软件: &lt;a href=&quot;https://tiddlywiki.com/&quot;&gt;TiddlyWiki&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
一个个人 wiki 工具，它自称是一个用于捕获、组织、分享复杂信息的非线性笔记本，可以通过《&lt;a href=&quot;http://blog.dimpurr.com/tiddly-wiki/&quot;&gt;使用 TiddlyWiki 打造轻便个人 Wiki 知识库&lt;/a&gt;》这篇文章了解其特点。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
插件: &lt;a href=&quot;https://github.com/nobiot/org-transclusion&quot;&gt;org-transclusion&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
在 Emacs org-mode 中实现 transclusion 的一款插件，要求 Emacs&amp;gt;=27.1 &amp;amp; org-mode&amp;gt;=9.4，目前该项目的开发还处于非常早期的状态。对 transclusion 概念不是很熟悉的读者可以通过&lt;a href=&quot;https://www.youtube.com/watch?v=hz92vaO8IgQ&amp;amp;feature=share&quot;&gt;这个 Youtube 视频&lt;/a&gt;获取更直观的认识。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd155b4e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgd155b4e&quot;&gt;时间&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgd155b4e&quot;&gt;

&lt;div id=&quot;orgddc7811&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20201117-time-usage.png&quot; alt=&quot;20201117-time-usage.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;昨晚睡得很不错&lt;/li&gt;
&lt;li&gt;今天去公司上班，但因为要通勤的缘故，相比昨天 remote 工作时间反倒减少了&lt;/li&gt;
&lt;li&gt;中午吃了涮羊肉，感觉还能再来几盘&lt;/li&gt;
&lt;li&gt;同事带的风吹饼吃得停不下来&lt;/li&gt;
&lt;li&gt;公司 2080Ti+3090 的 GPU 机器过于耗电，导致了一次断电事故&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;&amp;#33050;&amp;#27880;: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.1&quot; class=&quot;footnum&quot; href=&quot;#fnr.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/Help:Transclusion&quot;&gt;https://en.wikipedia.org/wiki/Help:Transclusion&lt;/a&gt;
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>ZMonster's 每日摘要 2020-11-16</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2020/11/16/daily-post-of-20201116.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2020/11/16/daily-post-of-20201116</id>
    <published>2020-11-16T00:00:00+00:00</published>
    <updated>2020-11-16T00:00:00+00:00</updated>
    <description>
    
      <p>尝试在本周每天写一个当日摘要发到博客上，对于当日摘要要写些什么东西，暂定会有「笔记」和「时间」两块，不过我的想法随时可能会变，也许会在之后的几天产生新的想法，这一周时间一来是想确认一下我每天可以输出什么东西，然后也看一下自己是否能坚持这种写作方式吧。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org4368dbc&quot;&gt;笔记&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgfb288eb&quot;&gt;时间&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;
尝试在本周每天写一个当日摘要发到博客上，对于当日摘要要写些什么东西，暂定会有「笔记」和「时间」两块，不过我的想法随时可能会变，也许会在之后的几天产生新的想法，这一周时间一来是想确认一下我每天可以输出什么东西，然后也看一下自己是否能坚持这种写作方式吧。
&lt;/p&gt;

&lt;div id=&quot;outline-container-org4368dbc&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4368dbc&quot;&gt;笔记&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org4368dbc&quot;&gt;

&lt;div id=&quot;orge7e1c2b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20201116-daily-notes.png&quot; alt=&quot;20201116-daily-notes.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
术语: 内部协方差漂移(Internel Covariate Shift, &lt;b&gt;ICS&lt;/b&gt;)
&lt;/p&gt;

&lt;p&gt;
指深度学习模型在训练过程中，每次迭代后因为参数被改变导致模型输出的分布发生变化，导致训练过程为了适应不同的模型输出分布而训练收敛慢的问题。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
术语: Batch Normalization
&lt;/p&gt;

&lt;p&gt;
指在训练时用一个 batch 的数据计算均值和方差后将每层输出归一化到标准正态分布，以解决内部协方差漂移使得模型训练慢的问题，实际做法中为了保持每一层的表达能力，在归一化到正态分布后又会通过两个可学习参数（均值和方差）再变换到一个非标准正态分布上，所以实际上内部协方差还是会在漂移，后来也有研究说这种做法会使得 loss 曲面更加平滑所以有效。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
术语: Layer Normalization
&lt;/p&gt;

&lt;p&gt;
指在训练时用一个样本在每层的输出单独计算均值和方差后将这个输出归一化到标准正态分布上的做法，据说也能缓解内部协方差漂移问题从而提高模型的收敛速度。Transformer 系的模型都使用了 Layer Normalization，下图中的 Norm 指的就是 Layer Normalization。
&lt;/p&gt;


&lt;div id=&quot;org5b57524&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/transformer.png&quot; alt=&quot;transformer.png&quot; width=&quot;400px&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
术语: Pre Layer Normalization
&lt;/p&gt;

&lt;p&gt;
在 Transformer 之类的模型中，输入经过 self-attention 后，经过一次线性变换后才做 Layer Normalization 处理，所谓 Pre Layer Normalization 是指在类似的情况下，在线性变换之前就进行 Layer Normalization 处理。提出这一方法的论文&lt;sup&gt;&lt;a id=&quot;fnr.1&quot; class=&quot;footref&quot; href=&quot;#fn.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;声称它这一简单的修改就能对模型有提高。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
观点: Pre Layer Normalization 在 Transformer 模型上比 Layer Normalization 好
&lt;/p&gt;

&lt;p&gt;
论据:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;从理论上分析，先做线性变换再做 Layer Normalization 的问题在于，线性变换的参数矩阵如果是从一个各向同性的高斯分布中采样初始化的话，即使输出不是零均值的，经过变换后也会变成零均值，这会使得 Layer Normalization 的效果变差&lt;/li&gt;
&lt;li&gt;在 LM1B 数据集上，改成使用 Pre Layer Normalization 的模型比原版模型的 PPL 低 0.3（38.341-&amp;gt;38.002）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
个人看法
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;实际上到目前为止 Batch Normalization/Layer Normalization 起作用的原因也并没有研究很清楚，所谓 ICS 问题，在 Batch Normalization 上其实不太站得住脚，倒是让 loss 曲面更加平滑这个理由更好理解一些，所以在 Transformer 中线性变换在前而 Layer Normalization 在后会导致效果变差，可能并不是一个很强的理论分析&lt;/li&gt;
&lt;li&gt;再说效果，PPL 只降了区区 0.3 不到 1%，这也不是一个很强的改进，再说了 LM1B 是个啥数据集？不在 GLUE 上跑一跑难以服众啊&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgfb288eb&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgfb288eb&quot;&gt;时间&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgfb288eb&quot;&gt;

&lt;div id=&quot;org17786d3&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20201116-time-usage.png&quot; alt=&quot;20201116-time-usage.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;&amp;#33050;&amp;#27880;: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.1&quot; class=&quot;footnum&quot; href=&quot;#fnr.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Is Batch Norm unique? An empirical investigation and prescription to emulatethe best properties of common normalizers without batch dependence
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>用 Huginn 为高频 RSS 生成每日摘要并输出新的 RSS</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2020/10/24/make-digest-rss-with-huginn.html"/>
    <category term="数字生活" scheme="http://www.zmonster.me/categories.html#数字生活"/>
    <id>http://www.zmonster.me/2020/10/24/make-digest-rss-with-huginn</id>
    <published>2020-10-24T00:00:00+00:00</published>
    <updated>2020-10-24T00:00:00+00:00</updated>
    <description>
    
      <p>一些资讯类的 RSS 通常都会有较高的更新频率，但我只是想保持关注，了解一下大致有什么事情发生，并不想在一天内接收到几十上百个更新，于是用 Huginn 把一段时间内更新的条目合并起来再输出一个更新频率更低的 RSS。</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
我订阅了一些资讯类的 RSS，但是这种 RSS 通常更新频率都较高，好一点的一天十来篇文章，烦一点几十篇都有可能。但其实我订阅这些 RSS，只是想要对相关的领域（如时事、游戏）保持一定的关注度，更希望是定期（比如每天）整体扫一眼看有没有关心的内容，而不是在一天的各个时间段内连续不断地收到更新。
&lt;/p&gt;

&lt;p&gt;
基于这个想法，我就想找个现成的工具为这种 RSS 生成一个每日摘要，但是只能找到从 RSS 生成摘要邮件的一些方法，而在邮件里看资讯并不是我习惯的方式，还是得自己动手啊。
&lt;/p&gt;

&lt;p&gt;
思考尝试了下，这个问题有两种解决方法:
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;先用 Email Digest 工具(如&lt;a href=&quot;https://ifttt.com/email_digest&quot;&gt;IFTTT&lt;/a&gt;)将 RSS 转成摘要邮件，然后再将邮件转成 RSS，最后这一步可以用 &lt;a href=&quot;https://zapier.com/&quot;&gt;Zapier&lt;/a&gt;；&lt;/li&gt;
&lt;li&gt;直接上 &lt;a href=&quot;https://github.com/huginn/huginn/issues/2599&quot;&gt;Huginn&lt;/a&gt;，RSS Agent + Digest Agent + Delay Agent + Data Output Agent 一套搞定&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
第一个方案我虽然也能操作，但是始终要在邮箱里过一遍，我还是嫌麻烦，而 &lt;a href=&quot;https://github.com/huginn/huginn/issues/2599&quot;&gt;Huginn&lt;/a&gt; 是我非常熟悉的工具，于是就选用了第二套方案。花了几天验证效果，调整之后的 Scenario 如下图所示：
&lt;/p&gt;


&lt;div id=&quot;org60f0409&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/digest-scenario.png&quot; alt=&quot;digest-scenario.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
以&lt;a href=&quot;https://www.gcores.com/&quot;&gt;机核&lt;/a&gt;的 RSS 为例，从上到下五个 Agent 分别是：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
RSS Agent：负责监听原始的 RSS 源，接收更新生成 event
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-javascript&quot;&gt;{
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;expected_update_period_in_days&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;5&quot;&lt;/span&gt;,
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;clean&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;false&quot;&lt;/span&gt;,
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;url&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;https://www.gcores.com/rss&quot;&lt;/span&gt;
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Digest Aget：负责聚合一定时间 RSS Agent 输出的 event 产生一个新的 event，我设定为每天凌晨 1 点执行，这样能把前一天所有的 RSS 更新聚合起来
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-javascript&quot;&gt;{
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;message&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;lt;ul&amp;gt;{% for event in events %}&amp;lt;li&amp;gt;&amp;lt;a href={{ event.url }}&amp;gt;{{ event.title }}&amp;lt;\/a&amp;gt;&amp;lt;\/li&amp;gt;{% endfor %}&amp;lt;\/ul&amp;gt;&quot;&lt;/span&gt;,
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;expected_receive_period_in_days&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;2&quot;&lt;/span&gt;,
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;retained_events&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;0&quot;&lt;/span&gt;
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Event Formatting Agent：给 Digest Agent 产生的 event 添加一个标题
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-javascript&quot;&gt;{
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;instructions&quot;&lt;/span&gt;: {
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;content&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;{{ message }}&quot;&lt;/span&gt;,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;title&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#26426;&amp;#26680;{% assign current_date = 'now' | date: '%s' | minus: 86400 %} {{current_date | date: \&quot;%Y-%m-%d\&quot; }} &amp;#25688;&amp;#35201;&quot;&lt;/span&gt;
  },
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;matchers&quot;&lt;/span&gt;: [

  ],
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;mode&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;clean&quot;&lt;/span&gt;
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Delay Agent：延迟一定时间后将 Event Formatting Agent 的输出再传递给最后的 Data Output Agent，我设置为延迟到早上六点
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-javascript&quot;&gt;{
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;expected_receive_period_in_days&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;3&quot;&lt;/span&gt;,
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;max_events&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;100&quot;&lt;/span&gt;,
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;keep&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;newest&quot;&lt;/span&gt;,
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;max_emitted_events&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;1&quot;&lt;/span&gt;
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Data Output Agent：将最终结果输出为新的 RSS
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-javascript&quot;&gt;{
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;secrets&quot;&lt;/span&gt;: [
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;gcore-daily&quot;&lt;/span&gt;
  ],
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;expected_receive_period_in_days&quot;&lt;/span&gt;: 2,
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;template&quot;&lt;/span&gt;: {
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;title&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#26426;&amp;#26680;-&amp;#27599;&amp;#26085;&amp;#25688;&amp;#35201;&quot;&lt;/span&gt;,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;description&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#26426;&amp;#26680;&amp;#27599;&amp;#26085;&amp;#28040;&amp;#24687;&amp;#27719;&amp;#24635;&quot;&lt;/span&gt;,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;item&quot;&lt;/span&gt;: {
      &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;title&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;{{ title }}&quot;&lt;/span&gt;,
      &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;description&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;{{ content }}&quot;&lt;/span&gt;,
      &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;link&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;https://www.gcores.com/&quot;&lt;/span&gt;
    }
  },
  &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;ns_media&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;true&quot;&lt;/span&gt;
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
这样我每天早上六点就能收到一个前一天的汇总列表了，效果如下：
&lt;/p&gt;


&lt;div id=&quot;org84593a7&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/digest-rss-item.png&quot; alt=&quot;digest-rss-item.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
除了机核，当然还会有其他资讯类 RSS 想做这个转换，每次都在 Huginn 上手动创建一个个 agent 也不是个事，就顺手在我的&lt;a href=&quot;https://github.com/Linusp/zs&quot;&gt;个人脚本仓库&lt;/a&gt;里加了一个脚本，还是以机核为例，只要执行下面的命令就会生成一个  Huginn 的 Scenario 文件，然后到 Huginn 上直接导入就好了：
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;zs-rss gen-daily-scenario --feed-url &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;https://www.gcores.com/rss&quot;&lt;/span&gt; -n &amp;#26426;&amp;#26680; -o gcore.json
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
目前制作了两个这样的每日摘要 RSS，分别是：
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;机核: &lt;a href=&quot;https://feedpress.me/gcore-daily&quot;&gt;https://feedpress.me/gcore-daily&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Engadget 中国版: &lt;a href=&quot;https://feedpress.me/engadget-cn-daily&quot;&gt;https://feedpress.me/engadget-cn-daily&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
输出的 RSS 里只有原始 RSS 里文章的标题和链接，文章内容被我丢掉了，之后考虑改一下把内容加上（如果有的话）。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>把自我作为方法</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2020/10/11/the-self-as-method.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2020/10/11/the-self-as-method</id>
    <published>2020-10-11T00:00:00+00:00</published>
    <updated>2020-10-11T00:00:00+00:00</updated>
    <description>
    
      <p>我对自我的建模</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgc8af367&quot;&gt;自我是什么&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org90b7a32&quot;&gt;把自我作为方法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org0dd1950&quot;&gt;漫谈&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc8af367&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgc8af367&quot;&gt;自我是什么&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgc8af367&quot;&gt;
&lt;p&gt;
在面对生活中各种压力的时候，总能发现一些自己身上以前没有注意过的问题，早些年我会将其中一些问题归咎于外界，认为这是世界的问题、他人的问题，带着愤怒消极或者激烈地去对抗，有时候会有点效果，但更多的时候不过都是徒劳。世界不以个体为中心而存在，这个道理或许很早的时候我们就能脱口而出，但希望世界是以我为中心这种隐秘的想法，或多或少、某时某刻，还是会涌现出来，为了对抗我们自身存在的虚无感。
&lt;/p&gt;

&lt;p&gt;
遭遇挫折后，首先，我们会发现我们掌控不了全世界，接着就会发现自己周围的小世界也是如此，疾病随后当头一棒逼迫我们认识到即使是掌握自己的身体也需要持久的付出，而心灵 —— 连笛卡尔也只能说我思故我在，普通人心灵的浅薄和无知，老实说并没有什么价值。这种对自我存在价值的全面否定 —— 或者说找不到自我存在价值的感受，我想所有人都会有。哲学家、心理学家、科学家在这方面都有很多讨论，但最终怎么在废墟上把自己捡起来，还是得靠自己的学习、思考和实践。很惭愧，我在哲学、心理学、科学的相关方面都涉猎不深，不过是断断续续有一些自己的想法，并且觉得这些想法开始慢慢形成一个不那么脆弱的整体，勉强可以应付一些小问题，所以尝试把这些想法写下来。
&lt;/p&gt;

&lt;p&gt;
既然自我价值的崩塌是由外而内的，那么重建的时候不妨逆着这个过程，由内而外来进行，先把自我观念建立起来，简单来说，就是好好认识自己，诚实地面对自己的想法，在此基础上，或许能更为有效地与周围的世界共存，不说改变世界，起码过得开心自在，岂不美哉。不过所谓内、外可能并没有那么界限分明，我所谓的由外而内、由内而外不过是由于我这个人类个体浅薄的认知和语言的无力而产生的不精确表述，不必纠结。
&lt;/p&gt;

&lt;p&gt;
在我的想法里，自我观念会是支撑世界观、人生观、价值观的基石，因为：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;我们所认识到的世界不过是真实世界通过我们的感受器官形成的一个投影 —— 按照柏拉图的说法，我们只是在山洞里看到了外部世界的影子；从生物学上来说，人类能感受到的可见光只有波长 300 多纳米到 800 纳米这么小小一段，可感知的声音也只是频率为 20 赫兹到 20000 赫兹的一段；从物理学上来说，时空是十一维的，我们不过能感知其中的四个维度 —— 三维空间和时间，想象一下四维空间就能让普通人的大脑宕机，这方面我们不比蚂蚁有太多优势，数学家除外……这些与生俱来的限制，决定了我们对世界的认识必然是极其不完善的，我们没有办法去克服这些限制，但认识到这些限制，或许能帮助我们纠正一些对世界的错误看法&lt;/li&gt;
&lt;li&gt;所谓人生观，不过是如何看待自己的过去、如何看待自己的未来，而人类记忆的不靠谱和自我欺骗的习性都会扭曲我们对过去的印象，至于对未来的看法，无外乎基于过去的经验对未来进行预测或规划，首先受到过去经验的限制，接着又受到此刻自我观念的影响，所以更清楚地认识自己，能帮我们更理智地看待过去并应对未来的各种不确定性&lt;/li&gt;
&lt;li&gt;世界观和人生观方面，我们或许还可以努力客观一点，但价值观则完全是主观的，因此也和自我观念的关系更加紧密；此外，自我观念是时刻在变化的，价值观又可以反过来模拟「理想自我」来帮助自我改进&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
事实上自我观念、世界观、人生观、价值观四者之间的关系很复杂，并不能简单区分开来，但整体上来说，不妨抛开哲学、心理学的话语，将「自我」作为一件认识、影响世界和实现自我价值的工具，熟悉和改进这个工具则是我的目的。至于为什么要抛开哲学、心理学的话语，自己新发明一套话语，主要是哲学、心理学方面的话语我不懂（吃了没有文化的亏），另外就是觉得哲学、心理学的话语都不够精确。
&lt;/p&gt;

&lt;p&gt;
我将「自我」简化为这样一个系统:
&lt;/p&gt;

&lt;p&gt;
\[y_{t} = f(x_{t}|C, b, h)\]
&lt;/p&gt;

&lt;p&gt;
其中 \(x_{t}\) 表示当前发生的事件，\(C\) 表示当前的环境，\(b\) 表示当前我的身体状况，\(h = x_{0},x_{1},...,x_{t-1}\) 表示我的过往经历（由过去发生在我身上的事件序列构成），\(y_{t}\) 表示这个系统输出的一个事件。也就是说，它接受一个事件输入，根据当前的环境、身体状况和过往经历作出反馈，仅此而已。
&lt;/p&gt;

&lt;p&gt;
这样定义之后，我就可以摆脱「我思故我在第一个我和第二个我是不是同一个对象」这种无比纠结的语言游戏了，也不用在什么本我、自我、超我、经验自我、纯粹自我、现实自我、理想自我、客我、主我……的话语里打转了。我所定义的这个系统局部来看是处理好一个个事件，也就是做好当下的一件件小事情，全局来看则是将来也能处理好一件件事情，这样就足够了。
&lt;/p&gt;

&lt;p&gt;
在这个基础上，我也可以尝试去回答一些以前难以回答的问题了，比如说：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
如何认识自我？
&lt;/p&gt;

&lt;p&gt;
简单，给定各种场景，询问自己在该场景下会如何反应，仅此而已，不需要去刻画一个整体的「人格」，也可以摆脱「我爱读书」、「我很内向」这种标签化的自我评价。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
如何改善自我？
&lt;/p&gt;

&lt;p&gt;
简单，改进这个系统，让它能在未来，对相同的事件作出更好的响应，仅此而已，不用考虑什么幸福、自由之类的虚无缥缈的概念 —— 我并不是说幸福、自由没有意义，只不过幸福、自由是一个难以界定的准则，直接以此作为评价标准是否具有指导意义很不好说。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
如何确定自我价值？
&lt;/p&gt;

&lt;p&gt;
简单……好吧，仍然不简单。必须要承认，确定自己的价值，仍然是一个很困难的事情，毕竟人类的存在毫无意义。但基于我这个定义，仍然可以尝试来回答这个问题：好比软件的价值是其所具备的功能，我所描述的这个系统也是一样，它的功能就是输入一个事件然后输出一个事件，那么这些功能得到使用就是其价值所在，换言之活着就是自我的价值所在（看来我是一个存在主义者）；或者换另外一种说法，还是类比软件，软件的价值是对用户有用，我所描述的这个系统，大一点不妨将整个世界当作用户，小一点不妨将和我有互动的人、物当作用户，响应这些用户的操作就是这个系统的价值所在，只不过这样的话，对无神论者来说要满足很多很多用户的需求，宗教信徒的话只要让神这个 VIP 用户满意就好了。
&lt;/p&gt;

&lt;p&gt;
虽然这样得到的回答仍然不令人信服，但至少我有了一个相对自洽的结果，对此我很满意了。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
初步解决了「自我」的建模后，仍然存在一些根本性的问题需要回答，比如说：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;改善自我方法中提到了「更好的响应」，所谓的「更好」是什么？&lt;/li&gt;
&lt;li&gt;在上一个问题未得到满意回答的情况下，是否有办法制定「更好的自我」的评判标准？&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
第一个问题，所谓的「更好的响应」，是无法由这个系统本身来给出精确答案的，让系统评价自己的行为是否合理，这将会陷入一个死循环。但正如我作出这个定义是为了避免去追寻一个单一、绝对的自我评价一样，一个单一、绝对的判断这个系统行为是好是坏的准则，在我这里也不需要存在，它可以是一个动态的、随时变化的标准，简单来说就是好坏是需要根据当时所处的环境 \(C\)、身体状况 \(b\) 以及个人经历 \(h\) 来共同做决定，比如说
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;早上睡醒了，根据过去的经验，在床上刷手机会推迟起床时间影响当日计划导致晚上因为碌碌无为而心生懊悔，那么马上起床就是一个更好的行为&lt;/li&gt;
&lt;li&gt;出门去上班，此时天气晴朗微风缕缕气温舒适，那么骑车 10 公里去上班，比坐地铁去上班，就是一个更好的行为&lt;/li&gt;
&lt;li&gt;……&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
虽然上述例子已经把评价的前提条件缩减到了「当前场景」，但其实还是隐含了一些价值判断在这里，比如说「完成今天计划做的事情」比「没有完成今天计划做的事情」更好，这就涉及到价值观的问题，仍然非常模糊，但这样已经足够了，一件件小的事情的价值是相对容易判断、记录、分析的。
&lt;/p&gt;

&lt;p&gt;
如果非要用一个终极的准则比如说幸福感去指导，会怎么样呢？早起会让我更幸福吗，不见得，躺被窝里多幸福啊；骑车 10 公里去上班会让我更幸福吗，那也未必，顶多就是心情舒畅一些。再说了，幸福到底又是什么呢？
&lt;/p&gt;

&lt;p&gt;
对这种标准的另外一个担心是，只看眼前，会不会因为过于短视而损害未来的长期收益？当然会有这个问题，但我的理念是，未来是不可预测的，长期收益也很难判断，至少我判断不了，与其在每一件事情上去衡量未来能有多少回报，不如做好当下的事情；此外，可以将长期收益逐级分解，比如说把一年目标分解成很多小目标，这些小目标就有可能作为指导当前行为的一个准则，也不失为解决短视的一个办法，但这需要很强大的问题拆分、执行能力，不知道有多少人能做到呢？
&lt;/p&gt;

&lt;p&gt;
熟悉人工智能的人，大概能看出来我对「自我」的建模，其实借鉴了强化学习的模型，在强化学习里也是一样，评估长期价值很困难。最近有看到一篇新的论文很有意思，是在 NLP 任务中应用强化学习，然后用情感分析的结果作为每一个决策的收益，这个也可以借鉴到这这篇文章讨论的问题上来，比如说，如果一个事件响应完后能让「我」感到开心、平静这种正面的情绪，那么它就是一个好的响应。甚至可以用金钱收益（或损失）作为标准，这里就不再展开了。
&lt;/p&gt;

&lt;p&gt;
第二个问题，我认为是有的，那就是去考察这个系统内在的一些特性，比如说
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;连续性: 在短时间内，相似的场景下，对相同的事件，系统能作出相近的响应 —— 不要做一个反复无常的人&lt;/li&gt;
&lt;li&gt;可解释性: 对每个事件的反应，可以用语言给出合理的解释 —— 不要做一个不可理喻的人&lt;/li&gt;
&lt;li&gt;适应性: 当场景、身体状况、事件发生变化时，能给出不同的响应，但这种变化的程度不应大到破坏「连续性」 —— 不要做一个顽固死板的人&lt;/li&gt;
&lt;li&gt;逻辑上的一致性: 从可解释性那里提炼的逻辑，应该在适用的场景下也发挥作用，如果在某个适用该逻辑的场景下实际的响应逻辑与前面的逻辑矛盾，那么视为破坏了逻辑一致性 —— 不要做一个自相矛盾的人&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
对「自我」这个系统的内在评判指标，暂时就想到这么多了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org90b7a32&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org90b7a32&quot;&gt;把自我作为方法&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org90b7a32&quot;&gt;
&lt;p&gt;
前面我聊了很多我建模「自我」的想法，但说到底，这些都不过是思维游戏，或者说语言游戏，如果它不能真地在我的个人生活中发挥作用，那么无论我将其设计得多么精确、细致，也不过是空中楼阁、纸上谈兵。工具当然要拿来使用，模型当然要拿来进行预测。项飚在《把自己作为方法》一书中表达的一个核心观点，就是「亲身实践」对认识世界和社会是很重要的，看起来像是废话，但我们可以反思一下，我们很多行为的动机和依据，可能都不是来自于自己的经验，而是「别人都是这么做的」、「我听说……所以……」，很多人口口声声独立思考、自由人格，实则不堪一击。
&lt;/p&gt;

&lt;p&gt;
我将「自我」建模，就是要将其作为一件工具，这件工具的目的是自我完善、探索世界甚至影响世界 —— 不要误解，影响我周围一平方米也算是影响，我并没有什么很大的野心。为此，我首先要做的是熟悉这件工具，与自己磨合，并逐步改善。
&lt;/p&gt;

&lt;p&gt;
作为一个程序员，在我的学习、工作经验中得到的一个经验就是，如果你想了解一个工具，那么就去使用它，然后进行观察，在足够的观察之后对其进行分析，在此基础上才能进行改进。为什么自我改进、自我提高这么难，因为很多人对「自我」这个系统并没有有意识地、主动地去使用和观察，在这种情况下何谈改进呢？因此，为熟悉「自我」这件工具，我正在做以下几件事情
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;记录我的情绪反应，包括当时的场景、事件，并尝试解释我的情绪反应是如何发生的&lt;/li&gt;
&lt;li&gt;记录我每天的时间使用，包括我的工作、学习、日常生活和娱乐，目前我已经坚持了一个多月，平均能将自己每天 90% 以上的时间使用情况记录下来&lt;/li&gt;
&lt;li&gt;记录我每天的支出状况，已经坚持进行四年有余&lt;/li&gt;
&lt;li&gt;记录我读过的书、看过的影视剧、玩过的游戏&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
通过这些记录，我比过去更加清楚了我自己的一些特性，在详细的记录下，自我欺骗无所遁形，比如说我的情绪控制能力其实很差，过去我会给自己各种借口，比如说工作压力很大啊、我是对的别人是错的怎么对方那么顽固啊，但记录下来当时的细节后，哪怕我当时做记录的时候还有情绪，但是对环境、人物的描写仍然会尽量客观，那么之后在冷静下来后再去回顾，就会发现我自己的顽固和进攻性是那么的明显。
&lt;/p&gt;

&lt;p&gt;
做记录还有一个好处，就是觉察自己的每一个行为 —— 比如说，在我开始做时间使用记录前，我决定去玩游戏可能是一个潜意识的行为，可能是因为厌倦了工作想要松口气或者心情不好想要发泄一下，但这些都是下意识完成的，但相比玩游戏，可能去休息 10 分钟会更好一些；当我开始做记录后，我需要在开始玩游戏时进行计时，这里就让我获得了一个停顿的时间点，让我能意识到我要主动地去玩游戏了，多这么一个停顿，就能觉察到自己所要做的事情，就给了我判断这个行为合理性的时间，这对我来说是非常有用的。觉察到自己的行为，除了帮助我更好地决策外，还让我对「现在」的感受更加的强烈和清晰了，让我感受到了更多的乐趣。
&lt;/p&gt;

&lt;p&gt;
目前为止，我做的主要事情，还是在记录上，在分析、改进方面做得并不多，接下来的计划有这么一些
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;做更多方面的记录，比如食物的摄入、周围环境的变化、我对不同事件（除情绪外）的反应……&lt;/li&gt;
&lt;li&gt;定期（按周或按月）回顾这些记录，分析问题、总结经验&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
除了记录、分析外，需要注意的是，这个工具是会受到环境、身体状况影响的，所以学习相关的知识也是很有必要的（看，学习的意义也有了！），不过学习是一件终身的事情，不太好做很具体的规划，目前也还是以记录为主，我目前是这样记录阅读过程的：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;用 Zotero 从豆瓣或者 Amazon 抓取一本书的元信息（作者、出版社、ISBN 等）&lt;/li&gt;
&lt;li&gt;找到这本书的电子版，作为附件添加到 Zotero 条目中&lt;/li&gt;
&lt;li&gt;Zotero 使用 Better BibTex 导出成一个文献数据库文件，其中包含了这个书籍&lt;/li&gt;
&lt;li&gt;在 Emacs 中使用 helm-bibtex 查找到这本书，使用 org-roam 创建阅读记录，使用 org-noter 进行阅读，记录标注、笔记&lt;/li&gt;
&lt;li&gt;使用 org-roam 将阅读过程中学习到的概念、方法分离出去形成单独的笔记，并链接回来&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
关于笔记、知识管理，准备之后单独写一篇文章来阐述细节，这里就不展开了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0dd1950&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org0dd1950&quot;&gt;漫谈&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org0dd1950&quot;&gt;
&lt;p&gt;
前面也提到，我为「自我」所做的定义，其实很大程度借鉴了人工智能里的强化学习模型，就是击败围棋世界冠军的 AlphaGo 所使用的核心算法。人工智能领域的很多算法、模型，都比心理学、哲学更具有参考价值，首先里面的模型其实本来就是从认知科学里分化出来的，然后为了应对实际问题而进行了简化、量化，消解掉「心智」这个神秘的成分，留下冷酷的数学公式，这就使得这些模型天然地就和人类的认知过程贴近，同时又精确而可执行，是任何人都能借鉴的。
&lt;/p&gt;

&lt;p&gt;
除了强化学习，我再列举一些人工智能、机器学习里的概念
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;误差反向传播: 对比实际结果和预期结果之间的差异，从后往前反推差异的来源并进行调整 —— 类比到人类身上的话，就是设定预期，然后复盘分析问题，很直白的道理&lt;/li&gt;
&lt;li&gt;过拟合: 当一个模型只在很少的数据上进行学习时，往往会过度适应这些数据，导致无法应对正确新的数据 —— 类比到人身上的话，见识太少，面对新问题时就很容易手足无措&lt;/li&gt;
&lt;li&gt;对比学习; 通过大量相同事物的有差异的表现来认识这个事物&lt;/li&gt;
&lt;li&gt;知识蒸馏: 用一个很大但效果很好的模型去教一个小模型，让这个小模型也能表现很好 —— 类比到人身上的话，向优秀的人学习是提高自己的一个很好的方法&lt;/li&gt;
&lt;li&gt;对抗训练: 模型 A 的目标是生成数据，尽量让模型 B 分辨不出来这是生成的，而模型 B 则要努力辨别出来，最终会让模型 A 生成的结果特别逼真 —— 类比到人身上的话，有一个水平相当的对手竞争，会让人得到快速的提高&lt;/li&gt;
&lt;li&gt;……&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
这些类比还能写很多，一时半会是写不完的。总之，哪怕不是人工智能行业的从业人员，泛泛地了解一点相关的理论知识也对自我认识和改善会有帮助的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>使用 org-roam 构建自己的知识网络</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2020/06/27/org-roam-introduction.html"/>
    <category term="Emacs" scheme="http://www.zmonster.me/categories.html#Emacs"/>
    <id>http://www.zmonster.me/2020/06/27/org-roam-introduction</id>
    <published>2020-06-27T00:00:00+00:00</published>
    <updated>2020-06-27T00:00:00+00:00</updated>
    <description>
    
      <p>最近 Roam Research 一类的以网状结构来关联笔记、并以 backlink 来展现笔记上下文的工具非常热门，Emacs 上也出现了一个类似的工具 org-roam，本文将简单介绍该工具及个人初步使用感受</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga7b35dc&quot;&gt;前言&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org575209e&quot;&gt;环境说明&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge3ac302&quot;&gt;安装及初步配置&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8ca3405&quot;&gt;org-roam 的基本使用&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgbf7c137&quot;&gt;org-roam 进阶&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgec47e48&quot;&gt;定制笔记模板&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6fd36c4&quot;&gt;实现网页内容摘录&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga7b35dc&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga7b35dc&quot;&gt;前言&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga7b35dc&quot;&gt;
&lt;p&gt;
最近 &lt;a href=&quot;https://roamresearch.com/&quot;&gt;Roam Research&lt;/a&gt; 一类的以网状结构来关联笔记、并以 backlink 的形式来展现笔记上下文的工具非常热门。所谓网状结构，是认为知识和知识是互相关联的，并通过这种互联形成复杂的网络，就像我们的大脑一样；所谓 backlink，是指对单条笔记，展示出链接到这条笔记的其他笔记，这样有助于更好地理解这条笔记的意义。本质上，网状结构和 backlink 其实是一回事，说的都是知识之间的互相链接，不过网状结构着眼于整体结构，而 backlink 则呈现局部形态。
&lt;/p&gt;

&lt;p&gt;
Roam Research 这类工具中的理念，叫做卡片盒笔记法，本文无意对这一想法做过多介绍，如果想进一步了解，可以参考下列文章：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://sspai.com/post/60787&quot;&gt;Roam Research 到底好在哪儿？ - 少数派&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sspai.com/post/60802&quot;&gt;从卡片链接到大脑联想，基于 Obsidian 的卡片盒笔记法实践 - 少数派&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mp.weixin.qq.com/s?__biz=MzI3NDEzMjIyMQ==&amp;amp;mid=2649474090&amp;amp;idx=1&amp;amp;sn=bf2fcc5c3a909e939795eb36b1ec33ae&amp;amp;chksm=f307d9b8c47050ae1f88ed976deef2e7e51b44fd4eac768b5541743a9876cc1a505df11a3a71#rd&quot;&gt;真正的思考技术：来自德国社会学 Niklas Luhmann 的 Zettelkasten 方法&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
在 Emacs 中，很早就有一个工具 &lt;a href=&quot;https://github.com/Kungsgeten/org-brain&quot;&gt;org-brain&lt;/a&gt;，想要以 org-mode 为基础让人能建立自己的知识网络，本质上思想是类似的，但交互并不算特别友好，所以我以前稍微用了下就没有继续下去了，而最近出现的 &lt;a href=&quot;https://www.orgroam.com/&quot;&gt;Org-roam&lt;/a&gt; 则对标 Roam Research，实现了非常友好的交互，并提供了 &lt;a href=&quot;https://github.com/org-roam/org-roam-server&quot;&gt;org-roam-server&lt;/a&gt; 这样非常棒的知识网络可视化界面，经过短时间的使用后，我推荐所有使用 org-mode 来记录自己笔记的人都用一下 org-roam，理由如下：
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;org-mode 本来就提供了极其强大的链接能力，可以链接到文件、headline 甚至文件的随便一行，也支持了对大量不同类型的外部链接，而 org-roam 为这种能力提供了友好而高效的交互操作&lt;/li&gt;
&lt;li&gt;org-roam 复用了 org-capture 的强大功能，使得我们可以自定义各种笔记模板来更好地表示、呈现知识&lt;/li&gt;
&lt;li&gt;org-roam-server 提供的笔记网络可视化界面和 org-roam 深度集成，点击界面上的笔记节点就能在 Emacs 中打开对应的笔记&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org575209e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org575209e&quot;&gt;环境说明&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org575209e&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;操作系统： Ubuntu 16.04&lt;/li&gt;
&lt;li&gt;Emacs 版本： GNU Emacs 26.1&lt;/li&gt;
&lt;li&gt;org-mode 版本： 9.3.7&lt;/li&gt;
&lt;li&gt;org-roam 版本： 开发版 20200615&lt;/li&gt;
&lt;li&gt;org-roam-server 版本： 开发版 20200621&lt;/li&gt;
&lt;li&gt;浏览器： Firefox/Chrome&lt;/li&gt;
&lt;li&gt;GIF 录制工具： &lt;a href=&quot;https://linux.die.net/man/1/byzanz-record&quot;&gt;byzanz-record&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge3ac302&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge3ac302&quot;&gt;安装及初步配置&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge3ac302&quot;&gt;
&lt;p&gt;
直接从 &lt;a href=&quot;https://melpa.org/&quot;&gt;MELPA&lt;/a&gt; 安装即可
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(package-install 'org-roam)
(package-install 'org-roam-server)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
安装完成后，首先需要设置 org-roam-directory 指向一个目录，用来存放使用 org-roam 创建的笔记。我把笔记都放在 Dropbox 里，所以设置如下
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; org-roam-directory &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/roam&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后让 org-roam 在 Emacs 启动后就启用
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-hook 'after-init-hook 'org-roam-mode)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后设置并启动 org-roam-server 来监听笔记的变化并进行可视化（见&lt;a href=&quot;https://github.com/org-roam/org-roam-server#installation&quot;&gt;org-roam-server 安装说明&lt;/a&gt;）
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; org-roam-server-host &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;127.0.0.1&quot;&lt;/span&gt;
      org-roam-server-port 9090
      org-roam-server-export-inline-images t
      org-roam-server-authenticate nil
      org-roam-server-network-label-truncate t
      org-roam-server-network-label-truncate-length 60
      org-roam-server-network-label-wrap-length 20)
(org-roam-server-mode)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上面的配置生效后，会在本地启动一个网页服务，访问 &lt;a href=&quot;http://127.0.0.1:9090&quot;&gt;http://127.0.0.1:9090&lt;/a&gt; ，会看到下面这样的界面：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-roam-server-web.png&quot; alt=&quot;org-roam-server-web.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
由于刚开始并没有创建笔记，上面只会显示一片空白。
&lt;/p&gt;

&lt;p&gt;
然后启用 org-roam-protocol，用来在笔记可视化网页上和 org-roam-server 通信
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;require&lt;/span&gt; '&lt;span style=&quot;color: #6699cc;&quot;&gt;org-roam-protocol&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这个 org-roam-protocol 是使用 org-protocol 实现的，依赖操作系统的相关功能，相关设置参考&lt;a href=&quot;https://www.orgroam.com/manual/Installation-_00281_0029.html&quot;&gt;文档&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
完成上述设置后，就可以开始体验 org-roam 了，执行 M-x org-roam-find-file 创建一条新的笔记，然后刷新笔记可视化页面，就能看到页面上多了一个新的节点了，如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-roam-new.gif&quot; alt=&quot;org-roam-new.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8ca3405&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org8ca3405&quot;&gt;org-roam 的基本使用&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org8ca3405&quot;&gt;
&lt;p&gt;
首先来看下 org-roam 的基本功能
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;函数&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;功能&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;org-roam-find-file&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;打开或新建笔记&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;org-roam-capture&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;新建笔记&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;org-roam-insert&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;插入一个指向其他笔记的链接，如果不存在会新建一个笔记&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;org-roam-insert-immediate&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;类似 org-roam-insert，但新建笔记后不打开这个笔记&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;需要 org-roam 1.2.1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;org-roam&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;显示 backlink&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
核心的功能就这么多，没有太多概念、操作要学习，这也是我推荐大家使用它的原因。其基本工作流也很简单，下面是一个示例：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;打开已有笔记，或新建笔记

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
使用 org-roam-find-file 来新建一个笔记
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-roam-new.gif&quot; alt=&quot;org-roam-new.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
或者，使用 org-roam-find-file 来打开已有的笔记
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-roam-open-note.gif&quot; alt=&quot;org-roam-open-note.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
或者，在笔记可视化网页上浏览，点击想要查看或编辑的笔记节点，在 Emacs 中打开这个笔记
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-roam-open-note-2.gif&quot; alt=&quot;org-roam-open-note-2.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
选中笔记内容中的某些关键词，使用 org-roam-insert-immediate，创建新的笔记并链接过去，并继续编辑当前的笔记
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-roam-insert-immediate.gif&quot; alt=&quot;org-roam-insert-immediate.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
从图上右侧可以看到产生了一个名为 org-mode 的新节点，并和 Emacs 这个节点关联起来了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
或者，选中笔记内容中的关键词，使用 org-roam-insert，创建新的笔记并链接过去，同时打开新的笔记进行编辑
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-roam-insert-new.gif&quot; alt=&quot;org-roam-insert-new.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
从图上右侧可以看到产生了一个名为 calc 的新节点，并和 Emacs 这个节点关联起来了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
或者，用 org-roam-insert-immediate/org-roam-insert 插入一个指向已有笔记的链接
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-roam-link-to.gif&quot; alt=&quot;org-roam-link-to.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
上图和步骤 3 一样执行的是 org-roam-insert，但从图上右侧可以看到，只是已有的两个节点之间产生了一条关联，并没有新的节点产生。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
使用 org-roam 展示笔记的 backlinks
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-roam-show-backlinks.gif&quot; alt=&quot;org-roam-show-backlinks.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
用 org-roam-capture 在已有笔记中新增内容
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-roam-append.gif&quot; alt=&quot;org-roam-append.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
org-roam-capture 也可以用于新建笔记，实际上 org-roam-find-file 的逻辑就是：先检查笔记文件是否存在，如果存在就打开，否则就调用 org-roam-capture 来新建笔记。但 org-roam-capture 除了用于新建笔记文件，还可以快捷地在已有笔记中新增内容，且新增内容时可以利用模板来提高效率，比用 org-roam-find-file 打开笔记文件再手工新增会更高效一些。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;重复上述过程&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
掌握上述工作流后，剩下的事情就是把自己所学到的东西用 org-roam 来进行记录、整理了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgbf7c137&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgbf7c137&quot;&gt;org-roam 进阶&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgbf7c137&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgec47e48&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgec47e48&quot;&gt;定制笔记模板&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgec47e48&quot;&gt;
&lt;p&gt;
用 &lt;b&gt;org-roam-find-file/org-roam-capture&lt;/b&gt; 新建笔记的时候，会要求我们输入笔记标题，假如我们输入的笔记标题是 &quot;org-roam&quot;，那么会在新建这个笔记后发现这个笔记只在第一行把我们输入的标题写上去了，别的什么都没有：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #99cc99;&quot;&gt;#+title:&lt;/span&gt; &lt;span style=&quot;color: #f99157; font-size: 144%; font-weight: bold;&quot;&gt;org-roam&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
在实际使用中，我们可能会有不同的笔记需求，比如说：当我为一个专业术语记录笔记时，我想写下这个术语所属的领域以及它的含义；当我记录一个观点时，我会想写上这个观点是谁提出来的、论据是什么、我自己是支持还是反对；当我读一篇深度学习的论文时，我要记录这篇论文的相关工作、要解决的问题、使用了什么方法、进行了怎么样的实验……
&lt;/p&gt;

&lt;p&gt;
这些需求用 org-roam 是能够满足的，因为 org-roam 通过 org-roam-capture-templates 这个变量提供了定制笔记模板的能力。
&lt;/p&gt;

&lt;p&gt;
具体来说，默认的笔记模板是这样的
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;'((&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;d&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;default&quot;&lt;/span&gt; plain (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;function&lt;/span&gt; org-roam-capture--get-point)
   &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%?&quot;&lt;/span&gt;
   &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:file-name&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%&amp;lt;%Y%m%d%H%M%S&amp;gt;-${slug}&quot;&lt;/span&gt;
   &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:head&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+title: ${title}\n&quot;&lt;/span&gt;
   &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:unnarrowed&lt;/span&gt; t))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
每个模板都由 8 个部分组成，我这里以上面的默认模板来进行说明
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;模板组成&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;对应默认模板中的内容&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;key&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&quot;d&quot;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;用来选择模板的快捷键&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;description&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&quot;default&quot;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;展示用的模板描述&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;type&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;plain&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;新增内容的类型&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;target&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;(function org-roam-capture&amp;#x2013;get-point)&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;新增内容的位置， &lt;b&gt;不可更改&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;template&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&quot;%?&quot;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;新增内容的模板&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;file-name&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;:file-name &quot;%&amp;lt;%Y%m%d%H%M%S&amp;gt;-${slug}&quot;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;新增笔记文件的文件名模板&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;head&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;:head &quot;#+title: ${title}\n&quot;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;新增笔记的初始化内容，仅新建时生效&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;properties&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;:unnarrowed t&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;新增笔记的其他属性&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
下面对这 8 个模板元素分别说明一下
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
用来选择模板的 key：
&lt;/p&gt;

&lt;p&gt;
对应默认模板里的 &quot;d&quot;，一个字符的情况下用来直接选择模板，两个字符的情况下用第一个字符表示模板分组、第二个字符用来选择这个分组下的实际模板。
&lt;/p&gt;

&lt;p&gt;
下面的配置设置了四个模板，其中第二个 (&quot;g&quot; &quot;group&quot;) 用来指明一个模板分组，后面的 &quot;ga&quot; 和 &quot;gb&quot; 是这个模板下的子模板。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; org-roam-capture-templates
      '(
        (&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;d&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;default&quot;&lt;/span&gt; plain (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;function&lt;/span&gt; org-roam-capture--get-point)
         &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%?&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:file-name&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%&amp;lt;%Y%m%d%H%M%S&amp;gt;-${slug}&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:head&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+title: ${title}\n#+roam_alias:\n\n&quot;&lt;/span&gt;)
        (&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;g&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;group&quot;&lt;/span&gt;)
        (&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;ga&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Group A&quot;&lt;/span&gt; plain (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;function&lt;/span&gt; org-roam-capture--get-point)
         &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%?&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:file-name&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%&amp;lt;%Y%m%d%H%M%S&amp;gt;-${slug}&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:head&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+title: ${title}\n#+roam_alias:\n\n&quot;&lt;/span&gt;)
        (&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;gb&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Group B&quot;&lt;/span&gt; plain (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;function&lt;/span&gt; org-roam-capture--get-point)
         &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%?&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:file-name&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%&amp;lt;%Y%m%d%H%M%S&amp;gt;-${slug}&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:head&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+title: ${title}\n#+roam_alias:\n\n&quot;&lt;/span&gt;)))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上面的模板生效后，首先在执行 org-roam-find-file 新建笔记时，就会看到一个选择界面，如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-roam-capture-select-template.gif&quot; alt=&quot;org-roam-capture-select-template.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
如果输入 d 会直接打开新建笔记的编辑窗口，如果输入 g 会展开分组模板要求我们再输入一次来选择具体的模板，如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-roam-capture-select-group-template.gif&quot; alt=&quot;org-roam-capture-select-group-template.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;用来描述模板的 description：这个元素就是起到单纯的描述作用，没有功能上的意义&lt;/li&gt;
&lt;li&gt;用来说明新增内容类型的 type：本来有 plain/entry/item/checkitem/table-line 五种取值，但在 org-roam 中作用都是一样的，建议一律使用 plain&lt;/li&gt;
&lt;li&gt;用来说明新增内容位置的 target：这一项在 org-roam 中不可更改&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
设置新增内容模板的 template：
&lt;/p&gt;

&lt;p&gt;
这个元素是整个模板中的核心，其中的内容可以分为两类：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;普通的文本，将会原样出现在新增内容中&lt;/li&gt;
&lt;li&gt;以 % 开头的特殊标记，如默认模板中的 &quot;%?&quot;，将会在最后根据类型自动扩展成不同的内容&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
对于第一类内容没啥可说的，唯一值得一提的是，如果需要模板是多行的文本，需要在模板中用 &quot;\n&quot; 来指明要换行，如模板内容 &quot;第一行\n第二行&quot; 最后就会在笔记中显示为：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&amp;#31532;&amp;#19968;&amp;#34892;
&amp;#31532;&amp;#20108;&amp;#34892;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这里说一下以 % 开头的特殊标记，由于这块内容很多，这里只列举一些常用的供读者参考：
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;标记&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%&amp;lt;…&amp;gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;自定义格式的时间戳，如: %&amp;lt;%Y-%m-%d&amp;gt;，会得到 &lt;span class=&quot;timestamp-wrapper&quot;&gt;&lt;span class=&quot;timestamp&quot;&gt;&amp;lt;2018-03-04 日&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%t&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;当前日期，展开后的格式固定为 &lt;span class=&quot;timestamp-wrapper&quot;&gt;&lt;span class=&quot;timestamp&quot;&gt;&amp;lt;2018-03-04 日&amp;gt; &lt;/span&gt;&lt;/span&gt; 这样&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%T&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;当前日期和时间，展开后的格式固定为 &lt;span class=&quot;timestamp-wrapper&quot;&gt;&lt;span class=&quot;timestamp&quot;&gt;&amp;lt;2018-03-04 日 19:26&amp;gt; &lt;/span&gt;&lt;/span&gt; 这样&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%u&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;当前日期，展开后的格式固定为 &lt;span class=&quot;timestamp-wrapper&quot;&gt;&lt;span class=&quot;timestamp&quot;&gt;[2018-03-04 日] &lt;/span&gt;&lt;/span&gt; 这样&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%U&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;当前日期和时间，展开后的格式固定为 &lt;span class=&quot;timestamp-wrapper&quot;&gt;&lt;span class=&quot;timestamp&quot;&gt;[2018-03-04 日 19:26] &lt;/span&gt;&lt;/span&gt; 这样&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%&lt;sup&gt;prompt&lt;/sup&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;用 prompt 作为提示要求我们输入并填充在这个模板元素所在的位置&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%?&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;其他所有特殊标记填充完毕后，光标将停留在这个元素的位置等待我们编辑&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
指定新增笔记文件名的 file-name：
&lt;/p&gt;

&lt;p&gt;
org-roam 中新建笔记一般都是以一个新文件的形式来创建的，支持用 file-name 来设置这个新文件的文件名，默认模板中的这块设置为 &quot;%&amp;lt;%Y%m%d%H%M%S&amp;gt;-${slug}&quot;，分为两部分
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;b&gt;%&amp;lt;%Y%m%d%H%M%S&amp;gt;&lt;/b&gt; ：参考上一节 template 部分的特殊标记&lt;/li&gt;
&lt;li&gt;&lt;b&gt;${slug}&lt;/b&gt; ：将笔记标题文字做处理后得到的文本，这些处理包括大写字母转小写、去除一些特殊字符等&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
这块建议使用默认模板就好。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
设置新增笔记初始内容的 head：
&lt;/p&gt;

&lt;p&gt;
这个设置用来在新建笔记文件时设置初始内容，只会执行一次，也就是说之后如果使用 org-roam-capture 新增内容到已有笔记中时，这个设置的内容是不会再写入到文件中的。
&lt;/p&gt;

&lt;p&gt;
默认模板这块的内容是 &quot;#+title: ${title}\n&quot;，只设置了笔记文件的标题，建议改为如下内容：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:head&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+title: ${title}\n#+roam_alias: \n#+roam_tags: \n&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这样设置后新建笔记文件的初始内容将会是：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #99cc99;&quot;&gt;#+title:&lt;/span&gt; &lt;span style=&quot;color: #f99157; font-size: 144%; font-weight: bold;&quot;&gt;&amp;#31034;&amp;#20363;&amp;#26631;&amp;#39064;&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+roam_alias:&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+roam_tags:&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
&quot;#+roam_alias&quot; 可以给这条笔记设置别名，这样在其他笔记中引用的时候会更方便；&quot;#+roam_tags&quot; 可以用来为这条笔记添加标签，使得在用 org-roam-find-file 查找已有笔记时能根据 tag 来进行过滤。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
设置新增内容其他属性的 properties：
&lt;/p&gt;

&lt;p&gt;
这些属性用于对新建笔记内容的行为做一些额外的控制，列举几个常用的：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;b&gt;:unnarrowed t&lt;/b&gt;: org-roam 推荐的设置，表示现实整个笔记文件，如果不加这个设置，用 org-roam-capture 增加内容到已有笔记文件中时，仅会显示当前我们输入的内容，而不会显示这个笔记文件中已有的内容&lt;/li&gt;
&lt;li&gt;&lt;b&gt;:empty-lines 1&lt;/b&gt;: 在新增的笔记内容前后加一个空行，使用 org-roam-capture 增加内容到已有笔记文件中时比较有用&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
org-roam 的笔记模板是利用 &lt;a href=&quot;https://orgmode.org/manual/Capture.html&quot;&gt;org-capture&lt;/a&gt; 实现的，上述模板元素中 file-name 和 head 是 org-roam 在 org-capture 模板的基础上增加的新元素；其他六个部分，target 在 org-roam 中不可更改，key、description、type 和 template 的更详细说明可以参考我之前写的一篇介绍 org-capture 文章中的相关内容，&lt;a href=&quot;https://www.zmonster.me/2018/02/28/org-mode-capture.html#org1a3d856&quot;&gt;capture 模板的五个部分&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
为了能更直观地理解模板的工作机制，这里给几个模板的示例：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
用于记录专业术语的模板
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-roam-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;t&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Term&quot;&lt;/span&gt; plain (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;function&lt;/span&gt; org-roam-capture--get-point)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;- &amp;#39046;&amp;#22495;: %^{&amp;#26415;&amp;#35821;&amp;#25152;&amp;#23646;&amp;#39046;&amp;#22495;}\n- &amp;#37322;&amp;#20041;:&quot;&lt;/span&gt;
               &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:file-name&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%&amp;lt;%Y%m%d%H%M%S&amp;gt;-${slug}&quot;&lt;/span&gt;
               &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:head&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+title: ${title}\n#+roam_alias:\n#+roam_tags: \n\n&quot;&lt;/span&gt;
               &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:unnarrowed&lt;/span&gt; t
               ))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
将上面的配置拷贝到你的 Emacs 配置中，并置于所有 org-roam 相关配置的后面，就可以在你的 org-roam 中使用这个模板，后面的示例模板也是一样，但要注意不同模板的 key 不要有冲突。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-roam-new-term.gif&quot; alt=&quot;org-roam-new-term.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
用于记录论文笔记的模板
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-roam-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;p&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Paper Note&quot;&lt;/span&gt; plain (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;function&lt;/span&gt; org-roam-capture--get-point)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* &amp;#30456;&amp;#20851;&amp;#24037;&amp;#20316;\n\n%?\n* &amp;#35266;&amp;#28857;\n\n* &amp;#27169;&amp;#22411;&amp;#21644;&amp;#26041;&amp;#27861;\n\n* &amp;#23454;&amp;#39564;\n\n* &amp;#32467;&amp;#35770;\n&quot;&lt;/span&gt;
               &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:file-name&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%&amp;lt;%Y%m%d%H%M%S&amp;gt;-${slug}&quot;&lt;/span&gt;
               &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:head&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+title: ${title}\n#+roam_alias:\n#+roam_tags: \n\n&quot;&lt;/span&gt;
               &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:unnarrowed&lt;/span&gt; t
               ))
&lt;/pre&gt;
&lt;/div&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-roam-new-paper-note.gif&quot; alt=&quot;org-roam-new-paper-note.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
另外，org-roam-insert-immediate 不使用 org-roam-capture-templates，而是使用一个专门的 org-roam-capture-immediate-template 来设置新建内容的模板，且只能有一个模板，所以设置这个模板的配置是这样的（以默认配置为例）
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; org-roam-capture-immediate-template
      '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;d&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;default&quot;&lt;/span&gt; plain (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;function&lt;/span&gt; org-roam-capture--get-point)
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%?&quot;&lt;/span&gt;
        &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:file-name&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%&amp;lt;%Y%m%d%H%M%S&amp;gt;-${slug}&quot;&lt;/span&gt;
        &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:head&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+title: ${title}\n&quot;&lt;/span&gt;
        &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:unnarrowed&lt;/span&gt; t))
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6fd36c4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6fd36c4&quot;&gt;实现网页内容摘录&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6fd36c4&quot;&gt;
&lt;p&gt;
这部分内容需要 org-protocol，后续内容是在 org-protocol 已经设置好的基础上展开的，如果 org-protocol 设置存在问题，请查阅&lt;a href=&quot;https://www.orgroam.com/manual/Installation-_00281_0029.html&quot;&gt;文档&lt;/a&gt;，或这评论区留言来讨论。
&lt;/p&gt;

&lt;p&gt;
利用 org-protocol 这样的外部程序和 Emacs 进行通信的机制，我们可以使用 javascript 来抓取网页上的信息发送到 Emacs 中，而 org-roam 也支持了这种机制。在 org-roam 中可以通过 org-roam-capture-ref-templates 来设置网页捕获相关的模板，默认的设置是这样的：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; org-roam-capture-ref-templates
      '((&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;r&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;ref&quot;&lt;/span&gt; plain (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;function&lt;/span&gt; org-roam-capture--get-point)
         &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:file-name&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;${slug}&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:head&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+title: ${title}\n#+roam_key: ${ref}\n&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:unnarrowed&lt;/span&gt; t)))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到，模板本身和前面的笔记模板是一样的，没有什么特别。但我们可以创建一个&lt;a href=&quot;https://zh.wikipedia.org/zh-cn/%E5%B0%8F%E4%B9%A6%E7%AD%BE&quot;&gt;小书签&lt;/a&gt;，来利用这个模板，抓取网页标题和链接然后新建一个笔记到 org-roam 中，如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-roam-store-link.gif&quot; alt=&quot;org-roam-store-link.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
上图中小书签的内容来自 org-roam 的&lt;a href=&quot;https://www.orgroam.com/manual/The-roam_002dref-Protocol.html#The-roam_002dref-Protocol&quot;&gt;文档&lt;/a&gt;，具体内容为：
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-javascript&quot;&gt;javascript:location.href = &lt;span style=&quot;color: #66cccc;&quot;&gt;'org-protocol://roam-ref?template=r&amp;amp;ref='&lt;/span&gt; + encodeURIComponent(location.href) + &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;amp;title='&lt;/span&gt; + encodeURIComponent(document.title)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
添加的方法是在浏览器中新增一个书签，书签的名字随意（上图中我设置为了“网页抓取”），书签的 URL 填上上面的 javascript 代码。下图是 Firefox 中创建这样的小书签的示意图：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/create-bookmarklet-in-firefox.gif&quot; alt=&quot;create-bookmarklet-in-firefox.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这个小书签的内容分成几部分：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
第一部分说明小书签要访问的地址，这个就是 org-roam-protocol 的通信地址
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-javascript&quot;&gt;javascript:location.href=&lt;span style=&quot;color: #66cccc;&quot;&gt;'org-protocol://roam-ref'&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
第二部分指定要使用的笔记模板，从 org-roam-capture-ref-templates 中匹配
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-javascript&quot;&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;'?template=r'&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
第三部分获取一些网页的信息，并设置到变量中，供模板填充使用
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;'&lt;span style=&quot;color: #6699cc;&quot;&gt;&amp;amp;ref=&lt;/span&gt;' + encodeURIComponent(location.href) + '&lt;span style=&quot;color: #6699cc;&quot;&gt;&amp;amp;title=&lt;/span&gt;' + encodeURIComponent(document.title)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
前面的默认模板中，head 部分内容为
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:head&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+title: ${title}\n#+roam_key: ${ref}\n&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
需要填充 &quot;title&quot; 和 &quot;ref&quot; 两个变量，小书签中第三部分内容就是获取了当前网页的链接赋值给 &quot;ref&quot; 变量，并获取网页标题文本赋值给 &quot;title&quot; 变量了，这样这个模板就能自动填充好了。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
不过这个模板和小书签过于简单，只能记录网页链接，我设计了一个模板和对应的小书签，可以做到进行网页标注、摘录，效果见下图：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-roam-annotate-web.gif&quot; alt=&quot;org-roam-annotate-web.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
要达到上图的效果，首先，在 org-roam-capture-ref-templates 中新增一个模板
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-roam-capture-ref-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;a&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Annotation&quot;&lt;/span&gt; plain (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;function&lt;/span&gt; org-roam-capture--get-point)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%U ${body}\n&quot;&lt;/span&gt;
               &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:file-name&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;${slug}&quot;&lt;/span&gt;
               &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:head&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+title: ${title}\n#+roam_key: ${ref}\n#+roam_alias:\n&quot;&lt;/span&gt;
               &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:immediate-finish&lt;/span&gt; t
               &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:unnarrowed&lt;/span&gt; t))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后新建一个小书签，内容为
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-javascript&quot;&gt;javascript:location.href = &lt;span style=&quot;color: #66cccc;&quot;&gt;'org-protocol://roam-ref?template=a&amp;amp;ref='&lt;/span&gt; + encodeURIComponent(location.href) + &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;amp;title='&lt;/span&gt;+encodeURIComponent(document.title) + &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;amp;body='&lt;/span&gt;+encodeURIComponent(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;function&lt;/span&gt;(){&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;var&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;html&lt;/span&gt; = &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&quot;&lt;/span&gt;;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;var&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;sel&lt;/span&gt; = window.getSelection();&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; (sel.rangeCount) {&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;var&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;container&lt;/span&gt; = document.createElement(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;div&quot;&lt;/span&gt;);&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;var&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;i&lt;/span&gt; = 0, &lt;span style=&quot;color: #ffcc66;&quot;&gt;len&lt;/span&gt; = sel.rangeCount; i &amp;lt; len; ++i) {container.appendChild(sel.getRangeAt(i).cloneContents());}html = container.innerHTML;}&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;var&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;dataDom&lt;/span&gt; = document.createElement(&lt;span style=&quot;color: #66cccc;&quot;&gt;'div'&lt;/span&gt;);dataDom.innerHTML = html;[&lt;span style=&quot;color: #66cccc;&quot;&gt;'p'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'h1'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'h2'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'h3'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'h4'&lt;/span&gt;].forEach(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;function&lt;/span&gt;(&lt;span style=&quot;color: #ffcc66;&quot;&gt;tag&lt;/span&gt;, &lt;span style=&quot;color: #ffcc66;&quot;&gt;idx&lt;/span&gt;){dataDom.querySelectorAll(tag).forEach(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;function&lt;/span&gt;(item, index) {&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;var&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;content&lt;/span&gt; = item.innerHTML.trim();&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; (content.length &amp;gt; 0) {item.innerHTML = content + &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;amp;#13;&amp;amp;#10;'&lt;/span&gt;;}});});&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; dataDom.innerText.trim();}())
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>我所使用过的微信公众号文章转 RSS 的方法</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2020/04/17/wechat-articles-rss-solution.html"/>
    <category term="数字生活" scheme="http://www.zmonster.me/categories.html#数字生活"/>
    <id>http://www.zmonster.me/2020/04/17/wechat-articles-rss-solution</id>
    <published>2020-04-17T00:00:00+00:00</published>
    <updated>2020-04-17T00:00:00+00:00</updated>
    <description>
    
      <p>微广场关闭之后，我开始自己去为微信公众号输出 RSS，在这三年里尝试了多种方法，在此分享一下。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org2291282&quot;&gt;背景&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgadb6262&quot;&gt;Huginn 简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5dc36cf&quot;&gt;基于搜狗微信搜索的方案&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3f4ef78&quot;&gt;(已失效)基于即刻/快知和 RSSHub 的方案&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org0ab99c4&quot;&gt;基于 EFB 和 Telegram 的方案&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org7aff131&quot;&gt;其他参考方案&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org19ab5b2&quot;&gt;后记&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2291282&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org2291282&quot;&gt;背景&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org2291282&quot;&gt;
&lt;p&gt;
作为一个 RSS 重度用户，在&lt;a href=&quot;https://zhuanlan.zhihu.com/p/26638306&quot;&gt;微广场关闭&lt;/a&gt;前，我一直使用微广场来把自己想看的微信公众号、知乎专栏转成 RSS。在微广场关闭后，不仅是我，很多人也意识到了，类似的公开服务最终都可能走向同样的结局。在那之后，我就开始探索自己的方案，尝试不依赖第三方服务来把微信公众号转成 RSS。比较幸运的是，当时我已经接触到了 &lt;a href=&quot;https://github.com/huginn/huginn&quot;&gt;Huginn&lt;/a&gt;，&lt;a href=&quot;https://www.zmonster.me/2016/10/22/pkm-information-collection.html#orgheadline7&quot;&gt;使用它&lt;/a&gt;来获取一些学术论文资讯，而我加入的一个 Huginn 交流群里，早就有人在做相关的尝试了。基于交流群中朋友分享的方案，我也开始使用 Huginn 来为公众号输出 RSS，在这三年时间里，我前后使用过的方案有下面这些：
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;基于&lt;a href=&quot;https://weixin.sogou.com/&quot;&gt;搜狗微信搜索&lt;/a&gt;的方案&lt;/li&gt;
&lt;li&gt;基于即刻/快知和 &lt;a href=&quot;https://github.com/DIYgod/RSSHub/&quot;&gt;RSSHub&lt;/a&gt; 的方案&lt;/li&gt;
&lt;li&gt;基于 &lt;a href=&quot;https://github.com/blueset/ehForwarderBot&quot;&gt;EFB&lt;/a&gt; 和 Telegram 的方案&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
我将在后文中按顺序讲一下这三种方案。
&lt;/p&gt;

&lt;p&gt;
当然，除了这三种方案外，也有一些门槛相对低的方案，不想折腾的人可能会更感兴趣一些，所以我会在文末也介绍一下这些方法。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgadb6262&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgadb6262&quot;&gt;Huginn 简介&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgadb6262&quot;&gt;
&lt;p&gt;
由于几个方案主要都是使用 Huginn 来实现的，这里简单介绍一下 Huginn。
&lt;/p&gt;


&lt;div id=&quot;org9d9cdeb&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/huginn.png&quot; alt=&quot;huginn.png&quot; width=&quot;50%&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;a href=&quot;https://github.com/cantino/huginn&quot;&gt;Huginn&lt;/a&gt; 是一个 Ruby 编写的自动化工具，在理念上类似 IFTTT 和天国的 Yahoo! Pipes，即进行事件的监听然后根据预先设定的规则自动化地进行后续操作。
&lt;/p&gt;

&lt;p&gt;
Huginn 的 wiki 上列举了一些典型的使用场景，如:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Never Forget Your Umbrella Again: 下雨提醒&lt;/li&gt;
&lt;li&gt;Adding RSS Feeds to Any Site: 为任意网站生成 RSS 输出&lt;/li&gt;
&lt;li&gt;Follow stock prices: 监听股票价格&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
在 Huginn 中，主要有 event 和 agent 两个概念，agent 类似 IFTTT 里的 channel，event 则是 agent 的输出。在 Huginn 中可以将一个 agent 的输出作为另外一个 agent 的输入，由此产生复杂的自动化操作。
&lt;/p&gt;


&lt;div id=&quot;org4083c2d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/huginn_diagram.png&quot; alt=&quot;huginn_diagram.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
上图来自 &lt;a href=&quot;https://web.archive.org/web/20170315013204/http://www.jianshu.com/p/4a47e452abc9&quot;&gt;Huginn:烧录RSS的神器&lt;/a&gt; 一文，该文对 Huginn 的使用做了很详细的介绍。
&lt;/p&gt;

&lt;p&gt;
和 IFTTT 不同的是，Huginn 需要自己部署，很多细节需要自己定制，因此在使用门槛上会高很多。想尝试一下的话，可以参考&lt;a href=&quot;https://github.com/huginn/huginn#heroku&quot;&gt;文档&lt;/a&gt;一键免费部署 Huginn 到 PaaS 平台 &lt;a href=&quot;http://heroku.com/&quot;&gt;Heroku&lt;/a&gt; 上，轻度使用的话足够了。
&lt;/p&gt;

&lt;p&gt;
本文的目的并不是专门介绍 Huginn，如果读者想了解更多关于 Huginn 的内容，可以自行搜索、阅读文档和相关资料。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5dc36cf&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org5dc36cf&quot;&gt;基于搜狗微信搜索的方案&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org5dc36cf&quot;&gt;
&lt;p&gt;
&lt;a href=&quot;https://weixin.sogou.com/&quot;&gt;搜狗微信搜索&lt;/a&gt;是一个开放的网站，同时又能获取指定公众号的最新文章，所以就成了早期的公众号文章转 RSS 的重要工具。
&lt;/p&gt;

&lt;p&gt;
在搜狗微信搜索中，如果知道一个微信公众号的 ID，可以直接拼接出该公众号在搜狗微信搜索上的页面，以“经济学人”的公众号举例，其公众号 ID 是 &lt;i&gt;TheEconomistGroup&lt;/i&gt; ，那么其对应的搜狗微信搜索页面就是 &lt;a href=&quot;https://weixin.sogou.com/weixin?query=TheEconomistGroup&quot;&gt;https://weixin.sogou.com/weixin?query=TheEconomistGroup&lt;/a&gt; ，访问这个页面，可以看到如下内容：
&lt;/p&gt;


&lt;div id=&quot;org9d91280&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/sogou_wexin_search.png&quot; alt=&quot;sogou_wexin_search.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
从最下方的“最近文章”处就可以解析出该公众号最新文章的标题和链接，因此基于搜狗微信搜索的方案，通过下面几个步骤来得到公众号的 RSS 输出：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;解析公众号的搜狗微信搜索页面，获取最新文章的标题和链接&lt;/li&gt;
&lt;li&gt;访问文章的链接，解析出文章的全文&lt;/li&gt;
&lt;li&gt;输入包含文章标题、文章链接、文章内容的 RSS&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
看起来是比较简单的，然而这个方案在实际中却遇到了一个比较大的问题，那就是搜狗的反爬机制。大概是出于保护内容、流量的缘故，搜狗微信搜索虽然能够比较方便地访问到微信公众号文章，但我们通过它获得的文章链接，都不是文章的原始链接：2017 年的时候这个链接是一个有时效性的临时链接，这个链接在不到一天的时间内就会失效而不可访问，所以早期的方案都会在链接没有失效的时候先解析出全文，这样在 RSS 阅读器里直接就能阅读；而现在，这个链接是一个重定向链接，在重定向后才会得到一个临时的文章链接。
&lt;/p&gt;

&lt;p&gt;
我个人没有办法解决链接重定向的问题，所以认为这个方案现在已经无效了，如果有读者认为该问题可以被解决，那么可以参考 &lt;a href=&quot;https://web.archive.org/web/20170719092304/http://www.jianshu.com/p/22167468300f&quot;&gt;Huginn教程：微信公众号 转换成 RSS&lt;/a&gt; 一文去尝试一下。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3f4ef78&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3f4ef78&quot;&gt;(已失效)基于即刻/快知和 RSSHub 的方案&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3f4ef78&quot;&gt;
&lt;p&gt;
&lt;a href=&quot;https://baike.baidu.com/item/%25E5%258D%25B3%25E5%2588%25BB/18672117&quot;&gt;即刻&lt;/a&gt;上线机器人功能后，用户就可以自定义微信公众号机器人来抓取任意公众号并生成一个主题了，而即刻的每个主题，又是存在公开 WEB 链接的，所以就可以用 Huginn 解析一个即刻的公众号主题页面，来获取一个公众号的文章列表更新了。而后来 RSSHub 又能直接输出一个即刻主题的 RSS，所以这个流程又能进一步简化一下，省略掉解析即刻主题页面这一步，直接从 RSSHub 输出的 RSS 中，进一步解析出公众号文章的原始链接并抓取全文了。
&lt;/p&gt;

&lt;p&gt;
在即刻服务可用的时候，我就彻底抛弃了基于搜狗微信搜索的方案，因为基于即刻和 RSSHub 的方案一来可以获取文章的原始链接，二来在整体流程上比前者都更简单。
&lt;/p&gt;

&lt;p&gt;
可惜的是，即刻也因为某些暂不了解的原因而停止服务了，不过依赖第三方服务服务会有这个下场我也是有心理准备的，后来就有了第三个方案。
&lt;/p&gt;

&lt;p&gt;
在说第三个方案之前得说一下，现在有一个非常类似即刻的 APP 叫做&lt;a href=&quot;http://kzfeed.com/&quot;&gt;快知&lt;/a&gt;，可以充当这个方案里即刻的替代品，唯一的差别是没有办法获得文章的原始链接，所以在 Huginn 中就少了一个文章直链获取的 Agent，见下图对比：
&lt;/p&gt;


&lt;div id=&quot;org93e4c6d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/huginn_scenarios_comparison.png&quot; alt=&quot;huginn_scenarios_comparison.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
目前基于快知的这个方案是可用的，如果想使用这个方案，可以有两种办法：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
安装我的个人项目 &lt;a href=&quot;https://github.com/Linusp/zs/&quot;&gt;zs&lt;/a&gt; 然后执行下面的命令来生成一个 Huginn Scenario 文件，然后在 Huginn 中导入
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;zs-rss gen-scenario -t kz -n &amp;#26202;&amp;#28857;LatePost -i postlate --kz-topic-id k69QJvO82RKoA -o postlate.json
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
命令参数解释如下：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&quot;-t kz&quot; 表示生成一个基于快知的 Huginn Scenario&lt;/li&gt;
&lt;li&gt;&quot;-n 晚点LatePost&quot; 将这个 Scenario 命名为“晚点LatePost”，同时也设置了最后输出的 RSS 的标题&lt;/li&gt;
&lt;li&gt;&quot;-i postlate&quot; 指定这个公众号的微信 ID，会用在最终的 RSS URL 中，比如这里指定的是 postlate，假设 Huginn 服务的域名是 &lt;a href=&quot;https://myhuginn.com&quot;&gt;https://myhuginn.com&lt;/a&gt; 那么最终的 RSS URL 可能是 &lt;a href=&quot;https://myhuginn.com/users/1/web_requests/395/wx-postlate.xml&quot;&gt;https://myhuginn.com/users/1/web_requests/395/wx-postlate.xml&lt;/a&gt; —— 这里如果不在乎可维护性的话，不用公众号的微信 ID 也可以，给一个自己喜欢的英文 id 即可&lt;/li&gt;
&lt;li&gt;&quot;&amp;#x2013;kz-topic-id k69QJvO82RKoA&quot; 这里指定“晚点LatePost”这个公众号在快知中的主题 ID，可以通过快知搜索到公众号后，分享链接到浏览器获得，比如“晚点LatePost”在快知中对应的主题链接是 &lt;a href=&quot;https://kz.sync163.com/web/topic/k69QJvO82RKoA&quot;&gt;https://kz.sync163.com/web/topic/k69QJvO82RKoA&lt;/a&gt; ，那么主题 ID 就是尾部那串符号 &quot;k69QJvO82RKoA&quot;&lt;/li&gt;
&lt;li&gt;&quot;-o postlate.json&quot; 指定输出文件名，随意&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;直接下载我准备好的 Huginn Scenario 文件 &lt;a href=&quot;https://raw.githubusercontent.com/Linusp/zs/master/zs/rss/kz_scenario_template.json&quot;&gt;kz_scenario_template.json&lt;/a&gt; ，在 Huginn 中导入后再修改其中的设置&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
基于快知的方案目前可用，但我并不看好这个方案，按照经验，这种做信息抓取的服务，总是存在风险的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0ab99c4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org0ab99c4&quot;&gt;基于 EFB 和 Telegram 的方案&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org0ab99c4&quot;&gt;
&lt;p&gt;
由于我一直使用 Linux 系统，工作中需要使用微信进行沟通的时候非常不方便，后来了解到 &lt;a href=&quot;https://github.com/blueset/ehForwarderBot&quot;&gt;EFB&lt;/a&gt; 后就用它来把收到的微信消息转发到 Telegram，而 Telegram 是有 Linux 客户端的，这样我就能在 Linux 系统上查看微信消息了。
&lt;/p&gt;

&lt;p&gt;
EFB 本质上是在服务器上登录网页微信，然后监听网页微信上的消息来做转发，只要不去搞什么自动回复机器人之类的，那么在使用 EFB 的过程中，所有通过 EFB 收到的消息就是微信上好友、关注的公众号主动发过来的消息，通过 EFB 发送的消息也都是以个人身份发出去的，总之是一个正常用户的正常行为，并不会有封号之类的风险。我使用 EFB 已经有两年了，除了偶尔需要重新登录一下，并没有遇到什么大问题。
&lt;/p&gt;

&lt;p&gt;
使用 EFB 后可以在 Telegram 上收到我关注的公众号的更新消息，而 Telegram 的 API 丰富易用，完全可以写点代码把 Telegram 上收到的公众号文章更新收集起来再转成 RSS。于是在即刻停止服务后，我就开始摸索出了一套新的方案，大致流程是这样的：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;写一个脚本，利用 Telegram 的 API，定时获取更新的公众号文章，并保存下来&lt;/li&gt;
&lt;li&gt;在 Huginn 上新建一个 WebhookAgent，它会提供一个对应的 webhooks&lt;/li&gt;
&lt;li&gt;将保存下来的公众号文章发往到 WebhookAgent，然后通过后续的其他 Agent 进行全文解析和 RSS 输出&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
一个完整的 Scenario 是下面这个样子的：
&lt;/p&gt;


&lt;div id=&quot;orgd0e37ae&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/huginn_efb_scenario.png&quot; alt=&quot;huginn_efb_scenario.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这个方案的好处有：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;不依赖除 Telegram 外的任何第三方服务，因此也不用担心反爬、服务停止等各种问题&lt;/li&gt;
&lt;li&gt;能获得极低延时的 RSS 更新&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
不过相对的，这个方案的门槛也是最高的：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;需要自己部署 EFB 和 Huginn，其中 Huginn 虽然可以免费部署，但 EFB 却不行，所以至少需要一个 VPS&lt;/li&gt;
&lt;li&gt;需要熟悉 Telegram 的 API 并编写代码 —— 不过这块我已经做了，其他人有兴趣可以直接使用我的代码&lt;/li&gt;
&lt;li&gt;需要一个能登录网页微信的个人微信号，而 2017 年 9 月份之后注册的微信号已经无法登录网页微信&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
这个方案的总体过程是这样的：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;部署 EFB，可参考小众软件的文章：&lt;a href=&quot;https://www.appinn.com/efb-tutorial-with-docker/&quot;&gt;EFB 简明安装教程：用 Telegram 收发微信&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;在 Telegram 上新建一个频道，比如“微信.公众号”&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
与 EFB 机器人对话，将需要输出 RSS 的公众号链接到刚才建立的频道，如 &quot;/link 晚点LatePost&quot;，这样该公众号的消息就会被 EFB 发送到这个频道了
&lt;/p&gt;


&lt;div id=&quot;org85bc46f&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/telegram_linked_channel.png&quot; alt=&quot;telegram_linked_channel.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
创建一个包含 WebhookAgent 的 Huginn Scenario，同样有两种方法
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
第一种方法是安装我的项目 &lt;a href=&quot;https://github.com/Linusp/zs/&quot;&gt;zs&lt;/a&gt;，然后执行下面的命令来生成 Scenario 文件
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;zs-rss gen-scenario -n &amp;#26202;&amp;#28857;LatePost -i postlate -o postlate.json
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
参数含义同之前生成基于快知的 Scenario 时一样
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;也可以直接下载我项目中提供的 Huginn Scenario 文件 &lt;a href=&quot;https://raw.githubusercontent.com/Linusp/zs/master/zs/rss/efb_scenario_template.json&quot;&gt;efb_scenario_template.json&lt;/a&gt; 然后在 Huginn 中导入&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
创建好 Huginn Scenario 后，点击进入“微信公众号 Webhooks”这个 Agent，获取 webhooks 链接，比如：&lt;a href=&quot;https://myhuginn.com/users/1/web_requests/318/4SXo3X2T2X7HCDjv&quot;&gt;https://myhuginn.com/users/1/web_requests/318/4SXo3X2T2X7HCDjv&lt;/a&gt;
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;在 VPS 或某台能 24 小时开机的机器上上新建定时任务

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;首先安装前面反复提到的我的个人项目 zs&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
然后创建本地数据库，用来存储收集到的微信公众号文章更新
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;zs-rss create-db
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这条命令会在 $HOME/.zs/data 目录下新建一个数据文件 rss.db
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
在 $HOME/.zs/config 目录下新建配置文件 rss.json，写入刚才获得的 webhooks 链接，如
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-js&quot;&gt;{
    &lt;span style=&quot;color: #16a085;&quot;&gt;&quot;huginn_webhooks&quot;&lt;/span&gt;: {
        &lt;span style=&quot;color: #16a085;&quot;&gt;&quot;default&quot;&lt;/span&gt;: &lt;span style=&quot;color: #16a085;&quot;&gt;&quot;https://myhuginn.com/users/1/web_requests/372/d742b76e&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #16a085;&quot;&gt;&quot;&amp;#26202;&amp;#28857;LatePost&quot;&lt;/span&gt;: &lt;span style=&quot;color: #16a085;&quot;&gt;&quot;https://myhuginn.com/users/1/web_requests/372/4SXo3X2T2X7HCDjv&quot;&lt;/span&gt;
    }
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这个配置的意思是，公众号“晚点LatePost”的更新发送到一个 webhooks，其他的发送到另外的 webhooks。如果每个公众号都要输出一个 RSS，那么就需要为每个公众号都设置一个 webhooks 链接；如果有多个公众号想要合并输出一个 RSS，那么可以不设置 webhooks 而使用 default 对应的 webhooks。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
使用 &lt;a href=&quot;http://man7.org/linux/man-pages/man1/crontab.1.html&quot;&gt;crontab&lt;/a&gt; 新增两条定时任务
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;org8270be7&quot;&gt;
7,17,27,37,47,57 * * * * zs-rss fetch-wx-articles -n 微信.公众号 &amp;gt;&amp;gt; log.txt
*/10 * * * * zs-rss send-wx-articles &amp;gt;&amp;gt; log.txt
&lt;/pre&gt;

&lt;p&gt;
具体的时间频率可以自己调整。
&lt;/p&gt;

&lt;p&gt;
其中第一条定时任务需要 Telegram 的授权认证，具体来说是需要在 $HOME/.zs/config/telegram.json 中有如下内容
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-js&quot;&gt;{
    &lt;span style=&quot;color: #16a085;&quot;&gt;&quot;api_id&quot;&lt;/span&gt;: &lt;span style=&quot;color: #16a085;&quot;&gt;&quot;561071&quot;&lt;/span&gt;,
    &lt;span style=&quot;color: #16a085;&quot;&gt;&quot;api_hash&quot;&lt;/span&gt;: &lt;span style=&quot;color: #16a085;&quot;&gt;&quot;22691769c5decd501fd49d96ecff58e3&quot;&lt;/span&gt;,
    &lt;span style=&quot;color: #16a085;&quot;&gt;&quot;session&quot;&lt;/span&gt;: &lt;span style=&quot;color: #16a085;&quot;&gt;&quot;AUTHENTICATION SESSION CODE&quot;&lt;/span&gt;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
其中 &quot;api_id&quot; 和 &quot;api_hash&quot; 可以在 &lt;a href=&quot;https://my.telegram.org/&quot;&gt;https://my.telegram.org/&lt;/a&gt; 上获取，而 session 的值会在第一次运行时生成并自动写入到上面的配置文件里。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
目前 zs 这个项目仅考虑了我自己的需求，所以设计未必很合理，如果有开发能力的话可以参考我的代码自行更改、增加功能。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org7aff131&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org7aff131&quot;&gt;其他参考方案&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org7aff131&quot;&gt;
&lt;p&gt;
如果不想折腾，也有一定的经济来源，可以考虑一些付费服务，比如：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://www.jintiankansha.me/&quot;&gt;今天看啥&lt;/a&gt;：以前可以免费订阅若干个公众号的，现在必须付费了，价格见&lt;a href=&quot;http://www.jintiankansha.me/about/rss&quot;&gt;今天看啥-RSS订阅方法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://werss.app&quot;&gt;WeRss&lt;/a&gt;：免费试用三天，试用期间可订阅 8 个公众号，具体价格见&lt;a href=&quot;https://werss.app/price/&quot;&gt;WeRss 付费价格&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
另外，&lt;a href=&quot;http://kindle4rss.com/&quot;&gt;Kindle4rss&lt;/a&gt; 上面有不少热门的微信公众号全文 RSS，我大致数了下差不多有 100 个，如下图所示：
&lt;/p&gt;


&lt;div id=&quot;org330f787&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/kindle4rss_feeds.png&quot; alt=&quot;kindle4rss_feeds.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
Kindle4rss 的免费用户可以有 12 个订阅，付费价格也不贵，一年 36 人民币就可以订阅 300 个源，比前面两个便宜多了，而且这个服务存在很多年了，可以说一直很稳定，非常推荐。
&lt;/p&gt;

&lt;p&gt;
此外 RSSHub 也有微信公众号支持，见&lt;a href=&quot;https://docs.rsshub.app/new-media.html#wei-xin&quot;&gt;文档&lt;/a&gt;。在 RSSHub 里支持了六种方案，分别是：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;基于 &lt;a href=&quot;https://wemp.app/&quot;&gt;WeMP&lt;/a&gt; 的方案&lt;/li&gt;
&lt;li&gt;基于&lt;a href=&quot;https://chuansongme.com/&quot;&gt;传送门&lt;/a&gt;的方案&lt;/li&gt;
&lt;li&gt;基于北美生活引擎 &lt;a href=&quot;https://careerengine.us/about&quot;&gt;CareerEngine&lt;/a&gt; 的方案&lt;/li&gt;
&lt;li&gt;基于微信公众号数据分析平台&lt;a href=&quot;https://www.ershicimi.com/&quot;&gt;二十次幂&lt;/a&gt;的方案&lt;/li&gt;
&lt;li&gt;基于知识管理工具&lt;a href=&quot;https://uread.ai/&quot;&gt;优读&lt;/a&gt;的方案&lt;/li&gt;
&lt;li&gt;基于 EFB 和 Telegram 的方案&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
RSSHub 的前五个方案都是基于一些第三方信息抓取服务的，相对来说非常易用，但仍然存在第三方服务被关停的风险，最后那个方案和我的第三个方案类似，只不过把 Huginn 替换成了 RSSHub。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org19ab5b2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org19ab5b2&quot;&gt;后记&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org19ab5b2&quot;&gt;
&lt;p&gt;
也许有人会说微信就是个大毒瘤我就不看微信公众号，但确实有一些很好的作者只在微信公众号上写作，还有很多博客时代的知名写作者也迁移到了微信公众号上，原来的博客不再更新甚至不可访问了，加上微信生态的封闭，所以一个微信公众号文章的抓取和开放访问需求始终是存在的，也因此各种第三方抓取服务层出不穷。厌恶微信到完全不想碰微信产品包括微信公众号的人自然是有的，但既然大众的需求存在，我想也没什么好争辩的，每个人都有自己选择的自由。虽说如此，在看到一个好的公众号的时候，也不妨先去了解一下作者是否有同步更新的独立博客或知乎专栏，如果有的话还是更推荐去订阅其博客或知乎专栏等更开放的文章来源。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>我制作的微信公众号RSS(2)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2020/04/11/wx-article-rss-2.html"/>
    <category term="数字生活" scheme="http://www.zmonster.me/categories.html#数字生活"/>
    <id>http://www.zmonster.me/2020/04/11/wx-article-rss-2</id>
    <published>2020-04-11T00:00:00+00:00</published>
    <updated>2020-04-11T00:00:00+00:00</updated>
    <description>
    
      <p>花了点时间，又制作了一批微信公众号的全文 RSS。</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
和&lt;a href=&quot;https://www.zmonster.me/2020/03/10/wx-article-rss.html&quot;&gt;上一篇文章&lt;/a&gt;一样，都是全文 RSS，罗列如下：
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;公众号名称&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;RSS 链接&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;简介&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;晚点LatePost&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-postlate&quot;&gt;https://feedpress.me/wx-postlate&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;《财经》杂志与小晚团队推出的商业新闻媒体&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;深响&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-deep-echo&quot;&gt;https://feedpress.me/wx-deep-echo&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;看理想&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-ikanlixiang&quot;&gt;https://feedpress.me/wx-ikanlixiang&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;华山感染&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-hsinfect&quot;&gt;https://feedpress.me/wx-hsinfect&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;张文宏所在的华山医院感染科的公众号&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;民俗学论坛&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-folklore-forum&quot;&gt;https://feedpress.me/wx-folklore-forum&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;中国民俗学会的公益学术公众号&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;LCA&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-lca&quot;&gt;https://feedpress.me/wx-lca&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;“热爱生活 喜欢文化 关注艺术”&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;余晟以为&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-yurii-says&quot;&gt;https://feedpress.me/wx-yurii-says&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;老顾谈几何&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-conformalgeometry&quot;&gt;https://feedpress.me/wx-conformalgeometry&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;观人看世界&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-iwatch1024&quot;&gt;https://feedpress.me/wx-iwatch1024&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;“传递认知，让你看到我眼中的世界”&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;笔下求生&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-tmt-invest&quot;&gt;https://feedpress.me/wx-tmt-invest&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;“互联网分析师，CFA，在某创业公司扫地”&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;筹码&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-chouma2016&quot;&gt;https://feedpress.me/wx-chouma2016&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;“认知是唯一的筹码”&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;艾格吃饱了&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-aigechibaole&quot;&gt;https://feedpress.me/wx-aigechibaole&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;美食类公众号&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;碗丸食事&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-foodfile-111010&quot;&gt;https://feedpress.me/wx-foodfile-111010&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;美食类公众号&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
其中 LCA 是网友在上一篇博客的评论中推荐的。
&lt;/p&gt;

&lt;p&gt;
注：若公众号作者看到本文认为我制作的 RSS 侵犯了版权还请告知我，我会关闭全文输出。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>一次与公务员朋友的疫情讨论</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2020/04/04/a-discussion-about-sars-cov-2.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2020/04/04/a-discussion-about-sars-cov-2</id>
    <published>2020-04-04T00:00:00+00:00</published>
    <updated>2020-04-04T00:00:00+00:00</updated>
    <description>
    
      <p>周二的时候，一位高中同学调动到我所在的乡政府工作，到我家小坐，我们讨论了一下疫情。</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
H 和我是高一同学，人长得帅气、高大，我总觉得和周润发有几分神似。高一时的事情我已经不太有印象了，但高考后复读的那年，我和他在一个复读班里，他做班长，尽心尽力，也帮助过不少人，这些我仍然记得很清楚 —— 总体来说，他是一个很友善、乐于帮助他人的人。去年冬天他去北京出差，我请他吃了顿壹圣元，就着火锅，我给他讲互联网和 Aaron Swartz，他给我讲地方政府的经济困境。毕业多年，我们联系并不太多，但是如果碰在一起，仍是能自在地聊天。
&lt;/p&gt;

&lt;p&gt;
他前些年考了公务员，就在家里工作，疫情发生后，也投身到地方疫情防控的一线工作中，比我这种只会窝在家里对着四面墙壁发脾气的人是做了更多实事的。三月初的时候，他联系我，说之后会调动到我在的乡镇的政府部门工作，周二的时候似乎是安排妥当了，就跟我打了招呼，从乡政府开车十几分钟到了我家。由于今年情况特殊，我们并没有聊工作家庭这些平常会聊的事情，只聊了下疫情。
&lt;/p&gt;

&lt;p&gt;
方才也说了，H 是一个友善的人，所以我并不担心我们观点不一样而争吵，但他毕竟所处的环境不一样，思考模式肯定是会与我不一样的，这点我是有心理准备的，同时我也好奇在 H 是怎么看待这次灾难的。
&lt;/p&gt;

&lt;p&gt;
开始的时候，H 表达了这么一些看法：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;这次疫情是美国政府为了搞乱中国政府而制造的人祸，但因为大意而把自己也拖下水了&lt;/li&gt;
&lt;li&gt;这次疫情对中国来说是一个好机会，可以趁此机会获得更好的世界地位&lt;/li&gt;
&lt;li&gt;中国政府防控有力，在一个月内控制了国内疫情，是值得肯定的&lt;/li&gt;
&lt;li&gt;美国如果能狠下心来强力防控的话，疫情今年内结束是有可能的&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
H 认同中国政府的工作这点是很好理解的，他作为一个亲身参与到其中的人，对于其中细节的认识是远多于我的；此外湖北省外的其他省份的政府，不管是出于政绩也好还是出于安全也好，也确实做了迅速的反应，积极进行防控，这点从各个省份的确诊人数的变化是能看出来的，我认为是值得肯定的。
&lt;/p&gt;

&lt;p&gt;
至于病毒美国制造说，从外交部的几次发言以及中国政府对网络上的相关言论不加管控来看，中国政府是在有意地散播这种观点的，身为体制内的 H，受到这种信息的冲刷肯定远多于我。当然，我并不认同这一说法，但是有意思的是，我们双方在这个本应严肃的话题上，都拿不出什么有力的论据。
&lt;/p&gt;

&lt;p&gt;
H 提出了这些论据：第一，中国外交部赵立坚都暗示病毒来自美国，肯定是中央政府授意的，而中央政府一定是有足够证据才会这样做；第二，据某篇论文说，美国存在中国没有的一些病毒株，且比在我国发现的更原始。我呢，我其实也给不出什么很明确的反对证据，我认为病毒不一定源自美国的理由有这些：第一、我不相信中国外交部特别是赵立坚说的话；第二、我认为流行病学调查不是短期就能得出结论的，且我知道学术论文往往表述都比较谨慎，不会轻易给出特别明确的结论；第三、我在网上看过较多批驳美国源头说、病毒人造说的言论，并且相信。
&lt;/p&gt;

&lt;p&gt;
我和 H 在这个观点上，都是有一些先行的立场，然后看了一些网络上的言论并选择性地采信了，所以在这个事情上，我们有什么区别呢？我们所自以为的思考，又有多少是周围的环境强加给我们的呢？我想了一下，这段时间里，我们朋友、同事讨论这些事情时，其实有不少时候都是抛出一个报道、截图，然后共同批评、驳斥，鲜少去反思我们所看到的东西，也没几个人去深入了解相关的研究 —— 我们这些人的价值观是近似的，我们所讨论的观点大都是我们认可的观点，我们所相信的也大都是我们选择去相信的，所以我是不是也是在一个信息茧房里呢？
&lt;/p&gt;

&lt;p&gt;
之前有一次和朋友聊中医话题 —— 总体来说我们都对中医持负面态度 —— 稍微聊深一点，就有一个朋友觉得我在钻牛角尖而不想聊下去了，深入的讨论交流在价值观近似的人之间也很难进行下去，就别提观点冲突的人群之间了。万幸我跟 H 一来没有做很深入的讨论，二来我们都不是那种认为对方观点与自己不同就无话可说的人。
&lt;/p&gt;

&lt;p&gt;
在病毒来源这个事情上，我跟 H 勉强达成了几点共识：第一、从外交部观点推测病毒源自美国，是一种主观推测，不管你多相信中国政府，它也只是推测，而不是事实；第二、应当以科学研究为准，不能扭曲学术研究的结论，把相关性当作因果性，在学术界明确病毒来源并达成共识之前，我们都不应该对病毒来源这个问题轻易下结论。
&lt;/p&gt;

&lt;p&gt;
最后，作为一个政府工作人员，H 比较乐于相信一些宏大叙事和事件后面的积极意义，我觉得这无可厚非，但我不喜欢这种东西。我试图脱离他的语境，跟他讨论一线医护人员待遇、李文亮的调查结果、湖北人遭受歧视、失业影响等更小的问题。一方面，我希望他不要总将目光投向高处，而忽视了一个个真实存在的个体之间的差异和不同的境遇；另一方面，我想我也应当向他学习，多一些更宏观的视角和积极的心态，而不是一味沉溺在情绪里。
&lt;/p&gt;

&lt;p&gt;
我不是一个善于待客的人，H 在我家小坐了一会就忙着回去工作了。我觉得这次讨论，虽然没有让我获得更多、更深入的关于疫情的信息，但让我看到了自己思考模式和信息获取上的问题，还算是比较有收获吧，如果他也能从我这获得一些有价值的东西那就更好了。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>基于 Github Pages 的博客快速启用 HTTPS</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2020/03/27/enable-https.html"/>
    <category term="博客" scheme="http://www.zmonster.me/categories.html#博客"/>
    <id>http://www.zmonster.me/2020/03/27/enable-https</id>
    <published>2020-03-27T00:00:00+00:00</published>
    <updated>2020-03-27T00:00:00+00:00</updated>
    <description>
    
      <p>基于 Github Pages 的博客可以很简单地就启用 HTTPS 了。</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
我这个个人博客一直是基于 Github Pages 的，前几年&lt;a href=&quot;https://www.zmonster.me/2016/09/18/rename-blog.html&quot;&gt;启用了自定义域名&lt;/a&gt;，但一直都是 HTTP 访问的，鉴于越来越恶劣的网络环境，启用 HTTPS 这个事情就变得越来越重要了。不过我个人对于 WEB 方面的知识其实很薄弱，再加上懒，就一直没有去做这个事情，今天做完工作，想着处理一下这个问题，没想到简单一搜索就找到了简单的解决方案。
&lt;/p&gt;

&lt;p&gt;
我用 &quot;github pages https&quot; 搜索了一下，结果发现 Github Pages 服务已经有这个支持了。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/search-github-pages-https.png&quot; alt=&quot;search-github-pages-https.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
根据 Github 2018 年的&lt;a href=&quot;https://github.blog/2018-05-01-github-pages-custom-domains-https/&quot;&gt;这篇博客&lt;/a&gt;，只需要在对应项目的设置里勾选 &quot;Enable HTTPS&quot; 即可，如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/github-pages-https.png&quot; alt=&quot;github-pages-https.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这样设置后，我的博客也可以通过 HTTPS 来访问啦！如果有朋友的博客、网站也是基于 Github Pages 的，那么也推荐用这个方法来启用 HTTPS 哦。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>我制作的微信公众号RSS</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2020/03/10/wx-article-rss.html"/>
    <category term="数字生活" scheme="http://www.zmonster.me/categories.html#数字生活"/>
    <id>http://www.zmonster.me/2020/03/10/wx-article-rss</id>
    <published>2020-03-10T00:00:00+00:00</published>
    <updated>2020-03-10T00:00:00+00:00</updated>
    <description>
    
      <p>公布一下目前为止我制作好的微信公众号RSS</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
都是全文 RSS，罗列如下：
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;公众号名称&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;RSS 链接&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;AINLP&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-ainlp&quot;&gt;https://feedpress.me/wx-ainlp&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;CatCoder&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-catcoder&quot;&gt;https://feedpress.me/wx-catcoder&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;微广场作者的个人公众号&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;LateNews by 小晚&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-latenews&quot;&gt;https://feedpress.me/wx-latenews&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;L先生说&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-lxiaoshengmiao&quot;&gt;https://feedpress.me/wx-lxiaoshengmiao&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;ResysChina&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-resyschina&quot;&gt;https://feedpress.me/wx-resyschina&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;中文信息学报&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-jcip1986&quot;&gt;https://feedpress.me/wx-jcip1986&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;六神磊磊读金庸&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-dujinyong&quot;&gt;https://feedpress.me/wx-dujinyong&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;利维坦&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-liweitan&quot;&gt;https://feedpress.me/wx-liweitan&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;哈工大SCIR&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-hit-scir&quot;&gt;https://feedpress.me/wx-hit-scir&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;孟岩&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-dreamytalks&quot;&gt;https://feedpress.me/wx-dreamytalks&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;安静的书桌&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-quiet-desk&quot;&gt;https://feedpress.me/wx-quiet-desk&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;MorningRocks&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-morningrocks&quot;&gt;https://feedpress.me/wx-morningrocks&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;微软研究院AI头条&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-msrasia&quot;&gt;https://feedpress.me/wx-msrasia&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;程序媛的日常&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-girlswhocode&quot;&gt;https://feedpress.me/wx-girlswhocode&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;视觉求索&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-thevisionseeker&quot;&gt;https://feedpress.me/wx-thevisionseeker&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;语音杂谈&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-yyzt&quot;&gt;https://feedpress.me/wx-yyzt&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;长赢指数投资&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-chinaetfs&quot;&gt;https://feedpress.me/wx-chinaetfs&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;单读&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-dandureading&quot;&gt;https://feedpress.me/wx-dandureading&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;大象公会&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-idxgh2013&quot;&gt;https://feedpress.me/wx-idxgh2013&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;呦呦鹿鸣&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://feedpress.me/wx-youyouluming&quot;&gt;https://feedpress.me/wx-youyouluming&lt;/a&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
读者如果有好的公众号可以推荐给我，我感兴趣的话会去为其制作 RSS。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>数字独立与自由</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2020/03/07/digital-independence-and-freedoom.html"/>
    <category term="数字生活" scheme="http://www.zmonster.me/categories.html#数字生活"/>
    <id>http://www.zmonster.me/2020/03/07/digital-independence-and-freedoom</id>
    <published>2020-03-07T00:00:00+00:00</published>
    <updated>2020-03-07T00:00:00+00:00</updated>
    <description>
    
      <p>谈谈我对数字生活的一些想法</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
1996年 的时候，&lt;a href=&quot;https://www.eff.org&quot;&gt;电子前线基金会&lt;/a&gt;的创始人之一 John Perry Barlow 发表了《&lt;a href=&quot;https://www.eff.org/cyberspace-independence&quot;&gt;数字空间独立宣言&lt;/a&gt;》，在宣言中，他说道：
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
Governments of the Industrial World, you weary giants of flesh and steel, I come from Cyberspace, the new home of Mind. On behalf of the future, I ask you of the past to leave us alone. You are not welcome among us. You have no sovereignty where we gather。
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
在这份宣言中，John Perry Barlow 宣称数字空间是无国界的，是一个不在所有政府的疆界内的自由的空间，是一个人人可以表达自己的信仰和思想的新世界，并拒绝政府以解决现实世界问题的借口来侵犯这个空间。当时持这种态度的人不少，比如说 &lt;a href=&quot;https://en.wikipedia.org/wiki/RSS&quot;&gt;RSS&lt;/a&gt; 发明人、&lt;a href=&quot;https://en.wikipedia.org/wiki/Markdown&quot;&gt;Markdown&lt;/a&gt; 作者之一的 &lt;a href=&quot;https://en.wikipedia.org/wiki/Aaron_Swartz&quot;&gt;Aaron Swartz&lt;/a&gt;，但最终，他死于捍卫网络世界的自由，年仅 26 岁。
&lt;/p&gt;

&lt;p&gt;
从 Aaron Swartz 自杀到现在，我们已经可以清楚的知道，数字空间并非天堂，并没有真正地把人类的心灵都联结起来。跨国界的自由，似乎也没有真正地实现过，各个国家都建起了自己的围墙，并以反恐等各种名义监视着每个数字空间里的个体；与此同时，数字空间里的住民们，也在这种畸形的环境里，展现出了很多丑陋的姿态。
&lt;/p&gt;

&lt;p&gt;
深受以 Aaron Swartz 为代表的早期互联网先驱们影响的我们，该如何面对这样一个世界呢？作为一个技术人员，最好的形式，当然是利用自己的技术能力来让这个世界变得更好一些，然而这个世界的复杂性有很大一部分其实来自于人性的复杂，在行动的同时，我觉得，我们也应当进行更多的思考和讨论，本文就是我对相关问题的一些思考的记录。
&lt;/p&gt;

&lt;p&gt;
大体上，我仍然是抱持数字空间独立与自由理念的，但在当下的大环境里，谈论整个数字空间与现实世界的独立，似乎已经不太现实，我更想谈的是，个人在数字空间中，如何保持独立与自由。如果每个个体，都能对自身在数字空间中的权利与义务有足够的认识，我相信即使技术没有得到革新，这个世界也会有很大的改观。
&lt;/p&gt;

&lt;p&gt;
要谈独立与自由，那就得了解我们在数字空间中有哪些权利和义务。由于各国相关法律也并不统一，数字空间内所有人也并没有形成共识，下面的一些内容，仅仅是参考了一些相关资料后我个人的想法。
&lt;/p&gt;

&lt;p&gt;
首先，最基本的权利是互联网接入权。
&lt;/p&gt;

&lt;p&gt;
2009 年 10 月 14，芬兰交通运输部&lt;a href=&quot;https://www.loc.gov/law/foreign-news/article/finland-broadband-access-to-be-a-legal-right/?__cf_chl_jschl_tk__=4c1534f7c2a34217370c7a6b6afd8dd428df34eb-1583194810-0-ATNHPMHlsAFxsf08kJMOeC1tDQuq1zYhbTO5OtDFey1ngJKYZUx5gJPTMINPr4GSPXwDrS-EgGqBgH1RJ4A5H17xskES07FAzpcyWads3yQ9N38eh7KuvUs9Y3H7862si3TWeV9eaOQ4Kf9IsfS_LpISf6vyWMVFQKJEe7hAraVvtKgwEEh4fX2gbFYzE2IPXLaVcu0n7VLYiAl6Reow4vbELaDGB7yyCBgaIhgJnuYpwN9jreg3LF_340WHPsPAEm_upaL6dPE_5QOn78oponXBjT9WqurWIMoRATp68D-dKfl7NaXps9lymi6cmsjpxBy1Jg-hxlFX-UiRCWryMSnCz74AyV4qm6D1NVbOTL-p&quot;&gt;宣布&lt;/a&gt;互联网访问权成为法定权利，从 2010 年 7 月开始，芬兰公民将具有至少 1Mb/s 带宽的互联网访问权利，并计划在 2015 年将这个带宽下限提高到 100Mb/s，这应该是第一个将互联网接入权写入到法律里的案例。在这之后，很多国家以成文或不成文的形式承认这个权利。从现实世界来看，我们想要接入到互联网，似乎是轻而易举的事情，但是这个权利仍然面临如下威胁：贫穷导致一部分人无法支付宽带接入的费用、被滥用的监管导致每个人都可能被断网。一方面我们应当努力去促成合理、完善的法律法规的产生，另外一方面我们也应该在法律法规完善并且能被正确实施前，掌握足够的方法和工具来保障我们的权利。
&lt;/p&gt;

&lt;p&gt;
另外，并不是我们能上网，我们的互联网接入权就得到保障了。重点是，我们应当可以接入世界互联网，而不是一个受限的局域网络；再更进一步，接入网络后，我们还应当具有自由地访问网络上的内容的权利。而这些延伸的权利，同样也受到很多威胁，当我们访问的文章、网站显示 404、被屏蔽或者被删除时，我们应该要意识到，在那一瞬间，我们的权利被剥夺了。
&lt;/p&gt;

&lt;p&gt;
其次，我们应当享有在数字空间上的言论自由权利，可以在网络上自由地表达自己的观点，也可以自由地创作文字、音频、视频等各种形式的作品。这份权利受到的威胁，我想有不少人是深有体会的，比如说发表的言论其他人完全看不到、创作的文章不被允许发表或被删除，有些人甚至因为在网络上的言论而导致现实中的人身权利受到威胁。一个理想的数字空间，当然是大家都可以堂堂正正地发表自己的言论，互相碰撞并求同存异，但在现今这样恶劣的环境里，我们也得考虑通过一些方法和工具来保障我们的言论自由权利，比如说脱离对垄断平台（如微信）的依赖，或在恶劣环境中隐匿自己。
&lt;/p&gt;

&lt;p&gt;
第三，我们应当享有在数字空间中的隐私和安全权，个人身份信息、个人数据都应该被保护，在未经个人允许的前提下，任何其他个人、机构，都不应该访问、利用我们的个人身份信息和个人数据。对于这点，很高兴看到欧盟《&lt;a href=&quot;https://gdpr-info.eu&quot;&gt;一般数据保护条例&lt;/a&gt;》(General Data Protection Regulation, &lt;b&gt;GDPR&lt;/b&gt;)的通过和施行，但如果我们并非身处 GDPR 作用范围内的地区，那么，在现实世界的法律法规并未完善时，我们还是得时刻谨记自己享有这份权利的正当性，并在这些权利受到侵犯时奋力抗争。
&lt;/p&gt;

&lt;p&gt;
在个体角度上，我并不信任大部分的法律、平台，或者说，出于对上述数字权利的敏感，必须得带着怀疑的目光看待所有可能侵犯这些权利的个体或者机构。为了保障我们的数字权利，我认为我们必须提高自身的认知、实践总结相关的方法并利用好一切能利用的工具。
&lt;/p&gt;

&lt;p&gt;
所谓的提高认知，包括但不限于：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;理解互联网的构成和原理&lt;/li&gt;
&lt;li&gt;了解现实世界与数字权利相关的法律法规&lt;/li&gt;
&lt;li&gt;认识数字空间中信息传播规律、群体构成等社会规律&lt;/li&gt;
&lt;li&gt;建立数字空间中的权利意识和道德观念&lt;/li&gt;
&lt;li&gt;掌握基本的信息搜集和甄别能力&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
保障我们数字权利的方法和工具，则可能有下面这些：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;数据加密的方法和工具&lt;/li&gt;
&lt;li&gt;突破互联网封锁的方法和工具&lt;/li&gt;
&lt;li&gt;数据备份与恢复的方法和工具&lt;/li&gt;
&lt;li&gt;信息搜集和筛选的方法和工具&lt;/li&gt;
&lt;li&gt;……&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
我计划在未来的几年内，阅读更多相关的书籍和资料、积极思考，以此提高自己的认知水平，同时实践相关的方法和工具。除此以外，还准备为如 EFF、GNU 这样符合我个人价值观的机构或组织贡献一点个人的力量，比如更积极地参与开源项目、定期捐赠、传播相关理念等。也欢迎志同道合的朋友的交流和补充。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>2019 年盘点</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2020/01/04/annual-summary-of-2019.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2020/01/04/annual-summary-of-2019</id>
    <published>2020-01-04T00:00:00+00:00</published>
    <updated>2020-01-04T00:00:00+00:00</updated>
    <description>
    
      <p>2019 年有很多东西发生了变化，也有很多东西一如既往。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga484ec9&quot;&gt;各方面的记录&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org9fdfca7&quot;&gt;睡眠时间统计&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga7661de&quot;&gt;工作时间统计&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org54b31f2&quot;&gt;日常开销统计&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3882672&quot;&gt;投资收益&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org84168ce&quot;&gt;书影音和游戏&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgba4ab34&quot;&gt;其他&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga484ec9&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga484ec9&quot;&gt;各方面的记录&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga484ec9&quot;&gt;
&lt;p&gt;
做 &lt;a href=&quot;http://www.zmonster.me/2019/01/01/annual-summary-of-2018.html&quot;&gt;2019 年计划&lt;/a&gt;时候，我的一个目标是在 2019 年能多记录一些东西，总体来说我还是做到了，这里简单罗列一下。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org9fdfca7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org9fdfca7&quot;&gt;睡眠时间统计&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org9fdfca7&quot;&gt;
&lt;p&gt;
数据来自 LifeCycle 的记录。由于我的作息大致上是以周为单位变化的，所以统计的是一周每一天的平均值和中位数，如下图所示。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2019_sleep.png&quot; alt=&quot;2019_sleep.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
我的睡眠状况是比较糟糕的，这个统计基本反映了事实。九月和十月有一段时间我其实保持了比较好的睡眠时间，不过入冬后没能维持下去。而九月十月我是如何改善睡眠的呢？大概是做到了以下几点：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;给自己设闹钟，晚上到点就把手机放到桌子上，绝不带到床上，然后睡觉&lt;/li&gt;
&lt;li&gt;早上也定闹钟，但只是提醒自己到了起床的时间&lt;/li&gt;
&lt;li&gt;晚上定时煮粥啥的，早上到点后食物的味道会增强我起来的动力&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
当然，这些事情什么时候都能做，但那段时间执行得更好一些，原因可能在于那段时间北京天气比较舒服，精神状态也比较放松。
&lt;/p&gt;

&lt;p&gt;
今年我有看到好几篇关于睡眠的论文，这些论文提到，睡眠过程中大脑会进行自我修复，所以说如果长期睡眠不好是会导致各种认知上的问题的。这些论文如下所示：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Coupled electrophysiological, hemodynamic, and cerebrospinal fluid oscillations in human sleep&lt;/li&gt;
&lt;li&gt;Sleep increases chromosome dynamics to enable reduction of accumulating DNA damage in single neurons&lt;/li&gt;
&lt;li&gt;Zebrafish as an emerging model for studying complex brain disorders&lt;/li&gt;
&lt;li&gt;Characterization of Sleep in Zebrafish and Insomnia in Hypocretin Receptor Mutants&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
第一篇是 2019 年 11 月份发表的，相关的研究人员发现睡眠时血液会周期性的、大量地流出大脑，然后&lt;a href=&quot;https://zh.wikipedia.org/wiki/%E8%84%91%E8%84%8A%E6%B6%B2&quot;&gt;脑脊液&lt;/a&gt;会大量流入，而脑脊液会清除各种有害的代谢副产物，从而起到修复大脑的作用。
&lt;/p&gt;

&lt;p&gt;
第一篇论文是在宏观层面观察到了睡眠时大脑的运行机制，后面几篇论文则是在微观层面发现了睡眠的一些好处：在对斑马鱼进行实验后，发现睡眠时神经元的 DNA 损伤在减少。
&lt;/p&gt;

&lt;p&gt;
总之睡眠真的是蛮重要的，2020 年的话我希望能改善下自己的睡眠质量。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga7661de&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga7661de&quot;&gt;工作时间统计&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga7661de&quot;&gt;
&lt;p&gt;
数据同样来自 LifeCycle。需要说明的是，LifeCycle 在记录工作时间时，会把我午饭的时间排除在外，也就是说这个工作时间是我的实际工作时间，不是简单用下班时间减去上班时间得到的。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2019_work.png&quot; alt=&quot;2019_work.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
总的来说，我的每日工作时间约为 9 小时，按照劳动法规定我应该有加班工资的，不过我们是弹性工作制，大家都懂的。
&lt;/p&gt;

&lt;p&gt;
我上半年比较惨，一直在出差，驻场做一些没什么意义的事情；下半年相对好一些了，我的业务性工作也少了很多，主要在做一些基础工具和代码重构的事情，不过就那样吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org54b31f2&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org54b31f2&quot;&gt;日常开销统计&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org54b31f2&quot;&gt;
&lt;p&gt;
记账我用的 EasyCost，一个简单的记账 App，每笔都得自己记那种。虽然功能很简单，但我目前没复式记账这种复杂的需求，所以从 2016 年起一直都用的这个，2019 年的话结合且慢小账本进行预算控制，我觉得还 OK 吧。
&lt;/p&gt;

&lt;p&gt;
按月统计了下餐饮、家居和交通三大块的支出，如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2019_cost.png&quot; alt=&quot;2019_cost.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
上半年的数据有点奇怪，主要是因为在各种出差（前面有提到）。六月份搬家后不免要购置各种生活用具，导致这个月的数据比较高。在那之后也就是下半年，除了工作日的午餐外，我一直坚持自己做饭，所以每月的餐饮支出略有下降，不过降的幅度和我的直觉还是有点差异，大概是因为自己做饭省了钱后我会更放肆地去进行饭罪活动吧……
&lt;/p&gt;

&lt;p&gt;
总之呢，每月的日常开销要 2000+，房租目前是 4900，每月能领 1500 的公积金，所以一个月的固定开销大概是 5000~6000 左右……
&lt;/p&gt;

&lt;p&gt;
2019 年的时候，每月的日常开销我都是预算制的，也就是说每月发下工资后，给自己留一笔固定数额的钱，剩下的钱全都转走，放到货币基金和各种理财产品里。自我感觉这种形式还蛮好的，预算划出去后我就当这钱不是我的了，花完了的话就去喝西北风，没花完的话就当赚到累积到下一个月，这样换了一个角度去看这笔钱后感觉心态会好很多，支出也更容易控制。目前是每个月给自己 3000 预算，一般都用不完，2020 年的话会尝试降低这个预算，比如到 2500 这个样子。
&lt;/p&gt;

&lt;p&gt;
家居那个分类主要是一些家居用品的购置，交通的话主要是每月的通勤支出，这些就没太多好说的。
&lt;/p&gt;

&lt;p&gt;
除了日常开销外，我在进行预算制的支出还有游戏和网络服务，游戏给了自己一年 2000 的预算，网络服务是一年 3000，到年底的时候都差不多用完了。网络服务主要有这些：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;RSS 阅读器 &lt;a href=&quot;https://www.inoreader.com&quot;&gt;Inoreader&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;RSS 烧录工具 &lt;a href=&quot;https://feed.press/&quot;&gt;FeedPress&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;两个 &lt;a href=&quot;https://www.vultr.com/&quot;&gt;Vultr&lt;/a&gt; 的 VPS，分别部署了 &lt;a href=&quot;https://github.com/huginn/huginn&quot;&gt;Huginn&lt;/a&gt; 和 &lt;a href=&quot;https://github.com/blueset/ehForwarderBot&quot;&gt;EFB&lt;/a&gt;：前者用来给不输出 RSS 的网站制作 RSS，比如说微信公众号；后者用来将微信消息转发到 Telegram 上，这样我就能在电脑上回复微信消息了 —— 我是 Linux 用户，没有微信客户端呀。Vultr 有点贵，在想要不要换成别家的 VPS。&lt;/li&gt;
&lt;li&gt;若干其他 VPS&lt;/li&gt;
&lt;li&gt;某不能说的代理工具&lt;/li&gt;
&lt;li&gt;域名&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
目前这两个预算不变，进入 2020 后我已经重新分配了预算，可以开心地买买买啦，什么健身环啊、丝之歌啊，我全都要～
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3882672&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3882672&quot;&gt;投资收益&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org3882672&quot;&gt;
&lt;p&gt;
投资的话以前也有做，不过 2019 年的话，了解了更多东西，自己也做了一些尝试。目前的收益状况如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2019_investment.png&quot; alt=&quot;2019_investment.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
图上的“现金1”、“现金2”、“现金3” 其实就是流动资金，目前分别放到了三个地方（主要是货币基金），之所以这么做是因为货币基金每日提取额度只有一万，六月份换房子的时候就因为钱在一个货币基金里，提取额度不够交房租，最后跟同事借的钱……这之后就把钱分散到多个地方了。不过现在有些产品也在解决这个问题，做法就是在外部包装成一个产品，然后能让你配置多个不同的货币基金，比如腾讯理财通的“余额+”就是这样的。
&lt;/p&gt;

&lt;p&gt;
网格投资是下半年才开始做的，目前还不会自己挑选投资目标，主要是根据 &lt;a href=&quot;https://weibo.com/chinaetfs&quot;&gt;E 大&lt;/a&gt;的一些推荐买了一些，小额投入，尝试熟悉操作方法和相关知识。在掌握了更多知识后，计划 2020 年慎重地加大投入。
&lt;/p&gt;

&lt;p&gt;
基金定投和长赢计划的话，是我的长期投资计划，是会长期持有的，所以就算现在有 10 几个百分点的浮盈我也很淡定，不会想着赚了就赶紧退出，这种心态的变化，是我跟投长赢计划后最有价值的收获 —— 涨跌都舒服，踏踏实实的。
&lt;/p&gt;

&lt;p&gt;
另外，年初我自己鼓捣了个总额 1000 元的组合，瞎加了几个债券进去，没想到现在也有 10 几个百分点的收益，我在想 2020 年是不是也多买点债券呢？
&lt;/p&gt;

&lt;p&gt;
一年下来，对指数基金投资更有信心了，相信 2020 年我会在投资方面有更多的进步。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org84168ce&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org84168ce&quot;&gt;书影音和游戏&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org84168ce&quot;&gt;
&lt;p&gt;
主要是用豆瓣记录的，我挨个去把图片存下来，然后写了点代码把同一个分类下的图片拼接成一张大图，之后完善一下，期望是直接从自己的豆瓣主页上抓取。
&lt;/p&gt;

&lt;p&gt;
2019 年读了 11 本书，主要是以小说特别是科幻小说为主，如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2019_books.jpg&quot; alt=&quot;2019_books.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
小说里面最喜欢&lt;a href=&quot;https://book.douban.com/subject/33395237/&quot;&gt;《龙蛋》&lt;/a&gt;这一本，非常正能量的一本小说，故事的大致情节是：人类发现一颗中子星上的名为奇拉的生物后，这些生物逐步进化的故事，人类和奇拉互通有无，共建和谐宇宙！
&lt;/p&gt;

&lt;p&gt;
然后&lt;a href=&quot;https://book.douban.com/subject/27077129/&quot;&gt;《华氏451》&lt;/a&gt;和&lt;a href=&quot;https://book.douban.com/subject/30442837/&quot;&gt;《水刀子》&lt;/a&gt;也挺不错的。
&lt;/p&gt;

&lt;p&gt;
电影和剧的话看了这些：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2019_movies.jpg&quot; alt=&quot;2019_movies.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
《千与千寻》和《天气之子》虽然也是动画，不过是电影院看的，所以归到电影分类里去了。动漫的话看了这些：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2019_animes.jpg&quot; alt=&quot;2019_animes.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;a href=&quot;https://movie.douban.com/subject/27166039/&quot;&gt;《Rick and Morty》&lt;/a&gt;是期待了一年的动画，看了两集，剩下的还攒着没看，所以暂时不做什么评论。
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;https://movie.douban.com/subject/2085545/&quot;&gt;《电脑线圈》&lt;/a&gt;是比较老的一部动画了，不过意外的不错，里面涉及了 VR、AR、人工智能、意识等各种放现在也不过时的元素，而且程序员奶奶太厉害了，我也想老了还能写程序！
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;https://movie.douban.com/subject/30206430/&quot;&gt;《约定的梦幻岛》&lt;/a&gt;故事讲得太好了，各种转折、反转，看的过程中惊喜不断，看完后我还去追了漫画。不过这种叙事非常巧妙的故事，重复观看的乐趣会衰减很多。相比之下&lt;a href=&quot;https://movie.douban.com/subject/30174419/&quot;&gt;《冰海战记》&lt;/a&gt;就是一部非常耐看的动画了，是 2019 年我最喜欢的日本动画。
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;https://movie.douban.com/subject/27011763/&quot;&gt;《灵能百分百 第二季》&lt;/a&gt;和&lt;a href=&quot;https://movie.douban.com/subject/30458442/&quot;&gt;《动物狂想曲》&lt;/a&gt;我也很喜欢，由于后者是校园故事，所以我会喜欢前者多一些。
&lt;/p&gt;

&lt;p&gt;
剩下的&lt;a href=&quot;https://movie.douban.com/subject/30174410/&quot;&gt;《多罗罗》&lt;/a&gt;、&lt;a href=&quot;https://movie.douban.com/subject/30377498/&quot;&gt;《石纪元》&lt;/a&gt;、&lt;a href=&quot;https://movie.douban.com/subject/30483637/&quot;&gt;《小书痴的下克上》&lt;/a&gt;和&lt;a href=&quot;https://movie.douban.com/subject/33218388/&quot;&gt;《刀剑神域 爱丽丝篇》&lt;/a&gt;都是优秀但在我看来存在一些问题的动画。
&lt;/p&gt;

&lt;p&gt;
一年下来，能看的新番大概不到 10 部，不知道 2020 年会不会好点。
&lt;/p&gt;

&lt;p&gt;
玩过和在玩的游戏一共有 9 部，如下所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2019_games.jpg&quot; alt=&quot;2019_games.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
Hollow Knight 我吹过一次，就不再吹了，这回强势吹一波黑魂：地图设计实在是太厉害啦！第一次有这个感觉，是在不死镇打完第一个 BOSS 牛头恶魔后，找到回不死镇篝火点捷径的时候，之后在城外不死教区乘电梯回到传火祭祀场的时候也非常震惊。另外游戏剧情非常晦涩，所以也给人强烈地想要搞明白的冲动，我们戏称黑魂的叙事手法是“废墟考古式叙事”，玩家在游戏里就像考古学家一样，只能从游戏里各种物品、对话中得到各种故事的残片，需要自己进行大量的联想、推理才能得到相对完整的剧情，非常有意思。另外，玩多了后，发现 Hollow Knight 从黑魂里借鉴的元素太多了，难怪我都喜欢。
&lt;/p&gt;

&lt;p&gt;
GRIS 和 ORI 在音乐和画面上都当得上艺术品的称呼，不过相对来说，GRIS 有它想要表达的核心思想，而 ORI 的剧情过于简单，我就把它当作一个画面好看音乐好听的平台跳跃游戏，2020 年的续作我就不打算玩了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgba4ab34&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgba4ab34&quot;&gt;其他&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgba4ab34&quot;&gt;
&lt;p&gt;
这一年里，整个世界发生了很多变化，大部分都是不太好的；身边的小世界也发生了一些变化，难说好坏，毕竟具体到不同的人看法会不一样。总的来说，大部分人对将来社会的走向都持偏悲观的态度，我也不例外。但是除了表示悲观外，我其实还想知道：为什么会发生这些变化？这些变化是怎么发生的？我们能做什么？
&lt;/p&gt;

&lt;p&gt;
对于这些问题，我没有答案，一方面我知道我并没有提出正确的问题，另一方面其实也没有太多可以讨论的人。
&lt;/p&gt;

&lt;p&gt;
带着这些想不明白，八月底去青岛散了散心，倒是想明白了一些事情。一来确认自己是个不适合旅行的人，无论去哪估计只要有个安静人少的角落就行了，什么美食、景点一概没太多兴趣 —— 可能也是因为独自一人的缘故吧，但如果不是一个人的话就压根没法想事情了；再就是在散心的时候想明白了关于“人生意义”的一些小问题，对于将来自己要做什么事情更清楚了一点，对于什么事情是自己想要的或不想要的、在乎的或不在乎的也更明白了。
&lt;/p&gt;

&lt;p&gt;
我很难描述我在青岛时“想明白”的具体是什么，但它给我带来的心态变化是很明显的。下半年我的精神状态一直很平稳，完全没有出现过往年时常会出现的空虚感、无意义感；对于工作、家庭上的一些问题，我的承受能力也更好了一些，因之而来的情绪变化也更加平缓了；此外，我开始强烈地意识到，哪怕是一个很强的团体，想要做成一些事情也是很难的，所以指望靠着其他人的帮助来达到自己的目标，不如多想想自己能做点什么。
&lt;/p&gt;

&lt;p&gt;
从这个“想明白”出发，我找到了一些自己想做的事情，有些在计划表上，有些已经在进行（包括但不限于个人项目、写作），希望 2020 年会有一些成果出来。
&lt;/p&gt;

&lt;p&gt;
外界不需要谁来拯救，能够拯救的唯有还肯接纳外界的自己。新的一年，我想更好地认识、接纳自己，践行自己的想法。
&lt;/p&gt;

&lt;p&gt;
祝所有阅读此文的朋友 2020 年快乐。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>更新了“关于”页面</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2019/12/08/update-about-page.html"/>
    <category term="博客" scheme="http://www.zmonster.me/categories.html#博客"/>
    <id>http://www.zmonster.me/2019/12/08/update-about-page</id>
    <published>2019-12-08T00:00:00+00:00</published>
    <updated>2019-12-08T00:00:00+00:00</updated>
    <description>
    
      <p>
更新了下关于页面，见 http://www.zmonster.me/about.html


</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
更新了下关于页面，见 &lt;a href=&quot;http://www.zmonster.me/about.html&quot;&gt;http://www.zmonster.me/about.html&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
关于页面改过多次，后来不知道写什么好就空着了。主要是，不太清楚该怎么介绍自己会比较合适，说太具体自己嫌烦，想抽象一点但发现给自己贴标签也挺困难的，而且觉得人都是复杂的，不太喜欢贴标签 —— 比如说，我虽然是十年的 Emacs 用户，但我也会用 Vim，非要写上的话 Vim 用户看到就跑了怎么办？
&lt;/p&gt;

&lt;p&gt;
今天简单写了写，以后觉得对自己认识更清楚了，或许会改一改。
&lt;/p&gt;

&lt;p&gt;
其实我尝试过写微信公众号，但是现在已经近于废弃了。我并不想说什么微信公众号封闭之类的话，只是单纯觉得这个博客才是我自己的小天地。在这里，我也不用操心谁关注了我谁没关注我，安静地写点到东西，偶尔就一些话题和网友聊一聊，感觉挺好。
&lt;/p&gt;

&lt;p&gt;
博客从开始写到现在已经 6 年多了，有一些早年间认识的网友，我们通过博客还在网络上保持着联系，说不定加个微信聊两句就会变成联系人列表里再也不会戳开的图标了。所以说我还是喜欢博客、论坛这种靠内容激发出来的交流，IM 上的碎片化消息，让我比较有心理负担。
&lt;/p&gt;

&lt;p&gt;
除了关于页面，其实我是有一系列改进博客体验的想法的，希望能让更多优秀的网友留下来，不过一直没空搞就是了，这就 12 月了，那就明年搞吧，哈哈哈！
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>论文笔记：Few-Shot Learning</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2019/12/08/few-shot-learning.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2019/12/08/few-shot-learning</id>
    <published>2019-12-08T00:00:00+00:00</published>
    <updated>2019-12-08T00:00:00+00:00</updated>
    <description>
    
      <p>阅读了几篇 Few-Shot Learning 方面的经典论文，索性写一起吧。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org3463b2d&quot;&gt;相关概念&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga70db8a&quot;&gt;相关数据集&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf91ad47&quot;&gt;论文笔记&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgbdbb1f1&quot;&gt;一、Matching Networks for One Shot Learning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgcbbd056&quot;&gt;二、Prototypical Networks for Few-shot Learning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2b6dfa5&quot;&gt;三、Learning to Compare: Relation Network for Few-Shot Learning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5691410&quot;&gt;四、Induction Networks for Few-Shot Text Classification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4eb7d97&quot;&gt;五、A Closer Look at Few-Shot Classification&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org51d7fa9&quot;&gt;总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3463b2d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3463b2d&quot;&gt;相关概念&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3463b2d&quot;&gt;
&lt;p&gt;
Few-Shot Learning 泛指从少量标注数据中学习的方法和场景，理想情况下，一个能进行 Few-Shot Learning 的模型，也能快速地应用到新领域上。Few-Shot Learning 是一种思想，并不指代某个具体的算法、模型，所以也并没有一个通用的、万能的模型，能仅仅使用少量的数据，就把一切的机器学习问题都解决掉，讨论 Few-Shot Learning 时，一般会聚焦到某些特定的问题上，比如 Few-Shot Learning 思想应用到分类问题上时就称之为 Few-Shot Classification。
&lt;/p&gt;

&lt;p&gt;
本文涉及的论文都是 Few-Shot Classification 相关的。
&lt;/p&gt;

&lt;p&gt;
在 Few-Shot Classification 里，问题是这样的：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;已有一定量的标注数据，数据中包含较多个类别，但每个类别的数据量不多，将这个数据称之为 train set&lt;/li&gt;
&lt;li&gt;用 train set 通过某种方法得到一个模型 \(M\)&lt;/li&gt;
&lt;li&gt;给定一个新的标注数据，有 \(N\) 个类，每类中有 \(k\) 个样本，称之为 support set，注意 support set 中的类别和 train set 的不存在交叉&lt;/li&gt;
&lt;li&gt;要求借助 support set 但不修改模型 M 的参数，使之在给定一个新的输入时，能将其识别为 \(N\) 个类中的一个&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
上述问题称之为 \(N\)-way \(k\)-shot 问题，\(k\) 一般较小（10 以下）。特别的，当 \(k=1\) 时称之为 one-shot，当 \(k=0\) 时称之为 zero-shot。
&lt;/p&gt;

&lt;p&gt;
本文涉及的论文，都是在相同的框架下来解决这个问题的，具体来说，模型 \(M\) 具有两大块能力
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;将一个类别的数据表示为一个向量，作为这个类的 representation&lt;/li&gt;
&lt;li&gt;将一个输入和一个类的 representation 进行比较，判断两者的匹配程度&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
第 1 点的存在，让其产生的模型能处理任意新的类别，不管你给什么样的 support set，它总能产生 \(N\) 个向量表示这 \(N\) 个类别。
&lt;/p&gt;

&lt;p&gt;
最简单的办法是用 train set 进行表示学习，然后对给定的 suppor set，将每个类中的 k 个样本的向量加和或平均作为类的 representation，待预测的数据也编码成向量和，和这些类的 representation 计算相似或距离就好了。之后可以看到本文中涉及的论文，其方法就是这个简单想法的扩充和改进。
&lt;/p&gt;

&lt;p&gt;
为了尽量和实际使用时接近，Few-Shot Classification 在训练时引入一个叫做 episode 的概念，每个 episode 包含从 train set 中采样出来的一部分数据，以及用这部分数据进行训练的过程：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;首先从 train set 的类别集合中随机选取 \(N\) 个类别&lt;/li&gt;
&lt;li&gt;然后，对每个类别，从 train set 中采样 \(k\) 个样本，这 \(N\times k\) 个样本，同样称之为 support set，用来模拟实际的 support set&lt;/li&gt;
&lt;li&gt;然后，对每个类别，在上一步采样后剩余的样本里，采样 \(N_{q}\) 个样本，这 \(N\times N_{q}\) 个样本，称之为 query set，用来模拟实际使用时的待预测输入&lt;/li&gt;
&lt;li&gt;模型 \(M\) 作用于 support set 上，得到 \(N\) 个向量 \(C = \{c_{1}, c_{2}, \ldots, c_{N}\}\)&lt;/li&gt;
&lt;li&gt;模型 \(M\) 作用于 query set 上，得到每个样本的向量，并和 \(c_{i}\) 计算距离，选择距离最小的作为预测类别&lt;/li&gt;
&lt;li&gt;根据 query set 上样本的预测结果与期望结果，得到损失，然后使用优化算法去调整模型 \(M\)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
模型测试时通常会在一个和 train set 类别不交叉的标注数据集上进行，称这个数据集为 test set。测试过程同样以 episode 为基础，一般是采样若干个 episode 计算 query set 的预测精度，然后地多个 episode 的结果平均作为整体结果。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga70db8a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga70db8a&quot;&gt;相关数据集&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga70db8a&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
&lt;a href=&quot;https://github.com/brendenlake/omniglot&quot;&gt;Omniglot&lt;/a&gt;: 一个手写字符数据集，包含 50 个类共 1623 个样本
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191208_15571575791863screenshot.png&quot; alt=&quot;20191208_15571575791863screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;miniImageNet: &lt;a href=&quot;http://www.image-net.org/about-overview&quot;&gt;ImageNet&lt;/a&gt; 数据集的子集，包含 100 个类，每类 6 个样本，共 600 个样本&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
&lt;a href=&quot;http://www.vision.caltech.edu/visipedia/CUB-200-2011.html&quot;&gt;CUB-200-2011&lt;/a&gt;: 一个图像分类数据集，包含 200 个不同的鸟类共 11788 个样本
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191208_16011575792067screenshot.png&quot; alt=&quot;20191208_16011575792067screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href=&quot;http://www.cs.jhu.edu/~mdredze/datasets/sentiment/&quot;&gt;Amazon Review Sentiment Classification&lt;/a&gt;: 按产品类型组织的亚马逊评论数据集&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf91ad47&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf91ad47&quot;&gt;论文笔记&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf91ad47&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgbdbb1f1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgbdbb1f1&quot;&gt;一、Matching Networks for One Shot Learning&lt;sup&gt;&lt;a id=&quot;fnr.1&quot; class=&quot;footref&quot; href=&quot;#fn.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgbdbb1f1&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orga274f8e&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;orga274f8e&quot;&gt;观点&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-orga274f8e&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
数据增强和正则化技术能减轻数据很少时的过拟合状况，但是不能算是解决了它。
&lt;/p&gt;

&lt;p&gt;
所谓的 Few-Shot Learning 也不能算解决啊，也没有什么方法敢说是解决了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
非参数化模型（如最近邻方法）能直接用已有的数据作为先验来对新的数据进行分类，也能快速地适应新的类别，这种优点值得借鉴
&lt;/p&gt;

&lt;p&gt;
考虑分类这个问题，非参数化模型的问题在于它需要将先验数据存储下来进行比对，当数据量很大时会有效率问题；另外就是现有的一些非参数化模型，往往只能使用一些通用的度量方法，往往会有泛化性问题。Few-Shot Learning 某种程度上来说确实算是借鉴了非参数化模型的思路，用 support set 作为先验知识，然后在度量计算上使用可训练的模块。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;论文作者认为，如果实际处理的数据和训练用数据的分布相差较大时，论文中提出的模型可能会没啥效果&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org510b96d&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org510b96d&quot;&gt;模型和方法&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org510b96d&quot;&gt;
&lt;p&gt;
模型的大致结构是这样的
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/screenshot_20191103_22171572790637.png&quot; alt=&quot;screenshot_20191103_22171572790637.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
Given Support Set \(S={(x_{i}, y_{i})}_{i=1}^{k}\) ——由于本文讨论的 One-shot 的，所以 support 里的每个样本的类别也就是 \(y_{i}\) 都是不同的。
&lt;/p&gt;

&lt;p&gt;
任给 \(\hat{x}\)，将它预测为 \(y_{i}\) 的概率为 \(P(y_{i}|\hat{x}, S)\)，最大概率的预测也就是 \(\mathop{\arg\max}\limits_{y}P(y|\hat{x}, S)\)
&lt;/p&gt;

&lt;p&gt;
Few-Shot Learning 要学习的，就是这个 \(P\)。
&lt;/p&gt;

&lt;p&gt;
如果用一个向量来表示预测输出的话（这也是通常做法），用 one hot  向量来表示每一个 \(y_{i}\) 的话，那么模型就可以写成
&lt;/p&gt;

&lt;p&gt;
\[\hat{y} = \sum_{i=1}^{k}a(\hat{x}, x_{i})y_{i}\qquad (x_{i}, y_{i})\in S\]
&lt;/p&gt;

&lt;p&gt;
这里的 \(a\) 可以是一个 attention 模块，其定义为
&lt;/p&gt;

&lt;p&gt;
\[a(\hat{x}, x_{i})=\frac{e^{c(f(\hat{x}), g(x_{i}))}}{\sum_{j=1}^{k}e^{c(f(\hat{x}), g(x_{j}))}}\]
&lt;/p&gt;

&lt;p&gt;
其中 \(f\) 和 \(g\) 都是一个 embedding 函数，在不同的任务上会不一样，比如在 NLP 任务上可以是一个 word embedding，在图像任务上则可以是一个 CNN 网络层；匹配函数 \(c(\cdot, \cdot)\) 则用来计算两个 embedding 的相关度，它可以是任意一个距离度量方法或相似度量方法，也可以是一个神经网络模块。
&lt;/p&gt;

&lt;p&gt;
在模型上，这篇论文针对 embedding 函数 \(f\) 和 \(g\) 做了一些特殊设计，文中称为 Full Context Embedding，简称 &lt;b&gt;FCE&lt;/b&gt; ；而匹配函数 \(c(\cdot, \cdot)\) 则统一使用 cosine 方法。下面则来看看这个 Full Context Embedding。
&lt;/p&gt;

&lt;p&gt;
所谓 &lt;b&gt;Context&lt;/b&gt; 指的是 support set \(S\)；进一步的，所谓的 Full Context Embedding，意思就是说，在计算 embedding 的时候，也要用到 \(S\)，而不是简单将数据输入到一个网络模块中然后得到一个表示向量。这个思想和观点，怎么说呢，熟悉 attention 机制的话应该不会觉得陌生。
&lt;/p&gt;

&lt;p&gt;
\(f\) 的 FCE 版本定义如下：
&lt;/p&gt;

&lt;p&gt;
\[f(\hat{x}, S) = attLSTM(f^{\prime}(\hat{x}), g(S), K)\]
&lt;/p&gt;

&lt;p&gt;
其中 \(f^{\prime}\) 是一个单纯的编码器，可以是任意一种合适的神经网络，其输入只有 \(\hat{x}\)，\(g(S)\) 是所有 \(g(x_{i})\) 的简化表示。\(K\) 表示处理步骤数 —— 打个比方，就是hi把 \(f^{\prime}(\hat{x})\) 重复 \(K\) 次作为 LSTM 的 \(K\) 个 timestep 的输入，然后用这 \(K\) 个 timestep 的 hidden state 输出和 \(g(S)\) 做 attention 计算，具体来说，在第 \(k\) 步，有：
&lt;/p&gt;

&lt;p&gt;
\[\hat{h_{k}},c_{k} = LSTM(f^{\prime}(\hat{x}), [h_{k-1},r_{k-1}], c_{k-1})\]
&lt;/p&gt;

&lt;p&gt;
\[h_{k}=\hat{h_{k}} + f^{\prime}(\hat{x})\]
&lt;/p&gt;

&lt;p&gt;
\[r_{k-1}=\sum_{i=1}^{|S|}a(h_{k-1}, g(x_{i}))g(x_{i})\]
&lt;/p&gt;

&lt;p&gt;
\[a(h_{k-1}, g(x_{i}))=softmax(h_{k-1}^{T}g(x_{i}))\]
&lt;/p&gt;

&lt;p&gt;
注意：上面的 \(k\) 与 support set 的大小 \(k\) 无关，仅仅是一个符号表示上的巧合。
&lt;/p&gt;

&lt;p&gt;
除了对 \(f\) 做改进外，\(g\) 也有 FCE 版本，如下所示：
&lt;/p&gt;

&lt;p&gt;
\[g(x_{i}) = \overrightarrow{h}_{i} + \overleftarrow{h}_{i} + g^{\prime}(x_{i})\]
&lt;/p&gt;

&lt;p&gt;
\[\overrightarrow{h}_{i}, \overrightarrow{c}_{i} = LSTM(g^{\prime}(x_{i}), \overrightarrow{h}_{i-1}, \overrightarrow{c}_{i-1})\]
&lt;/p&gt;

&lt;p&gt;
\[\overleftarrow{h}_{i}, \overleftarrow{c}_{i} = LSTM(g^{\prime}(x_{i}), \overleftarrow{h}_{i+1}, \overleftarrow{c}_{i+1})\]
&lt;/p&gt;

&lt;p&gt;
其中 \(g^{\prime}\) 和 \(f^{\prime}\) 类似，剩下的部分也很好理解，相当于把 \(g^{\prime}(x_{0})\ldots g^{\prime}(x_{k})\) 当作序列作为一个 BiLSTM 的输入了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4ef1171&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org4ef1171&quot;&gt;实验和结论&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org4ef1171&quot;&gt;
&lt;p&gt;
使用了 Omniglot 数据集、ImageNet 数据集和 Penn Treebank 三个数据集分别去和其他模型做对比实验，大致上，在三个数据集上，都是先划分出类别完全不交叉的训练集和测试集然后进行训练和测试，对测试的细节没有说清楚，我所谓的没说清楚包括：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;前面的模型部分都是以 one-shot 为背景来说的，但实验中却有 5-shot 的情况，模型在 5-shot 的时候是怎样的？直接将每个类别的 embedding 平均？&lt;/li&gt;
&lt;li&gt;Few-Shot Learning 的测试有别于普通的分类问题，一般来说是多次采样出 support set 和 query set 进行测试，然后对多次采样结果进行平均，那么，采样多少次，是否覆盖了测试集中的大部分数据？&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
在 Omniglot 数据集上实验时，对比用的模型有：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;PIXELS: 直接用图像的像素值做匹配&lt;/li&gt;
&lt;li&gt;BASELINE CLASSIFIER: 先在训练集上做训练，由于普通的分类器并不能识别测试集中未见过的类别，所以训练完后测试时，用模型最后一层的输出作为图像的特征向量，然后去进行匹配&lt;/li&gt;
&lt;li&gt;MANN: 一篇关于 Meta Learning 论文中&lt;sup&gt;&lt;a id=&quot;fnr.2&quot; class=&quot;footref&quot; href=&quot;#fn.2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;提出的模型&lt;/li&gt;
&lt;li&gt;CONVOLUTIONAL SIAMESE NET&lt;sup&gt;&lt;a id=&quot;fnr.3&quot; class=&quot;footref&quot; href=&quot;#fn.3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;MATCHING NETS: 这篇论文提出的模型&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
下面是在 Omniglot 数据集上的对比结果：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/screenshot_20191118_22501574088651.png&quot; alt=&quot;screenshot_20191118_22501574088651.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
我的疑惑：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;BASELINE CLASSIFIER 的第三个模式用的 Matching Fn 是 Softmax，是什么意思？ softmax 函数不是用来做匹配或者相似计算的呀？&lt;/li&gt;
&lt;li&gt;MATCHING NETS 的 embedding 部分具体用的什么结构，单层 CNN、多层 CNN 或者别的什么？&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
其中第三列的 Fine Tune 如果为 Y 则说明在测试时，会在测试集的 support set 上进行微调，然后再在 query set 上预测，下同。
&lt;/p&gt;

&lt;p&gt;
由于 Omniglot 数据集比较简单，所以这里的 MATCHING NETS 没有使用 FCE。
&lt;/p&gt;

&lt;p&gt;
在 ImageNet 上做实验时，由于 ImageNet 太大，不方便实验，所以实际上作者是从 ImageNet 中按每类 600 个样本采样了 100 个类得到了 60000 个样本组成的更小的数据集，作者称之为 miniImageNet。其中 80 个类用来做训练，剩下 20 个类用来做测试。
&lt;/p&gt;

&lt;p&gt;
下面是在 miniImageNet 上的对比结果：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/screenshot_20191118_22521574088764.png&quot; alt=&quot;screenshot_20191118_22521574088764.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
我的疑惑：为什么这里就不用 MANN、CONVOLUTIONAL SIAMESE NETS 两个模型来对比了，是不是因为这两个模型的效果都比 MATCHING NETS 好，被打脸了？
&lt;/p&gt;

&lt;p&gt;
除了在 miniImageNet 上做实验外，作者也尝试在完整的 ImageNet 上做实验，但做了一些特殊的设置
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;从 ImageNet 中随机去除了 118 个类别作为训练集，称之为 randImageNet，测试时在那 118 个类别的数据上进行&lt;/li&gt;
&lt;li&gt;从 ImageNet 中去除狗狗相关的所有类别共 118 个，用剩下的作为训练集，称之为 dogsImageNet，测试时在 118 个狗狗类别的数据上进行&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
对比的模型除了 PIXELS，还有就是两个 INCEPTION 的分类器
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;INCEPTION CLASSIFIER: 在去除 118 个类别后的数据上训练，然后同 BASELINE CLASSIFIER 一样，在测试时只用模型来输出图像的向量表示，得到向量表示后用进行匹配&lt;/li&gt;
&lt;li&gt;INCEPTION ORACLE: 用完整的 ImageNet 进行训练，测试时同 INCEPTION CLASSIFIER&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
同时，由于从头训练会比较慢，所以 MATCHING NETS 直接使用训练好的 INCEPTION CLASSIFIER 来计算图像特征，在这个基础上再去训练 MATCHING NETS。
&lt;/p&gt;

&lt;p&gt;
结果如下：
&lt;/p&gt;

&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/screenshot_20191118_23541574092492.png&quot; alt=&quot;screenshot_20191118_23541574092492.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
注：表中的 \(\neq L_{rand}\) 和 \(\neq L_{dogs}\)表示训练集，，\(L_{rand}\) 和 \(L_{dogs}\) 表示测试集。
&lt;/p&gt;

&lt;p&gt;
从表中可以看到，MATCHING NETS 在 dogsImageNet 上表现是比较差的，对此作者的猜测是训练时只去除狗狗的类别，对数据的分布产生了较大的影响，导致训练集上的数据分布和测试集上的数据分布差异很大，从而表现出了较差的结果。说白了，领域迁移性、泛化性差呗……
&lt;/p&gt;

&lt;p&gt;
最后用 Penn Treebank 做了一个类似语言模型的实验，大致是这样的：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;给定 support set，里面有 5 条句子，每个句子都被挖了一个空，并给出了这个空要填的词是什么&lt;/li&gt;
&lt;li&gt;给定一个被挖掉一个词的句子，预测要填入的词，是 support set 中哪个被挖掉的词&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
如下所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/screenshot_20191119_00051574093146.png&quot; alt=&quot;screenshot_20191119_00051574093146.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
有点像语言模型，有点像阅读理解，但又都不是，奇奇怪怪的。
&lt;/p&gt;

&lt;p&gt;
和 LSTM 语言模型做的对比：LSTM 语言模型能达到 72.8% 的效果；本文的模型，在 one-shot 的时候效果为 32.4%，2-shot 的时候是 36.1%，3-shot 的时候是 38.2% —— 就比瞎猜的 20% 高一点点吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6e86f60&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org6e86f60&quot;&gt;个人总结&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org6e86f60&quot;&gt;
&lt;p&gt;
首先，放到现在来讲，这个 MATCHING NETS 的结构在 NLP 领域是很常见的，就是一个常规的匹配模型啊，不同之处在于使用 FCE 的时候它会用整个 support set 去做 attention，但这也不是什么新奇的东西。当然了这篇论文是 2016 年的，那个时候无论是 attention 机制还是我刚说的匹配模型，可能都还是挺创新的吧。
&lt;/p&gt;

&lt;p&gt;
然后就是论文在一些细节上有没说清楚的，这个我已经在前面用「我的疑惑」这样的字眼指出来了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgcbbd056&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgcbbd056&quot;&gt;二、Prototypical Networks for Few-shot Learning&lt;sup&gt;&lt;a id=&quot;fnr.4&quot; class=&quot;footref&quot; href=&quot;#fn.4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgcbbd056&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org4d528e8&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org4d528e8&quot;&gt;观点&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org4d528e8&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
虽然 Few-Shot Classification 很难，但人类具备很强的这种能力，甚至在某类事物只见过一次后就能在之后非常精准地辨认出来
&lt;/p&gt;

&lt;p&gt;
嗯，这些论文都这么说，但也没见有引用哪怕一篇认知科学方面的论文来说明这点 —— 成年人见过一次新事物就能辨认出来我是相信的，但婴儿从出生后到什么阶段才具备这种能力呢？我对这个还是比较好奇的，总之对这种抛出一个看起来大家都认可的但没什么实质内容的观点感到无趣。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Vinyals 提出的 Matching Networks 可以视作一个在 embedding 空间中的加权最近邻分类器
&lt;/p&gt;

&lt;p&gt;
FCE 是 Matching Networks 里比较精髓的一个设计，虽然整个模型要说是一个最近邻分类器也没错，但这么说未免有点简化过头，而且当前这篇论文提出的 Prototypical Networks，也可以说是一个 embedding 空间中的加权最近邻分类器啊……没有营养的话……
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Vinyals 提出的 episode 的概念让训练结果更加可信、更具有泛化性了
&lt;/p&gt;

&lt;p&gt;
我不知道在 Vinyals 提出基于 episode 的训练流程之前，做 Few-Shot Learning 的学者们都是怎么做的，但毫无疑问的是这套流程已经在之后成为了一个标准了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
在 Prototypical Networks 中，距离度量的选择至关重要，实验表明选择欧式距离比余弦距离好得多
&lt;/p&gt;

&lt;p&gt;
后面有一堆推论，不是很能看懂。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org286ba6e&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org286ba6e&quot;&gt;模型和方法&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org286ba6e&quot;&gt;
&lt;p&gt;
一个假设: 每个类别都能在空间中对应到一个类比为「原型」的点上，该类的其他数据的表示以这个点为中心分布。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191125_22491574693389screenshot.png&quot; alt=&quot;20191125_22491574693389screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
如上图所示，模型要做的事情是将 support set 中的数据映射到一个 embedding 空间中，然后对同类数据的 embedding 平均作为原型的 embedding；同时在预测的时候将输入数据也映射到这个 embedding 空间中，计算与各个原型的距离后，选择距离最小的类别作为预测结果。也就是说，这个模型的重点是：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;训练一个 encoder&lt;/li&gt;
&lt;li&gt;选择合适的距离度量方法&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
下面是模型的具体说明。
&lt;/p&gt;

&lt;p&gt;
给定一个 support set \(S=\{(x_{1}, y_{1}),\ldots, (x_{N},y_{N})\}\)，其中 \(x_{i} \in \mathbb{R}^{D}\) 是一个 \(D\) 维的向量，而 \(y_{i}\in \{1,\ldots, K\}\) 表示 \(K\) 个类别中的一个。特别的，\(S\) 中所有第 \(k\) 类组成的子集记为 \(S_{k}\)。
&lt;/p&gt;

&lt;p&gt;
然后，第 \(k\) 个类别的原型，就可以表示为：
&lt;/p&gt;

&lt;p&gt;
\[c_{k} = \frac{1}{|S_{k}|}\sum\limits_{(x_{i},y_{i})\in S_{k}}f_{\phi}(x_{i})\]
&lt;/p&gt;

&lt;p&gt;
其中 \(f_{\phi}: \mathbb{R}^{D}\rightarrow \mathbb{R}^{M}\) 就是要学习的 encoder。
&lt;/p&gt;

&lt;p&gt;
预测的时候，选定一个距离函数 \(d: \mathbb{R}^{M}\times\mathbb{R}^{M} \rightarrow \left[0,+\infty\right)\)，然后对给定的输入 \(x\) 按如下方式进行预测：
&lt;/p&gt;

&lt;p&gt;
\[p_{\phi}(y=k|x)= \frac{exp(-d(f_{\phi}(x), c_{k}))}{\sum_{k^{\prime}}(-d(f_{\phi}(x), c_{k^{\prime}}))}\]
&lt;/p&gt;

&lt;p&gt;
对应的，训练的目标就是最小化损失函数 \(J(\phi) = -\mathop{log}p_{\phi}(y=k|x)\)。
&lt;/p&gt;

&lt;p&gt;
下面是训练过程的伪代码描述：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191126_21421574775748screenshot.png&quot; alt=&quot;20191126_21421574775748screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org92f862e&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org92f862e&quot;&gt;实验和结论&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org92f862e&quot;&gt;
&lt;p&gt;
注：这篇论文还做了一部分 Zero-Shot Learning 的实验，这个和 Few-Shot Learning 的细节还是有一点区别，我这篇文章专注于 Few-Shot Learning，所以 zero-shot learning 部分的内容暂且忽略，有需要的可以自行阅读论文。
&lt;/p&gt;

&lt;p&gt;
在 Omniglot、miniImageNet 两个数据集上进行了 Few-Shot Learning 的实验。
&lt;/p&gt;

&lt;p&gt;
在 Omniglot 数据集上做实验时，对模型做如下设置：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;使用一个四层的 CNN 作为 \(f_{\phi}\)&lt;/li&gt;
&lt;li&gt;每层由 64 个 3x3 的卷积核组成，并使用 Batch Normalization，激活函数用 ReLU，最后来一个 2x2 的 max-pooling&lt;/li&gt;
&lt;li&gt;使用 Adam 优化算法&lt;/li&gt;
&lt;li&gt;学习率初始化为 \(10^{-3}\)，每 2000 个 episodes 裁剪一半&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
实验结果如下表所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191126_22041574777087screenshot.png&quot; alt=&quot;20191126_22041574777087screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这个实验没有和其他模型做对比 —— 可能是各个算法在这个数据集上的效果都能比较轻松地达到 90% 多吧。
&lt;/p&gt;

&lt;p&gt;
作者从这个实验得到这么两个结论：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;训练和测试时 support set 中的类别数比测试时的多，会带来更好的效果，这个从上面的表可以很清晰的看出来：1-shot 时 60-way 的效果好于 20-way 好于 5-way，5-shot 时也是同样的。&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
训练和测试时每类中样本的数量一样会比较好 —— 这我倒看不出来，不知道是不是我理解的不对，原文是这样的
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
We found that it is advantageous to match the training-shot with the test-shot.
&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
在 miniImageNet 数据集上做实验时，因为要和 Matching Networks 做对比，所以采用了同样的数据集划分方式。模型设置仍然和前一个实验一样使用四层 CNN。
&lt;/p&gt;

&lt;p&gt;
实验结果如下：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191126_22171574777857screenshot.png&quot; alt=&quot;20191126_22171574777857screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
作者从实验中得到的结论是：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;使用欧式距离比余弦距离要好，这个结论不光是对 Prototypical Networks 而言，甚至在 Matching Networks 上也成立；&lt;/li&gt;
&lt;li&gt;进行 N-way k-shot 训练时，N 的值越大，总体上看来模型效果会越好，可能是因为训练时类别数多会导致模型能更好地学习到不同类别之间的细微差别，从而提高了泛化性&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgbb97d3e&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;orgbb97d3e&quot;&gt;个人总结&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-orgbb97d3e&quot;&gt;
&lt;p&gt;
作者在论文中不厌其烦地说自己的方法是 simple method，我觉得确实如此，其模型结构一目了然，非常直白。作者在文中有说到这么一句话：
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
We hypothesize this is because all of the required non-linearity can be learned within the embedding function.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
也就是说，为什么简单的方法也会有效，很大的成分还是因为模型学到了一个很好的表示。那么，如果将 encoder 的部分替换成一个表示学习能力更强的模块，是不是就能做到更好的效果？我觉得是的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2b6dfa5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2b6dfa5&quot;&gt;三、Learning to Compare: Relation Network for Few-Shot Learning&lt;sup&gt;&lt;a id=&quot;fnr.5&quot; class=&quot;footref&quot; href=&quot;#fn.5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2b6dfa5&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org5944bd3&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org5944bd3&quot;&gt;观点&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org5944bd3&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;之前的一些工作将工作重心放在学习一个好的数据表示上，然后使用一个已有的度量方法来进行分类，如果距离度量（或相似度量）也通过训练得到，可以得到泛化性更好的模型&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
一些 meta learning 的方法在用于 Few-Shot Learning 问题时，都需要在新的数据上进行 fine tuning 才能得到较好效果，而本文提出的模型可以无需更新模型参数就能用于新类别数据的预测
&lt;/p&gt;

&lt;p&gt;
这个观点可以分几方面来看
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;我这个模型哪怕不 fine tuning 也能表现不错&lt;/li&gt;
&lt;li&gt;提到的那几个 meta learning 的模型不 fine tuning 效果就不行&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
对于第一点，看后面的实验结论即可，不过第二点在这篇论文中就看不到什么有力的证据了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
与本文工作最接近的是 Prototypical Networks 和 siamese networks
&lt;/p&gt;

&lt;p&gt;
其实我觉得和 Matching Networks 也很像啦。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1a6ec84&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org1a6ec84&quot;&gt;模型和方法&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org1a6ec84&quot;&gt;
&lt;p&gt;
Relation Network(RN) 模型由 embedding 模块 \(f_{\varphi}\) 和 relation 模块 \(g_{\phi}\) 组成，如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191127_22311574865070screenshot_20191101_11331572579231.png&quot; alt=&quot;20191127_22311574865070screenshot_20191101_11331572579231.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
对比一下这张图和 Matching Networks 的结构图，实在是太像了。
&lt;/p&gt;

&lt;p&gt;
具体来说
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;embedding 模块使用 4 层 CNN，每层 64 个 3x3 的卷积核，使用 Batch Normalization，激活函数用 ReLU —— 基本上和 Matching Networks、Prototypical Networks 是一样的，不过稍有区别，就是这里的 embedding 模块的后两层 CNN 没有加 max pooling，这个是为了适配 relation 模块做的修改&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
relation 模块用来将 support sample 和 query sample 的 feature map 融合起来并计算匹配分数
&lt;/p&gt;

&lt;p&gt;
因此首先有一个拼接函数 \(C(\cdot, \cdot)\)，这个函数将两个 feature map 在 depth 通道上拼接起来。
&lt;/p&gt;

&lt;p&gt;
拼接起来后再通过一个 \(g(\phi)\) 进行融合并计算分数。
&lt;/p&gt;

&lt;p&gt;
对一个 N-way 1-shot 的任务，在给一个 query sample \(x_{j}\) 的时候，会得到 N 个分数：
&lt;/p&gt;

&lt;p&gt;
\[r_{i,j} = g_{\phi}(C(f_{\varphi}(x_{i}), f_{\varphi}(x_{j})))\qquad i=1,2,\ldots, N\]
&lt;/p&gt;

&lt;p&gt;
如果是 N-way K-shot 任务且 \(k &gt; 1\)，则把 support set 中同一类的 embedding 简单加起来再输入到 relation 模块中 —— 这里我有一个疑问，同一类的多个样本的 embedding 加起来后不平均一下吗？
&lt;/p&gt;

&lt;p&gt;
此处的 \(g_{\phi}\) 是两层 CNN 再加上两层全连接层。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
模型的总体结构如下图所示：
&lt;/p&gt;

&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191127_22521574866354screenshot.png&quot; alt=&quot;20191127_22521574866354screenshot.png&quot; width=&quot;300px&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
训练时使用 MSE 作为 loss。
&lt;/p&gt;

&lt;p&gt;
完了，模型上可以说也是比较简单直白的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org54f0004&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org54f0004&quot;&gt;实验和结论&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org54f0004&quot;&gt;
&lt;p&gt;
和前两篇论文一样在 Omniglot 和 miniImageNet 两个数据集上做的实验。
&lt;/p&gt;

&lt;p&gt;
统一的训练设置
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;使用 Adam 优化算法&lt;/li&gt;
&lt;li&gt;初始学习率置为 0.001&lt;/li&gt;
&lt;li&gt;每 10 万个 episodes 后对学习率进行裁剪&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
在 Omniglot 数据集上实验时，有如下额外设置：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;训练时的数据采样设置
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;5-way 1-shot 时，query set 中每个类别有 19 张图片&lt;/li&gt;
&lt;li&gt;5-way 5-shot 时，query set 中每个类别有 15 张图片&lt;/li&gt;
&lt;li&gt;20-way 1-shot 时，query set 中每个类别有 10 张图片&lt;/li&gt;
&lt;li&gt;20-way 5-shot 时，query set 中每个类别有 5 张图片&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;测试时，从 test set 中采样了 1000 个 episodes，将这 1000 个 episodes 的测试结果平均作为整体测试结果&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
实验结果如下：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191128_22571574953069screenshot.png&quot; alt=&quot;20191128_22571574953069screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在 miniImageNet 数据集上实验时，有如下额外设置：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;训练时的数据采样设置

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;5-way 1-shot 时，query set 中每个类别有 15 张图片&lt;/li&gt;
&lt;li&gt;5-way 5-shot 时，query set 中每个类别有 10 张图片&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;测试时，对 600 个 episodes 的结果平均作为整体结果&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
实验结果如下：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191128_23021574953320screenshot.png&quot; alt=&quot;20191128_23021574953320screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
此外还有 zero shot learning 的实验，略。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org781a272&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org781a272&quot;&gt;个人总结&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org781a272&quot;&gt;
&lt;p&gt;
从结果上来看，Relation Networks 的效果并没有显著好于 Matching Networks 和 Prototypical Networks，在 miniImageNet 上的 5-way 5-shot 设置时甚至还比 Prototypical Networks 差一些。不过我觉得这个思路是没有问题的。
&lt;/p&gt;

&lt;p&gt;
以及，可以看到各个方法都能轻松在 Omniglot 数据集上达到 99% 的准确率，所以这个数据集其实已经没有什么参考意义了……倒是各个模型在 miniImageNet 上都还有很大的提升空间。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5691410&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5691410&quot;&gt;四、Induction Networks for Few-Shot Text Classification&lt;sup&gt;&lt;a id=&quot;fnr.6&quot; class=&quot;footref&quot; href=&quot;#fn.6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5691410&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgfe2f4c7&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;orgfe2f4c7&quot;&gt;观点&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-orgfe2f4c7&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
之前的一些工作在计算一个类别的 representation 的时候，只是简单的将这个类的 support sample 的 representation 加起来或平均一下，这样做可能会丢失一些重要的信息
&lt;/p&gt;

&lt;p&gt;
不对哦，Matching Networks 那里用的 FCE 已经是很接近 attention 的思路了，可不是将 support sample 的 representation 简单加起来或平均的。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
一个 Few-Shot Classification 的任务，如果有足够多的类别供训练，那么过拟合的风险会比较低。
&lt;/p&gt;

&lt;p&gt;
文中说这个的时候举了一个例子：假设一个数据集中有 159 个训练用类别，按 5-way 的设置来训练的话，也就是从 159 个类里选 5 个类用于训练，这样可以有 794747031 种不同的子任务。
&lt;/p&gt;

&lt;p&gt;
我在想啊，这个想法能不能借鉴到普通的匹配任务上。在如检索式问答一类的匹配任务上，通常是做二分类，也就是选两个样本，判断他们是否属于同一类。而当 \(N &gt; 3\) 且 \(k&gt;2\) 的时候，组合数 \(C^k_{N}\) 总是比 \(C^{2}_{N}\) 大，所以如果借鉴 Few-Shot Learning 里的 episode 的思想的话，就能得到更多的训练机会；其次，原来在匹配的时候，对于负样本之间（可能属于不同的问题簇）是不做区分的，区分一下的话感觉也会有好处。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc8bc487&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;orgc8bc487&quot;&gt;模型和方法&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-orgc8bc487&quot;&gt;

&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191207_16081575706118screenshot.png&quot; alt=&quot;20191207_16081575706118screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
上图是一个 3-way 2-shot 的模型结构示例图。
&lt;/p&gt;

&lt;p&gt;
模型由 Encoder 模块、Induction 模块和 Relation 模块组成。
Encoder 模块是双向 LSTM，加上 self attention —— 给定输入文本 \(x=\left(w_{1}, w_{2}, \ldots, w_{T}\right)\)，最终得到一个向量 \[e = \sum_{t=1}^{T}a_{t}\cdot h_{t}\]
&lt;/p&gt;

&lt;p&gt;
其中 \(h_{t}\) 是一个 biLSTM 的 hidden state：
&lt;/p&gt;

&lt;p&gt;
\[\overrightarrow{h_{t}} = \overrightarrow{LSTM}(w_{t}, h_{t-1})\]
&lt;/p&gt;

&lt;p&gt;
\[\overleftarrow{h_{t}} = \overleftarrow{LSTM}(w_{t}, h_{t+1})\]
&lt;/p&gt;

&lt;p&gt;
\[h_{t} = concatenate(\overrightarrow{h_{t}}, \overleftarrow{h_{t}})\]
&lt;/p&gt;

&lt;p&gt;
而 \(a_{t}\) 是 attention 权重，所有 \(a_{t}\) 组成的向量 \(a\) 是这样计算出来的：
&lt;/p&gt;

&lt;p&gt;
\[a = softmax(W_{a2} tanh(W_{a1} H))\]
&lt;/p&gt;

&lt;p&gt;
其中 \(W_{a1} \in R^{d_{a}\times 2u}\)，\(W_{a2}\in R^{d_{a}}\)，\(H = \left[h_{1} \ldots h_{T}\right]\) 表示由所有 \(h_{t}\) 组成的矩阵， \(2u\) 是 \(h_{t}\) 的向量长度，\(d_{a}\) 是超参数。
&lt;/p&gt;

&lt;p&gt;
Induction 模块要做的是将 \(C\times K\) 个 support sample 的向量表示 \(e\) 转换成 \(C\) 个类的向量表示 —— 之前的一些工作在这里大都是通过将一个类中的 support sample 的向量表示平均或相加得到。这篇论文创新的地方是，在 Induction 模块这里，用了胶囊网络里的动态路由机制&lt;sup&gt;&lt;a id=&quot;fnr.7&quot; class=&quot;footref&quot; href=&quot;#fn.7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;。
&lt;/p&gt;

&lt;p&gt;
胶囊网络我不是太懂，暂时也没太多兴趣和精力去看 Hinton 那篇论文。论文中列出了 Induction 模块的计算过程，还是比较清楚的，如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191208_16101575792611screenshot.png&quot; alt=&quot;20191208_16101575792611screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;p&gt;
可以理解为在计算类的向量表示的时候，对这个类中的 support sample 做了加权，然后不同的 support sample 的权重是靠这个动态路由机制来计算的，其中所需的一些参数（如 \(W_{s}\) 和 \(b_{s}\)）也是在训练中得到的。
&lt;/p&gt;

&lt;p&gt;
最后的 Relation 模块，用来比对 query sample 也就是待预测的样本和每个类的向量表示 \(c_{i}\)，以判断这个 query sample 应该被分到哪个类上。
&lt;/p&gt;

&lt;p&gt;
Relation 模块首先用一个张量网络&lt;sup&gt;&lt;a id=&quot;fnr.8&quot; class=&quot;footref&quot; href=&quot;#fn.8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;来建模两个向量（也就是 query sample 的向量和类向量 \(c_{i}\)）的关系，然后再经过一个全连接层输出匹配分数：
&lt;/p&gt;

&lt;p&gt;
\[v(c_{i}, e^{q}) = f(c_{i}^{T}M^{\left[1:h\right]}e^{q})\]
&lt;/p&gt;

&lt;p&gt;
\[r_{iq} = sigmoid(W_{r}v(c_{i}, e^{q}) + b_{r})\]
&lt;/p&gt;

&lt;p&gt;
训练时的目标函数则为：
&lt;/p&gt;

&lt;p&gt;
\[L(S, Q) = \sum\limits_{i=1}^{C}\sum\limits_{q=1}^{n}(r_{iq} - \mathbf{1}(y_{q} == i))^{2}\]
&lt;/p&gt;

&lt;p&gt;
训练时候使用的优化算法是 Adagrad&lt;sup&gt;&lt;a id=&quot;fnr.9&quot; class=&quot;footref&quot; href=&quot;#fn.9&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org9fa60c5&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org9fa60c5&quot;&gt;实验和结论&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org9fa60c5&quot;&gt;
&lt;p&gt;
在两个数据集上做了实验，一个是 Amazon Review Sentiment Classification 数据集（简称为 ARSC 数据集），另外一个是阿里巴巴整理出来的 Open Domain Intent Classification for Dialog System 数据集（简称为 ODIC 数据集）。
&lt;/p&gt;

&lt;p&gt;
两个实验都和这些模型进行对比：Matching Networks, Prototypical Networks, Relation Networks, Graph Network&lt;sup&gt;&lt;a id=&quot;fnr.10&quot; class=&quot;footref&quot; href=&quot;#fn.10&quot;&gt;10&lt;/a&gt;&lt;/sup&gt;, SNAIL&lt;sup&gt;&lt;a id=&quot;fnr.11&quot; class=&quot;footref&quot; href=&quot;#fn.11&quot;&gt;11&lt;/a&gt;&lt;/sup&gt;, ROUBUSTTC-FSL&lt;sup&gt;&lt;a id=&quot;fnr.12&quot; class=&quot;footref&quot; href=&quot;#fn.12&quot;&gt;12&lt;/a&gt;&lt;/sup&gt;。
&lt;/p&gt;

&lt;p&gt;
ARSC 数据集是在不同的电商产品类型上的评论数据，每个数据会被标记为正向、负向和不确定三个类别，总共有 23 个产品类型，所以加起来有 69 个类别。在该数据上实验时，设置如下：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;将四个产品的 12 个类别作为 test set，剩下产品的 57 个类别作为 train set&lt;/li&gt;
&lt;li&gt;使用 300 维的 Glove embedding&lt;/li&gt;
&lt;li&gt;LSTM 的 hidden state size 设置为 128&lt;/li&gt;
&lt;li&gt;计算 self attention 时的超参 \(d_{a}\) 设置为 64&lt;/li&gt;
&lt;li&gt;训练时 support set 为 2-way 5-shot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
实验结果如下：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191207_20121575720750screenshot.png&quot; alt=&quot;20191207_20121575720750screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
ODIC 数据集有 216 个类别，将其中 159 个类别共 195775 个样本作为 train set，剩下 57 个类别共 2279 个样本作为 test set。在该数据集上实验时，设置如下：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;使用 300 维的中文 word embedding&lt;/li&gt;
&lt;li&gt;LSTM 的 hidden state size 和 self attention 的超参同 ARSC 数据集&lt;/li&gt;
&lt;li&gt;分别进行了 5-way 5-shot、5-way 10-shot、10-way 5-shot 和 10-way 10-shot 四种实验&lt;/li&gt;
&lt;li&gt;测试时，在 test set 上采样 600 个 episode 进行测试，然后将平均测试结果作为整体结果&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
在 ODIC 数据集上的实验结果如下所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191207_20121575720767screenshot.png&quot; alt=&quot;20191207_20121575720767screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;p&gt;
除了两个对比实验外，论文还做了一些模型的分析。
&lt;/p&gt;

&lt;p&gt;
第一个分析是尝试将 Induction Networks 中的部分模块替换为更简单的模块，看模型的最终效果变化，来衡量这个模块是否有效。结果如下：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191207_20131575720787screenshot.png&quot; alt=&quot;20191207_20131575720787screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
上图中前三行是 Induction Networks 自己的结果，后面三行就是替换其中部分模块或的结果，其中：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;第四行表示将 Relation 模块替换为简单的余弦相似方法&lt;/li&gt;
&lt;li&gt;第五行表示将 Induction 模块替换为将类中向量加和作为 \(c_{i}\) 的方法&lt;/li&gt;
&lt;li&gt;最后一行表示用 Attention 替代 Induction 模块 —— 文中说是 self attention，应该是指在计算一个类内 support sample 的权重时，对该类内所有的 support sample 进行 attention 计算来得到权重&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
可以看到，直接使用 Attention 替代 Induction 模块，比 Induction 模块不做迭代要好一点点，但三步迭代后本文模型还是会好一些。
&lt;/p&gt;

&lt;p&gt;
然后还有一些可视化的分析，都是在论证 Induction Networks 比其他模型要好，这里不一一列举了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgcc84e8a&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;orgcc84e8a&quot;&gt;个人总结&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-orgcc84e8a&quot;&gt;
&lt;p&gt;
论文声称的「其他方法都是将 support sample 的向量表示简单加起来或平均作为」其实并不是事实，早在 2016 年的时候提出 Matching Networks 的论文中所使用的 Full Context Embedding 即 FCE 的目标和这篇论文里的 Induction 模块就是一样的，无非是方法不同而已。
&lt;/p&gt;

&lt;p&gt;
借鉴胶囊网络思路的那个 Induction 模块还有点意思。
&lt;/p&gt;

&lt;p&gt;
ODIC 数据集好像没有开放出来，遗憾。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4eb7d97&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4eb7d97&quot;&gt;五、A Closer Look at Few-Shot Classification&lt;sup&gt;&lt;a id=&quot;fnr.13&quot; class=&quot;footref&quot; href=&quot;#fn.13&quot;&gt;13&lt;/a&gt;&lt;/sup&gt;&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4eb7d97&quot;&gt;
&lt;p&gt;
这篇 ICLR 2019 的论文旨在分析现有 Few-Shot Classification 方法的一些问题。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb587131&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;orgb587131&quot;&gt;观点&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-orgb587131&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Few-Shot Classification 虽然在最近取得了不少进展，但是各个方法由于复杂的模型设计和不同的实现细节，导致他们很难互相比较&lt;/li&gt;
&lt;li&gt;Few-Shot Classification 所使用的 baseline 方法效果被显著地低估了&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
目前的 Few-Shot Classification 模型评估，都是从同样的数据集中采样出来进行的，导致模型的领域迁移性较低
&lt;/p&gt;

&lt;p&gt;
我理解之所以这么说，是因为 Few-Shot Learning 本来宣称的一个目标就是能应付新的类别的数据，而如果这个所谓的「新的类别」必须是在同一个领域内的，那么其实会很受限制。
&lt;/p&gt;

&lt;p&gt;
这点在 Matching Networks 那篇论文里也有提到。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1aa82b2&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org1aa82b2&quot;&gt;模型和方法&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org1aa82b2&quot;&gt;
&lt;p&gt;
这篇论文的目标不是提出一个新的模型来在 Few-Shot Classification 问题上得到更好的效果，所以在模型部分，只是对一个简单的 baseline 模型做了增强得到了 baseline++ 模型，用来在之后和其他模型对比，以论证前面的「baseline 方法效果被显著低估了」这个观点。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191208_10521575773575screenshot.png&quot; alt=&quot;20191208_10521575773575screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
如上图所示，baseline 模型由一个 feature extractor 或者说 encoder 和一个分类模块组成，作者之所以认为之前的一些工作里 baseline 模型效果被低估了，是因为之前的一些论文，在分类模块这里，用的是一个固定的、简单的距离函数（如余弦距离、欧式距离）。
&lt;/p&gt;

&lt;p&gt;
作者在这里做了一些改动，包括：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;baseline 模型的分类模块使用一个全连接层，训练好后，用于新类别数据时，会用新的 support set 进行 fine tuning （之前一些工作里是不做的）&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
baseline++ 在 baseline 模型的基础上对全连接层的计算做了简单的调整
&lt;/p&gt;

&lt;p&gt;
记权重矩阵 \(\mathbf{W} = [\mathbf{w}_{1}, \mathbf{w}_{2}, \ldots, \mathbf{w}_{c}]\)，最终分类模块会输出一个长度为 \(c\) 的向量，表示预测为各个类别的概率，记为 \(\mathbf{s} = [s_{1}, s_{2}, \ldots, s_{c}]\)。
&lt;/p&gt;

&lt;p&gt;
在 baseline 模型里，是这么计算的：\(\mathbf{s} = softmax(\mathbf{W}^{T}f_{\theta}(x))\)
&lt;/p&gt;

&lt;p&gt;
而在 baseline 模型里，则是这么计算的：\(s_{i} = \frac{f_{\theta}(x)^{T}\mathbf{w}_{i}}{\parallel f_{\theta}(x) \parallel\parallel \mathbf{w}_{i} \parallel}\)
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
当然，作者在这里强调，这个 baseline++ 模型并不是他们的贡献，而是来自于 2018 年的一篇论文&lt;sup&gt;&lt;a id=&quot;fnr.14&quot; class=&quot;footref&quot; href=&quot;#fn.14&quot;&gt;14&lt;/a&gt;&lt;/sup&gt;。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org80ed55d&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org80ed55d&quot;&gt;实验和结论&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org80ed55d&quot;&gt;
&lt;p&gt;
作者对比了 Matching Networks、Prototypical Networks、Relation Networks 和一个 meta learning 的方法 MAML 模型。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191208_11271575775643screenshot.png&quot; alt=&quot;20191208_11271575775643screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这个对比图还是挺直观的，对于理解不同模型之间的差异挺有帮助。
&lt;/p&gt;

&lt;p&gt;
图上的 meta-training 和 meta-testing，其实就是指训练和测试。但是 Few-Shot Classification 的训练用数据和实际使用是要预测的类别原则上是不一样的，学到的更多的是区分不同类别的能力而不是区分某个指定类别的能力，这个还有监督分类问题是不太一样的，这里加个 meta 是和普通的分类模型的训练、测试进行区分，不用太在意。b
&lt;/p&gt;

&lt;p&gt;
进行了三个实验：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;使用 miniImageNet 数据集进行一般的图像分类实验&lt;/li&gt;
&lt;li&gt;使用 CUB-200-2011 数据集（后面简称为 CUB 数据集）进行细粒度图像分类实验&lt;/li&gt;
&lt;li&gt;使用 miniImageNet 数据集训练，在 CUB 数据集上进行验证和测试，对比各个模型的跨领域适应能力&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
实验的通用设置为：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;分别进行 5-way 1-shot 和 5-way 5-shot 实验，训练时的 query set 每类 16 个样本&lt;/li&gt;
&lt;li&gt;对 1-shot 实验，训练 60000 个 episodes；对 5-shot 实验，训练 40000 个 episodes&lt;/li&gt;
&lt;li&gt;测试时，将 600 个 episodes 上测平均测试结果作为整体结果&lt;/li&gt;
&lt;li&gt;baseline 模型和 baseline++ 模型训练时设置 batch size 为 16，训练 400 个 epochs&lt;/li&gt;
&lt;li&gt;baseline 模型和 baseline++ 模型，在测试时，让 encoder 参数不变，用 support set 对分类模块进行 fine tuning，batch size 设置为 4 训练 100 次&lt;/li&gt;
&lt;li&gt;所有模型训练时都使用 Adam 优化算法，初始学习率设置为 0.001&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
由于作者自己重新实现了用于对比的几个模型，所以先和原作者论文中报告的结果做了对比，如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191208_11571575777421screenshot.png&quot; alt=&quot;20191208_11571575777421screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到作者实现的这几个模型和它们的原实现的效果相比，大部分是稍差一些，也有些表现更好的。
&lt;/p&gt;

&lt;p&gt;
在 CUB 和 miniImageNet 两个数据集上做实验时，使用四层 CNN 作为 encoder，实验结果如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191208_11591575777591screenshot.png&quot; alt=&quot;20191208_11591575777591screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到，baseline++ 模型和这些 SOTA 的模型相比并没有很大的差距，甚至在一些情况下比 SOTA 的模型还要好。baseline++ 模型仅仅是对 baseline 模型的一个简单修改，所以作者说 baseline 模型的能力被显著地低估了。
&lt;/p&gt;

&lt;p&gt;
接着，作者认为 encoder 是很重要的，所以尝试了将 encoder 替换成更深的网络，结果显示使用更深的网络后大部分模型的效果都有了显著的提升。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191208_12071575778024screenshot.png&quot; alt=&quot;20191208_12071575778024screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;p&gt;
第三个实验 —— 也就是那个先在 miniImageNet 数据集上训练然后在 CUB 数据集上测试的实验，统一使用更深的 ResNet-18 作为 encoder，结果显示 baseline 模型的效果最好。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191208_14091575785358screenshot.png&quot; alt=&quot;20191208_14091575785358screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
由于 CUB 数据集都是鸟类的数据，所以训练与测试时的领域差异性很小；miniImageNet 数据集包含了很多不同类别的物体，所以领域差异性比 CUB 要大；当训练使用 miniImageNet 数据集而测试时使用 CUB 时，领域差异性是最大的。同样使用 ResNet-18 作为 encoder 时，三个不同的 5-way 5-shot 实验对比结果也说明了目前这些 Few-Shot Classification 模型在领域迁移上的问题，如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191208_14131575785609screenshot.png&quot; alt=&quot;20191208_14131575785609screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
而之所以 baseline 模型会最好，有可能是因为 baseline 模型进行了 fine tuning，所以作者再进一步实验，在其他模型上也加上 fine tuning 操作，结果显示领域差异性大时，fine tuning 是很有必要的，如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/20191208_14151575785741screenshot.png&quot; alt=&quot;20191208_14151575785741screenshot.png&quot; align=&quot;center&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-org51d7fa9&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org51d7fa9&quot;&gt;总结&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org51d7fa9&quot;&gt;
&lt;p&gt;
Few-Shot Learning 这个概念最早是李飞飞提出来的&lt;sup&gt;&lt;a id=&quot;fnr.15&quot; class=&quot;footref&quot; href=&quot;#fn.15&quot;&gt;15&lt;/a&gt;&lt;/sup&gt;，不过早先的一些工作方法都比较复杂，除了上述我看的一些论文外，还有一些从 meta learning 的方向来做的。目前看来，Few-Shot Learning 特别是 Few-Shot Classification 的方法，主要都是在 2016 年 Matching Networks 提出的框架下使用越来越复杂的模型，比如还有一篇我没有通读的微软的论文&lt;sup&gt;&lt;a id=&quot;fnr.16&quot; class=&quot;footref&quot; href=&quot;#fn.16&quot;&gt;16&lt;/a&gt;&lt;/sup&gt;的做法就是使用复杂的 attention 模型，我相信 ELMo、BERT 等更强大的预训练模型也会逐步用到这个领域里。
&lt;/p&gt;

&lt;p&gt;
回到这几篇论文，可以看到 Few-Shot Learning 应用到分类问题上时，能取得一定的成果，但也还是有一些问题或者限制的
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;train set 中需要有足够多的类别，虽然每类的数据可以不多 —— 一定要认识清楚这点，不要以为 Few-Shot Learning 就真的只需要很少很少的数据就够了&lt;/li&gt;
&lt;li&gt;领域迁移能力不够好 —— 当然这是目前几乎所有模型的问题，但 Few-Shot Learning 本来就想要去解决新类别的学习问题，希望未来能看到在这方面更多的一些讨论吧&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
我个人对于数据稀缺时该如何训练模型这个话题是很感兴趣的，除了 Few-Shot Learning，目前了解到的一些方法还有：数据增强、远程监督、多任务学习。从这几篇论文来看，表示学习也是很重要的一环，一个表示能力很强的预训练模型，也会很有帮助。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;&amp;#33050;&amp;#27880;: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.1&quot; class=&quot;footnum&quot; href=&quot;#fnr.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Vinyals, Oriol, Charles Blundell, Timothy Lillicrap, Koray Kavukcuoglu, and Daan Wierstra. “Matching Networks for One Shot Learning.” ArXiv:1606.04080 {Cs, Stat}, June 13, 2016. &lt;a href=&quot;http://arxiv.org/abs/1606.04080&quot;&gt;http://arxiv.org/abs/1606.04080&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.2&quot; class=&quot;footnum&quot; href=&quot;#fnr.2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Santoro, Adam, et al. &quot;Meta-learning with memory-augmented neural networks.&quot; International conference on machine learning. 2016.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.3&quot; class=&quot;footnum&quot; href=&quot;#fnr.3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Koch, Gregory, Richard Zemel, and Ruslan Salakhutdinov. &quot;Siamese Neural Networks for One-Shot Image Recognition.&quot; In ICML Deep Learning Workshop, Vol. 2, 2015.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.4&quot; class=&quot;footnum&quot; href=&quot;#fnr.4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Snell, Jake, Kevin Swersky, and Richard S. Zemel. &quot;Prototypical Networks for Few-shot Learning.&quot; ArXiv:1703.05175 {Cs, Stat}, March 15, 2017. &lt;a href=&quot;http://arxiv.org/abs/1703.05175&quot;&gt;http://arxiv.org/abs/1703.05175&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.5&quot; class=&quot;footnum&quot; href=&quot;#fnr.5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Sung, Flood, Yongxin Yang, Li Zhang, Tao Xiang, Philip H. S. Torr, and Timothy M. Hospedales. &quot;Learning to Compare: Relation Network for Few-Shot Learning.&quot; ArXiv:1711.06025 {Cs}, March 27, 2018. &lt;a href=&quot;http://arxiv.org/abs/1711.06025&quot;&gt;http://arxiv.org/abs/1711.06025&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.6&quot; class=&quot;footnum&quot; href=&quot;#fnr.6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Geng, Ruiying, Binhua Li, Yongbin Li, Xiaodan Zhu, Ping Jian, and Jian Sun. &quot;Induction Networks for Few-Shot Text Classification.&quot; ArXiv:1902.10482 {Cs}, September 29, 2019. &lt;a href=&quot;http://arxiv.org/abs/1902.10482&quot;&gt;http://arxiv.org/abs/1902.10482&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.7&quot; class=&quot;footnum&quot; href=&quot;#fnr.7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Sabour, Sara, Nicholas Frosst, and Geoffrey E. Hinton. &quot;Dynamic Routing between Capsules.&quot; In Advances in Neural Information Processing Systems, 3856–3866, 2017.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.8&quot; class=&quot;footnum&quot; href=&quot;#fnr.8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Socher, Richard, Danqi Chen, Christopher D. Manning, and Andrew Ng. &quot;Reasoning with Neural Tensor Networks for Knowledge Base Completion.&quot; In Advances in Neural Information Processing Systems, 926–934, 2013.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.9&quot; class=&quot;footnum&quot; href=&quot;#fnr.9&quot;&gt;9&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Duchi, John, Elad Hazan, and Yoram Singer. &quot;Adaptive Subgradient Methods for Online Learning and Stochastic Optimization.&quot; Journal of Machine Learning Research 12, no. Jul (2011): 2121–2159.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.10&quot; class=&quot;footnum&quot; href=&quot;#fnr.10&quot;&gt;10&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Garcia, Victor, and Joan Bruna. &quot;Few-Shot Learning with Graph Neural Networks.&quot; ArXiv:1711.04043 {Cs, Stat}, February 20, 2018. &lt;a href=&quot;http://arxiv.org/abs/1711.04043&quot;&gt;http://arxiv.org/abs/1711.04043&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.11&quot; class=&quot;footnum&quot; href=&quot;#fnr.11&quot;&gt;11&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Mishra, Nikhil, Mostafa Rohaninejad, Xi Chen, and Pieter Abbeel. &quot;A Simple Neural Attentive Meta-Learner.&quot; ArXiv Preprint ArXiv:1707.03141, 2017.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.12&quot; class=&quot;footnum&quot; href=&quot;#fnr.12&quot;&gt;12&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Yu, Mo, Xiaoxiao Guo, Jinfeng Yi, Shiyu Chang, Saloni Potdar, Yu Cheng, Gerald Tesauro, Haoyu Wang, and Bowen Zhou. &quot;Diverse Few-Shot Text Classification with Multiple Metrics.&quot; ArXiv:1805.07513 {Cs}, May 19, 2018. &lt;a href=&quot;http://arxiv.org/abs/1805.07513&quot;&gt;http://arxiv.org/abs/1805.07513&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.13&quot; class=&quot;footnum&quot; href=&quot;#fnr.13&quot;&gt;13&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Chen, Wei-Yu, Yen-Cheng Liu, Zsolt Kira, Yu-Chiang Frank Wang, and Jia-Bin Huang. &quot;A Closer Look at Few-Shot Classification.&quot; ArXiv:1904.04232 {Cs}, April 8, 2019. &lt;a href=&quot;http://arxiv.org/abs/1904.04232&quot;&gt;http://arxiv.org/abs/1904.04232&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.14&quot; class=&quot;footnum&quot; href=&quot;#fnr.14&quot;&gt;14&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Gidaris, Spyros, and Nikos Komodakis. &quot;Dynamic Few-Shot Visual Learning without Forgetting.&quot; In Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition, 4367–4375, 2018.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.15&quot; class=&quot;footnum&quot; href=&quot;#fnr.15&quot;&gt;15&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Fei-Fei, Li, Rob Fergus, and Peitro Perona. &quot;One-Shot Learning of Object Categories,&quot; 2006.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.16&quot; class=&quot;footnum&quot; href=&quot;#fnr.16&quot;&gt;16&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Sun, Shengli, Qingfeng Sun, Kevin Zhou, and Tengchao Lv. “Hierarchical Attention Prototypical Networks for Few-Shot Text Classification.” In Proceedings of the 2019 Conference on Empirical Methods in Natural Language Processing and the 9th International Joint Conference on Natural Language Processing (EMNLP-IJCNLP), 476–485, 2019.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>NLP哪里跑: 文本分类工具一览</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2019/10/20/nlp-thinking-4.html"/>
    <category term="NLP" scheme="http://www.zmonster.me/categories.html#NLP"/>
    <id>http://www.zmonster.me/2019/10/20/nlp-thinking-4</id>
    <published>2019-10-20T00:00:00+00:00</published>
    <updated>2019-10-20T00:00:00+00:00</updated>
    <description>
    
      <p>常见文本分类工具的使用方法罗列</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgb88d858&quot;&gt;关于文本分类&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org9f9025e&quot;&gt;踩坑列表&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgffa60ab&quot;&gt;腾讯的 NeuralClassifier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga6e1f68&quot;&gt;无人维护的 keras-text&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org0a650e3&quot;&gt;差强人意的 text-classification-keras&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org96810e9&quot;&gt;可用的文本分类工具及其使用方法&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org103b445&quot;&gt;使用 NLTK 进行文本分类&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6d13b9e&quot;&gt;使用 TextBlob 进行文本分类&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2225d3a&quot;&gt;使用 TextGrocery 进行文本分类&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org98269f3&quot;&gt;使用 sklearn 进行文本分类&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4428836&quot;&gt;使用 FastText 进行文本分类&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org243d4a6&quot;&gt;使用 Kashgari 进行文本分类&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgc94711d&quot;&gt;进行常规的文本分类&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6d4406e&quot;&gt;基于 BERT 进行文本分类&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd485d3f&quot;&gt;使用 AllenNLP 进行文本分类&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org3cb8159&quot;&gt;进行常规的文本分类&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgcdca18c&quot;&gt;基于 BERT 进行文本分类&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
本文是《NLP 哪里跑》系列的第四篇文章，系列文章如下：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zmonster.me/2018/03/26/nlp-thinking-1.html&quot;&gt;NLP哪里跑: 开篇及一些碎碎念 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zmonster.me/2018/06/25/nlp-thinking-2.html&quot;&gt;NLP哪里跑: 什么是自然语言处理 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zmonster.me/2018/10/20/nlp-road-3-unicode.html&quot;&gt;NLP哪里跑: Unicode相关的一些小知识和工具 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zmonster.me/2019/10/20/nlp-thinking-4.html&quot;&gt;NLP哪里跑: 文本分类工具一览 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div id=&quot;outline-container-orgb88d858&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgb88d858&quot;&gt;关于文本分类&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgb88d858&quot;&gt;
&lt;p&gt;
所谓的文本分类，其实就是机器学习中分类问题在 NLP 领域中的应用，它的理论相对简单、工具成熟、上手简单，大家基本上是把它当作一个「理论上已经解决」的问题来看待，但其实在实际场景中处理文本分类任务时还是会遇到不少问题的，加上文本分类又是 NLP 领域中最常见的任务之一，我想把自己在这方面的一些经验和学习成果慢慢地整理出来。
&lt;/p&gt;

&lt;p&gt;
2017 年的时候，为了提高做文本分类任务的效率，将 &lt;a href=&quot;https://scikit-learn.org/stable/index.html&quot;&gt;sklearn&lt;/a&gt; 中的文本分类功能做了一些封装，后来断断续续地优化，产出了一个我自己用起来很顺手的文本分类工具。在我开始写《NLP 哪里跑》这个系列的博客后，我计划是把自己在 NLP 方面的经验进行系统地梳理，第一块就是文本分类 —— 这一块当然有很多很多想讲的东西和想做的事情，一篇文章是写不完的，所以最初的想法是先看一下工具方面的情况。我对我在公司维护的文本分类工具还是挺满意的，但也会想自己会不会对一些先进的工具认识不够，所以就去了解了很多其他的同类工具，本篇文章就是对这些工具的一个简单的罗列，不涉及分类模型的理论，也不涉及某个分类模型的具体实现的优劣评价，仅仅是一个非常工具向、实用向的整理记录。
&lt;/p&gt;

&lt;p&gt;
我在挑选文本分类工具时是有一些标准的，不是非常严格，但大概能分成以下几点：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;工程化程度良好的，能提供易用的编程接口或命令行接口&lt;/li&gt;
&lt;li&gt;以 Python 生态内的工具为主 —— 很多其他语言实现的同类工具，限于精力就没有了解了&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
后面的内容会分成两块：第一部分讲我的踩坑经历，主要是一些本来以为会好用的工具结果发现不符合我标准的情况；第二部分是我实验之后确认可用的工具和它们的使用方法。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org9f9025e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org9f9025e&quot;&gt;踩坑列表&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org9f9025e&quot;&gt;
&lt;p&gt;
本节中列举的工具，建议读者不要浪费时间在上面。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgffa60ab&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgffa60ab&quot;&gt;腾讯的 NeuralClassifier&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgffa60ab&quot;&gt;
&lt;p&gt;
&lt;b&gt;注：下文仅代表个人观点和感受，不服不管。&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
三个月前腾讯开源的，见：&lt;a href=&quot;https://cloud.tencent.com/developer/article/1459733&quot;&gt;【开源公告】NeuralNLP-NeuralClassifier - 深度学习文本分类工具 - 云+社区 - 腾讯云&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
项目地址：&lt;a href=&quot;https://github.com/Tencent/NeuralNLP-NeuralClassifier&quot;&gt;https://github.com/Tencent/NeuralNLP-NeuralClassifier&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
在我的列表里最坑的一个：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;作为一个 Python 项目，没有发布到 pypi 就算了，连 setup.py 也没有，无法安装，项目组织也没眼看，只能像个原始人一样拷贝代码到自己的目录跑跑脚本，很难想象是一个大厂的项目&lt;/li&gt;
&lt;li&gt;训练需要使用一个格式复杂的 json 格式的配置文件，然后这个配置的文档太过简略，不少细节藏在项目提供的脚本里……&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
最终我魔改了一通后跑起来了，但是已经恶心到我了，弃。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga6e1f68&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga6e1f68&quot;&gt;无人维护的 keras-text&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga6e1f68&quot;&gt;
&lt;p&gt;
项目地址：&lt;a href=&quot;https://github.com/raghakot/keras-text&quot;&gt;https://github.com/raghakot/keras-text&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
这个项目我觉得蛮可惜的，从文档和实际使用来看，作者在代码结构和使用流程上是做了一些用心的设计的，但是有些关键模块没有完成，在很多细节上存在令人难以忍受的小问题。
&lt;/p&gt;

&lt;p&gt;
项目已经两年没有更新了，可以参考它的代码，但不建议作为一个正经的工具在实际任务中使用。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0a650e3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org0a650e3&quot;&gt;差强人意的 text-classification-keras&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org0a650e3&quot;&gt;
&lt;p&gt;
项目地址：&lt;a href=&quot;https://github.com/jfilter/text-classification-keras&quot;&gt;https://github.com/jfilter/text-classification-keras&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
该项目是对 keras-text 项目的改进，总体上来说是一个可用的项目，但存在以下问题：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;使用文档不齐全&lt;/li&gt;
&lt;li&gt;代码上仍然有一些致命伤，比如

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;将文本转成特征向量后，先存了一个文件，然后从文件中加载后再喂给模型……意义不明……&lt;/li&gt;
&lt;li&gt;每次调用的时候都要把 &lt;a href=&quot;https://spacy.io&quot;&gt;spaCy&lt;/a&gt; 的模型重新加载一遍，慢得要死&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
作者应该是从 keras-text 项目 fork 过来然后改成能用的状态的，也挺不容易的，但不管怎么说在我这里是一个不合格的工具。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org96810e9&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org96810e9&quot;&gt;可用的文本分类工具及其使用方法&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org96810e9&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org103b445&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org103b445&quot;&gt;使用 NLTK 进行文本分类&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org103b445&quot;&gt;
&lt;p&gt;
安装: &lt;code&gt;pip install nltk&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;
文档: &lt;a href=&quot;https://www.nltk.org/api/nltk.classify.html&quot;&gt;https://www.nltk.org/api/nltk.classify.html&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
NLTK 提供了大量的文本处理方法，同时提供了通用的分类器接口，组合起来就能进行文本分类了。
&lt;/p&gt;

&lt;p&gt;
以其中的朴素贝叶斯 NaiveBayesClassifier 为例，可以这样来进行文本分类
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
实现一个方法，将文本转成 dict 形式的特征
&lt;/p&gt;

&lt;p&gt;
以英文为例，可以直接用 NLTK 中的分词方法，需要的话还可以加上 &lt;a href=&quot;https://en.wikipedia.org/wiki/Stemming&quot;&gt;stemming&lt;/a&gt; 或者 &lt;a href=&quot;https://en.wikipedia.org/wiki/Lemmatisation&quot;&gt;lemmatization&lt;/a&gt;。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; nltk.corpus &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; stopwords
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; nltk.tokenize &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; word_tokenize


&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;extract_feature&lt;/span&gt;(text):
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;feature&lt;/span&gt; = {}
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; word &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; word_tokenize(text):
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; word &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;not&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; stopwords:
            &lt;span style=&quot;color: #ffcc66;&quot;&gt;feature&lt;/span&gt;[word] = 1

    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; feature
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
中文的话可以换成 jieba 或者其他中文分词工具。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
训练
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; nltk.classify &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; NaiveBayesClassifier


&lt;span style=&quot;color: #ffcc66;&quot;&gt;train_texts&lt;/span&gt; = [
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;...&lt;/span&gt;
]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;train_labels&lt;/span&gt; = [
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;...&lt;/span&gt;
]

&lt;span style=&quot;color: #ffcc66;&quot;&gt;train_features&lt;/span&gt; = [extract_feature(text) &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; text &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; train_texts]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;train_samples&lt;/span&gt; = &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;list&lt;/span&gt;(&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;zip&lt;/span&gt;(train_features, train_labels))
&lt;span style=&quot;color: #ffcc66;&quot;&gt;classifier&lt;/span&gt; = NaiveBayesClassifier.train(train_samples)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
评估
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; nltk.classify &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; accuracy

&lt;span style=&quot;color: #ffcc66;&quot;&gt;test_texts&lt;/span&gt; = [
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;...&lt;/span&gt;
]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;test_labels&lt;/span&gt; = [
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;...&lt;/span&gt;
]

&lt;span style=&quot;color: #ffcc66;&quot;&gt;test_features&lt;/span&gt; = [extract_feature(text) &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; text &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; test_texts]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;test_samples&lt;/span&gt; = &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;list&lt;/span&gt;(&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;zip&lt;/span&gt;(test_features, test_labels))
&lt;span style=&quot;color: #ffcc66;&quot;&gt;acc&lt;/span&gt; = accuracy(classifier, test_samples)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
预测
&lt;/p&gt;

&lt;p&gt;
用 classify 方法直接预测最可能的类别
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;text&lt;/span&gt; = &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;blablabla&quot;&lt;/span&gt;              &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#24453;&amp;#39044;&amp;#27979;&amp;#30340;&amp;#25991;&amp;#26412;&lt;/span&gt;
&lt;span style=&quot;color: #ffcc66;&quot;&gt;feature&lt;/span&gt; = extract_feature(text)
&lt;span style=&quot;color: #ffcc66;&quot;&gt;pred_label&lt;/span&gt; = classifier.classify(feature)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
用 prob_classify 方法获得所有可能类别的预测分数
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;text&lt;/span&gt; = &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;blablabla&quot;&lt;/span&gt;              &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#24453;&amp;#39044;&amp;#27979;&amp;#30340;&amp;#25991;&amp;#26412;&lt;/span&gt;
&lt;span style=&quot;color: #ffcc66;&quot;&gt;feature&lt;/span&gt; = extract_feature(text)
&lt;span style=&quot;color: #ffcc66;&quot;&gt;prob&lt;/span&gt; = classifier.prob_classify(feature)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
模型保存和读取
&lt;/p&gt;

&lt;p&gt;
可以直接用 pickle 保存、读取训练好的模型
&lt;/p&gt;

&lt;p&gt;
保存：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; pickle

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;with&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;open&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;'model.pkl'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'wb'&lt;/span&gt;) &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;as&lt;/span&gt; f:
    pickle.dump(classifier, f)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
读取：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; pickle

&lt;span style=&quot;color: #ffcc66;&quot;&gt;classifier&lt;/span&gt; = &lt;span style=&quot;color: #6699cc;&quot;&gt;None&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;with&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;open&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;'model.pkl'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'rb'&lt;/span&gt;) &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;as&lt;/span&gt; f:
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;classifier&lt;/span&gt; = pickle.load(f)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
NLTK 中还有其他分类器，使用方法和 NaiveBayesClassifier 大同小异。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6d13b9e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6d13b9e&quot;&gt;使用 TextBlob 进行文本分类&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6d13b9e&quot;&gt;
&lt;p&gt;
&lt;b&gt;注意：TextBlob 仅支持英文&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
安装: &lt;code&gt;pip install textblob&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;
文档: &lt;a href=&quot;https://textblob.readthedocs.io/en/dev/classifiers.html&quot;&gt;https://textblob.readthedocs.io/en/dev/classifiers.html&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
TextBlob 是一个基于 NLTK 的文本处理工具，其中的文本分类功能也是建立在 NLTK 中分类器的基础上的。
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
训练
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; textblob.classifiers &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; NaiveBayesClassifier

&lt;span style=&quot;color: #ffcc66;&quot;&gt;train_texts&lt;/span&gt; = [
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;...&lt;/span&gt;
]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;train_labels&lt;/span&gt; = [
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;...&lt;/span&gt;
]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;train_samples&lt;/span&gt; = &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;list&lt;/span&gt;(&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;zip&lt;/span&gt;(train_texts, train_labels))
&lt;span style=&quot;color: #ffcc66;&quot;&gt;classifier&lt;/span&gt; = NaiveBayesClassifier(train_samples)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
评估
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;test_texts&lt;/span&gt; = [
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;...&lt;/span&gt;
]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;test_labels&lt;/span&gt; = [
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;...&lt;/span&gt;
]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;test_samples&lt;/span&gt; = &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;list&lt;/span&gt;(&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;zip&lt;/span&gt;(test_texts, test_labels))
&lt;span style=&quot;color: #ffcc66;&quot;&gt;acc&lt;/span&gt; = classifier.accuracy(test_samples)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
预测
&lt;/p&gt;

&lt;p&gt;
只有一个 classify 接口预测得到最有可能的类别
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;label&lt;/span&gt; = classifier.classify(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;this is a sentence to be classified&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
模型保存和读取
&lt;/p&gt;

&lt;p&gt;
同 NLTK。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
相比 NLTK 中原来的文本分类，TextBlob 的封装隐藏了一些细节，简化了接口，用起来还是挺方便的。不好的一点是，TextBlob 里强制依赖了 NLTK 里的 word_tokenize，虽然说 word_tokenize 可以通过 language 参数设置语言，但在 TextBlob 里没有提供传递这个参数的机会，这就导致 TextBlob 只能对英文进行分类。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2225d3a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2225d3a&quot;&gt;使用 TextGrocery 进行文本分类&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2225d3a&quot;&gt;
&lt;p&gt;
&lt;b&gt;注意：TextGrocery 仅支持 Python2&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
安装: &lt;code&gt;pip install tgrocery&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;
文档: &lt;a href=&quot;https://github.com/2shou/TextGrocery/blob/master/README_CN.md&quot;&gt;https://github.com/2shou/TextGrocery/blob/master/README_CN.md&lt;/a&gt;
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
初始化
&lt;/p&gt;

&lt;p&gt;
需要给分类器指定一个名字
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; tgrocery &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; Grocery

&lt;span style=&quot;color: #ffcc66;&quot;&gt;classifier&lt;/span&gt; = Grocery(&lt;span style=&quot;color: #66cccc;&quot;&gt;'test'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
默认使用 jieba 作为分词器，但也支持在初始化分类器的时候通过 custom_tokenize 参数来自定义分词器
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;classifier&lt;/span&gt; = Grocery(&lt;span style=&quot;color: #66cccc;&quot;&gt;'test'&lt;/span&gt;, custom_tokenize=&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;list&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
要求 custom_tokenize 的参数值是一个 python 的函数。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
训练
&lt;/p&gt;

&lt;p&gt;
支持传入 python 数据进行训练：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;train_src&lt;/span&gt; = [
    (&lt;span style=&quot;color: #66cccc;&quot;&gt;'education'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#21517;&amp;#24072;&amp;#25351;&amp;#23548;&amp;#25176;&amp;#31119;&amp;#35821;&amp;#27861;&amp;#25216;&amp;#24039;&amp;#65306;&amp;#21517;&amp;#35789;&amp;#30340;&amp;#22797;&amp;#25968;&amp;#24418;&amp;#24335;'&lt;/span&gt;),
    (&lt;span style=&quot;color: #66cccc;&quot;&gt;'education'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#20013;&amp;#22269;&amp;#39640;&amp;#32771;&amp;#25104;&amp;#32489;&amp;#28023;&amp;#22806;&amp;#35748;&amp;#21487; &amp;#26159;&amp;#8220;&amp;#29436;&amp;#26469;&amp;#20102;&amp;#8221;&amp;#21527;&amp;#65311;'&lt;/span&gt;),
    (&lt;span style=&quot;color: #66cccc;&quot;&gt;'sports'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#22270;&amp;#25991;&amp;#65306;&amp;#27861;&amp;#32593;&amp;#23391;&amp;#33778;&amp;#23572;&amp;#26031;&amp;#33510;&amp;#25112;&amp;#36827;16&amp;#24378; &amp;#23391;&amp;#33778;&amp;#23572;&amp;#26031;&amp;#24594;&amp;#21564;'&lt;/span&gt;),
    (&lt;span style=&quot;color: #66cccc;&quot;&gt;'sports'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#22235;&amp;#24029;&amp;#20025;&amp;#26865;&amp;#20030;&amp;#34892;&amp;#20840;&amp;#22269;&amp;#38271;&amp;#36317;&amp;#30331;&amp;#23665;&amp;#25361;&amp;#25112;&amp;#36187; &amp;#36817;&amp;#19975;&amp;#20154;&amp;#21442;&amp;#19982;'&lt;/span&gt;)
]
classifier.train(train_src)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
也支持从文件中读取训练数据然后训练，要求文件中一行是一个数据，且行中有一个分隔符把文本和文本的类别标签分隔开，如用竖线分隔：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
education|名师指导托福语法技巧：名词的复数形式
education|中国高考成绩海外认可 是“狼来了”吗？
sports|图文：法网孟菲尔斯苦战进16强 孟菲尔斯怒吼
sports|四川丹棱举行全国长距登山挑战赛 近万人参与
&lt;/pre&gt;

&lt;p&gt;
假设上面的内容存储在 train.txt 中，则将 train.txt 作为 train 的参数，同时要用 delimiter 参数指明分隔符
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;classifier.train(&lt;span style=&quot;color: #66cccc;&quot;&gt;'train.txt'&lt;/span&gt;, delimiter=&lt;span style=&quot;color: #66cccc;&quot;&gt;'|'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
评估
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;test_src&lt;/span&gt; = [
    (&lt;span style=&quot;color: #66cccc;&quot;&gt;'education'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#31119;&amp;#24314;&amp;#26149;&amp;#23395;&amp;#20844;&amp;#21153;&amp;#21592;&amp;#32771;&amp;#35797;&amp;#25253;&amp;#21517;18&amp;#26085;&amp;#25130;&amp;#27490; 2&amp;#26376;6&amp;#26085;&amp;#32771;&amp;#35797;'&lt;/span&gt;),
    (&lt;span style=&quot;color: #66cccc;&quot;&gt;'sports'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#24847;&amp;#30002;&amp;#39318;&amp;#36718;&amp;#34917;&amp;#36187;&amp;#20132;&amp;#25112;&amp;#35760;&amp;#24405;:&amp;#31859;&amp;#20848;&amp;#23458;&amp;#22330;8&amp;#25112;&amp;#19981;&amp;#36133;&amp;#22269;&amp;#31859;10&amp;#24180;&amp;#36830;&amp;#32988;'&lt;/span&gt;),
]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;report&lt;/span&gt; = classifier.test(test_src)
report.show_result()
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上述代码会输出如下内容：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
               accuracy       recall
education      50.00%         100.00%
sports         0.00%          0.00%
&lt;/pre&gt;

&lt;p&gt;
也可以从文件中读取数据进行评估，文件的要求同训练
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;report&lt;/span&gt; = classifier.test(&lt;span style=&quot;color: #66cccc;&quot;&gt;'test.txt'&lt;/span&gt;, delimiter=&lt;span style=&quot;color: #66cccc;&quot;&gt;'|'&lt;/span&gt;)
report.show_result()
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
预测
&lt;/p&gt;

&lt;p&gt;
使用 predict 接口来进行预测
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;preds&lt;/span&gt; = classifier.predict(&lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#24847;&amp;#30002;&amp;#39318;&amp;#36718;&amp;#34917;&amp;#36187;&amp;#20132;&amp;#25112;&amp;#35760;&amp;#24405;:&amp;#31859;&amp;#20848;&amp;#23458;&amp;#22330;8&amp;#25112;&amp;#19981;&amp;#36133;&amp;#22269;&amp;#31859;10&amp;#24180;&amp;#36830;&amp;#32988;'&lt;/span&gt;)
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; preds.dec_values         &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;=&amp;gt; {'education': 0.00604235155848336, 'sports': -0.006042351558483356}&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; preds.predicted_y        &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;=&amp;gt; education&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;str&lt;/span&gt;(preds)               &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;=&amp;gt; education&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
模型保存和读取
&lt;/p&gt;

&lt;p&gt;
用 save 方法来保存模型
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;classifier.save()
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
保存模型时会用分类器初始化时给的名字来创建一个目录，比如最开始给的名字是 test，所保存的模型会在 test 目录下，如下所示：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
test
├── converter
│   ├── class_map.config.pickle
│   ├── feat_gen.config.pickle
│   └── text_prep.config.pickle
├── id
└── learner
    ├── idf.pickle
    ├── liblinear_model
    └── options.pickle
&lt;/pre&gt;

&lt;p&gt;
用相同的名字创建一个分类器，然后执行 load 方法来读取模型
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;classifier&lt;/span&gt; = Grocery(&lt;span style=&quot;color: #66cccc;&quot;&gt;'test'&lt;/span&gt;, custom_tokenize=&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;list&lt;/span&gt;)
classifier.load()
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这里需要注意的是，保存模型的时候，自定义的分词器是没有被保存下来的，所以在读取的时候，还需要重新设置一下分词器。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
TextGrocery 是一个基于 liblinear 的小巧的文本分类实现，可惜作者已经放弃维护了，目前只能在 Python2 环境里面使用。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org98269f3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org98269f3&quot;&gt;使用 sklearn 进行文本分类&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org98269f3&quot;&gt;
&lt;p&gt;
安装: &lt;code&gt;pip install scikit-learn&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;
文档: &lt;a href=&quot;https://scikit-learn.org/stable/tutorial/text_analytics/working_with_text_data.html#training-a-classifier&quot;&gt;https://scikit-learn.org/stable/tutorial/text_analytics/working_with_text_data.html#training-a-classifier&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
sklearn 中实现了很多的分类器，并且提供了统一的接口，我个人是比较喜欢的。
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
训练
&lt;/p&gt;

&lt;p&gt;
首先创建一个 vectorizer 用来将文本编码成向量，最常用的可能是 TfidfVectorizer 了
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; sklearn.feature_extraction.text &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; TfidfVectorizer

&lt;span style=&quot;color: #ffcc66;&quot;&gt;vectorizer&lt;/span&gt; = TfidfVectorizer()
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
默认会按空格来分词，如果需要自定义分词器，可以通过 tokenizer 参数来传入一个函数，比如
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; jieba

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;jieba_tokenize&lt;/span&gt;(text):
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; jieba.lcut(text)

&lt;span style=&quot;color: #ffcc66;&quot;&gt;vectorizer&lt;/span&gt; = TfidfVectorizer(tokenizer=jieba_tokenize)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;b&gt;注意：由于 jieba 中加了线程锁，将 jieba.lcut 直接传入，会导致模型无法保存&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
这个 vectorizer 是需要训练的
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;texts&lt;/span&gt; = [
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#21517;&amp;#24072;&amp;#25351;&amp;#23548;&amp;#25176;&amp;#31119;&amp;#35821;&amp;#27861;&amp;#25216;&amp;#24039;'&lt;/span&gt;,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#20013;&amp;#22269;&amp;#39640;&amp;#32771;&amp;#25104;&amp;#32489;&amp;#28023;&amp;#22806;&amp;#35748;&amp;#21487;'&lt;/span&gt;,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#27861;&amp;#32593;&amp;#23391;&amp;#33778;&amp;#23572;&amp;#26031;&amp;#33510;&amp;#25112;&amp;#36827;16&amp;#24378;'&lt;/span&gt;,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#22235;&amp;#24029;&amp;#20025;&amp;#26865;&amp;#20030;&amp;#34892;&amp;#30331;&amp;#23665;&amp;#25361;&amp;#25112;&amp;#36187;'&lt;/span&gt;,
]
vectorizer.fit(texts)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
一旦训练后，对任意一个文本，会产生一个固定长度的向量，比如：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt;(vectorizer.transform([&lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#21517;&amp;#24072;&amp;#25351;&amp;#23548;&amp;#25176;&amp;#31119;&amp;#35821;&amp;#27861;&amp;#25216;&amp;#24039;'&lt;/span&gt;]).toarray())
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上面的代码会输出
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;[[0.        0.        0.        0.        0.4472136 0.        0.
  0.        0.        0.4472136 0.4472136 0.4472136 0.        0.
  0.        0.        0.        0.        0.        0.4472136 0.
  0.       ]]
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
向量化还有其他方法，如下：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; sklearn.feature_extraction.text &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; (
    TfidfVectorizer,
    CountVectorizer,
    HashingVectorizer,
)
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; sklearn.feature_extraction &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; DictVectorizer
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
创建一个分类器，比如 SVM
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; sklearn.svm &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; LinearSVC

&lt;span style=&quot;color: #ffcc66;&quot;&gt;classifier&lt;/span&gt; = LinearSVC()
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
如果想使用 GBDT 分类器的话，可以执行 &lt;code&gt;pip install xgboost&lt;/code&gt; 安装 &lt;a href=&quot;https://xgboost.readthedocs.io/en/latest/&quot;&gt;XGBoost&lt;/a&gt; 这个包，它提供了符合 sklearn 规范的接口，可以直接使用并像 sklearn 的分类器一样用在后面的训练、预测过程中：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; xgboost &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; XGBClassifier

&lt;span style=&quot;color: #ffcc66;&quot;&gt;classifier&lt;/span&gt; = XGBClassifier()
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
首先用 vectorizer 将训练数据中的文本转成矩阵，然后喂给分类器进行训练
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;train_texts&lt;/span&gt; = [
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;blablabla&lt;/span&gt;
]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;train_labels&lt;/span&gt; = [
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;blablabla&lt;/span&gt;
]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;train_feats&lt;/span&gt; = vectorizer.transform(train_texts)
classifier.fit(train_feats, train_labels)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
评估
&lt;/p&gt;

&lt;p&gt;
用分类器的 score 方法可以计算测试集的 accuracy
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;test_texts&lt;/span&gt; = [
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;...&lt;/span&gt;
]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;test_labels&lt;/span&gt; = [
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;...&lt;/span&gt;
]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;test_feats&lt;/span&gt; = vectorizer.transform(test_texts)
&lt;span style=&quot;color: #ffcc66;&quot;&gt;acc&lt;/span&gt; = classifier.score(test_feats, test_labels)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这个方法其实是调用了 &lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.metrics.accuracy_score.html#sklearn.metrics.accuracy_score&quot;&gt;accuracy_score&lt;/a&gt; 这个函数，所以也可以自己来计算
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; sklearn.metrics &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; accuracy_score

&lt;span style=&quot;color: #ffcc66;&quot;&gt;pred_labels&lt;/span&gt; = classifier.predict(test_feats)
&lt;span style=&quot;color: #ffcc66;&quot;&gt;acc&lt;/span&gt; = accuracy_score(test_labels, pred_labels)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
还可以用 &lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.metrics.classification_report.html&quot;&gt;classification_report&lt;/a&gt; 这个函数来得到更详细的评估报告
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; sklearn.metrics &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; classification_report

&lt;span style=&quot;color: #ffcc66;&quot;&gt;pred_labels&lt;/span&gt; = classifier.predict(test_feats)
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt;(classification_report(test_labels, pred_labels))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
输出结果是下面这个样子的：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
              precision    recall  f1-score   support

     class 0       0.50      1.00      0.67         1
     class 1       0.00      0.00      0.00         1
     class 2       1.00      0.67      0.80         3

    accuracy                           0.60         5
   macro avg       0.50      0.56      0.49         5
weighted avg       0.70      0.60      0.61         5
&lt;/pre&gt;

&lt;p&gt;
有时候我们还需要输出分类的混淆矩阵，虽然 sklearn 提供了 &lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html#sklearn.metrics.confusion_matrix&quot;&gt;sklearn.metrics.confusion_matrix&lt;/a&gt; 这个方法来计算混淆矩阵，但它的输出不够直观，我个人比较喜欢用 &lt;a href=&quot;https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.crosstab.html&quot;&gt;pandas.crosstab&lt;/a&gt;
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; pandas

&lt;span style=&quot;color: #ffcc66;&quot;&gt;pred_labels&lt;/span&gt; = classifier.predict(test_feats)
&lt;span style=&quot;color: #ffcc66;&quot;&gt;cnf_matrix&lt;/span&gt; = pandas.crosstab(
    pandas.Series(test_labels), pandas.Series(pred_labels),
    rownames=[&lt;span style=&quot;color: #66cccc;&quot;&gt;'targets'&lt;/span&gt;], colnames=[&lt;span style=&quot;color: #66cccc;&quot;&gt;'preds'&lt;/span&gt;]
)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
输入结果是下面这个样子：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
preds     negative  positive

targets
negative       590       126
positive       383       901
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
预测
&lt;/p&gt;

&lt;p&gt;
用 predict 方法来预测最可能的类别，或用 predict_proba 方法来获得所预测类别的分数
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;texts&lt;/span&gt; = [&lt;span style=&quot;color: #66cccc;&quot;&gt;'text1'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'text2'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'text3'&lt;/span&gt;]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;feats&lt;/span&gt; = vectorizer.transform(texts)
&lt;span style=&quot;color: #ffcc66;&quot;&gt;labels&lt;/span&gt; = classifier.predict(feats) &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;labels: ['label1', 'label2', 'label3']&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;or&lt;/span&gt;
&lt;span style=&quot;color: #ffcc66;&quot;&gt;prob_list&lt;/span&gt; = classifier.predict_proba(feats)
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;prob_list:&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;[&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#     &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;{'label1': 0.1, 'label2': 0.3, 'label3': 0.6},&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#     &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;{'label1': 0.1, 'label2': 0.3, 'label3': 0.6},&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#     &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;{'label1': 0.1, 'label2': 0.3, 'label3': 0.6},&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
注意 sklearn 中的 predict/predict_proba 都被设计为批量预测，没有单个数据预测的接口。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
模型保存和读取
&lt;/p&gt;

&lt;p&gt;
保存模型用 pickle 或者 joblib 都可以，注意要把 vectorizer 和 classifier 一起保存。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; pickle
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; sklearn.externals &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; joblib

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;with&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;open&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;'model.pkl'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'wb'&lt;/span&gt;) &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;as&lt;/span&gt; f:
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;data&lt;/span&gt; = [vectorizer, classifier]
    pickle.dump(data, f)

&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;or&lt;/span&gt;
&lt;span style=&quot;color: #ffcc66;&quot;&gt;data&lt;/span&gt; = [vectorizer, classifier]
joblib.dump(data, &lt;span style=&quot;color: #66cccc;&quot;&gt;'model.pkl'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
如果使用 &lt;code&gt;pickle.dump&lt;/code&gt; 保存的模型，则用 &lt;code&gt;pickle.load&lt;/code&gt; 来读取；如果是用 &lt;code&gt;joblib.dump&lt;/code&gt; 保存的则用 &lt;code&gt;joblib.load&lt;/code&gt; 读取
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;vectorizer&lt;/span&gt;, &lt;span style=&quot;color: #ffcc66;&quot;&gt;classifier&lt;/span&gt; = &lt;span style=&quot;color: #6699cc;&quot;&gt;None&lt;/span&gt;, &lt;span style=&quot;color: #6699cc;&quot;&gt;None&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;with&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;open&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;'model.pkl'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'rb'&lt;/span&gt;) &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;as&lt;/span&gt; f:
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;vectorizer&lt;/span&gt;, &lt;span style=&quot;color: #ffcc66;&quot;&gt;classifier&lt;/span&gt; = pickle.load(f)

&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;or&lt;/span&gt;
&lt;span style=&quot;color: #ffcc66;&quot;&gt;vectorizer&lt;/span&gt;, &lt;span style=&quot;color: #ffcc66;&quot;&gt;classifier&lt;/span&gt; = joblib.load(&lt;span style=&quot;color: #66cccc;&quot;&gt;'model.pkl'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
除了上面这样先创建 vectorizer 再创建 classifier 的方法，sklearn 还提供了 &lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html&quot;&gt;Pipeline&lt;/a&gt; 这个类来简化这个过程，非常推荐使用。
&lt;/p&gt;

&lt;p&gt;
创建 vectorizer 和 classifier 后，用 Pipeline 把它们组合起来：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; sklearn.pipeline &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; Pipeline

&lt;span style=&quot;color: #ffcc66;&quot;&gt;vectorizer&lt;/span&gt; = TfidfVectorizer()
&lt;span style=&quot;color: #ffcc66;&quot;&gt;classifier&lt;/span&gt; = LinearSVC()
&lt;span style=&quot;color: #ffcc66;&quot;&gt;pipeline&lt;/span&gt; = Pipeline([(&lt;span style=&quot;color: #66cccc;&quot;&gt;'vec'&lt;/span&gt;, vectorizer), (&lt;span style=&quot;color: #66cccc;&quot;&gt;'model'&lt;/span&gt;, classifier)])
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后可以直接将文本喂给 pipeline，不用自己再去调用 vectorizer.fit 和 vectorizer.transform 来将文本编码成向量了！
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;train_texts&lt;/span&gt; = [
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;blablabla&lt;/span&gt;
]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;train_labels&lt;/span&gt; = [
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;blablabla&lt;/span&gt;
]
pipeline.fit(train_texts, train_labels)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
评估、预测和非 pipeline 方式的差不多，都是可以省略掉将文本转成向量的这个步骤；模型保存时只需要将 pipeline 保存成文件即可。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4428836&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4428836&quot;&gt;使用 FastText 进行文本分类&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4428836&quot;&gt;
&lt;p&gt;
安装: &lt;code&gt;pip install fasttext&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;
文档: &lt;a href=&quot;https://fasttext.cc/docs/en/python-module.html#text-classification-model&quot;&gt;https://fasttext.cc/docs/en/python-module.html#text-classification-model&lt;/a&gt;
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
数据格式
&lt;/p&gt;

&lt;p&gt;
fasttext 的训练和评估都只能从文件中读取数据，而不能直接传入 Python 的值，而且对文件的格式是有要求的
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;文件中一行一个样本&lt;/li&gt;
&lt;li&gt;每行用制表符分隔，第一列是标签，第二列是文本&lt;/li&gt;
&lt;li&gt;第一列的标签要有 &lt;code&gt;__label__&lt;/code&gt; 前缀&lt;/li&gt;
&lt;li&gt;第二列的文本必须是用空格分隔的词序列，对中文来说，意味着需要先分好词&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
文件内容示例如下：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
__label__education	名师 指导 托福 语法 技巧 ： 名词 的 复数 形式
__label__education	中国 高考 成绩 海外 认可 是 “ 狼 来了 ” 吗 ？
__label__sports	图文 ： 法网 孟菲尔斯 苦战 进 16强 孟菲尔斯 怒吼
__label__sports	四川 丹棱 举行 全国 长距 登山 挑战赛 近 万人 参与
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
训练
&lt;/p&gt;

&lt;p&gt;
假设训练数据按照前面的要求写在了 train_data.txt 里，则用下面的代码来训练：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; fasttext

&lt;span style=&quot;color: #ffcc66;&quot;&gt;model&lt;/span&gt; = fasttext.train_supervised(&lt;span style=&quot;color: #66cccc;&quot;&gt;'train_data.txt'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
评估
&lt;/p&gt;

&lt;p&gt;
假设测试数据在 test_data.txt 中，使用 test 方法来评估模型效果，它会返回数据集中的样本数量，以及 precesion 和 recall 值：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;num&lt;/span&gt;, &lt;span style=&quot;color: #ffcc66;&quot;&gt;precesion&lt;/span&gt;, &lt;span style=&quot;color: #ffcc66;&quot;&gt;recall&lt;/span&gt; = model.test(&lt;span style=&quot;color: #66cccc;&quot;&gt;'test_data.txt'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
也可以用 test_label 方法获得每个类别的 precesion、recall 和 f1 值：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt;(model.test_label(&lt;span style=&quot;color: #66cccc;&quot;&gt;'test_data.txt'&lt;/span&gt;))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
输出结果是下面这个样子的：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;{
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'__label__education'&lt;/span&gt;: {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;'precision'&lt;/span&gt;: 0.8830022075055187,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;'recall'&lt;/span&gt;: 0.8784773060029283,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;'f1score'&lt;/span&gt;: 0.8807339449541285
    },
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'__label__sports'&lt;/span&gt;: {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;'precision'&lt;/span&gt;: 0.883881230116649,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;'recall'&lt;/span&gt;: 0.853121801432958,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;'f1score'&lt;/span&gt;: 0.8682291666666667
    }
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
预测
&lt;/p&gt;

&lt;p&gt;
用 predict 接口来对单条文本进行预测，同样要求文本是用空格分隔的、分好词的
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;top3_labels&lt;/span&gt;, &lt;span style=&quot;color: #ffcc66;&quot;&gt;top3_scores&lt;/span&gt; = model.predict(&lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#22303;&amp;#35910;&amp;#32593; &amp;#25311; &amp;#26126;&amp;#24180; &amp;#30331;&amp;#38470; &amp;#32435;&amp;#24066; &amp;#21215;&amp;#36164; 1.5 &amp;#20159;&amp;#32654;&amp;#20803;'&lt;/span&gt;, k=3)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
模型保存和读取
&lt;/p&gt;

&lt;p&gt;
保存
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;model.save_model(&lt;span style=&quot;color: #66cccc;&quot;&gt;'model.bin'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
读取
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; fasttext
&lt;span style=&quot;color: #ffcc66;&quot;&gt;model&lt;/span&gt; = fasttext.load_model(&lt;span style=&quot;color: #66cccc;&quot;&gt;'model.bin'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-org243d4a6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org243d4a6&quot;&gt;使用 Kashgari 进行文本分类&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org243d4a6&quot;&gt;
&lt;p&gt;
安装: &lt;code&gt;pip install kashgari-tf tensorflow==1.14.0&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;
文档: &lt;a href=&quot;https://kashgari.bmio.net/&quot;&gt;https://kashgari.bmio.net/&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Kashgari 是一个基于神经网络模型的 NLP 工具，内部实现大多数常用的神经网络模型，也支持了最新的 BERT，使用体验挺不错的。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc94711d&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;orgc94711d&quot;&gt;进行常规的文本分类&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-orgc94711d&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
训练
&lt;/p&gt;

&lt;p&gt;
Kashgari 要求输入的文本是分好词的，把分词的事情留给用户自己处理。不过分好词就能直接输入到模型中了，不需要像 sklearn 一样通过 vectorizer 转成向量：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; kashgari.tasks.classification.models &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; CNN_Model

&lt;span style=&quot;color: #ffcc66;&quot;&gt;train_x&lt;/span&gt; = [[&lt;span style=&quot;color: #66cccc;&quot;&gt;'Hello'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'world'&lt;/span&gt;], [&lt;span style=&quot;color: #66cccc;&quot;&gt;'Hello'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'Kashgari'&lt;/span&gt;]]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;train_y&lt;/span&gt; = [&lt;span style=&quot;color: #66cccc;&quot;&gt;'a'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'b'&lt;/span&gt;]

&lt;span style=&quot;color: #ffcc66;&quot;&gt;model&lt;/span&gt; = CNN_Model()
model.fit(train_x, train_y)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
训练时还可以设置校验集
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;val_x&lt;/span&gt; = [[&lt;span style=&quot;color: #66cccc;&quot;&gt;'Hello'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'world'&lt;/span&gt;], [&lt;span style=&quot;color: #66cccc;&quot;&gt;'Hello'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'Kashgari'&lt;/span&gt;]]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;val_y&lt;/span&gt; = [&lt;span style=&quot;color: #66cccc;&quot;&gt;'a'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'b'&lt;/span&gt;]

model.fit(val_x, val_y)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
评估
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;test_x&lt;/span&gt; = [[&lt;span style=&quot;color: #66cccc;&quot;&gt;'Hello'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'world'&lt;/span&gt;], [&lt;span style=&quot;color: #66cccc;&quot;&gt;'Hello'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'Kashgari'&lt;/span&gt;]]
&lt;span style=&quot;color: #ffcc66;&quot;&gt;test_y&lt;/span&gt; = [&lt;span style=&quot;color: #66cccc;&quot;&gt;'a'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'b'&lt;/span&gt;]
model.evaluate(test_x, test_y)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
会打印测试结果到标准输出，其内容是下面这个格式的：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
              precision    recall  f1-score   support

      sports     1.0000    1.0000    1.0000      1000
   education     1.0000    0.9980    0.9990      1000
  technology     0.9930    1.0000    0.9965      1000

    accuracy                         0.9985     10000
   macro avg     0.9985    0.9985    0.9985     10000
weighted avg     0.9985    0.9985    0.9985     10000
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
预测
&lt;/p&gt;

&lt;p&gt;
使用 predict 方法来预测最可能的类别
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;tokens&lt;/span&gt; = [&lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#23002;&amp;#26126;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#65306;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#23545;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#22885;&amp;#23612;&amp;#23572;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#19981;&amp;#24471;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#19981;&amp;#26381;'&lt;/span&gt;]
model.predict([tokens])          &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;=&amp;gt; ['sports']&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
或者用 predict_top_k_class 来获取 topk 的预测结果及分数
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt;(model.predict_top_k_class([tokens], top_k=3))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;[
    {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;'label'&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;'sports'&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;'confidence'&lt;/span&gt;: 0.50483656,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;'candidates'&lt;/span&gt;: [
            {&lt;span style=&quot;color: #66cccc;&quot;&gt;'label'&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;'education'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'confidence'&lt;/span&gt;: 0.057417843},
            {&lt;span style=&quot;color: #66cccc;&quot;&gt;'label'&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;'technology'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'confidence'&lt;/span&gt;: 0.048766118},
        ]
    }
]
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;模型保存和读取

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
保存
&lt;/p&gt;

&lt;p&gt;
使用 save 方法将模型保存到 test 目录中，目录不存在会创建
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;model.save(&lt;span style=&quot;color: #66cccc;&quot;&gt;'test'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
目录中会有一个描述模型结构的 model_info.json 和记录模型参数的 model_weights.h5
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
test
├── model_info.json
└── model_weights.h5

0 directories, 2 files
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
读取
&lt;/p&gt;

&lt;p&gt;
使用 &lt;code&gt;kashgari.utils.d_model&lt;/code&gt; 来读取模型
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; kashgari.utils &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; load_model

&lt;span style=&quot;color: #ffcc66;&quot;&gt;model&lt;/span&gt; = load_model(&lt;span style=&quot;color: #66cccc;&quot;&gt;'test'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6d4406e&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org6d4406e&quot;&gt;基于 BERT 进行文本分类&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org6d4406e&quot;&gt;
&lt;p&gt;
先下载 BERT 模型。
&lt;/p&gt;

&lt;p&gt;
中文的话可以用 Google 开放的: &lt;a href=&quot;https://storage.googleapis.com/bert_models/2018_11_03/chinese_L-12_H-768_A-12.zip&quot;&gt;https://storage.googleapis.com/bert_models/2018_11_03/chinese_L-12_H-768_A-12.zip&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
中文模型下载后解压得到 chinese_L-12_H-768_A-12 这个目录
&lt;/p&gt;

&lt;p&gt;
然后创建基于 BERT 的分类器
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; kashgari.embeddings &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; BERTEmbedding
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; kashgari.tasks.classification.models &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; CNN_Model

&lt;span style=&quot;color: #ffcc66;&quot;&gt;embedding&lt;/span&gt; = BERTEmbedding(&lt;span style=&quot;color: #66cccc;&quot;&gt;'chinese_L-12_H-768_A-12/'&lt;/span&gt;, task=kashgari.CLASSIFICATION)
&lt;span style=&quot;color: #ffcc66;&quot;&gt;model&lt;/span&gt; = CNN_Model(embedding)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
之后的训练、评估、预测，都和非 BERT 的模型一样。
&lt;/p&gt;

&lt;p&gt;
默认情况下 BERTEmbedding 被设置为不可训练，如果需要对 BERT 进行 finetuning 的话，那么按如下设置：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;embedding&lt;/span&gt; = BERTEmbedding(&lt;span style=&quot;color: #66cccc;&quot;&gt;'chinese_L-12_H-768_A-12/'&lt;/span&gt;, task=kashgari.CLASSIFICATION, trainable=&lt;span style=&quot;color: #6699cc;&quot;&gt;True&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd485d3f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd485d3f&quot;&gt;使用 AllenNLP 进行文本分类&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd485d3f&quot;&gt;
&lt;p&gt;
安装: &lt;code&gt;pip install allennlp&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;
文档: &lt;a href=&quot;https://allennlp.org/tutorials&quot;&gt;https://allennlp.org/tutorials&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3cb8159&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org3cb8159&quot;&gt;进行常规的文本分类&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org3cb8159&quot;&gt;
&lt;p&gt;
AllenNLP 完全通过配置文件来对数据处理、模型结果和训练过程进行设置，最简单的情况下可以一行代码不写就把一个文本分类模型训练出来。下面是一个配置文件示例：
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-js&quot;&gt;{
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;dataset_reader&quot;&lt;/span&gt;: {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;text_classification_json&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;tokenizer&quot;&lt;/span&gt;: {
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;word&quot;&lt;/span&gt;,
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;word_splitter&quot;&lt;/span&gt;: {
                &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;jieba&quot;&lt;/span&gt;,
            }
        }
    },
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;train_data_path&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;allen.data.train&quot;&lt;/span&gt;,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;test_data_path&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;allen.data.test&quot;&lt;/span&gt;,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;evaluate_on_test&quot;&lt;/span&gt;: &lt;span style=&quot;color: #6699cc;&quot;&gt;true&lt;/span&gt;,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;model&quot;&lt;/span&gt;: {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;basic_classifier&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;text_field_embedder&quot;&lt;/span&gt;: {
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;tokens&quot;&lt;/span&gt;: {
                &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;embedding&quot;&lt;/span&gt;,
                &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;embedding_dim&quot;&lt;/span&gt;: 100,
                &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;trainable&quot;&lt;/span&gt;: &lt;span style=&quot;color: #6699cc;&quot;&gt;true&lt;/span&gt;
            }
        },
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;seq2vec_encoder&quot;&lt;/span&gt;: {
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;cnn&quot;&lt;/span&gt;,
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;embedding_dim&quot;&lt;/span&gt;: 100,
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;num_filters&quot;&lt;/span&gt;: 1,
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;ngram_filter_sizes&quot;&lt;/span&gt;: [2, 3, 4]
        }
    },
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;iterator&quot;&lt;/span&gt;: {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;bucket&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;sorting_keys&quot;&lt;/span&gt;: [[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;tokens&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;num_tokens&quot;&lt;/span&gt;]],
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;batch_size&quot;&lt;/span&gt;: 64
    },
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;trainer&quot;&lt;/span&gt;: {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;num_epochs&quot;&lt;/span&gt;: 40,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;patience&quot;&lt;/span&gt;: 3,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;cuda_device&quot;&lt;/span&gt;: -1,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;grad_clipping&quot;&lt;/span&gt;: 5.0,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;validation_metric&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;+accuracy&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;optimizer&quot;&lt;/span&gt;: {
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;adam&quot;&lt;/span&gt;
        }
    }
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
配置文件中的内容可以分成
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;数据部分: 包括 dataset_reader/train_data_path/test_data_path 这几个 key 及其 value&lt;/li&gt;
&lt;li&gt;模型部分: 就是 model 这个 key 的内容&lt;/li&gt;
&lt;li&gt;训练部分: 包括 evaluate_on_test/iterator/trainer 这几个 key 及其 value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
由于本文不是专门介绍 AllenNLP 的文章，所以只对这些配置做简要说明，详细内容可查看文档。
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
数据部分
&lt;/p&gt;

&lt;p&gt;
train_data_path 和 test_data_path 比较好理解，它们指定了训练数据和测试数据的文件路径；而 data_reader 则限定了数据文件的格式。
&lt;/p&gt;

&lt;p&gt;
data_reader 中的配置，会被用来构建一个 &lt;a href=&quot;https://allenai.github.io/allennlp-docs/api/allennlp.data.dataset_readers.dataset_reader.html&quot;&gt;DatasetReader&lt;/a&gt; 的子类的对象，用来读取数据并转换成一个个 &lt;a href=&quot;https://allenai.github.io/allennlp-docs/api/allennlp.data.instance.html&quot;&gt;Instance&lt;/a&gt; 对象。
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
内置的可用来读取分类数据的 DataReader 是 &lt;a href=&quot;https://allenai.github.io/allennlp-docs/api/allennlp.data.dataset_readers.text_classification_json.html&quot;&gt;TextClassificationJsonReader&lt;/a&gt; ，所以配置中有
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
&quot;type&quot;: &quot;text_classification_json&quot;
&lt;/pre&gt;

&lt;p&gt;
这个 type 的值是 TextClassificationJsonReader 这个类实现的时候注册上的，去看代码会看到有这样的片段
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;@DatasetReader.register&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;text_classification_json&quot;&lt;/span&gt;)
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #6699cc;&quot;&gt;TextClassificationJsonReader&lt;/span&gt;(DatasetReader):
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这个 TextClassificationJsonReader 要求的数据文件是一行一个 json 数据，如下：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
{&quot;label&quot;: &quot;education&quot;, &quot;text&quot;: &quot;名师指导托福语法技巧：名词的复数形式&quot;}
{&quot;label&quot;: &quot;education&quot;, &quot;text&quot;: &quot;中国高考成绩海外认可是“狼来了”吗？&quot;}
{&quot;label&quot;: &quot;sports, &quot;text&quot;: &quot;图文：法网孟菲尔斯苦战进16强孟菲尔斯怒吼&quot;}
{&quot;label&quot;: &quot;sports, &quot;text&quot;: &quot;四川丹棱举行全国长距登山挑战赛近万人参与&quot;}
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
DataReader 通过配置中 tokenizer 部分会创建一个分词器，用来将文本转换为词序列
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
&quot;tokenizer&quot;: {
    &quot;type&quot;: &quot;word&quot;,
    &quot;word_splitter&quot;: {
        &quot;type&quot;: &quot;jieba&quot;,
    }
}
&lt;/pre&gt;

&lt;p&gt;
type 的值设置为 word，这没什么好说的。
&lt;/p&gt;

&lt;p&gt;
tokenizer 中的 word_splitter 指定的才是真正的分词器（比较绕）。
&lt;/p&gt;

&lt;p&gt;
如果是英文的数据，那么 word_splitter 的配置可以不写，默认就是支持英文分词的。
&lt;/p&gt;

&lt;p&gt;
但如果是用于中文处理的话，有一个 SpacyWordSplitter 可以用于中文分类，但是现有的&lt;a href=&quot;https://github.com/howl-anderson/Chinese_models_for_SpaCy&quot;&gt;中文 spaCy 模型&lt;/a&gt;仅支持 spaCy 2.0.x，和 AllenNLP 中 spaCy 要求的版本不兼容，这个是比较坑的。
&lt;/p&gt;

&lt;p&gt;
好在 AllenNLP 提供了加载自定义模块的方法，按照如下方法来处理这个问题
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;mkdir allen_ext/
touch allen_ext/__init__.py
touch allen_ext/word_splitter.py
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后在 allen_ext/word_splitter.py 中写入如下内容
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; typing &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; List

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; jieba
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; overrides &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; overrides
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; allennlp.data.tokenizers.token &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; Token
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; allennlp.data.tokenizers.word_splitter &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; WordSplitter


&lt;span style=&quot;color: #6699cc;&quot;&gt;@WordSplitter.register&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;'jieba'&lt;/span&gt;)
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #6699cc;&quot;&gt;JiebaWordSplitter&lt;/span&gt;(WordSplitter):

    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;__init__&lt;/span&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;self&lt;/span&gt;):
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;pass&lt;/span&gt;

    &lt;span style=&quot;color: #6699cc;&quot;&gt;@overrides&lt;/span&gt;
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;split_words&lt;/span&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;self&lt;/span&gt;, sentence: &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;str&lt;/span&gt;) -&amp;gt; List[Token]:
        &lt;span style=&quot;color: #ffcc66;&quot;&gt;offset&lt;/span&gt; = 0
        &lt;span style=&quot;color: #ffcc66;&quot;&gt;tokens&lt;/span&gt; = []
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; word &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; jieba.lcut(sentence):
            &lt;span style=&quot;color: #ffcc66;&quot;&gt;word&lt;/span&gt; = word.strip()
            &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;not&lt;/span&gt; word:
                &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;continue&lt;/span&gt;

            &lt;span style=&quot;color: #ffcc66;&quot;&gt;start&lt;/span&gt; = sentence.find(word, offset)
            tokens.append(Token(word, start))

            &lt;span style=&quot;color: #ffcc66;&quot;&gt;offset&lt;/span&gt; = start + &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;len&lt;/span&gt;(word)

        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; tokens
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
使用 &lt;code&gt;WordSplitter.register('jieba')&lt;/code&gt; 后就可以在配置中 word_splitter 部分写上 &lt;code&gt;&quot;type&quot;: &quot;jieba&quot;&lt;/code&gt; 来启用。
&lt;/p&gt;

&lt;p&gt;
在 allen_ext/__init__.py 中写入如下内容
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; .word_splitter &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; JiebaWordSplitter

&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;__all__&lt;/span&gt; = [&lt;span style=&quot;color: #66cccc;&quot;&gt;'JiebaWordSplitter'&lt;/span&gt;]
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
自定义了 JiebaWordSplitter 后在训练的时候还要加载 allen_ext 这个目录才能生效，这个之后再说。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
模型部分
&lt;/p&gt;

&lt;p&gt;
因为是做文本分类，所以 type 设置为 &lt;a href=&quot;https://allenai.github.io/allennlp-docs/api/allennlp.models.basic_classifier.html&quot;&gt;basic_classifier&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
这个分类器需要 text_field_embedder 和 seq2vec_encoder 两个参数：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
text_field_embedder 用来定义 word embedding，这个配置应该还好理解
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
&quot;text_field_embedder&quot;: {
    &quot;tokens&quot;: {
        &quot;type&quot;: &quot;embedding&quot;,
        &quot;embedding_dim&quot;: 100,
        &quot;trainable&quot;: true
    }
}
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
seq2vec_encoder 则用来产生句子的编码向量用于分类，这里选择了 CNN
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
&quot;seq2vec_encoder&quot;: {
    &quot;type&quot;: &quot;cnn&quot;,
    &quot;embedding_dim&quot;: 100,
    &quot;num_filters&quot;: 1,
    &quot;ngram_filter_sizes&quot;: [2, 3, 4]
}
&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;训练部分：略&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
配置文件写好后，假设配置文件为 config.json，直接执行下面的命令来训练即可
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;allennlp train config.json -s model_save_dir --include-package allen_ext
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
选项 &lt;code&gt;--include-package allen_ext&lt;/code&gt; 用来来加载自定义的模块。
&lt;/p&gt;

&lt;p&gt;
最终会在 save_dir 目录下产生一个 model.tar.gz 文件，就是模型参数，然后目录下还会产生 tensorboard 能读取的 log，这个挺方便的。
&lt;/p&gt;

&lt;p&gt;
评估的话，用 evaluate 命令
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
allennlp evaluate model_save_dir/model.tar.gz test.jsonl --include-package allen_ext
&lt;/pre&gt;

&lt;p&gt;
比较麻烦的是，预测需要一个 Predictor，而 AllenNLP 中内置的 &lt;a href=&quot;https://allenai.github.io/allennlp-docs/api/allennlp.predictors.html#text-classifier&quot;&gt;TextClassifierPredictor&lt;/a&gt; 要求的输入是 &lt;code&gt;{&quot;sentence&quot;: &quot;xxx&quot;}&lt;/code&gt; ，这个和 TextClassificationJsonReader 的要求不一样……
&lt;/p&gt;

&lt;p&gt;
如果是在代码里进行预测，那么是没有问题的，可以这样
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; allen_ext &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; *         &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;noqa&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; allennlp.models.archival &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; load_archive
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; allennlp.predictors.predictor &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; Predictor

&lt;span style=&quot;color: #ffcc66;&quot;&gt;archive&lt;/span&gt; = load_archive(&lt;span style=&quot;color: #66cccc;&quot;&gt;'model_save_dir/model.tar.gz'&lt;/span&gt;)
&lt;span style=&quot;color: #ffcc66;&quot;&gt;predictor&lt;/span&gt; = Predictor.from_archive(archive)

&lt;span style=&quot;color: #ffcc66;&quot;&gt;inputs&lt;/span&gt; = {&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;sentence&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#21517;&amp;#24072;&amp;#25351;&amp;#23548;&amp;#25176;&amp;#31119;&amp;#35821;&amp;#27861;&amp;#25216;&amp;#24039;&amp;#65306;&amp;#21517;&amp;#35789;&amp;#30340;&amp;#22797;&amp;#25968;&amp;#24418;&amp;#24335;&quot;&lt;/span&gt;}
&lt;span style=&quot;color: #ffcc66;&quot;&gt;result&lt;/span&gt; = predictor.predict_json(inputs)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
得到的 result 是这样的结构
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;{
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'label'&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;'education'&lt;/span&gt;,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'logits'&lt;/span&gt;: [
        15.88630199432373,
        0.7209644317626953,
        7.292031764984131,
        5.195938587188721,
        5.073373317718506,
        -35.6490478515625,
        -7.7982988357543945,
        -35.44648742675781,
        -18.14293098449707,
        -14.513381004333496
    ],
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'probs'&lt;/span&gt;: [
        0.999771773815155,
        2.592259420453047e-07,
        0.0001851213601185009,
        2.2758060367777944e-05,
        2.013285666180309e-05,
        4.153195524896307e-23,
        5.1737975015342386e-11,
        5.085729773519049e-23,
        1.6641527142180782e-15,
        6.273159211056881e-14
    ],
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这个输出结构完全是由 TextClassifierPredictor 决定的。
&lt;/p&gt;

&lt;p&gt;
如果要自定义 Predictor，可以参考&lt;a href=&quot;https://github.com/allenai/allennlp/blob/master/tutorials/getting_started/predicting_paper_venues/predicting_paper_venues_pt2.md#creating-a-predictor&quot;&gt;文档&lt;/a&gt;。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgcdca18c&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;orgcdca18c&quot;&gt;基于 BERT 进行文本分类&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-orgcdca18c&quot;&gt;
&lt;p&gt;
AllenNLP 是基于 pytorch 实现的，所以 Google 提供的 BERT 模型在它这里没法用，需要下载它自己提供的模型，以中文模型为例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;mkdir chinese_bert_torch &amp;amp;&amp;amp; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;cd&lt;/span&gt; chinese_bert_torch
wget https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-chinese-pytorch_model.bin -O pytorch_model.bin
wget https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-chinese-config.json -O config.json
wget https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-chinese-vocab.txt -O vocab.txt
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后 config.json 中 data_reader 部分这样写
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-js&quot;&gt;{
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;dataset_reader&quot;&lt;/span&gt;: {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;text_classification_json&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;tokenizer&quot;&lt;/span&gt;: {
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;word&quot;&lt;/span&gt;,
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;word_splitter&quot;&lt;/span&gt;: {
                &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;bert-basic&quot;&lt;/span&gt;,
            }
        },
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;token_indexers&quot;&lt;/span&gt;: {
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;bert&quot;&lt;/span&gt;: {
                &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;bert-pretrained&quot;&lt;/span&gt;,
                &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;pretrained_model&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;./chinese_bert_torch/vocab.txt&quot;&lt;/span&gt;
            }
        }
    }
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
model 部分这么写
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-js&quot;&gt;{
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;model&quot;&lt;/span&gt;: {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;bert_for_classification&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;bert_model&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;./chinese_bert_torch&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;trainable&quot;&lt;/span&gt;: &lt;span style=&quot;color: #6699cc;&quot;&gt;false&lt;/span&gt;
    }
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这里 trainable 设置成 false 的话 BERT 就只是充当一个 encoder，不参与训练；如果要进行 finetuning 的话将其改为 true。
&lt;/p&gt;

&lt;p&gt;
完整的配置是这个样子的
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-js&quot;&gt;{
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;dataset_reader&quot;&lt;/span&gt;: {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;text_classification_json&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;tokenizer&quot;&lt;/span&gt;: {
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;word&quot;&lt;/span&gt;,
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;word_splitter&quot;&lt;/span&gt;: {
                &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;bert-basic&quot;&lt;/span&gt;,
            }
        },
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;token_indexers&quot;&lt;/span&gt;: {
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;bert&quot;&lt;/span&gt;: {
                &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;bert-pretrained&quot;&lt;/span&gt;,
                &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;pretrained_model&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;./chinese_bert_torch/vocab.txt&quot;&lt;/span&gt;
            }
        }
    },
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;train_data_path&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;allen.data.train&quot;&lt;/span&gt;,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;test_data_path&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;allen.data.test&quot;&lt;/span&gt;,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;evaluate_on_test&quot;&lt;/span&gt;: &lt;span style=&quot;color: #6699cc;&quot;&gt;true&lt;/span&gt;,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;model&quot;&lt;/span&gt;: {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;bert_for_classification&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;bert_model&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;./chinese_bert_torch&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;trainable&quot;&lt;/span&gt;: &lt;span style=&quot;color: #6699cc;&quot;&gt;false&lt;/span&gt;
    },
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;iterator&quot;&lt;/span&gt;: {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;bucket&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;sorting_keys&quot;&lt;/span&gt;: [[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;tokens&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;num_tokens&quot;&lt;/span&gt;]],
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;batch_size&quot;&lt;/span&gt;: 64
    },
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;trainer&quot;&lt;/span&gt;: {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;num_epochs&quot;&lt;/span&gt;: 5,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;patience&quot;&lt;/span&gt;: 3,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;cuda_device&quot;&lt;/span&gt;: -1,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;grad_clipping&quot;&lt;/span&gt;: 5.0,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;validation_metric&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;+accuracy&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;optimizer&quot;&lt;/span&gt;: {
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;adam&quot;&lt;/span&gt;
        }
    }
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
训练、评估、预测等操作同未使用 BERT 的时候一样。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>论文笔记：Reading Wikipedia to Answer Open-Domain Questions</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2019/08/07/drqa.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2019/08/07/drqa</id>
    <published>2019-08-07T00:00:00+00:00</published>
    <updated>2019-08-07T00:00:00+00:00</updated>
    <description>
    
      <p>Facebook 的 DrQA 项目的原理解析</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgf5bed87&quot;&gt;作者&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgbb16979&quot;&gt;相关工作&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3021a2d&quot;&gt;术语&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3a394f4&quot;&gt;观点&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org410bb4c&quot;&gt;数据集&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org585ed46&quot;&gt;模型和方法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgead4cd1&quot;&gt;实验和结论&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgfc9de11&quot;&gt;个人总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;



&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/drqa.png&quot; alt=&quot;drqa.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这篇论文实现了一个基于维基百科的开放域问答系统，其实可以归类到机器阅读理解里面。相应的，这篇论文有配套的开源代码（见 &lt;a href=&quot;https://github.com/facebookresearch/DrQA&quot;&gt;facebookresearch/DrQA&lt;/a&gt;），这个系统的工程部分还是蛮实在的。
&lt;/p&gt;

&lt;p&gt;
论文地址：&lt;a href=&quot;https://arxiv.org/abs/1704.00051&quot;&gt;https://arxiv.org/abs/1704.00051&lt;/a&gt;
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgf5bed87&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf5bed87&quot;&gt;作者&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf5bed87&quot;&gt;
&lt;p&gt;
一作是毕业于 Stanford 的&lt;a href=&quot;https://www.cs.princeton.edu/~danqic/&quot;&gt;陈丹琦，目前在 Facebook 人工智能研究院(Facebook AI Research, FAIR) &lt;/a&gt;。陈丹琦在机器阅读理解方面做了不少工作，博士论文《Neural Reading Comprehension and Beyond》我计划之后也读一下。
&lt;/p&gt;

&lt;p&gt;
其他参与者是 FAIR 的几个人：Adam Fisch, Jason Weston, Antoine Bordes。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgbb16979&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgbb16979&quot;&gt;相关工作&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgbb16979&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Ryu et al. 2014: They combine article content with multiple other answe matching modules based on different types of semi-structured knowledge such as infoboxes, arfticle structures, category structure and definitions&lt;/li&gt;
&lt;li&gt;Ahn et al. 2004: combine Wikipedia as a text resource with other resources, in this case with information retrieval over other documents&lt;/li&gt;
&lt;li&gt;Sun et al. 2015, QuASE: full pipeline QA approche&lt;/li&gt;
&lt;li&gt;Microsoft's AskMSR, 2002&lt;/li&gt;
&lt;li&gt;IBM's DeepQA, 2010: DeepQA is a very sophisticated system that relies on both unstructured information including text documents as well as structured data such as KBs, databases and ontologies to generate candidate answers or vote over evidence.&lt;/li&gt;
&lt;li&gt;YodaQA, 2015&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3021a2d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3021a2d&quot;&gt;术语&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3021a2d&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
Open-Domain Question Answering
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
Open-domain QA was originally defined as finding answers in collections of unstructured documents, following the setting of the annual TREC competitions
&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Machine Reading at Scale, MRS
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
In order to answer any question, one must first retrieve the few relevant articles among more than 5 million items, and then scan them carefully to identify the answer. We term this setting, &lt;b&gt;machine reading at scale&lt;/b&gt;.
&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
MurMurHash 算法
&lt;/p&gt;

&lt;p&gt;
我去了解了下，MurMurHash 算法是一种被广泛应用的速度快且碰撞少的哈希算法，sklearn 里的 HashingVectorizer、Redis 中都用到了这个算法。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3a394f4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3a394f4&quot;&gt;观点&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3a394f4&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
Freebase/DBPedia 等知识库对计算机友好，但是过于稀疏，直接用于 open-domain question answering 并不好
&lt;/p&gt;

&lt;p&gt;
标了一个来源: Miller et al., 2016
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;如 IBM DeepQA(Ferrucci et al., 2010) 的大规模 QA 系统，依赖多个不同的数据源之间的信息冗余来提高回答效果，比如说 Wikipedia、知识库、词典、大量的新闻文章、书籍……&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org410bb4c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org410bb4c&quot;&gt;数据集&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org410bb4c&quot;&gt;
&lt;p&gt;
论文中提到的数据集
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://nlp.stanford.edu/software/sempre/&quot;&gt;WebQuestions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://research.fb.com/downloads/babi/&quot;&gt;SimpleQuestions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://people.cs.umass.edu/~miyyer/qblearn/&quot;&gt;QuizBowl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/deepmind/rc-data/&quot;&gt;CNN/Mail Daily&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/google-research-datasets/wiki-reading&quot;&gt;WikiReading&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;WikiAnswers&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://research.fb.com/downloads/babi/&quot;&gt;WikiMovies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/brmson/dataset-factoid-curated/tree/master/trec&quot;&gt;CuratedTREC&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
论文中使用的数据集
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;2016 年 12 月 21 日导出的&lt;a href=&quot;https://dumps.wikimedia.org/enwiki/&quot;&gt;英文维基百科数据&lt;/a&gt;，包含 5075182 篇文章&lt;/li&gt;
&lt;li&gt;SQuAD 数据集，这个是机器阅读理解领域最有名的数据集了&lt;/li&gt;
&lt;li&gt;CuratedTREC 数据集，包含 2180 个问题&lt;/li&gt;
&lt;li&gt;WebQuestions 数据集&lt;/li&gt;
&lt;li&gt;WikiMovies 数据集，包含了 96000 对电影领域的问答数据&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
SQuAD 数据集是标准的阅读理解数据集，每一个样本都包含一个 (Q, A) 对，以及关联的维基百科文章中的段落，但 CuratedTREC、WebQuestions 和 WikiMovies 三个数据集只有单纯的 (Q, A) 对，所以论文中需要为后面这三个数据集补充上关联的文章段落数据才能用于训练。
&lt;/p&gt;

&lt;p&gt;
具体来说，是通过远程监督的手段来为 CuratedTREC/WebQuestions/WikiMovies 三个数据集补充相关的文章段落数据的，过程如下：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;从数据集中选择一个 (Q, A) 对&lt;/li&gt;
&lt;li&gt;用问题文本也就是 Q 作为 query，检索 5 篇维基百科的文章&lt;/li&gt;
&lt;li&gt;将这 5 篇百科文章切分成段落，并按下面的步骤去除无关的内容

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;若段落中不能找到 A，则去除&lt;/li&gt;
&lt;li&gt;去除字数在 25 以下或 1000 以上的段落&lt;/li&gt;
&lt;li&gt;如果 Q 中有命名实体（如人名、地名等），而某个段落中没有这个命名实体，则去除这个段落&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;如果没有剩余可用段落，那么丢弃这个样本，如果有则进行排序：取段落中匹配到 A 的位置，以其为中心取一个 20 个词的窗口，计算其与 Q 的重叠程度（我理解是 LCS 之类的），选择最匹配的 5 个段落&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org585ed46&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org585ed46&quot;&gt;模型和方法&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org585ed46&quot;&gt;
&lt;p&gt;
模型分为两大块，首先有一个 Document Retriever，对给定的问题 question，从所有维基百科文章中检索；检索到文章后切分成段落，然后用一个称之为 Document Reader 的模块在段落中预测答案位置并给出分数。后者其实就是标准的阅读理解模型了，完全可以替换成其他的机器阅读理解模型。
&lt;/p&gt;

&lt;p&gt;
总体上来说这个模型不复杂，或者说非常的简单直观……所以我就不在这里写那些模型的计算式了，需要的话可以自行查阅论文。
&lt;/p&gt;

&lt;p&gt;
Document Retriever 部分，我去阅读了对应开源项目的代码，有两种方法
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
&lt;a href=&quot;https://github.com/facebookresearch/DrQA/blob/master/drqa/retriever/tfidf_doc_ranker.py#L23&quot;&gt;TfidfDocRanker&lt;/a&gt;: 将 question 用 TFIDF+BOW 编码成向量，然后和文档的向量表示做內积进行排序
&lt;/p&gt;

&lt;p&gt;
看代码的话是直接和所有文档的向量组成的矩阵相乘的，维基百科的所有文章数量是很多的，我只能说像我这种穷惯了的人没法想象吧……
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href=&quot;https://github.com/facebookresearch/DrQA/blob/master/drqa/retriever/elastic_doc_ranker.py#L23&quot;&gt;ElasticDocRanker&lt;/a&gt;: 这个直接就是把所有维基百科的文章存到 ES 上，然后用 ES 的 search 接口进行检索，用检索结果里 _score 来排序&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
可以看到，所谓的 DocumentRetriever 的部分真的是超简单的……
&lt;/p&gt;

&lt;p&gt;
DocumentReader 是一个标准的机器阅读理解模型了，输入一个段落和一个 Q，从段落中预测一个 start 位置和一个 end 位置，取两个位置中间的文本作为答案输出。其中 start 和 end 的计算都是一样的，用 question 的向量表示和段落的向量表示做 attention 得到每个位置的 score。对任意一个 (start, end) 区间，取两者 score 的乘积作为这个区间的 score 并用之来排序，要求区间长度不超过 15。
&lt;/p&gt;

&lt;p&gt;
由于使用的数据有一部分是靠远程监督产生出来的，必然会存在噪音，所以这篇论文在训练阶段做了一些特殊处理，具体来说做了两个尝试：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;用 SQuAD 数据先训练出一个模型，然后在远程监督的数据上进行 finetuning&lt;/li&gt;
&lt;li&gt;或者，SQuAD 数据和远程监督数据一起作为训练数据，进行多任务学习，也就是分开训练，但是共享部分参数&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgead4cd1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgead4cd1&quot;&gt;实验和结论&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgead4cd1&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
单独在 SQuAD 上做训练，本文的 Document Reader 模型，在 dev 集上效果要好于 R-net 等一干模型，在 test 集上基本与 R-net 持平而好于剩下的模型，如下表所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/drqa_eval.png&quot; alt=&quot;drqa_eval.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
注: 这个表的结果是指不做文档检索、已经给定文章段落时预测答案的模型效果，而下文那个表则是包含文档检索、答案预测的整体效果。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
加远程监督数据，无论是 finetunning 还是多任务学习，效果都有显著提升，如下表所示
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/drqa_eval2.png&quot; alt=&quot;drqa_eval2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
虽然说在 WikiMovies 数据集上有多达 12 个百分点的提升，不过 top1 的精度最好也就 30% 多……
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgfc9de11&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgfc9de11&quot;&gt;个人总结&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgfc9de11&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;这是一篇工程向的论文，在模型结构上并没有什么亮点&lt;/li&gt;
&lt;li&gt;远程监督制造大量带噪声的数据，然后以多任务学习或者 finetuning 的形式参与模型训练，这个其实是蛮有用的一个经验，我个人也在多个领域看到不少这种做法，对于深度学习这种对数据太过贪婪的方法，这也是被逼出来的方法吧&lt;/li&gt;
&lt;li&gt;DocumentRetriever 部分做得太简单了，我认为这是最终系统整体效果才 30% 多的一个较大原因，顺便吐槽一下，加个 ES 检索就说自己是「Machine Reading at Scale」了……&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>搬家记</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2019/06/09/move-house.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2019/06/09/move-house</id>
    <published>2019-06-09T00:00:00+00:00</published>
    <updated>2019-06-09T00:00:00+00:00</updated>
    <description>
    
      <p>来北京后第三次搬家，时隔四年，再度独居。</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
经过一周的奔走，看了十来个房子，最终我在 2019 年儿童节这天选定了一个并迅速和房东签好了合同，然后马不停蹄地打包东西，在次日搬入了新居，正式回归了独居生活。从 2015 年 3 月初起，我已经和朋友一起合租了 4.25 年，可以说室友是除家人外共同居住时间最长的人了。6 月 3 日，搬家后第一个工作日，在下班回去的公交车上，有一瞬间感觉特别的孤单，但其实，我刚来北京的时候就是独自居住的。
&lt;/p&gt;

&lt;p&gt;
刚来北京的时候，住在昌平沙河，一个城中村的区域，700 一个月的大开间，每月去二楼给房东交钱，房东收完钱后手写一张收据，这收据我现在还留着一张，不过也就一张了。同学 ZS 和我住在同一栋楼，数次 12 点才回来叫我下去帮他开门，有一次干脆连房门钥匙都忘了就在我那对付了一晚上。城中村里混乱而充满着活力，生活该有的东西一应俱全，包括但不限于：各种卖食物的小摊（记得西瓜很便宜）、大的小的服装店、杂货店百货店、各种风格的小饭馆、5 元一位的小三轮、象棋残局骗子、街边吆喝的房地产中介、深夜街头的吵架、挨家挨户寻找离家出走猫咪的姑娘……那个时候还没学会做饭，除了几个同学也不认识什么人，我又不是那种混得了酒吧趴踢的人，生活了无情趣，下班回到窝里，能做的事情只有打炉石、啃至今没啃完的机器学习英文原版书，没钱但是简单而无畏地快乐着。
&lt;/p&gt;

&lt;p&gt;
15 年初，跳槽工资 double 后，老板找我谈，先给了一胡萝卜，说给我开不了那么多工资能不能涨点工资然后给点期权，我哪懂什么期权就拒绝了；末了给了我一大棒，说我负责的工作还有很多问题希望我有点责任心云云。我很愧疚，然后回头就去办了离职手续。此时恰好另外一位同学 L 跳槽到华为，一合计就决定一起（包括同学 ZS）找一个房子合租。运气很好的是，L 在华为内部论坛看到一位前华为员工发帖，说自己房子想出租找一个华为员工，迅速约好去看，看完后我们在去地铁的路上，听到一个擦肩而过双肩包青年在给中介打电话，要去我们刚看过的小区，如临大敌，马上联系中介交了 1000 订金把事情定了下来。然后就是第一次搬家，印象很深刻，因为我和 ZS 一起叫了一个金杯车拉东西过去，然后我拎了几个装了我和 ZS 一些零碎东西的包坐地铁过去，结果 ZS 往包里塞了菜刀没有告诉我，在地铁被安检发现并没收，还让我签字留念了。
&lt;/p&gt;

&lt;p&gt;
第二个住处是在一个正经的小区内，往西走两百米是一个购物中心，往东走一百米是一个果蔬店，南边紧挨着北京体育大学，可以说是很舒服的。我在这里学会了做饭（厨艺一般），把至今没有啃完的英文原版书又多啃了三五章，后来还买了一自行车骑车上班 —— 刚开始在北京没有自行车道的大马路上穿行的时候我慌得不行。周末无聊就骑车在上地一片转，工作日这里大堆公司都灯火通明，但到周末就静悄悄的，能见到一群老大爷下象棋 —— 就是那种两个正主磨磨叽叽边上大爷摇着扇子说“您看他这車一过来你就……”的状况，偶尔也有一些路人，但大部分时候就是我在路口旋转跳跃都不会有人管的样子。由于客厅够大，这次租的房子，成了北京这波大学同学常用的聚会地点，多的时候来过四五个同学加上我们住那的就七八个人，我和 L 就各做几个菜来招待大伙，通常是 L 的更受好评一些哈哈。
&lt;/p&gt;

&lt;p&gt;
好景不长，两年后，我被告知，原来我们住的房子是廉租房，其实是租给我们的“房东”的。按照规定，我们的“房东”在租用廉租房若干年后是能够直接购买的，但在这之前不能将这房子拿来盈利（比如说转租），所以租给我们其实是不合规矩的，只不过“房东”和原来居委会关系好所以居委会睁一只眼闭一只没管，但两年后也就是 2017 年居委会管事的换人了，这事就藏不住了。总之这是一个双输的事情，“房东”丢失了未来可能的买房机会，我们则失去了便宜的住房。
&lt;/p&gt;

&lt;p&gt;
于是第二次去看房子，还决定和 L 合租，而 ZS 因为工作原因已经提前搬出去，到了望京附近。L 忙前忙后约好中介，我们一晚上看了中科院家属楼、海淀路某小区一间房和圆明园地铁站附近一小区：中科院家属楼看起来像是那种有人住了十来年刚搬出去的样子，破旧异常；海淀路小区在四环边上，正对着北大南门，地理位置可以说非常好了，然而天花板残破脱落，我们看的时候簌簌地往下掉粉，屋里一大哥成堆印着 NVIDIA LOGO 的袋子让我一度以为这大哥是 NVIDIA 员工，回头才明白可能是电脑城卖显卡的；圆明园地铁站附近那个小区虽然是个老房子，但是装修贼好（相对前两个而言），我和 L 刚进门，相视无言，心里想得大概都一样，“就是它了！”。然而之后中介告诉我们我们之前已经有人看过了准备签，无奈只好又去清河（小米总部所在地）附近看，结果正在看一个装修正点南北通透的房子时，中介又打电话过来，说圆明园那小区，租客太小器惹毛了房东于是谈崩了。于是我们最终住进了圆明园地铁站附近那个小区。这次搬家呢，在出发地从三楼把东西搬下去，然后在目的地把东西搬到六楼，都没有电梯，委实是辛苦了搬家师傅。
&lt;/p&gt;

&lt;p&gt;
在这地方一住又是两年。从五环外搬到五环内，离市中心更近了，但生活并没有变方便太多，某些方面甚至更加不方便了。由于是在景区（圆明园）附近，周围没有近距离的商超，最近的菜市场也要坐两站公交，小区背后的博雅酒店半夜三四点大卡车卸货还是什么经常吵得我睡不好。我放弃了啃英文原版书，开始买书如山倒干脆不看书，也放弃了在厨房中探索我对豆腐的爱，转而给 L 洗碗刷锅来免费蹭饭，并这样持续到今年的儿童节。这两年零三个月发生了很多事情：我第一次出差并在之后变本加厉地出差，买了 Nintendo Switch 并浪费了我人生五六百个小时在上面，由于工作开始跟投长赢计划并开始接触投资知识……
&lt;/p&gt;

&lt;p&gt;
合租的好处是不那么孤单，但 L 有女朋友（后来领证了）没什么孤单可言，孤单其实都是我的。感到孤单也没什么可耻的，我一向如此 —— 当然，也没什么可自豪的。哪怕是合租的四年里，那种陡然间觉得一切毫无意义的时刻也不在少数，这吊诡的世道在人心里造成的空洞，钻进人群中时只是被掩盖起来，是无法彻底填满的，擘起火把向前走是唯一的路，我在最绝望的时候已然明白这个道理。我需要面对自己，而不是靠人群、加班来假装自己一切都好。
&lt;/p&gt;

&lt;p&gt;
又一次冗长的出差回来，我以超高的效率开始看房，在一周的时间内，生生让一个知春路片区的链家中介陪我走了好几个北京城北部区域，最后敲定五个候选，最优的两个一个被租走一个只租给女生，于是定了综合评分第三的这个，稍微偏远一些，但好在面积大价钱相对更便宜。五月三十一日敲定后，和中介约好六月一日签合同，隔天早上起来我就开始打包东西，六七箱书、两箱衣服、电器杂物若干，如此而已。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/packages.jpg&quot; alt=&quot;packages.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
搬后第一周的工作日里，箱子堆在屋子里没精力去整理。趁着这次端午加周末的三天时间，彻底收拾好了所有东西，重新调整屋内家居布局，做好各个角落的清扫，然后购置好各种厨房用具，到附近的菜市场疯狂扫购（了几个西红柿和鸡蛋）填满了冰箱，喝上第一碗前一晚预约煮好的小米粥时，觉得自己真是个家政小能手！前一个租客如果上门拜访，一定会把肠子都悔青了然后决定不再出国留学的，嗯。话说，你永远不知道清理上一任租客的遗留物品时会遇到什么惊喜……
&lt;/p&gt;

&lt;p&gt;
附豪宅照片。
&lt;/p&gt;

&lt;p&gt;
看到这光可鉴人的地板了吗？原来可脏了……
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/room1.jpg&quot; alt=&quot;room1.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
两张沙发原来拼在一起把图中空着的区域占满了
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/room2.jpg&quot; alt=&quot;room2.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
冰箱原来在外面，我给搬了进来。图中的桌子拿来办公娱乐用，堆着的书都是计算机、数学类书籍，和科幻小说
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/room3.jpg&quot; alt=&quot;room3.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
休息区和阅读区，配备大功率照明用具 —— 真的，这盏台灯是这屋子里晚上亮度最高的光源……
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/room4.jpg&quot; alt=&quot;room4.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
工作、娱乐区近照（晚上拍的有点黄）
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/desk1.jpg&quot; alt=&quot;desk1.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
阅读区近照
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/desk2.jpg&quot; alt=&quot;desk2.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
也许以后养个猫什么的，嗯哼～
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>图数据库 Neo4j 的部署、数据导入和简单使用</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2019/04/30/neo4j-introduction.html"/>
    <category term="数据库" scheme="http://www.zmonster.me/categories.html#数据库"/>
    <id>http://www.zmonster.me/2019/04/30/neo4j-introduction</id>
    <published>2019-04-30T00:00:00+00:00</published>
    <updated>2019-04-30T00:00:00+00:00</updated>
    <description>
    
      <p>本文介绍了 Neo4j Server 的不同部署方式，并以豆瓣电影图谱数据为例说明了不同的数据导入方式，并简单介绍了 Cypher 查询语言的使用。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgd44bad5&quot;&gt;Neo4j 简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org18b6dfc&quot;&gt;Neo4j 的部署&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org572aeb1&quot;&gt;数据加载&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org02654fb&quot;&gt;使用 neo4j-import 用 csv 数据创建实体和关系&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2889849&quot;&gt;使用 LOAD CSV 加载 csv 数据&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf5b3f23&quot;&gt;使用 Cypher 语句创建数据&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org88f2801&quot;&gt;Cypher 查询语言&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
本文介绍了 Neo4j Server 的不同部署方式，并以豆瓣电影图谱数据为例说明了不同的数据导入方式，并简单介绍了 Cypher 查询语言的使用。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgd44bad5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgd44bad5&quot;&gt;Neo4j 简介&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgd44bad5&quot;&gt;

&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/neo4j.jpg&quot; alt=&quot;neo4j.jpg&quot; width=&quot;400&quot; align=&quot;right&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;p&gt;
Neo4j 是一个流行的、Java 编写的图数据库 —— 所谓图数据库是一种 NoSQL 数据库，相比于 MySQL 之类的关系数据库(RDBMS)，能更灵活地表示数据，这种灵活性体现在多方面：
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;像所有 NoSQL 数据库一样可以灵活地设计、扩展 schema&lt;/li&gt;
&lt;li&gt;更适合表示实体之间的关系，特别是当实体之间存在大量的、复杂的关系的时候&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
图数据库强调实体和关系两个基本概念，虽然说在关系数据库中也可以表示实体和关系，但如果关系的种类繁多且实体之间通过关系构成复杂的结构的时候，用图数据库可能会更合适一些。此外，图数据库会对一些常见的图操作进行支持，典型的比如查询最短路径，如果用关系数据库来做就很比较麻烦。
&lt;/p&gt;

&lt;p&gt;
目前的图数据库有很多种，根据一些&lt;a href=&quot;https://db-engines.com/en/ranking/graph+dbms&quot;&gt;排行数据&lt;/a&gt;，Neo4j 应该是其中最流行、使用最多的了。
&lt;/p&gt;

&lt;p&gt;
Neo4j 由一个商业公司在开发、维护，并提供 GPLv3 协议的开源社区版本，当然相比他们商业授权的闭源版本，开源版本缺少一些特性，但基本功能都是完整的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org18b6dfc&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org18b6dfc&quot;&gt;Neo4j 的部署&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org18b6dfc&quot;&gt;
&lt;p&gt;
最简单的办法是从 Neo4j 的&lt;a href=&quot;https://neo4j.com/download-center/#releases&quot;&gt;下载中心&lt;/a&gt;下载 Neo4j Server，解压后运行即可。可以看到下载页有三个不同的版本
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/neo4j_downloads.png&quot; alt=&quot;neo4j_downloads.png&quot; width=&quot;600&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Enterprise Server: 企业版，需要付费获得授权，提供高可用、热备份等特性&lt;/li&gt;
&lt;li&gt;Community Server: 社区开源版，只能单点运行，在性能上较企业版可能差一些&lt;/li&gt;
&lt;li&gt;Neo4j Desktop: 顾名思义，是一个桌面版的客户端，可以用其连接 Neo4j Server 进行操作、管理，不过其中也内置了一个本地的 Neo4j Server，用户可以直接通过 Neo4j Desktop 来创建数据库并启动&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
对于仅仅想了解一下 Neo4j 的人来说，不妨下载 Neo4j Desktop 体验一下，本文则仅讨论 Neo4j Community Server。
&lt;/p&gt;

&lt;p&gt;
目前 Neo4j Server 的版本是 3.5.x，虽然更旧的版本也能用，但建议使用 3.5.0 之后的版本，因为更早的版本是不支持全文索引的。
&lt;/p&gt;

&lt;p&gt;
以 Linux 为例，假如下载的是最新的 3.5.5 版本，那么解压运行即可
&lt;/p&gt;

&lt;p&gt;
我的做法是解压放到 /opt 目录下，并把对应的目录加到环境变量 PATH 里
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;tar xzvf neo4j-community-3.5.5-unix.tar.gz
mv neo4j-community-3.5.5 /opt/neo4j/
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;PATH&lt;/span&gt;=$&lt;span style=&quot;color: #ffcc66;&quot;&gt;PATH&lt;/span&gt;:/opt/neo4j/bin
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这样之后就能使用 &lt;code class=&quot;src src-sh&quot;&gt;neo4j start&lt;/code&gt; 来启动服务了。
&lt;/p&gt;

&lt;p&gt;
另外一种办法是通过 docker 来启动服务，这个就更简单了，直接利用官方提供的镜像即可。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;docker pull neo4j:3.5.5
mkdir $&lt;span style=&quot;color: #ffcc66;&quot;&gt;HOME&lt;/span&gt;/neo4j/data -p
docker run -p 7474:7474 -p 7687:7687 -v $&lt;span style=&quot;color: #ffcc66;&quot;&gt;HOME&lt;/span&gt;/neo4j/data/:/data neo4j
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这之后就可以通过 &lt;a href=&quot;http://localhost:7474/browser/&quot;&gt;http://localhost:7474/browser/&lt;/a&gt; 这个地址访问 Neo4j Server 的 WebUI，可以在上面查询、修改数据。
&lt;/p&gt;

&lt;p&gt;
然后有一些 Server 设置，可以根据自己的情况适当地进行修改，完整的配置见&lt;a href=&quot;https://neo4j.com/docs/operations-manual/current/configuration/&quot;&gt;文档&lt;/a&gt;，这里罗列一些个人认为重要的
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
认证方式设置
&lt;/p&gt;

&lt;p&gt;
默认情况下启动的 neo4j，会要求在访问时通过用户名密码进行认证，初始的用户名密码为 &lt;b&gt;neo4j/neo4j&lt;/b&gt; ，但是会在第一次认证之后要求更换密码，有点不太方便。
&lt;/p&gt;

&lt;p&gt;
一个办法是彻底关闭用户名密码认证，如果是非 docker 模式部署的，直接改 /opt/neo4j/conf/neo4j.conf 这个文件，加上这行配置
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-conf&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;dbms.security.auth_enabled&lt;/span&gt;=false
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
如果是 docker 模式部署的，则在启动容器时，设置环境变量 &lt;code&gt;NEO4J_AUTH&lt;/code&gt; 为 none
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;docker run -p 7474:7474 &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -p 7687:7687 &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -v $&lt;span style=&quot;color: #ffcc66;&quot;&gt;HOME&lt;/span&gt;/neo4j/data/:/data &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -e &lt;span style=&quot;color: #ffcc66;&quot;&gt;NEO4J_AUTH&lt;/span&gt;=none &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       neo4j
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
另外一个办法是主动设置好密码，如果是非 docker 模式部署，需要在初次启动通过 &lt;code&gt;neo4j-admin&lt;/code&gt; 这个命令来设置
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;neo4j-admin set-initial-password neo4j_password
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
如果是 docker 模式部署，则在启动容器时通过环境变量 &lt;code&gt;NEO4J_AUTH&lt;/code&gt; 来设置
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;docker run -p 7474:7474 &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -p 7687:7687 &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -v $&lt;span style=&quot;color: #ffcc66;&quot;&gt;HOME&lt;/span&gt;/neo4j/data/:/data &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -e &lt;span style=&quot;color: #ffcc66;&quot;&gt;NEO4J_AUTH&lt;/span&gt;=neo4j/neo4j_password &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       neo4j
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
内存设置
&lt;/p&gt;

&lt;p&gt;
这块有三项设置，分别是
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;dbms.memory.heap.initial_size&lt;/li&gt;
&lt;li&gt;dbms.memory.heap.max_size&lt;/li&gt;
&lt;li&gt;dbms.memory.pagecache.size&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
前两者决定了查询语言运行时候可用的内存，第三个则用于缓存数据和索引以提高查询效率。
&lt;/p&gt;

&lt;p&gt;
非 docker 模式部署的，可以直接在 /opt/neo4j/conf/neo4j.conf 里修改，比如说这样
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-conf&quot;&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;dbms.memory.heap.initial_size&lt;/span&gt;=1G
&lt;span style=&quot;color: #ffcc66;&quot;&gt;dbms.memory.heap.max_size&lt;/span&gt;=2G
&lt;span style=&quot;color: #ffcc66;&quot;&gt;dbms.memory.pagecache.size&lt;/span&gt;=4G
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
docker 模式部署则还是在启动容器时通过环境变量来设置，如下所示
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;docker run -p 7474:7474 &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -p 7687:7687 &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -v $&lt;span style=&quot;color: #ffcc66;&quot;&gt;HOME&lt;/span&gt;/neo4j/data/:/data &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -e &lt;span style=&quot;color: #ffcc66;&quot;&gt;NEO4j_dbms_memory_heap_initial__size&lt;/span&gt;=1G &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -e &lt;span style=&quot;color: #ffcc66;&quot;&gt;NEO4j_dbms_memory_heap_max__size&lt;/span&gt;=2G &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -e &lt;span style=&quot;color: #ffcc66;&quot;&gt;NEO4j_dbms_memory_pagecache_size&lt;/span&gt;=4G &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       neo4j
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;其他

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
dbms.security.allow_csv_import_from_file_urls
&lt;/p&gt;

&lt;p&gt;
设置为 true，这样在执行 &lt;code&gt;LOAD CSV&lt;/code&gt; 语句时，可以使用远程而非本地的 csv 文件。
&lt;/p&gt;

&lt;p&gt;
docker 的话这样：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;docker run -d -p 7474:7474 &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -p 7687:7687 &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -e &lt;span style=&quot;color: #ffcc66;&quot;&gt;NEO4J_dbms_security_allow__csv__import__from__file__urls&lt;/span&gt;=true &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -v /home/emonster/data/neo4j/:/data &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       neo4j
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这个之后会具体再聊一下。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
dbms.connectors.default_listen_address
&lt;/p&gt;

&lt;p&gt;
这个不设置的话，部署起来的 server 就只能监听本地的请求，如果是在生产中用 Neo4j Server 的话，要设置成
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;dbms.connectors.default_listen_address=0.0.0.0
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
docker 的话默认已经设置好了，不用自己再单独设置。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
所有的配置项及其值可以用如下查询语言查询
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #d9d9d9;&quot;&gt;call&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;dbms&lt;/span&gt;.&lt;span style=&quot;color: #d9d9d9;&quot;&gt;listConfig&lt;/span&gt;()
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
如果要查询单独某项的值，比如 &quot;dbms.connectors.default_listen_address&quot;，则这样
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #d9d9d9;&quot;&gt;call&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;dbms&lt;/span&gt;.&lt;span style=&quot;color: #d9d9d9;&quot;&gt;listConfig&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;dbms.connectors.default_listen_address&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org572aeb1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org572aeb1&quot;&gt;数据加载&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org572aeb1&quot;&gt;
&lt;p&gt;
为方便说明，我准备了一份豆瓣电影的图谱数据（说是图谱其实结构很简单）放在 Github 上，可以先将其 clone 到本地
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;git clone https://github.com/Linusp/kg-example
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
在这个项目下的 movie 目录里有按照 Neo4j 支持的格式整理好的实体、关系数据
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;(shell) $ cd kg-example
(shell) $ tree movie
movie
&amp;#9500;&amp;#9472;&amp;#9472; actor.csv
&amp;#9500;&amp;#9472;&amp;#9472; composer.csv
&amp;#9500;&amp;#9472;&amp;#9472; Country.csv
&amp;#9500;&amp;#9472;&amp;#9472; director.csv
&amp;#9500;&amp;#9472;&amp;#9472; district.csv
&amp;#9500;&amp;#9472;&amp;#9472; Movie.csv
&amp;#9492;&amp;#9472;&amp;#9472; Person.csv

0 directories, 7 files
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上述数据包含三类实体数据：
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;实体类型&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;数据文件&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;数量&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Movie&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Movie.csv&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4587&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;电影实体&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Person&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Person.csv&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;22937&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;人员实体&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Country&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Country.csv&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;84&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;国家实体&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
此外还包含四类关系数据
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;关系类型&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;主语实体类型&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;宾语实体类型&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;数据文件&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;数量&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;actor&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Movie&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Person&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;actor.csv&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;35257&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;电影的主演&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;composer&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Movie&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Person&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;composer.csv&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;8345&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;电影的编剧&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;director&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Movie&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Person&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;director.csv&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;5015&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;电影的导演&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;district&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Movie&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Country&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;district.csv&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;6227&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;电影的制片国家/地区&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
下图是这份数据加载到 Neo4j 后的部分可视化示例
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/movie_graph.png&quot; alt=&quot;movie_graph.png&quot; width=&quot;800&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org02654fb&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org02654fb&quot;&gt;使用 neo4j-import 用 csv 数据创建实体和关系&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org02654fb&quot;&gt;
&lt;p&gt;
使用 &lt;code&gt;neo4j-import&lt;/code&gt; 命令行工具导入 csv 数据是几种数据加载方式中最快的一种，但它不能导入数据到已有的数据库中，每次执行都是产生一个全新的数据库，因此必须在一条命令里将数据库中要包含的数据全部都制定好。
&lt;/p&gt;

&lt;p&gt;
可以用下面的命令来导入豆瓣电影图谱数据
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;neo4j-import --into graph.db --id-type string &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
             --nodes:Person movie/Person.csv    &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
             --nodes:Movie movie/Movie.csv &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
             --nodes:Country movie/Country.csv &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
             --relationships:actor movie/actor.csv &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
             --relationships:composer movie/composer.csv &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
             --relationships:director movie/director.csv &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
             --relationships:district movie/district.csv
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上述命令会在当前目录下生成一个 graph.db 目录，就是最终产生的一个全新的数据库。要启用这个数据库，必须将其放置到 Neo4j Server 的 data 目录下：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
如果当前 Neo4j Server 正在运行，需要先停掉它
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;neo4j stop
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
删除或备份原有的数据库
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;mv /opt/neo4j/data/databases/graph.db /opt/neo4j/data/databases/graph.db.bak
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
将产生的 graph.db 放置到 server 的 data 目录下
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;cp graph.db /opt/neo4j/data/databases/ -r
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
重新启动 Neo4j Server
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;neo4j start
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
实体和关系一共 8 万多条，在我的个人电脑上一共花费 3s 多
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
IMPORT DONE in 3s 692ms.
Imported:
  27608 nodes
  54844 relationships
  91628 properties
Peak memory usage: 524.24 MB
&lt;/pre&gt;

&lt;p&gt;
如果是以 docker 的方式来使用 Neo4j，则稍有不同，需要在执行的时候将 movie 目录和输出结果所在的目录都挂载到容器里。假设说我们希望最终输出结果到 $HOME/neo4j/data 目录下，那么，先创建这个目录
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;mkdir $&lt;span style=&quot;color: #ffcc66;&quot;&gt;HOME&lt;/span&gt;/neo4j/data/databases -p
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后执行
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;docker run -v $&lt;span style=&quot;color: #ffcc66;&quot;&gt;PWD&lt;/span&gt;/movie:/movie:ro -v $&lt;span style=&quot;color: #ffcc66;&quot;&gt;HOME&lt;/span&gt;/neo4j/data:/data/ &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       neo4j neo4j-import --into /data/databases/graph.db --id-type string &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
             --nodes:Person /movie/Person.csv    &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
             --nodes:Movie /movie/Movie.csv &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
             --nodes:Country /movie/Country.csv &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
             --relationships:actor /movie/actor.csv &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
             --relationships:composer /movie/composer.csv &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
             --relationships:director /movie/director.csv &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
             --relationships:district /movie/district.csv
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后再用 docker 启动 Neo4j Server，并让其使用刚刚产生的数据库
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;docker run -p 7474:7474 &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -p 7687:7687 &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -v $&lt;span style=&quot;color: #ffcc66;&quot;&gt;HOME&lt;/span&gt;/neo4j/data/:/data &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       -e &lt;span style=&quot;color: #ffcc66;&quot;&gt;NEO4J_AUTH&lt;/span&gt;=neo4j/neo4j_password &lt;span style=&quot;color: #66cccc;&quot;&gt;\&lt;/span&gt;
       neo4j
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2889849&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2889849&quot;&gt;使用 LOAD CSV 加载 csv 数据&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2889849&quot;&gt;
&lt;p&gt;
用 &lt;code&gt;LOAD CSV&lt;/code&gt; 语句同样可以加载 csv 数据，不过和 &lt;code&gt;neo4j-import&lt;/code&gt; 不一样，本质上它只是负责从 csv 文件中读取数据，如果要将读取到的数据写入到数据库中，还必须通过 &lt;code&gt;CREATE&lt;/code&gt; 语句。也正因如此，用 &lt;code&gt;LOAD CSV&lt;/code&gt; 语句来加载数据，不需要将 Neo4j Server 停掉。
&lt;/p&gt;

&lt;p&gt;
用 &lt;code&gt;LOAD CSV&lt;/code&gt; 语句将豆瓣电影图谱加载到数据库中的做法是下面这样的
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
从 Movie.csv 中加载电影数据并创建 Movie 实体
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;USING PERIODIC COMMIT&lt;/span&gt; 1000
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;LOAD CSV&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;with&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;headers&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;'https://raw.githubusercontent.com/Linusp/kg-example/master/movie/Movie.csv'&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;as&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;line&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;CREATE&lt;/span&gt; (&lt;span style=&quot;color: #6699cc;&quot;&gt;:Movie&lt;/span&gt; {
       &lt;span style=&quot;color: #d9d9d9;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;id:ID&quot;&lt;/span&gt;],
       &lt;span style=&quot;color: #d9d9d9;&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;title&quot;&lt;/span&gt;],
       &lt;span style=&quot;color: #d9d9d9;&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;url&quot;&lt;/span&gt;],
       &lt;span style=&quot;color: #d9d9d9;&quot;&gt;cover&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;cover&quot;&lt;/span&gt;],
       &lt;span style=&quot;color: #d9d9d9;&quot;&gt;rate&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;rate&quot;&lt;/span&gt;],
       &lt;span style=&quot;color: #ffcc66;&quot;&gt;category:&lt;/span&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;split&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;category:String[]&quot;&lt;/span&gt;], &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;;&quot;&lt;/span&gt;),
       &lt;span style=&quot;color: #ffcc66;&quot;&gt;language:&lt;/span&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;split&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;language:String[]&quot;&lt;/span&gt;], &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;;&quot;&lt;/span&gt;),
       &lt;span style=&quot;color: #d9d9d9;&quot;&gt;showtime&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;showtime&quot;&lt;/span&gt;],
       &lt;span style=&quot;color: #d9d9d9;&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;length&quot;&lt;/span&gt;],
       &lt;span style=&quot;color: #ffcc66;&quot;&gt;othername:&lt;/span&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;split&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;othername:String[]&quot;&lt;/span&gt;], &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;;&quot;&lt;/span&gt;)
       })
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
其中 &quot;using periodic commit 1000&quot; 表示每读取 1000 行数据就写入一次。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
从 Person.csv 中加载人员数据并创建 Person 实体
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;USING PERIODIC COMMIT&lt;/span&gt; 1000
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;LOAD CSV&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;with&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;headers&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;'https://raw.githubusercontent.com/Linusp/kg-example/master/movie/Person.csv'&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;as&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;line&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;CREATE&lt;/span&gt; (&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt; {&lt;span style=&quot;color: #d9d9d9;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;id:ID&quot;&lt;/span&gt;], &lt;span style=&quot;color: #d9d9d9;&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;name&quot;&lt;/span&gt;]})
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
从 Country.csv 中加载国家数据并创建 Country 实体
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;USING PERIODIC COMMIT&lt;/span&gt; 1000
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;LOAD CSV&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;with&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;headers&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;'https://raw.githubusercontent.com/Linusp/kg-example/master/movie/Country.csv'&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;as&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;line&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;CREATE&lt;/span&gt; (&lt;span style=&quot;color: #6699cc;&quot;&gt;:Country&lt;/span&gt; {&lt;span style=&quot;color: #d9d9d9;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;id:ID&quot;&lt;/span&gt;], &lt;span style=&quot;color: #d9d9d9;&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;name&quot;&lt;/span&gt;]})
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
创建关系
&lt;/p&gt;

&lt;p&gt;
每个关系的 csv 文件都是如下格式（以 actor.csv 为例）
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
&quot;:START_ID&quot;,&quot;:END_ID&quot;
&quot;5ec851a8b7b7bbf0c9f42bbee021be00&quot;,&quot;3a20ded16ebce312f56a562e1bef7f05&quot;
&quot;5ec851a8b7b7bbf0c9f42bbee021be00&quot;,&quot;8101549e05e6c1afbea62890117c01c6&quot;
&quot;5ec851a8b7b7bbf0c9f42bbee021be00&quot;,&quot;111a3c7f6b769688da55828f36bbd604&quot;
&quot;5ec851a8b7b7bbf0c9f42bbee021be00&quot;,&quot;5cc5d969f42ce5d8e3937e37d77b89b5&quot;
&quot;5ec851a8b7b7bbf0c9f42bbee021be00&quot;,&quot;a5e6012efc56f0ca07184b9b88eb2373&quot;
&quot;5ec851a8b7b7bbf0c9f42bbee021be00&quot;,&quot;435c8172c14c24d6cd123c529a0c2a76&quot;
&quot;5ec851a8b7b7bbf0c9f42bbee021be00&quot;,&quot;5dfb355a385bcfe9b6056b8d322bfecb&quot;
&quot;5ec851a8b7b7bbf0c9f42bbee021be00&quot;,&quot;5076a2f7479462dcc4637b6fe3226095&quot;
&quot;5ec851a8b7b7bbf0c9f42bbee021be00&quot;,&quot;c7103a9ad17cf56fd572657238e49fff&quot;
&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
在创建关系的时候实际上是根据两个 id 查询到对应的实体，然后再为其建立关系。虽然我在准备这份数据时，已经保证了每个实体的 id 都是全局唯一的，但在没有创建索引的情况下，用这个 id 来查询实体会以遍历的形式进行，效率很差，所以在创建关系前，先创建一下索引。
&lt;/p&gt;

&lt;p&gt;
为 Movie 实体的 id 属性创建索引
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;CREATE&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;INDEX&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;ON&lt;/span&gt; &lt;span style=&quot;color: #6699cc;&quot;&gt;:Movie&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;id&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
为 Person 实体的 id 属性创建索引
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;CREATE&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;INDEX&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;ON&lt;/span&gt; &lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;id&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
为 Country 实体的 id 属性创建索引
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;CREATE&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;INDEX&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;ON&lt;/span&gt; &lt;span style=&quot;color: #6699cc;&quot;&gt;:Country&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;id&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后继续用 &lt;code&gt;LOAD CSV&lt;/code&gt; 来创建关系
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
从 actor.csv 中加载数据并创建 actor 关系
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;USING PERIODIC COMMIT&lt;/span&gt; 1000
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;LOAD CSV&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;with&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;headers&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;'https://raw.githubusercontent.com/Linusp/kg-example/master/movie/actor.csv'&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;as&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;line&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Movie&lt;/span&gt; {&lt;span style=&quot;color: #d9d9d9;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;:START_ID&quot;&lt;/span&gt;]})
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt; {&lt;span style=&quot;color: #d9d9d9;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;:END_ID&quot;&lt;/span&gt;]})
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;CREATE&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;)&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;[&lt;span style=&quot;color: #6699cc;&quot;&gt;:actor&lt;/span&gt;]&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&amp;gt;&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
从 composer.csv 中加载数据创建 composer 关系
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;USING PERIODIC COMMIT&lt;/span&gt; 1000
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;LOAD CSV&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;with&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;headers&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;'https://raw.githubusercontent.com/Linusp/kg-example/master/movie/composer.csv'&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;as&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;line&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Movie&lt;/span&gt; {&lt;span style=&quot;color: #d9d9d9;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;:START_ID&quot;&lt;/span&gt;]})
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt; {&lt;span style=&quot;color: #d9d9d9;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;:END_ID&quot;&lt;/span&gt;]})
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;CREATE&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;)&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;[&lt;span style=&quot;color: #6699cc;&quot;&gt;:composer&lt;/span&gt;]&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&amp;gt;&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
从 director.csv 中加载数据创建 director 关系
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;USING PERIODIC COMMIT&lt;/span&gt; 1000
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;LOAD CSV&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;with&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;headers&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;'https://raw.githubusercontent.com/Linusp/kg-example/master/movie/director.csv'&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;as&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;line&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Movie&lt;/span&gt; {&lt;span style=&quot;color: #d9d9d9;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;:START_ID&quot;&lt;/span&gt;]})
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt; {&lt;span style=&quot;color: #d9d9d9;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;:END_ID&quot;&lt;/span&gt;]})
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;CREATE&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;)&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;[&lt;span style=&quot;color: #6699cc;&quot;&gt;:director&lt;/span&gt;]&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&amp;gt;&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
从 district.csv 中加载数据并创建 district 关系
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;USING PERIODIC COMMIT&lt;/span&gt; 1000
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;LOAD CSV&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;with&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;headers&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;'https://raw.githubusercontent.com/Linusp/kg-example/master/movie/district.csv'&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;as&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;line&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Movie&lt;/span&gt; {&lt;span style=&quot;color: #d9d9d9;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;:START_ID&quot;&lt;/span&gt;]})
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Country&lt;/span&gt; {&lt;span style=&quot;color: #d9d9d9;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:line&lt;/span&gt;[&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;:END_ID&quot;&lt;/span&gt;]})
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;CREATE&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;)&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;[&lt;span style=&quot;color: #6699cc;&quot;&gt;:district&lt;/span&gt;]&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&amp;gt;&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf5b3f23&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf5b3f23&quot;&gt;使用 Cypher 语句创建数据&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgf5b3f23&quot;&gt;
&lt;p&gt;
严格来说，上面的 &lt;code&gt;LOAD CSV&lt;/code&gt; 的方式，也是在用 Cypher 语句，不过说到底它还是要依赖一个外部的 CSV 文件，自由度没那么高。而 Neo4j Server 本身还提供 RESTful API，利用这个 API 就可以进行编程来完成更复杂的需求。
&lt;/p&gt;

&lt;p&gt;
以创建实体为例来说明一下 Neo4j Server 的 RESTful API。假设说我们要创建三个 Person 实体，简单起见，我们假设每个 Person 实体需要有 id, name, age 三个属性，比如
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-js&quot;&gt;[
    {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;id&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;person1&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#24352;&amp;#24535;&amp;#26114;&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;age&quot;&lt;/span&gt;: 23
    },
    {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;id&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;person2&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#21016;&amp;#25991;&amp;#20992;&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;age&quot;&lt;/span&gt;: 18
    },
    {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;id&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;person3&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#23385;&amp;#23376;&amp;#23567;&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;age&quot;&lt;/span&gt;: 22
    }
]
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
通过 RESTful API，可以一次性创建这三个 Person 实体
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-restclient&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;POST&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;http://neo4j:neo4j_password@localhost:7474/db/data/cypher&lt;/span&gt;
&lt;span style=&quot;color: #ffcc66;&quot;&gt;Content-Type&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;application/json&lt;/span&gt;
{
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;query&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;UNWIND {values} as data CREATE (:Person {id: data.id, name: data.name, age: data.age})&quot;&lt;/span&gt;,
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;params&quot;&lt;/span&gt;: {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;values&quot;&lt;/span&gt;: [
            {&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;id&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;person1&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#24352;&amp;#24535;&amp;#26114;&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;age&quot;&lt;/span&gt;: 23},
            {&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;id&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;person2&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#21016;&amp;#25991;&amp;#20992;&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;age&quot;&lt;/span&gt;: 18},
            {&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;id&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;person3&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#23385;&amp;#23376;&amp;#23567;&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;age&quot;&lt;/span&gt;: 22}
        ]
    }
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这种通过带参数的 query 进行批量写入的方式，和 MySQL 等数据库的接口很相似，不过在 Cypher 中可以通过 &lt;code&gt;UNWIND&lt;/code&gt; 语句做一些复杂的事情。详见&lt;a href=&quot;https://neo4j.com/docs/cypher-manual/current/clauses/unwind/&quot;&gt;文档&lt;/a&gt;。
&lt;/p&gt;


&lt;p&gt;
用 Python 来做的话大概是这个样子
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; requests

&lt;span style=&quot;color: #ffcc66;&quot;&gt;url&lt;/span&gt; = &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;http://neo4j:neo4j_password@localhost:7474/db/data/cypher&quot;&lt;/span&gt;
&lt;span style=&quot;color: #ffcc66;&quot;&gt;payload&lt;/span&gt; = {
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;query&quot;&lt;/span&gt;: (
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;UNWIND {values} as data &quot;&lt;/span&gt;
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;CREATE (:Person {id: data.id, name: data.name, age: data.age})&quot;&lt;/span&gt;
    ),
    &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;params&quot;&lt;/span&gt;: {
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;values&quot;&lt;/span&gt;: [
            {&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;id&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;person1&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#24352;&amp;#24535;&amp;#26114;&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;age&quot;&lt;/span&gt;: 23},
            {&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;id&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;person2&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#21016;&amp;#25991;&amp;#20992;&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;age&quot;&lt;/span&gt;: 18},
            {&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;id&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;person3&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#23385;&amp;#23376;&amp;#23567;&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;age&quot;&lt;/span&gt;: 22}
        ]
    }
}
requests.post(url, json=payload)
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;
或者也可以使用 Neo4j 官方的 Python 客户端
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; neo4j

&lt;span style=&quot;color: #ffcc66;&quot;&gt;client&lt;/span&gt; = neo4j.GraphDatabase.driver(
    &lt;span style=&quot;color: #66cccc;&quot;&gt;'bolt://localhost:7687'&lt;/span&gt;, auth=(&lt;span style=&quot;color: #66cccc;&quot;&gt;'neo4j'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'neo4j_password'&lt;/span&gt;)
)
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;with&lt;/span&gt; client.session() &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;as&lt;/span&gt; session:
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;query&lt;/span&gt; = (
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;UNWIND {values} as data &quot;&lt;/span&gt;
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;create (:Person {id: data.id, name: data.name, age: data.age})&quot;&lt;/span&gt;
    )
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;values&lt;/span&gt; = [
        {&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;id&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;person1&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#24352;&amp;#24535;&amp;#26114;&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;age&quot;&lt;/span&gt;: 23},
        {&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;id&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;person2&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#21016;&amp;#25991;&amp;#20992;&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;age&quot;&lt;/span&gt;: 18},
        {&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;id&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;person3&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#23385;&amp;#23376;&amp;#23567;&quot;&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;age&quot;&lt;/span&gt;: 22}
    ]
    session.run(query, {&lt;span style=&quot;color: #66cccc;&quot;&gt;'values'&lt;/span&gt;: values})
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org88f2801&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org88f2801&quot;&gt;Cypher 查询语言&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org88f2801&quot;&gt;
&lt;p&gt;
此处仅记录我个人认为常用或重要的部分，完整内容请参考&lt;a href=&quot;https://neo4j.com/docs/cypher-manual/current/&quot;&gt;官方文档&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
在 Cypher 中，用小括号来表示一个实体，用中括号来表示关系，这个是 Cypher 语言中最基础的表示了。
&lt;/p&gt;

&lt;p&gt;
实体的各种表示方式如下：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
表示一个 Person 类型的实体，并记其名字为 &lt;code&gt;a&lt;/code&gt;
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
表示一个 id 值为 &quot;person1&quot; 的实体，并记其名字为 &lt;code&gt;a&lt;/code&gt;
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt; {&lt;span style=&quot;color: #ffcc66;&quot;&gt;id:&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;person1&quot;&lt;/span&gt;})
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
表示任意一个实体，并记其名字为 &lt;code&gt;a&lt;/code&gt; ，之后可以通过 &lt;code&gt;WHERE&lt;/code&gt; 语句来对其进行约束
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
表示一个任意的匿名实体
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;()
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
关系的各种表示方式如下
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
表示一个 actor 类型的实体，并记其名字为 &lt;code&gt;r&lt;/code&gt;
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;[&lt;span style=&quot;color: #d9d9d9;&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:actor&lt;/span&gt;]
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
表示任意一个实体，并记其名字为 &lt;code&gt;r&lt;/code&gt;
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;[&lt;span style=&quot;color: #d9d9d9;&quot;&gt;r&lt;/span&gt;]
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
表示一个任意的匿名实体
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;[]
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
在上面的基础之上，即可方便地表示图数据中的一条实际的边，比如说
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
表示命名为 &lt;code&gt;m&lt;/code&gt; 的 Movie 类型实体到命名为 &lt;code&gt;p&lt;/code&gt; 的 Person 类型实体、匿名的边
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;m&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Movie&lt;/span&gt;)&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;[]&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&amp;gt;&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这里的 &quot;-&amp;gt;&quot; 表示关系的方向是从 &lt;code&gt;m&lt;/code&gt; 到 &lt;code&gt;p&lt;/code&gt; 的
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
同上，但要求关系类型为 actor
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;m&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Movie&lt;/span&gt;)&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;[&lt;span style=&quot;color: #6699cc;&quot;&gt;:actor&lt;/span&gt;]&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&amp;gt;&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
同上，并记关系的名字为 &lt;code&gt;r&lt;/code&gt;
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;m&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Movie&lt;/span&gt;)&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;[&lt;span style=&quot;color: #d9d9d9;&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:actor&lt;/span&gt;]&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&amp;gt;&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
更复杂的表示：Person &lt;code&gt;p&lt;/code&gt; 是 Movie &lt;code&gt;m1&lt;/code&gt; 的主演，同时也是 Movie &lt;code&gt;m2&lt;/code&gt; 的导演
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;m&lt;/span&gt;1&lt;span style=&quot;color: #6699cc;&quot;&gt;:Movie&lt;/span&gt;)&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;[&lt;span style=&quot;color: #d9d9d9;&quot;&gt;r&lt;/span&gt;1&lt;span style=&quot;color: #6699cc;&quot;&gt;:actor&lt;/span&gt;]&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&amp;gt;&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;)&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;&amp;lt;-&lt;/span&gt;[&lt;span style=&quot;color: #d9d9d9;&quot;&gt;r&lt;/span&gt;2&lt;span style=&quot;color: #6699cc;&quot;&gt;:director&lt;/span&gt;]&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;m&lt;/span&gt;2&lt;span style=&quot;color: #6699cc;&quot;&gt;:Movie&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
掌握上述表示方法后，就可以用其来进行数据的创建、查询、修改和删除操作也就是俗称的 CRUD 了。
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
查询实体
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt; {&lt;span style=&quot;color: #ffcc66;&quot;&gt;name:&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#40644;&amp;#28196;&quot;&lt;/span&gt;}) &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;RETURN&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
或者
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;) &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;WHERE&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;.&lt;span style=&quot;color: #d9d9d9;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#40644;&amp;#28196;&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;RETURN&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果如下图所示
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/neo4j_match_1.png&quot; alt=&quot;neo4j_match_1.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
当然也可以不带筛选条件
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;) &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;RETURN&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;LIMIT&lt;/span&gt; 10
&lt;/pre&gt;
&lt;/div&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/neo4j_match_2.png&quot; alt=&quot;neo4j_match_2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
（没错，我非常心机地把结果排成了整齐的两排哈哈）
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
创建实体
&lt;/p&gt;

&lt;p&gt;
语法类似这样
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;create&lt;/span&gt; (&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt; {&lt;span style=&quot;color: #ffcc66;&quot;&gt;id:&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;ac1d6226&quot;&lt;/span&gt;, &lt;span style=&quot;color: #ffcc66;&quot;&gt;name:&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#29579;&amp;#22823;&amp;#38180;&quot;&lt;/span&gt;})
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
修改实体
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;) &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;WHERE&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;.&lt;span style=&quot;color: #d9d9d9;&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;ac1d6226&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;SET&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;.&lt;span style=&quot;color: #d9d9d9;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#40644;&amp;#22823;&amp;#38180;&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
删除实体
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;) &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;WHERE&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;.&lt;span style=&quot;color: #d9d9d9;&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;ac1d6226&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;DELETE&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
注意，删除实体时，如果这个实体还有和其他实体有关联关系，那么会无法删除，需要先将其关联关系解除才可以。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
查询关系
&lt;/p&gt;

&lt;p&gt;
查询 actor 类型的关系，不对起点、终点做任何约束
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;m&lt;/span&gt;)&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;[&lt;span style=&quot;color: #d9d9d9;&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:actor&lt;/span&gt;]&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&amp;gt;&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;) &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;RETURN&lt;/span&gt; * &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;LIMIT&lt;/span&gt; 10
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/neo4j_match_3.png&quot; alt=&quot;neo4j_match_3.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
查询 actor 类型的关系，对起点（或终点）做约束，比如说，查询主演是黄渤的所有电影
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;m&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Movie&lt;/span&gt;)&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;[&lt;span style=&quot;color: #d9d9d9;&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:actor&lt;/span&gt;]&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&amp;gt;&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;) &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;WHERE&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;.&lt;span style=&quot;color: #d9d9d9;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#40644;&amp;#28196;&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;RETURN&lt;/span&gt; *
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/neo4j_match_4.png&quot; alt=&quot;neo4j_match_4.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
创建关系
&lt;/p&gt;

&lt;p&gt;
语法如下，要求涉及到的两个实体 &lt;code&gt;a&lt;/code&gt; 和 &lt;code&gt;b&lt;/code&gt; 是已经存在的。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt; {&lt;span style=&quot;color: #ffcc66;&quot;&gt;id:&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;person_id_a&quot;&lt;/span&gt;}), &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt; {&lt;span style=&quot;color: #ffcc66;&quot;&gt;id:&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;person_id_b&quot;&lt;/span&gt;})
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;CREATE&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;)&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;[&lt;span style=&quot;color: #6699cc;&quot;&gt;:KNOWS&lt;/span&gt;]&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&amp;gt;&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
之前导入的豆瓣电影图谱其实缺少人和人之间的关系，比如说宁浩和黄渤彼此都认识，可以加上这个关系
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;), (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;) &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;WHERE&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;.&lt;span style=&quot;color: #d9d9d9;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#40644;&amp;#28196;&quot;&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;and&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;.&lt;span style=&quot;color: #d9d9d9;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#23425;&amp;#28009;&quot;&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;CREATE&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;)&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;&amp;lt;-&lt;/span&gt;[&lt;span style=&quot;color: #6699cc;&quot;&gt;:knows&lt;/span&gt;]&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&amp;gt;&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;), (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;)&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;[&lt;span style=&quot;color: #6699cc;&quot;&gt;:knows&lt;/span&gt;]&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&amp;gt;&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
删除关系
&lt;/p&gt;

&lt;p&gt;
先用 &lt;code&gt;MATCH&lt;/code&gt; 语句进行查询，并为其中的关系命名，然后在 DELETE 语句中用这个关系的名字即可。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;)&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;[&lt;span style=&quot;color: #d9d9d9;&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:knows&lt;/span&gt;]&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;) &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;WHERE&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;.&lt;span style=&quot;color: #d9d9d9;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#40644;&amp;#28196;&quot;&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;and&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;.&lt;span style=&quot;color: #d9d9d9;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#23425;&amp;#28009;&quot;&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;DELETE&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;r&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
查询两个节点之间的最短路径
&lt;/p&gt;

&lt;p&gt;
查询黄渤和汤姆·克鲁斯之间的最短路径
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;), (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;), &lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;=&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;shortestpath&lt;/span&gt;((&lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;)&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;[&lt;span style=&quot;color: #6699cc;&quot;&gt;:actor&lt;/span&gt;*]&lt;span style=&quot;color: #ff1493; background-color: #292929; font-weight: bold;&quot;&gt;-&lt;/span&gt;(&lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;))
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;WHERE&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;a&lt;/span&gt;.&lt;span style=&quot;color: #d9d9d9;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#40644;&amp;#28196;&quot;&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;and&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;b&lt;/span&gt;.&lt;span style=&quot;color: #d9d9d9;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#27748;&amp;#22982;&amp;#183;&amp;#20811;&amp;#40065;&amp;#26031;&quot;&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;RETURN&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/neo4j_match_5.png&quot; alt=&quot;neo4j_match_5.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
CRUD 之外，索引的创建也是很重要的，如果没有创建索引或者索引设计有问题，那么可能会导致查询效率特别差。我最早开始用 Neo4j 的时候，在批量导入数据时没有建索引，导致不到五十万的数据量（包括实体和关系）的导入需要近一个小时，而在正确设置了索引之后，十几秒就完成了。对于比较慢的查询，可以用 &lt;code&gt;PROFILE&lt;/code&gt; 语句来检查性能瓶颈。
&lt;/p&gt;

&lt;p&gt;
以本文用来做示例的豆瓣电影图谱来说，如果没有给 Person.name 建立索引，那么下面这个查询语句就会很慢
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;) &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;where&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;.&lt;span style=&quot;color: #d9d9d9;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#40644;&amp;#28196;&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;RETURN&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
用 &lt;code&gt;PROFILE&lt;/code&gt; 语句做一下分析，只需要再原来的 query 前加上 &lt;b&gt;PROFILE&lt;/b&gt; 这个关键词即可。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-cypher&quot;&gt;&lt;span style=&quot;color: #d9d9d9;&quot;&gt;PROFILE&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;MATCH&lt;/span&gt; (&lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;:Person&lt;/span&gt;) &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;where&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;.&lt;span style=&quot;color: #d9d9d9;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#40644;&amp;#28196;&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;RETURN&lt;/span&gt; &lt;span style=&quot;color: #d9d9d9;&quot;&gt;p&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
分析结果如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/neo4j_profile_1.png&quot; alt=&quot;neo4j_profile_1.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
从上图来看，这个查询语句的逻辑是遍历了一下所有 Person 实体，挨个比较哪个实体的 name 是「黄渤」，这无疑是极其低效的。而在创建了索引后，PROFILE 的结果是下图这个样子：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/neo4j_profile_2.png&quot; alt=&quot;neo4j_profile_2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
关于索引可以展开更多内容，准备另外写一篇，这里只是强调一下 &lt;code&gt;PROFILE&lt;/code&gt; 语句的作用。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>2018 年总结与 2019 年展望</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2019/01/01/annual-summary-of-2018.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2019/01/01/annual-summary-of-2018</id>
    <published>2019-01-01T00:00:00+00:00</published>
    <updated>2019-01-01T00:00:00+00:00</updated>
    <description>
    
      <p>有三年没有写年末总结了，2018 年觉得似乎可以写一下。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orge4753b2&quot;&gt;2018 年总结&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org8ddd0c4&quot;&gt;工作&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1049e88&quot;&gt;生活&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4f67543&quot;&gt;可能没什么用的 2019 年计划&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
有三年没有写年末总结了，2018 年觉得似乎可以写一下。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orge4753b2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge4753b2&quot;&gt;2018 年总结&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge4753b2&quot;&gt;
&lt;p&gt;
先定个性，2018 年是我工作以来「感觉」最累的一年。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8ddd0c4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8ddd0c4&quot;&gt;工作&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8ddd0c4&quot;&gt;
&lt;p&gt;
我有写日记和记工作日志的习惯，日记里多写一些心理、情绪感受，工作日志则主要记录工作事项的前因后果和过程。所以呢，日志基本能反映我这一年的心理状况，而工作日志则能反映我这一年来的工作状况。我过了一遍自己的工作日志，以下面的原则对一年的工作内容进行了一个统计：
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;若工作内容是某个算法功能的实现、优化，则统计为一项算法工作，并给一个类别&lt;/li&gt;
&lt;li&gt;若工作内容是将已有的某项算法功能应用到某个业务上，则记为业务工作，不做细分&lt;/li&gt;
&lt;li&gt;每项类别当一天中仅记一次&lt;/li&gt;
&lt;li&gt;去掉最终统计次数为 1 类别&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
得到的统计结果是这样的
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2018_job.png&quot; alt=&quot;2018_job.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到三大块分别是：信息抽取、业务和知识图谱。业务部分占了 1/4 ，不过没什么好说的。知识图谱的部分分为图谱的构建和图谱的应用两块，前者其实就是从信息抽取中产生的数据进一步处理得到的，而信息抽取最初也是为了给知识图谱提供数据的，不过到后来慢慢延伸到了其他方面了。知识图谱早期的验证、实践的技术工作基本都是我做的，一开始的时候对于图谱应该是什么结构、该怎么用都是不清楚的，和产品的同事辛苦地讨论、修改，一步步才形成雏形。与此同时，要从大量的未结构化数据里抽取出结构化数据再建立成知识图谱，这个过程的初期则更加令人痛苦；而在这个过程建立起来后，为了修复各种各样的适配问题以及支持新增的抽取需求，仍然有大量的精力投入到这里面去。
&lt;/p&gt;

&lt;p&gt;
知识图谱呢，至少推理问答的框架建立起来后，就是一些功能的增改的问题，倒还好。信息抽取和图谱构建这两个事情是我主要的压力来源，做过的人大概会明白的，这里就不想多说什么技术细节了。
&lt;/p&gt;

&lt;p&gt;
另外一方面，上半年的时候，大量的工作内容都是围绕着 POC(Proof Of Concept) 做的，也就是根据「潜在客户」的需求做一个原型，给对方演示，以求打动对方得到签单的机会。本来呢，应该是做一个原型的，但为了给客户足够的吸引力，基本上我们就是当作正式项目在做，该有的功能都要有 —— 但是呢，POC 要么就是没有了后续消息，或者有消息了，还要进行招投标，最后才能签单，于是在比较长的一段时间内，你看不到工作的任何直接成果，到后来突然说要正式签单，我都已经麻木了，内心毫无波澜。进一步的，我们在做的东西，到底有多少社会价值这个问题也很难回答，to B 的业务是这样，双方先花个半年一年进行 POC、招标、二次招标，签订合同后开始接入，之后又要过挺长一段时间你才能知道效果怎么样，而像算法功能呢就更不好评估了 —— 大部分的算法效果其实都只能在一个标注数据集上做评估，而系统上线后的新的数据到底怎么样你其实是不知道的，只能去定期采样然后交给人工来评估，总之就是挺难受的。就算是真的效果好了，企业真的就需要一个对话机器人吗？要我说这并不是必要的，还是锦上添花的东西。从目前业界的特定领域对话机器人的普遍效果来看，我觉得都还不够，或许应该先将 NLP 技术用到更基础、更普遍的一些问题上去。
&lt;/p&gt;

&lt;p&gt;
最后就是小公司的通病了，人力不足，杂事繁多。
&lt;/p&gt;

&lt;p&gt;
从我个人的角度上来说，我很担心自己的一点是，我几乎没法从工作中获得正面的情绪反馈，那种碰到新技术的激动感、写完代码赞美自己「哇我写得真好」的骄傲感之类的，可以说几乎没有了。我不太喜欢这样的变化，如果说工作对我来说只剩下折磨，不如向窃格瓦拉看齐好了。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dagong.gif&quot; alt=&quot;dagong.gif&quot; style=&quot;margin-left: auto; margin-right: auto;&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1049e88&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1049e88&quot;&gt;生活&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1049e88&quot;&gt;
&lt;p&gt;
年初买了 Nintendo Switch，然后陆续玩了几款游戏，分别有：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;塞尔达：荒野之息（救完公主索然无味）&lt;/li&gt;
&lt;li&gt;空洞骑士（三周目！）&lt;/li&gt;
&lt;li&gt;盐与避难所&lt;/li&gt;
&lt;li&gt;光之子&lt;/li&gt;
&lt;li&gt;星之卡比&lt;/li&gt;
&lt;li&gt;Gris&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
当然 Steam 上也买了一些游戏，但受限于电脑性能，多是一些体量较小的，玩的比较多的有
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;FEZ(补票)&lt;/li&gt;
&lt;li&gt;洞窟物语(补票)&lt;/li&gt;
&lt;li&gt;Reigns&lt;/li&gt;
&lt;li&gt;Pixel Dungeon：这个一直在刷，没有打穿&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
明年可能会考虑入 PS（想玩《赛博朋克2077》！），不过据说 2020 年会发 PS5，有点纠结，再说吧。
&lt;/p&gt;

&lt;p&gt;
我玩游戏其实不太多，加上之前没有买过主机也没有一个较高配置的 PC，所以基本就是 Steam 玩玩较小的游戏和手机上玩一些，早几年的话一直在玩炉石，2018 年买了 NS 后才开始萌生玩一些稍大型游戏的想法，因为游戏实在是很好玩呀。个人会比较喜欢有在讲故事的游戏，竞技、对抗类的就不太感冒了，FPS 头晕，弹幕类游戏苦手（东方简直是恶梦），太肝的游戏玩不动，大概是这样吧。
&lt;/p&gt;

&lt;p&gt;
游戏之外，影视作品（包括电影、动漫、电视剧等）看了一些，但并不多
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;看过的电影里，国产的《爆裂无声》、《无名之辈》和《无双》都很不错，倒是国外的感觉都不咋样，《神奇动物2》本来挺期待的，也就那样吧&lt;/li&gt;
&lt;li&gt;动漫的话，有印象的也不多：一月的《刻刻》设定有意思，不过后期反派突然漂白有点意犹未尽；四月的《Lost Song》的叙述性诡计非常赞；沙雕的《千绪的通学路》和（并不沙雕的）《赌博默示录》外传《中间管理录利根川》都很轻松愉快；年末的《刀剑神域 Alicization》的故事是我认为刀剑里叙事最好的一部分了，女性角色偏少，设定、剧情都更为合理，而且是《加速世界》中核心设定的来源；《恶魔人》和《石头门0》都还没看就不发表看法，其他的就没什么感觉了，然后又把一些老番重看了一遍 ，有《XXXHOLIC》、《希德尼亚的骑士》、《灵能百分百》（要出第二季了！）等&lt;/li&gt;
&lt;li&gt;似乎没看什么剧，西部世界？&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
书就没看太多了，而且没怎么记录，回顾起来是个问题。话说我对有花大力气记自己的工作内容，但生活内容似乎没怎么记录，过个几年要想了解之前自己是怎么过日子怎么想的，可能会有点困难，从新年开始调整一下吧 —— 我可能很难做到很会生活，但好好记录自己的生活，还是不难做到的，下班后少管点工作的事情就是了。
&lt;/p&gt;

&lt;p&gt;
现在住的地方周围没有方便的菜市场，厨房也很逼仄，所以2018 年完全没什么做饭的欲望，周末和工作日主要都是靠外卖和速食来解决的，靠着和同事互相交流经验倒是也收藏了好几家店铺，换着吃……好像有点惨，不过在公司里有一个吃委会，隔三岔五会出去大吃一顿，所以也还好。我其实还蛮喜欢吃的，不过我比较被动，就是那种如果有人号召我会积极参与但你要我主动去觅食有点困难那种……话说公司里的同事在吃这个事情上都有一些奇怪的设定，有喜欢吃各种土豆的、不吃葱蒜和猪肉的、不吃芒果的（我 OTZ）、不吃榴莲和香菜的（这个比较常见）……
&lt;/p&gt;

&lt;p&gt;
再就是开始尝试理财吧，现在把钱分散到了货币基金、大平台的网贷以及指数基金上，主要的钱现在都在&lt;a href=&quot;https://qieman.com/longwin/index&quot;&gt;长赢计划&lt;/a&gt;里面，赌赌国运吧。过程中规中矩，倒没指望能赚大钱，就是开始了解一点金融的概念。比较意外的是，年初的时候，2013 年获赠的 Ripple 大涨就提现了一部分，白赚了一万软妹币，但是 7 月份的时候在一个网贷里雷掉一万，两相抵消，就当小小地感受了一下生活的刺激吧。
&lt;/p&gt;

&lt;p&gt;
翻自己的日记都是在抱怨，这样回头一梳理事情还是蛮多的，可惜在日记里都没记。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4f67543&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4f67543&quot;&gt;可能没什么用的 2019 年计划&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org4f67543&quot;&gt;
&lt;p&gt;
工作方面可能不会有什么计划，主要还是跟着公司业务走，我能做的打算是，尽量减少在工作时间之外处理公司事务的时间支出。再像2018 年这样，我担心会触及自己的心理承受能力上限，到时候损失最大的是我，我想我没有必要真的给公司卖命对吧。倒也不是说就和公司彻底划清界限，就是尝试提高自己的效率吧，在工作时间处理完重要的事情，一些小的、琐碎的、不那么重要的事情，没有必要那么及时响应，对个人对公司都没什么好处。
&lt;/p&gt;

&lt;p&gt;
以及，我也不再奢望能在工作中学习、成长了，这方面还是得靠自己，为了达到这个目的，也需要更多的业余时间。这方面的具体内容需要动态调整，不可能现在就列出细则，不过大方向肯定是自然语言处理相关的，其他领域的可能也会涉及，随缘。
&lt;/p&gt;

&lt;p&gt;
春节后可能就不再和合租了四年的同学一起合租了，希望能租一个一居室能自己安安静静地看书打游戏，不过北京的一居室房租真的好贵……纠结……
&lt;/p&gt;

&lt;p&gt;
嗯……好像上述内容都不构成「计划」，更像是一种想法。按照经验的话，做太详细的计划往往会无法执行，而且在年初设想的过于具体的计划可能并不合理。我决定用 2018 年学到的一个工具 OKR(Objectives and Key Results)来写一下 2019 年的计划，这里只列出 Objectives，Key Results 的话则视情况而定再行制定，所以以下是我 2019 年的 Objectives:
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;完善自己的 NLP 工具箱，对于大部分 NLP 问题，可以快速寻找到工具来解决&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
实践并完善自己的学习、知识体系，并用之掌握两到三个领域的基础知识
&lt;/p&gt;

&lt;p&gt;
这方面 2018 年有做一些，目前把 org-mode 的笔记体系和 anki 结合起来了，但利用得不够充分。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
使用日记及其他工具来更充分地记录自己的生活
&lt;/p&gt;

&lt;p&gt;
2018 年有用 Life Cycle 来自动跟踪粗粒度的事件，还蛮不错的，2019 年会继续用下去。然后就是前面提到的游戏、阅读、观影这些东西希望也能好好记录下。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;读更多的小说，看更多的动漫，玩更多的游戏，收获更多的快乐&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
新的一年，重新出发～
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>论文笔记： ReDecode Framework for Iterative Improvement in Paraphrase Generation</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/11/24/paper-note-redecode.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2018/11/24/paper-note-redecode</id>
    <published>2018-11-24T00:00:00+00:00</published>
    <updated>2018-11-24T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


作者
观点与事实
相关工作
数据集
模型/方法/结论
总结




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org007ecf8&quot;&gt;作者&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge3794f6&quot;&gt;观点与事实&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org861cf95&quot;&gt;相关工作&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgaae8495&quot;&gt;数据集&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1c68599&quot;&gt;模型/方法/结论&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgfd85162&quot;&gt;总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org007ecf8&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org007ecf8&quot;&gt;作者&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org007ecf8&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Milan Aggarwal&lt;/li&gt;
&lt;li&gt;Nupur Kumari&lt;/li&gt;
&lt;li&gt;Ayush Bansal&lt;/li&gt;
&lt;li&gt;Balaji Krishnamurthyk&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge3794f6&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge3794f6&quot;&gt;观点与事实&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge3794f6&quot;&gt;
&lt;p&gt;
观点
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;当前的一些序列生成方法都是一锤子买卖，在生成的时候改正错误的能力太差，生成之后也不能去改进生成质量&lt;/li&gt;
&lt;li&gt;人类对话中用复杂的复述来表达相同意图的行为很普遍，但对机器来说要辨别或生成复述句是很困难的&lt;/li&gt;
&lt;li&gt;VAE 学习的是一个概率分布，所以用于生成式的任务很合适&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org861cf95&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org861cf95&quot;&gt;相关工作&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org861cf95&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;1983. Paraphrasing questions using givenand new information&lt;/li&gt;
&lt;li&gt;2003. Learning to paraphrase: anunsupervised approach using multiple-sequence alignment&lt;/li&gt;
&lt;li&gt;2004. Monolingualmachine translation for paraphrase generation. Associationfor Computational Linguistics.&lt;/li&gt;
&lt;li&gt;2004. Synonymous para-phrasing using wordnet and internet&lt;/li&gt;
&lt;li&gt;2016. Neural paraphrase genera-tion with stacked residual lstm networks&lt;/li&gt;
&lt;li&gt;2017. Learn-ing paraphrastic sentence embeddings from back-translatedbitext&lt;/li&gt;
&lt;li&gt;2017. Joint copying andrestricted generation for paraphrase&lt;/li&gt;
&lt;li&gt;2017. Learning to paraphrase for question answering&lt;/li&gt;
&lt;li&gt;2017. Adeep generative framework for paraphrase generation&lt;/li&gt;
&lt;li&gt;2018. Adversarial example generation with syn-tactically controlled paraphrase networks&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgaae8495&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgaae8495&quot;&gt;数据集&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgaae8495&quot;&gt;
&lt;p&gt;
论文里用到了两个数据集。
&lt;/p&gt;

&lt;p&gt;
第一个是 Quora 的相似问题数据集，这个没啥好说的。
&lt;/p&gt;

&lt;p&gt;
第二个是微软的 MSCOCO 数据集，这个其实是一个 Image Caption 的数据集，但是因为这个数据集里每张图片都标注了五个标题，可以认为这个五个标题互为复述句。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1c68599&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1c68599&quot;&gt;模型/方法/结论&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org1c68599&quot;&gt;
&lt;p&gt;
模型结构如下图所示
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/redecode.png&quot; alt=&quot;redecode.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
模型又三部分组成，分别是
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
Sampling Encoder
&lt;/p&gt;

&lt;p&gt;
这个 Encoder 用来根据输入句子 \(x_{o}\) 产生一个概率分布，然后从 x 中进行采样得到一个 latent vector \(z\)
&lt;/p&gt;

&lt;p&gt;
在这篇论文里，Sampling Encoder 由一个单层的 LSTM 和两个全连接层构成。
&lt;/p&gt;

&lt;p&gt;
首先输入句子 \(x_{o}\) 经过 LSTM 后得到整个句子的向量表示 \(v_{o}\)，然后分别输入一个全连接层，得到期望概率分布的均值 \(\mu\) 和方差 \(\sum\)，用这个均值和方差就得到了一个正态分布 \(N(\mu, \sum)\)，从这个概率分布中采样得到最终需要的 \(z\)。
&lt;/p&gt;

&lt;p&gt;
为了让最终模型的输出能更有多样性，在训练的时候，作者对 \(\mu\) 和 \(\sum\) 施加高斯噪声扰动来得到不同的 \(z\)。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Sentence Encoder
&lt;/p&gt;

&lt;p&gt;
这个 Encoder 用来对得到输入句子 x 的语义表示，用来作为 decoder 的语义输入。
&lt;/p&gt;

&lt;p&gt;
这个 Encoder 就比较简单了，一个两层的 LSTM，输出 hidden state 序列 \(H={h_{1}^{o}, h_{2}^{o}...h_{n}^{o}}\)，并在 Decoder 中对其进行 attention 计算。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Sequencd Decoders
&lt;/p&gt;

&lt;p&gt;
这个是最终用来生成的复述句的，也是整篇论文中的要点。
&lt;/p&gt;

&lt;p&gt;
和常规的一个 decoder 做法不一样的是，作者认为生成的部分，应该用多个 decoder 来迭代地生成结果。具体来说，这篇论文的做法是这样的
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
第一个 decoder 以 Sentence Encoder 输出的 hidden state 向量 \(H\) 和 Sampling Encoder 输出的 latent vector \(z\) 作为输入
&lt;/p&gt;

&lt;p&gt;
\(p_{1}=Dec_{\phi_{1}}(z, Attn(H))\)
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
随后的 decoder 则以前一个 decoder 的输出和 Sampling Encoder 输出的 \(z\) 作为输入
&lt;/p&gt;

&lt;p&gt;
\(p_{i}=Dec_{\phi_{i}}(z, Attn({s_{Dec_{\phi_{i-1}}}}))\)
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
下图是该模型在两个数据集上的效果。
&lt;img src=&quot;/assets/img/redecode_eval.png&quot; alt=&quot;redecode_eval.png&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;
以及一些输出示例
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/redecode_examples.png&quot; alt=&quot;redecode_examples.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgfd85162&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgfd85162&quot;&gt;总结&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgfd85162&quot;&gt;
&lt;p&gt;
总的来说，模型并不算很复杂，也很简单易懂。
&lt;/p&gt;

&lt;p&gt;
VAE 的部分我其实并不太熟悉，需要去补课。至于 Decoder 的部分，这种迭代生成的路子，其实早就见过了，比如说 &lt;a href=&quot;http://www.zmonster.me/2018/11/10/hmn_for_qa.html&quot;&gt;HMN&lt;/a&gt; 模型，以及一些在 attention 机制上的改进工作之类的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>论文笔记：Word Embedding based Edit Distance</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/11/17/paper-note-word-embedding-based-edit-distance.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2018/11/17/paper-note-word-embedding-based-edit-distance</id>
    <published>2018-11-17T00:00:00+00:00</published>
    <updated>2018-11-17T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


作者
观点
数据集
模型/方法/结论
相关工作
概念和术语




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgd7d2ee1&quot;&gt;作者&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org7c7ca76&quot;&gt;观点&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1c36287&quot;&gt;数据集&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1af4fe4&quot;&gt;模型/方法/结论&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org265043b&quot;&gt;相关工作&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf7273e0&quot;&gt;概念和术语&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-orgd7d2ee1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgd7d2ee1&quot;&gt;作者&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgd7d2ee1&quot;&gt;
&lt;p&gt;
Yilin Niu, Chao Qiao, Hang Li, and Minlie Huang
&lt;/p&gt;

&lt;p&gt;
看这篇论文才知道李航去今日头条 AI 实验室了……
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org7c7ca76&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org7c7ca76&quot;&gt;观点&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org7c7ca76&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;近年来深度学习被广泛应用到文本相似计算中，但这些方法一般都需要在标注数据上做有监督训练，而标注数据的收集、构建的代码是很高的&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
在特定条件下，WED 可以退化为编辑距离或者 jaccard 系数的变种
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
One can easily verify that WED degenerates to ED and a variant of Jaccard under certain condition.
&lt;/pre&gt;

&lt;p&gt;
不过论文并没有细说这些方法之间是怎么转换的。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1c36287&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1c36287&quot;&gt;数据集&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org1c36287&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Quora: The dataset released from Quora contains 400k question pairs in community questionanswering labeled as matched or not-matched, 40w 样本&lt;/li&gt;
&lt;li&gt;MSRP: The dataset for paraphrase detection released from Microsoft Research, 5.8k 句子对&lt;/li&gt;
&lt;li&gt;CPC: The dataset referred to as Crowdsourced Paraphrase Collection (CPC), 2.6k 对复述句子&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1af4fe4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1af4fe4&quot;&gt;模型/方法/结论&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org1af4fe4&quot;&gt;
&lt;p&gt;
记 \(S_{A}=(w_{A}^{1}, w_{A}^{2}, ..., w_{A}^{l_{A}})\) 和 \(S_{B}=(w_{B}^{1}, w_{B}^{2}, ..., w_{B}^{l_{B}})\) 为两个句子，其中 \(w_{A}^{i}\) 表示句子 \(S_{A}\) 中第 \(i\) 个词，\(w_{B}^{j}\) 表示句子 \(S_{B}\) 中第 \(j\) 个词。
&lt;/p&gt;

&lt;p&gt;
在计算编辑距离时，以 \(S_{A}\) 为基准句子，计算 \(S_{B}\) 相对 \(S_{A}\) 的编辑距离，即认为 \(S_{B}\) 是 \(S_{A}\) 经过删除、插入、替换后得到的新的句子。
&lt;/p&gt;

&lt;p&gt;
然后定义 \(c_{i,j}\) 为 \((w_{A}^{1}, w_{A}^{2}, ..., w_{A}^{i})\) 经过编辑变换成 \((w_{B}^{1}, w_{B}^{2}, ..., w_{B}^{j})\) 所需的最小操作代价。
&lt;/p&gt;

&lt;p&gt;
那么就有
&lt;/p&gt;

&lt;p&gt;
\[\begin{eqnarray}c_{i,j} = \begin{cases}
  c_{i,j-1}+i(w_{B}^{j}) \\
  c_{i-1,j}+d(w_{A}^{i})\\
  c_{i-1,j-1}+s(w_{A}^{i}, w_{B}^{j})
  \end{cases}\end{eqnarray}\]
&lt;/p&gt;

&lt;p&gt;
其中 \(i(w_{B}^{j})\) 表示插入 \(w_{B}^{j}\) 的代价；\(d(w_{A}^{i})\) 表示删除 \(w_{A}^{i}\) 的代码。这两者在传统的编辑距离里往往值是 1，在生物信息学的序列对比上，删除的代码可能会再适当地高一点。
&lt;/p&gt;

&lt;p&gt;
\(s(w_{A}^{i}, w_{B}^{j})\) 则表示将 \(w_{A}^{i}\) 替换为 \(w_{B}^{j}\) 的代价，当两者想等时代码就是 0 ，当两者不相等时这个代价就要大于 0。替换操作在不同的地方使用的代价会不一样，有些地方当作和插入、删除一样，即 1，本文的方法则是将替换视作先删除后插入两次操作，所以代价是 2。
&lt;/p&gt;

&lt;p&gt;
所谓的结合 embedding，就是对这三个代价函数做了修改，使之利用词的 embedding 信息。
&lt;/p&gt;

&lt;p&gt;
对插入操作，定义代价为：
&lt;/p&gt;

&lt;p&gt;
\[i(w_{B}^{j})=1 - \lambda \cdot max_{w_{A}^{k}\in S_{A}, w_{A}^{k} \neq w_{A}^{i}} (sim(w_{A}^{k}, w_{B}^{j}) + \mu)\]
&lt;/p&gt;

&lt;p&gt;
对删除操作，定义代价为：
&lt;/p&gt;

&lt;p&gt;
\[d(w_{A}^{i})=1 - \lambda \cdot max_{w_{B}^{k}\in S_{B}, w_{B}^{k} \neq w_{B}^{j}} (sim(w_{A}^{i}, w_{B}^{k}) + \mu)\]
&lt;/p&gt;

&lt;p&gt;
对替换操作，定义代价为：
&lt;/p&gt;

&lt;p&gt;
\[s(w_{A}^{i}, w_{B}^{j})=2 - 2 sim(w_{A}^{i}, w_{B}^{j})\]
&lt;/p&gt;

&lt;p&gt;
第三个替换操作的定义很好理解，但是前面两个感觉有点疑惑呀……
&lt;/p&gt;

&lt;p&gt;
能想到的解释是这样的
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;当插入新的词时，如果词和句子 A 中的词有相似的，那么对语义的影响就不是那么大&lt;/li&gt;
&lt;li&gt;当删除句子 A 中的词时，如果句子 B 中还有词和这个删除的词相似，那么对语义的影响也不会那么大&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
但是 LCS 的好处在于每个词是一一对应的，而这里在计算插入和删除的时候并没有保证有序的一一对应关系呀。
&lt;/p&gt;

&lt;p&gt;
和其他方法的对比
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;ED: 经典编辑距离&lt;/li&gt;
&lt;li&gt;TF-IDF: 基于 tfidf 的 cosine 相似&lt;/li&gt;
&lt;li&gt;Embedding: 基于 embedding 的 cosine 相似&lt;/li&gt;
&lt;li&gt;Jaccard: jaccard 系数&lt;/li&gt;
&lt;li&gt;Autoencoder: 这个应该是指语言模型一类的，但是为什么引用的是 Hinton 2006 年的论文……&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
BOW+MLP: 有监督方法，给定两个句子，先将句子中的 embedding 加和，然后拼接起来输入到 MLP
&lt;/p&gt;

&lt;p&gt;
分两种情况：一层 MLP 和三层 MLP
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
LSTM+MLP: 用 LSTM 编码句子，然后拼接起来输入到 MLP
&lt;/p&gt;

&lt;p&gt;
分两种情况：一层 MLP 和三层 MLP
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
对比结果如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/wed_results.png&quot; alt=&quot;wed_results.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
结论：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;本文的方法要优于这几种无监督方法：编辑距离、基于TFIDF的 cosine、基于 word embedding 的 cosine 方法、jaccard 系数&lt;/li&gt;
&lt;li&gt;对比两个有监督方法(BOW/LSTM+3层MLP)，发现大概在 30k 这个数据量以上，有监督的方法才会显著好于 WED 方法&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
在 Quora 数据集上做了一些采样来分析错误，发现超过 50% 的错误在于没有区分开关键词和非关键词，所以如果有机制能给关键词更高的权重，那么 WED 应该还会有更高的效果 —— 比如说用 TF/IDF 来给每个词加权？
&lt;/p&gt;

&lt;p&gt;
嗯，没有给一些例子呀……
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org265043b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org265043b&quot;&gt;相关工作&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org265043b&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Learning semantic representations using convolutional neural networks for web search, 2014&lt;/li&gt;
&lt;li&gt;Convolutional neural network architectures for matching natural language sentences, 2014&lt;/li&gt;
&lt;li&gt;Text matching as image recognition, 2016&lt;/li&gt;
&lt;li&gt;A deep architecture for semantic matching with multiple positional sentence representations, 2016&lt;/li&gt;
&lt;li&gt;A decomposable attention model for natural language inference, 2016&lt;/li&gt;
&lt;li&gt;编辑距离：Navarro 2001, Jurafsky and Martin 2009&lt;/li&gt;
&lt;li&gt;jaccard 系数：Tan et al 2005&lt;/li&gt;
&lt;li&gt;基于 word embedding 的 cosine 相似：Mitchell and Lapata 2008, Milajevs et al 2014&lt;/li&gt;
&lt;li&gt;基于 TFIDF 的 cosine 相似：Buckley, 1988&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf7273e0&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf7273e0&quot;&gt;概念和术语&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf7273e0&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;WED: Word Embedding based Edit Distance 缩写（不应该是 WEED 吗）&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>论文笔记：Visualizing and understanding recurrent networks</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/11/10/visualizing-and-understanding-rnn.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2018/11/10/visualizing-and-understanding-rnn</id>
    <published>2018-11-10T00:00:00+00:00</published>
    <updated>2018-11-10T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


作者
观点
数据集
模型/实验/结论




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org4acdd18&quot;&gt;作者&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc998236&quot;&gt;观点&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org89bf894&quot;&gt;数据集&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf53595c&quot;&gt;模型/实验/结论&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;hr /&gt;

&lt;div id=&quot;outline-container-org4acdd18&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4acdd18&quot;&gt;作者&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org4acdd18&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Andrej Karpathy&lt;/li&gt;
&lt;li&gt;Justin Johnson&lt;/li&gt;
&lt;li&gt;Li Fei-Fei&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc998236&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgc998236&quot;&gt;观点&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgc998236&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;LSTM 在实践中表现出了非常好的结果，但我们对其性能的来源和限制理解地都还很不够&lt;/li&gt;
&lt;li&gt;过去的一些分析都是靠最终测试集上的全局困惑度来评价 LSTM 的效果，并没有在「真实数据」上进行分析，也不够直观&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org89bf894&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org89bf894&quot;&gt;数据集&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org89bf894&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;托尔斯泰的《战争与和平》文本，共 3,258,246 字&lt;/li&gt;
&lt;li&gt;Linux 内核代码，共 6,206,996 字&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf53595c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf53595c&quot;&gt;模型/实验/结论&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf53595c&quot;&gt;
&lt;p&gt;
模型:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;RNN，分别尝试层数为 1 层、2 层和 3 层，隐层大小分别尝试 64, 128, 256 和 512，共 12 个模型&lt;/li&gt;
&lt;li&gt;LSTM，同 RNN&lt;/li&gt;
&lt;li&gt;GRU，同 RNN&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
实验和结论
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;用上述模型在两个数据集上训练语言模型，最后在测试集上计算交叉熵误差，对比三类共 36 个模型之间的结果&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
对 LSTM/GRU 的 gate 输出分布做可视化分析。如下图所示，图中的小圆圈代表一个神经元，横轴表示该神经元 gate 值超过 0.9 的比例，纵轴是 gate 值小于 0.1 的比例
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/lstm_gru_saturation.png&quot; alt=&quot;lstm_gru_saturation.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
其中
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;forget gate 值超过 0.9 的比例很大的神经元，说明它能一直记住比较早之前的信息&lt;/li&gt;
&lt;li&gt;input gate 值超过 0.9 的比例很大的神经元，说明它对当前输入比较敏感&lt;/li&gt;
&lt;li&gt;output gate 的值超过 0.9 的比例很大的神经元，没什么意义，单纯的控制大小&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
对 LSTM 而言
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;第一层只有很少一部分 gate 值超过 0.9 或小于 0.1，其比例比较密集地分布在 0 附近，说明大部分都是在 0.1 到 0.9 之间&lt;/li&gt;
&lt;li&gt;有一些神经元 forget gate 值超过 0.9 的比例超级大,也就是说它一直都超过 0.9，一直记着很早以前的东西&lt;/li&gt;
&lt;li&gt;有一些神经元 forget gate 的值小于 0.1 的比例很大，但没有一直都小于 0.1 的，比例最大在 0.8 左右&lt;/li&gt;
&lt;li&gt;input gate 倾向于超过 0.9(相对比例大的神经元更多), output gate 的值分布比较均匀&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
对 GRU 来说
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;第一层的 update gate 普遍比较大而 reset gate 普遍比较小，注意本文中的 update gate 相当于 LSTM 中的 input gate&lt;/li&gt;
&lt;li&gt;高层不像第一层那么极端，但总体形式差不多，就是 update gate 大而 reset gate 小这样&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
分析了 LSTM 在《战争与和平》文本上的错误类型
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;ngram 错误，1-9 阶 ngram 模型能预测正确但 LSTM 预测失败的部分&lt;/li&gt;
&lt;/ul&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;罕见词错误: 既由词频不大于 5 的词导致的错误。这部分错误通过扩充数据集和 pretraining 是可以得到缓解的&lt;/li&gt;

&lt;li&gt;词建模错误: 在遇到空格、换行、引号等词分隔符后，预测错了下一个词的第一个字符，和前面个动态长期记忆错误不一样的是，这个相当于在前面的词的基础上要选择一个词，而前面那个相当于是已经知道是什么词了，但是要补全它，这两者的信息量是完全不一样的&lt;/li&gt;

&lt;li&gt;标点符号预测错&lt;/li&gt;

&lt;li&gt;最后剩余的错误称为 boost error，&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
结论
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;多个隐藏层模型比单个隐藏层模型的效果要好&lt;/li&gt;
&lt;li&gt;LSTM 和 GRU 之间难分伯仲，但都显著好于 RNN&lt;/li&gt;
&lt;li&gt;LSTM 表现出了对长程结构的记忆能力，如在处理被引号括起来的长文本时，对开头和结尾的引号有特殊的响应&lt;/li&gt;
&lt;li&gt;在多层的 LSTM/GRU 中，高层的神经元都开始分化，会有一部分倾向于接收新信息，有一部分则倾向于记住旧的信息&lt;/li&gt;
&lt;li&gt;GRU 的第一层几乎不怎么使用旧的信息，即使到高层后也更倾向于使用当前输入&lt;/li&gt;
&lt;li&gt;LSTM 建模长程依赖的能力大大超过 ngram 模型，一个 11MB 的 LSTM 模型效果能略微超过一个 3GB 的 20-gram 模型&lt;/li&gt;
&lt;li&gt;对本身明显包含结构的文本(如内核代码)进行建模，当序列长度在 10 以下时，LSTM 和 20-gram 模型的差异不大，但随着序列变长，两者之间的差距逐渐变大，在 Linux 内核代码上，LSTM 能记忆的最大约 70 左右的距离&lt;/li&gt;
&lt;li&gt;LSTM 在迭代训练的过程中，首先建模了短程依赖，然后在此基础上逐渐地学习到对长程依赖的建模能力，这也是 seq2seq 论文中提到的逆序源语言序列有效的原因，因为这让模型先开始建模短程依赖再去建模长程依赖&lt;/li&gt;
&lt;li&gt;LSTM 并不能完全利用好最近的一些输入，LSTM 的错误中，有 42% 是 0-9 阶的 ngram 模型能够正确预测的&lt;/li&gt;
&lt;li&gt;相信像 Memory Networks 那样，如果能直接对序列中最近的历史进行 attention 操作，那么能够提高 RNNLM 的效果&lt;/li&gt;
&lt;li&gt;增大数据集、无监督预训练能提高 LSTM LM 对罕见词的效果&lt;/li&gt;
&lt;li&gt;增大模型大小，显著减小了 ngram 错误，但对其他类型的错误却没有明显的改善，这说明光是增大模型大小是不够的，可能需要设计更好、更新的结构&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>论文笔记：Visualization Analysis for Recurrent Networks</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/11/10/visualization-analysis-for-rnn.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2018/11/10/visualization-analysis-for-rnn</id>
    <published>2018-11-10T00:00:00+00:00</published>
    <updated>2018-11-10T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


简介
实验和结论




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org0f2633b&quot;&gt;简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb37ba0b&quot;&gt;实验和结论&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;hr /&gt;

&lt;div id=&quot;outline-container-org0f2633b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org0f2633b&quot;&gt;简介&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org0f2633b&quot;&gt;
&lt;p&gt;
这篇论文是清华大学语音和语言技术中心(Center for Speech and Language Technologies, &lt;b&gt;CSLT&lt;/b&gt;)2016 年的一篇论文，不过奇怪的是在 Google Scholar 上找了一圈，给出的引用链接竟然是 CSLT 的 wiki 链接，难道是没有正式发表的一篇论文吗？
&lt;/p&gt;

&lt;p&gt;
这篇论文主要从从近年来 LSTM 在 ASR 中的优异表现出发，用一些可视化方法，希望能深入理解这种有效性是如何产生的，非常有意思。这方面相关的工作有
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;2013 年的《Training and analysing deep recurrent neural networks》&lt;/li&gt;
&lt;li&gt;2014 年的《Empirical evaluation of gated recurrent neural networks on sequence modeling》&lt;/li&gt;
&lt;li&gt;2015 年的《LSTM: A search space odyssey》&lt;/li&gt;
&lt;li&gt;2015 年 Andrej Karpathy 的《Visualizing and understanding recurrent networks》&lt;/li&gt;
&lt;li&gt;2015 年的《Visualizing and understanding neural models in nlp》&lt;/li&gt;
&lt;li&gt;2016 年的《Representation of linguistic form and function in recurrent neural networks》&lt;/li&gt;
&lt;li&gt;2016 年的《Simplifying long short-term memory acoustic models for fast training and decoding》&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
后续这些论文的笔记我也会补充上来。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb37ba0b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgb37ba0b&quot;&gt;实验和结论&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgb37ba0b&quot;&gt;
&lt;p&gt;
首先论文用 LSTM 和 GRU 分别在华尔街日报(Wall Street Journal, &lt;b&gt;WSJ&lt;/b&gt;)数据集上进行对比，结果显示在 ASR 任务上，GRU 的效果要比 LSTM 稍好，至于为什么会更好，则在后面的实验中进行了可能的探讨。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0c30381&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org0c30381&quot;&gt;Activation patterns&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org0c30381&quot;&gt;
&lt;p&gt;
接着，在已经训练好的 ASR 模型上，输入 500 条音频数据，然后在网络的各层中随机挑选 50 个神经元，观察这些神经元的 cell value 的分布情况。
&lt;/p&gt;

&lt;p&gt;
在基于 LSTM 的模型上，1-4 层的 cell value 分布情况如下图所示:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/lstm_activation_distribution.png&quot; alt=&quot;lstm_activation_distribution.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到，在 LSTM 上，cell value 基本上分布在 [-10, 10] 这个区间，且在 0 附近比较密集，而这种密集程度在更高的层级上慢慢降低。
&lt;/p&gt;

&lt;p&gt;
而 GRU 的情况则很是不同，cell value 分布在 [-1,1] 这个区间中，然后在边界(即-1 和 1处)上比较密集，并且随层级变高而更加集中。如下图所示:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gru_activation_distribution.png&quot; alt=&quot;gru_activation_distribution.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
通过下面的图则能更直接地看到，LSTM 中的大部分 cell value 都在 (-2, 2) 区间上，而 GRU 中大部分 cell value 都在 [-1, -0.7] 和 [0.7, 1] 中。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/activation_percentage.png&quot; alt=&quot;activation_percentage.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
当然 GRU 的 cell value 分布在 [-1, 1] 这个区间是可以直接通过 GRU 的计算式推导出来的，只要 cell value 的初始值是 [-1, 1] 内的值，后面 cell value 的新值都会严格地被限制在 [-1, 1] 这个区间。
&lt;/p&gt;

&lt;p&gt;
论文对 LSTM 和 GRU在这点上的差异，作出如下结论:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;LSTM relies on greatpositive or negative cell values of some units to represent information.&lt;/li&gt;
&lt;li&gt;GRU relies on the contrast among cell values of different units to encode information.&lt;/li&gt;
&lt;li&gt;This difference in activationpatterns suggests that information in GRU is more distributed than in LSTM.&lt;/li&gt;
&lt;li&gt;this may lead to a more compact model with a better parameter sharing(in GRU)&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc433421&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc433421&quot;&gt;Neuronal Responsibility&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc433421&quot;&gt;
&lt;p&gt;
第二个可视化实验稍微复杂一些。首先要为一个神经元定义一个叫做 responsibility 的东西，这个 responsibility 指一个神经元对一个音素的 cell value 是 irregular 的概率，而所谓 irregular ，在 LSTM 上是至 cell value 超出 (-10, 10) 这个区间，在 GRU 上则指 cell value 包含在区间 (-0.5, 0.5) 之中。刚才的实验也说明了，神经元的 cell value，大部分都是 regular(和刚才的 irregular 对应)的，那么如果某个神经元对某个音素经常产生 irregular 的响应，这就说明这个神经元对这个音素很敏感，也就是说，它能识别出这个音素来。这个实验就是以此为出发点来进行的。
&lt;/p&gt;

&lt;p&gt;
在有上述定义后，统计 LSTM 各层对各个音素的 responsibility 超过 80% 的神经元数量，如下图所示:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/lstm_responsibility.png&quot; alt=&quot;lstm_responsibility.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
统计 GRU 各层对各个音素的 responsibility 超过 50% 的 unit 数量，如下图所示。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gru_responsibility.png&quot; alt=&quot;gru_responsibility.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
首先，两者都有一个共性，那就是同一层上，对某个音素的 responsibility 超过 80% 的神经元数量基本一样；区别是，在 LSTM 上，随着层数变高，对音素的 responsibility 超过 80% 的神经元总体呈现变多的趋势，而且会对某些个特别的音素的特别多；而 GRU 上层数变高，responsibility 超过 80% 的神经元在变少，也有对某些音素 responsibility 超过 80% 的神经元，但相对少一些。
&lt;/p&gt;

&lt;p&gt;
LSTM 在高层倾向于识别更多的音素，而 GRU 则相反倾向于只对少数音素作出响应。这种差异作何解释有待进一步讨论。
&lt;/p&gt;

&lt;p&gt;
就这个实验的出发点来说，在我看起来，应该是可以用统计物理学上的能量函数来作解释。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5bcd89a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5bcd89a&quot;&gt;Temporal Trace&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5bcd89a&quot;&gt;
&lt;p&gt;
第三个可视化实验也挺有意思，它将基于 LSTM 或 GRU 的 ASR 模型识别一条音频数据时的 cell vector 的连续变化情况记录下来，并用 t-SNE 降维后做可视化。结果如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/temporal_trace.png&quot; alt=&quot;temporal_trace.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到 LSTM 再次和 GRU 产生了区别。LSTM 的每层的轨迹大体上都是连续平滑的，论文里的解释是说 LSTM 能记得更多的东西，因此当前的输出会很大地受到过去记忆的影响，被平均后就变得平滑；而与此对比的 GRU，则倾向于给予新的数据更大的权重，换言之遗忘地会更快，因此在前几层的时候，轨迹变化地会更剧烈一些。
&lt;/p&gt;

&lt;p&gt;
另外一个不同是，GRU 的轨迹在高层后慢慢地也变得连续了，这就说明 GRU 的底层是倾向于记忆新的输入，但在高层则倾向于把旧的记忆也融合进来。这就很有意思了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd1d3f6a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd1d3f6a&quot;&gt;Memory robustness&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd1d3f6a&quot;&gt;
&lt;p&gt;
这个实验是为了比较 LSTM 和 GRU 的抗噪能力，方法也很简单，就是在输入数据的前部插入一些噪声数据，然后和正常的数据对比，观察网络中神经元的 cell value 的差异，结果如下图所示:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/noise_influence.png&quot; alt=&quot;noise_influence.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到 LSTM 中噪声的影响会长时间地持续下去，而在 GRU 中这种噪声的影响会比较快地被消除掉。也就是说 GRU 更鲁棒，从另外一方面来说，也可以认为 GRU 能记忆的东西更少，倾向于记忆新的输入，因而遗忘地更快，于是噪声数据产生的干扰就在后面被抹除了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1c73f5a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1c73f5a&quot;&gt;Application to structure design&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1c73f5a&quot;&gt;
&lt;p&gt;
在论文的最后，作者根据前几个实验得到的结论，尝试对 LSTM 作出一些调整。第一个调整是把 cell state 的更新操作放到计算输出之后，像 GRU 一样，并称这个特性为「lazy cell update」。结果显示这样修改后，LSTM 在 WSJ 数据集上的效果稍有提升并和 GRU 接近了。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/lstm_gru_improve.png&quot; alt=&quot;lstm_gru_improve.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
有意思的一个现象是在这样修改后，LSTM 高层的 temporal trace 变得更碎更不平滑了，接近 GRU 的情况。这就说明前面的一些差异，很可能是和 LSTM 与 GRU 更新 cell state 的顺序差异造成的，从计算式上来看似乎也说得通。
&lt;/p&gt;

&lt;p&gt;
此外作者还尝试在 LSTM/GRU 上加上 residual learning，效果也稍有提升。但是这个我持保留态度。
&lt;/p&gt;

&lt;p&gt;
此外比较遗憾的一点是，作者虽然尝试修改 LSTM 让 cell state 的更新延后，却没有尝试对 GRU 作出相反的修改也就是让 GRU 的 cell state 的更新提前。我的想法是这样修改后再去做对比，如果得到的结论和修改 LSTM 的结论一致，就更能说明问题了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>论文笔记：Sequence to Sequence Learning with Neural Networks</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/11/10/sequence_to_sequence_learning.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2018/11/10/sequence_to_sequence_learning</id>
    <published>2018-11-10T00:00:00+00:00</published>
    <updated>2018-11-10T00:00:00+00:00</updated>
    <description>
    
      <p>
三位来自 Google 的作者在这篇论文中提出了一种以两个 RNN 组合方式构成的网络结构，用来处理英语到法语的翻译问题，并且认为对于传统的深度神经网络(Deep Neural Network...</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
三位来自 Google 的作者在这篇论文中提出了一种以两个 RNN 组合方式构成的网络结构，用来处理英语到法语的翻译问题，并且认为对于传统的深度神经网络(Deep Neural Network, DNN)不能处理的输入和输出都是变长序列的问题，这种模型都能很好地进行处理。
&lt;/p&gt;

&lt;p&gt;
自 2006 年 Hinton 掀起深度学习这股浪潮，联结主义强势回归到现在已经有 10 年了，这 10 年里，深度学习已经在图像和语音两大领域取得了卓越的成就。然而大部分的深度神经网络仍然需要输入和输出的大小固定不变，并将一层一层不同类型的网络层组合在一起，通过巨量的数据、更有效的优化方法和训练技巧来达到目的，而这里的 &quot;输入和输出的大小固定不变&quot; 是一个很大的限制，比如说我们的语言、文字，天然就是变长的序列，这些网络结构要处理的话就必须要在核心模型之外在加上一些额外的处理。举个例子，图像识别中的图像一般也不是固定大小的，输入前一般都需要进行预处理将图像规整到同一尺寸。
&lt;/p&gt;

&lt;p&gt;
面对这一问题，一个很自然的方法就是使用循环神经网络(Recurrent Neural Network, RNN)，这是一种在空间结构上非常简单的模型，在一些不太复杂的问题上，甚至只需要三层结构就足够了，如下图所示(配图来自 Elman 的 《Find Structure in Time》)
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/simple_rnn.png&quot; alt=&quot;simple_rnn.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
相比传统的前馈神经网络(Feedforward Neural Network, FNN)，RNN 的独特之处在于其隐藏层的一个环状结构，这个结构相当于能够缓存当前的输入，并用之参与下一次的计算，这样就隐式地将 &lt;b&gt;时间信息&lt;/b&gt; 包含到模型中去了，在输入变长序列时，可以序列中的最小单元逐个输入。RNN 虽然在空间结构上可以很简单，但在进行训练时通常需要在 &lt;b&gt;时间维度&lt;/b&gt; 上展开(unroll)，所以可以认为它是一个在时间维度上的 DNN，于是 DNN 训练中会出现的 gradient vanish (梯度消失)也会出现，直观上可以将其理解为 &quot;记忆的衰退&quot;，换句话说， RNN 只能 &quot;记住&quot; 短期的信息。1997 年 &quot;长短期记忆单元(Long Short-Term Memory, LSTM)&quot; 被提出来解决这个问题，而本文提出的模型就是利用了 LSTM 的优点。
&lt;/p&gt;

&lt;p&gt;
虽说 RNN 能用于处理变长序列，但具体要怎么做呢？最早提出 RNN 之一的 Elman 做过的一些实验是这样的: 将序列中的元素逐个输入网络，并预测下一时刻的输入，比如一条句子逐个字符输入网络，并在输入第 n 个字符时预测第 n+1 个字符。这种方式虽然能处理变长的输入序列，但得到的输出序列却是和输入序列长度一样的，限制仍然还在。
&lt;/p&gt;

&lt;p&gt;
一种办法是在输出时增加一个 &quot;空白&quot; 的输出候选，然后在每次输出时取每一种可能输出结果的概率，得到一张路径网络后用类似 beam search 的方法来组装起真正的输出，由于 &quot;空白&quot; 输出的存在，最后得到的非空白输出序列的长度就变成可变的了。语音识别和一些 OCR、手写识别是这么做的，效果也还不错。
&lt;/p&gt;

&lt;p&gt;
而作者提出的方法是将两个 RNN 组合起来，以更加灵活地处理变长输入序列和变长输出序列。其模型结构如下(注意，这是一个已经 unroll 的网络结构)
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/seq2seq.png&quot; alt=&quot;seq2seq.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
模型的左侧(到输入为 &amp;lt;EOS&amp;gt; 为止)是一个 RNN 在输入序列 &quot;ABC&amp;lt;EOS&amp;gt;&quot; 上的展开，右侧是在输出序列 &quot;wxyz&amp;lt;EOS&amp;gt;&quot; 上的展开，其中 &amp;lt;EOS&amp;gt; 是一个表示序列结束的特殊符号。功能上，第一个 RNN 用来将输入序列映射成一个固定长度的向量，这个 &quot;固定长度的向量&quot; 即是 RNN 中间隐藏层所缓存的对整个输入序列的 &quot;记忆&quot;，我们可以说它表示了输入序列的语义；然后用第二个 RNN ，来从这个向量中得到期望的输出序列。
&lt;/p&gt;

&lt;p&gt;
除了这个特殊的模型结构之外，再就是用 LSTM 来保留 &lt;b&gt;一定程度&lt;/b&gt; 的长期记忆信息，并且作者表示复杂的网络结构(更多的参数)具有更强的表达能力，因此每个 RNN 用的都是 4 层的 LSTM, 参数两多达 380M, 也就是 38 亿 —— Google 的朋友们你们真是站着说话不腰疼啊，38 亿参数的模型，一般人哪来这么多数据喂饱这个大胃王，哪来那么强劲的机器来训练……
&lt;/p&gt;

&lt;p&gt;
再就是，作者说将输入序列倒序后，效果得到了显著地改善，BLEU 从使用该方法之前的 25.9 上升到 30.6，然而自己也对其原因表示不太清楚，只作出了一些猜想(也就是说，并无明确的理论依据)。
&lt;/p&gt;

&lt;p&gt;
原文中，作者对这个技巧的解释如下
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
While we do not have a complete explanation to this phenomenon, we believe that it is caused by the introduction of many short term dependencies to the dataset
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
以及
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
By reversing the words in the source sentence, the average distance between corresponding words in the source and target language is unchanged. However, &lt;b&gt;the first few words in the source language&lt;/b&gt; are now very close to the &lt;b&gt;first few words in the target language&lt;/b&gt;, so the problem's minimal time lag is greatly reduced.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
模型训练时，以最大化条件概率为目标，也就是说，其目标函数为
&lt;/p&gt;

&lt;p&gt;
\[\frac{1}{|S|}\sum \log P(T|S)\]
&lt;/p&gt;

&lt;p&gt;
而在模型训练好后，用于实际的预测时，则也采用了简单的 beam search 方法，即在模型参数确定的情况下，对输入序列 \(S\) ，按下面的式子求解输出序列
&lt;/p&gt;

&lt;p&gt;
\[\hat{T} = \arg\max_{T}P(T|S)\]
&lt;/p&gt;

&lt;p&gt;
下表是与其他模型在机器翻上的的效果对比，其中上面两行是其他模型的效果，下面六行是作者模型在不同参数设置时的结果。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/seq2seq_model_comparision.png&quot; alt=&quot;seq2seq_model_comparision.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
此外作者还尝试将自己的模型与传统的 SMT 系统进行结合，效果显著, BLEU 最好的达到了 37，超过 baseline system 4 个点。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/seq2seq_model_comparision2.png&quot; alt=&quot;seq2seq_model_comparision2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
sequence to sequence 模型被提出后，由于其灵活性，受到了广泛的关注，我个人是很喜欢这个模型中的想法的。然而现在流行的几个开源库对 sequence to sequence 模型的支持仍然不太理想，它们都要求在模型定义时就将输入序列的最大长度和输出序列的最大长度确定，对于长度不足的，则要用特殊符号进行填充，并在模型内部或外部做一些特殊处理。比如用 Python 的深度学习框架 Keras 来实现一个弱化版的 sequence to sequence 模型，可以这样:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;coding: utf-8&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;&quot;&quot;&quot;Sequence to Sequence with Keras 1.0&quot;&quot;&quot;&lt;/span&gt;

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; keras.models &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; Sequential
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; keras.layers.core &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; Dense, RepeatVector
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; keras.layers.recurrent &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; LSTM
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; keras.layers.wrappers &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; TimeDistributed

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;build_model&lt;/span&gt;(input_size, max_output_seq_len, hidden_size):
    &lt;span style=&quot;color: #cc99cc;&quot;&gt;&quot;&quot;&quot;&amp;#24314;&amp;#31435;&amp;#19968;&amp;#20010; sequence to sequence &amp;#27169;&amp;#22411;&quot;&quot;&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;model&lt;/span&gt; = Sequential()
    model.add(LSTM(input_dim=input_size, output_dim=hidden_size, return_sequences=&lt;span style=&quot;color: #6699cc;&quot;&gt;False&lt;/span&gt;))
    model.add(Dense(hidden_size, activation=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;relu&quot;&lt;/span&gt;))
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#19979;&amp;#38754;&amp;#36825;&amp;#37324;&amp;#23558;&amp;#36755;&amp;#20837;&amp;#24207;&amp;#21015;&amp;#30340;&amp;#21521;&amp;#37327;&amp;#34920;&amp;#31034;&amp;#22797;&amp;#21046; max_output_seq_len &amp;#20221;&amp;#20316;&amp;#20026;&amp;#31532;&amp;#20108;&amp;#20010; LSTM &amp;#30340;&amp;#36755;&amp;#20837;&amp;#24207;&amp;#21015;&lt;/span&gt;
    model.add(RepeatVector(max_output_seq_len))
    model.add(LSTM(hidden_size, return_sequences=&lt;span style=&quot;color: #6699cc;&quot;&gt;True&lt;/span&gt;))
    model.add(TimeDistributed(Dense(output_dim=input_size, activation=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;linear&quot;&lt;/span&gt;)))
    model.&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;compile&lt;/span&gt;(loss=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;mse&quot;&lt;/span&gt;, optimizer=&lt;span style=&quot;color: #66cccc;&quot;&gt;'adam'&lt;/span&gt;)

    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; model
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上面这段代码，从模型定义上，只对输出序列做了最大限制，但训练数据集中 &lt;b&gt;不允许出现不同长度的输入序列&lt;/b&gt; ，实际上不同长度的目标输出序列也不被允许。希望这种情况在将来能够有所改善，当然啦，不行的话可以自己用 Theano 写嘛～
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>论文笔记：Learning Phrase Representation using RNN Encode-Decoder for Statistical Machine Translation</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/11/10/phrase_representation_using_rnn_encoder_decoder.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2018/11/10/phrase_representation_using_rnn_encoder_decoder</id>
    <published>2018-11-10T00:00:00+00:00</published>
    <updated>2018-11-10T00:00:00+00:00</updated>
    <description>
    
      <p>
作者在这篇论文中提出了一种新的模型，并用来进行机器翻译和比较不同语言的短语/词组(phrase)之间的语义近似程度。这个模型由两个 RNN 组成，其中一个(Encoder)用来将输入的序列表示...</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
作者在这篇论文中提出了一种新的模型，并用来进行机器翻译和比较不同语言的短语/词组(phrase)之间的语义近似程度。这个模型由两个 RNN 组成，其中一个(Encoder)用来将输入的序列表示成一个固定长度的向量，另一个(Decoder)则使用这个向量重建出目标序列 —— 在机器翻译任务里，可以认为 Encoder 产生的向量是输入文本的 &lt;b&gt;语义表达&lt;/b&gt; ，而 Decoder 则根据这个语义表达产生目标语言的文本。
&lt;/p&gt;

&lt;p&gt;
模型结构如下图所示
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/encoder_decoder.png&quot; alt=&quot;encoder_decoder.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这个结构其实和 &quot;Sequence to Sequence Learning with Neural Networks&quot; (后面简称 &quot;Sequence to Sequence&quot;)里提出的结构是非常相似的，见下图:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/seq2seq.png&quot; alt=&quot;seq2seq.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
&quot;Sequence to Sequence&quot; 这篇论文的作者自己也表示 &quot;Our approach is very similar to Cho et al&quot; 。
&lt;/p&gt;

&lt;p&gt;
两种结构的不同之处在于，Encoder 输出的向量，在后者这里只用来作 Decoder 的第一个 time step 的输入，而在 Cho 的这篇论文里，它是要在 Decoder 的每一个 time step 中都参与计算的。即在 &quot;Sequence to Sequence&quot; 中，Decoder 中第 t 个 time step 时计算输出的式子为
&lt;/p&gt;

&lt;p&gt;
\[P(y_{t})=f(h_{t}, y_{t-1})\]
&lt;/p&gt;

&lt;p&gt;
而在 Cho 的论文中，则是
&lt;/p&gt;

&lt;p&gt;
\[P(y_{t})=f(h_{t}, y_{t-1}, c)\]
&lt;/p&gt;

&lt;p&gt;
其中 \(h_{t}\) 表示第 t 个 time step 时 Decoder 的内部状态(RNN 单元的 &quot;memory&quot;)，\(c\) 表示 Encoder 输出的向量。
&lt;/p&gt;

&lt;p&gt;
再有一点不同是，Cho 在这篇论文中提出了 GRU 这种 LSTM 的简化版本单元结构，使用的 RNN 也是以 GRU 而非 LSTM 组成的。对 LSTM、GRU 的细节这里就不深入了，反正 Cho 自己还有一篇论文就是比较 LSTM 和 GRU 的各自优缺点的，到时候也读一读记录一下笔记什么的。
&lt;/p&gt;

&lt;p&gt;
Cho 的 Encoder-Decoder 模型中，Encoder 的行为比较简单，重点在 Decoder 上。
&lt;/p&gt;

&lt;p&gt;
Decoder 中 t 时刻的内部状态的 \(h_{t}\) 为:
&lt;/p&gt;

&lt;p&gt;
\[h_{t}=g(h_{t-1}, y_{t-1}, c)\]
&lt;/p&gt;

&lt;p&gt;
该时刻的输出概率则为:
&lt;/p&gt;

&lt;p&gt;
\[P(y_{t}|y_{t-1}, y_{t-2},...,y_{1}, c)=f(h_{t}, y_{t-1}, c)\]
&lt;/p&gt;

&lt;p&gt;
模型训练时则去最大化给定输入序列 x 时输出序列为 y 的条件概率:
&lt;/p&gt;

&lt;p&gt;
\[\arg\max_{\theta}\frac{1}{N}\sum_{n=1}^{N}logP_{\theta}(Y_{n}|X_{n})\]
&lt;/p&gt;

&lt;p&gt;
这个模型用来做机器翻译是很自然的，除了机器翻译外，作者还用这个模型来得到英语 phrase 和法语 phrase 之间的语义近似值(或说相似性)，方法是用大量的英语和法语的 phrase pair 进行训练，每个 pair 在训练时最后都会有概率输出，就用这个概率值作为这个 pair 对的 score ，并在整个训练过程中更新，最后得到一张记录很多 phare pair 近似值的表，这个表可以在其他的统计机器翻译(Statistical Machine Translation, SMT)系统中使用 —— 比如要将某个英语 phrase 翻译成法语 phrase 时，可以从表中找到与该英语 phrase 最接近的 K 个法语 phrase 作为候选。
&lt;/p&gt;

&lt;p&gt;
在机器翻译上，作者用 Moses (一个 SMT 系统) 建立了一个 phrase based 的翻译模型作为 baseline system ，然后对比了以下四个模型的 BLEU 值
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Baseline configuration&lt;/li&gt;
&lt;li&gt;Baseline + RNN&lt;/li&gt;
&lt;li&gt;Baseline + CSLM + RNN&lt;/li&gt;
&lt;li&gt;Baseline + CSLM + RNN + Word penalty&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
所谓 BLEU 呢，是 BiLingual Evaluation Understudy 的缩写，是业界用来评估一个机器翻译系统水平的基准，如果遇到做机器翻译的上去问问 “你们的系统 BLEU 是多少” ，绝对会被认为你是专业人士，所以不妨记一下这个词 :) 。不过实际上 BLEU 和人工评价相差甚远，而且对于一些小的错误非常敏感，Yvette Graham 等人在 NAACL 2016 上专门有一篇长论文(Achieving Accurate conclusions in Evaluation of Automatic Machine Translation Metrics)讨论这个事情，这篇论文受到了很大的重视。
&lt;/p&gt;

&lt;p&gt;
回归正题，四种不同的模型的 BLEU 值如下表所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/bleu_of_models.png&quot; alt=&quot;bleu_of_models.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
其实也不见得比传统方法要好多少。当然据我所知， Encoder-Decoder 这个模型还是挺受重视的，如果我没记错的话，上次在 QCon 上看到阿里的跨境电商翻译系统应该是用上了 Encoder-Decoder 结构(不想误导，他们还有专业团队进行人工翻译)。
&lt;/p&gt;

&lt;p&gt;
phrase pair 打分的结果如下:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/pair_score.png&quot; alt=&quot;pair_score.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
其中第一栏是输入的英语 phrase ，第二栏是用传统的模型得到的最近似的三个法语 phrase，第三栏是用 Encoder-Decoder 模型得到的最近似的三个 phrase。
&lt;/p&gt;

&lt;p&gt;
就我对这篇论文的理解来说，应该是这样的。结尾再对计算两个序列之间的相似性这件事情说说自己的想法，在这件事情上，作者只是在训练过程中得到这样一个额外的、静态的结果，最后得到的那张表，其中包含的 phrase 是确定的、有限的，姑且认为其中的 phrase 都是粒度比 sentence 更细的合法单元，但实际上可以把 Decoder 的输出看成一个搜索空间，在给定 &lt;b&gt;任意&lt;/b&gt; 输入序列的时候，用输出序列在这个空间里确定搜索路径，这条路径上每一条边都是有置信度(概率)的，这样就可以直接得到一个条件概率来表征连个序列之间的相似程度，好处是可以处理任意的 sequence pair，这对实际问题应该会有帮助。当然这个想法可行性有待验证就是了。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>论文笔记：Memory Networks</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/11/10/memory-networks.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2018/11/10/memory-networks</id>
    <published>2018-11-10T00:00:00+00:00</published>
    <updated>2018-11-10T00:00:00+00:00</updated>
    <description>
    
      <p>

</p>
    
    </description>
    <content type="html">
      &lt;hr /&gt;

&lt;p&gt;
这篇论文是第一篇提出 Memory Network 的论文，和神经元图灵机(Neural Turing Machine)的论文在同一年。不过说实话，我觉得这篇论文的质量很一般，是比不上 NTM 那篇论文的，只不过其中提出来的一些观点和思想在后面逐渐被补充和完善，才有了现在 Memory Network 的名声。
&lt;/p&gt;

&lt;p&gt;
论文的出发点有这么几个:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;大部分 ML 方法都缺乏建立长期记忆(long term memory)的能力以及基于长期记忆的推理和处理 —— RNN 虽然能一定程度上做到，但由于 gradient vanish 的问题，实际上长期记忆在 RNN 中会衰退为短期记忆，LSTM 的提出对此问题有所改善，但效果有限&lt;/li&gt;
&lt;li&gt;作者主要是想进行基于知识库(Knowledge Base，或称知识图谱)的问答，但希望知识库可以作为模型的一部分并在此基础上进行 QA&lt;/li&gt;
&lt;li&gt;NTM 的结构很好，但是它能使用的 memory 还是太小了&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
首先明确一下这里的「Memory」也就是「记忆」的概念。在不同的领域，比如脑科学、认知科学、物理学，对记忆的定义和理解都不一样，我对这些学科不太懂，不知道该对应到其中的哪部分上去。在机器学习/深度学习里，所谓的记忆，只是指「处理过的数据中会对目前的处理过程造成影响的信息」，也就是说，是和时序存在关联的。图像识别里用大量的图片来训练模型，最后能识别出新的图像的类别，这算不算「记忆」呢？按照我们的观点，其实也算，但这种我们更多认为是从大量同类图片中提取出了「模式」，本文讨论的「记忆」并不是这样的，除了有时序关系，还要有一定的因果关系，比如说我前 1 分钟给我看一张搞笑图片，现在给我一张根据这个搞笑图片 PS 过的川普和希拉里的图片，我会 get 到笑点然后拍桌狂笑。
&lt;/p&gt;

&lt;p&gt;
总结一下的话是两点:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;时序性: 信息的输入是时序的，有先有后&lt;/li&gt;
&lt;li&gt;因果性: 先输入的信息对后输入的信息会产生影响，如果将两者调换，那么结果会不一样&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
看到时序性，很自然会想到 RNN，而它也满足第二点，只不过在它里面，「记忆」是隐式存在的，也就是它里面的 hidden state。但众所周知，RNN 因为 gradient vanish 的问题没法对长期记忆进行建模，LSTM 的提出倒是神来之笔，大大提高了 vanilla RNN 这方面的能力，后来 residual network 里的 skip connection 和 LSTM 里的 constant error flow 是很相似的。
&lt;/p&gt;

&lt;p&gt;
对概念的讨论就这样，先来看看论文的模型，大致如下：
&lt;/p&gt;



&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/memnn_model.png&quot; alt=&quot;memnn_model.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
整个模型分成五个模块，分别是:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;输入模块 I: 用来对输入进行特征提取&lt;/li&gt;
&lt;li&gt;泛化模块 G: 用来将输入根据一定的机制写入到 memory 中去&lt;/li&gt;
&lt;li&gt;记忆模块 memory: 用来存储信息，供后面的处理使用&lt;/li&gt;
&lt;li&gt;响应模块 R: 对特定的问题，用来从 memory 中提取信息并进行推理，得到输出信息&lt;/li&gt;
&lt;li&gt;输出模块 O: 对模块 R 的输出进行处理，表达成自然语言&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
如果读过神经元图灵机那篇论文，应该能一眼看出来模块 G 和模块 R 其实就是 NTM 里面的 write heads 和 read heads，在读写的时候计算 memory 里所有成分和当前数据的相似度，其实就是类似现在的 attention 机制了。然而有一个问题是，如果 memory 超级大，比如像作者说的一样，要将整个 freebase 作为 memory，别说计算 softmax 了，就是遍历 memory 都会是难以承受的，这问题该怎么解决呢？
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
Consequently, for efficiency at scale, G(and O) need not operate on all memories: they can operate on only a retrieved subset of candidates(only operating on memories that are on the right topic). We explore a simple variant of this in our experiments.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
如上，作者的办法是，建立 word 到 memory 的哈希，然后根据 question 来去检索出关联的 memory，只对这部分 memory 进行推理 —— 这其实就是一个倒排索引了……
&lt;/p&gt;

&lt;p&gt;
在这个模型中，模块 G 和模块 R 是核心所在，真的如作者所说要存储大规模的 memory 并在其基础上进行推理时，模块 G 和模块 R 的具体设计是很重要的，然后作者在后面描述基于 freebase 的 QA 任务时，模块 G 只是填充「下一个空白的 memory cell」，模块 R 则是「根据倒排索引去检索相关的 memory cell」，完全就是一套检索系统，整个训练过程也完全不是端到端的，臭不要脸 :)。直到 15 年 Sukhbaatar 提出了端到端的模型后， Memory Network 才算是真正意义上的完成了，我是这样认为的。
&lt;/p&gt;

&lt;p&gt;
总之我个人对这篇论文评价不高，虽然它提出的 Memory Network 这个模型的思想是不错的，某种意义上来说，它其实是一个框架而不是一个具体的模型，因为其中的 I/G/R/O 四个模块都是可以用不同 NN 来实现，扩展性很好，这也是后来持续地有 Memory Network 相关的工作的原因， NIPS 2015 还专门有一个 RAM workshop —— 所谓「RAM」是 &quot;RNN-Attention-Memory&quot; 的缩写。
&lt;/p&gt;

&lt;p&gt;
以上。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>论文笔记：LSTM: A Search Space Odyssey</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/11/10/lstm-a-search-space-odyssey.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2018/11/10/lstm-a-search-space-odyssey</id>
    <published>2018-11-10T00:00:00+00:00</published>
    <updated>2018-11-10T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


作者
观点
数据集
模型/实验/结论




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org514ac0e&quot;&gt;作者&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4d56869&quot;&gt;观点&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3bd67a7&quot;&gt;数据集&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf2acd86&quot;&gt;模型/实验/结论&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;hr /&gt;

&lt;div id=&quot;outline-container-org514ac0e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org514ac0e&quot;&gt;作者&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org514ac0e&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Klaus Greff&lt;/li&gt;
&lt;li&gt;Rupesh Kumar Srivastava&lt;/li&gt;
&lt;li&gt;Jan Koutnik&lt;/li&gt;
&lt;li&gt;Bas R. Steunebrink&lt;/li&gt;
&lt;li&gt;Jurgen Schmidhuber&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4d56869&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4d56869&quot;&gt;观点&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org4d56869&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;LSTM 结构的核心思想是其能维护历史状态的记忆单元，以及能调节信息出入的非线性门控单元(gating unit)&lt;/li&gt;
&lt;li&gt;自 LSTM 提出后，陆续有多种对 LSTM 结构的改进工作，并广泛应用到了许多规模、性质迥异的问题上，但却缺乏对 LSTM 及其变体中各个计算部件的系统性分析&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3bd67a7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3bd67a7&quot;&gt;数据集&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3bd67a7&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://catalog.ldc.upenn.edu/LDC93S1&quot;&gt;TIMIT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.fki.inf.unibe.ch/databases/iam-on-line-handwriting-database&quot;&gt;IAM 在线手写数据库&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.jsbchorales.net/index.shtml%20http://www-etud.iro.umontreal.ca/~boulanni/JSB%20Chorales.zip&quot;&gt;JSB Chorales 复调音乐数据集&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf2acd86&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf2acd86&quot;&gt;模型/实验/结论&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf2acd86&quot;&gt;
&lt;p&gt;
模型，LSTM 即八种待对比的 LSTM 变体
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;V: vanilla LSTM，即经典的 LSTM 模型&lt;/li&gt;
&lt;li&gt;NIG: 在 LSTM 基础上去除 input gate 得到的结构&lt;/li&gt;
&lt;li&gt;NFG: 在 LSTM 基础上去除 forget gate 得到的结构&lt;/li&gt;
&lt;li&gt;NOG: 在 LSTM 基础上去除 output gate 得到的结构&lt;/li&gt;
&lt;li&gt;NIAF: 在 LSTM 基础上去除 input activation function 得到的结构&lt;/li&gt;
&lt;li&gt;NOAF: 在 LSTM 基础上去除 output activation function 得到的结构&lt;/li&gt;
&lt;li&gt;NP: 在 LSTM 基础上去除 peephole 得到的结构&lt;/li&gt;
&lt;li&gt;CIFG: 既 GRU&lt;/li&gt;
&lt;li&gt;FGR: 在 LSTM 基础上让门控单元互相之间都有连接(full gate recurrence)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
实验
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;在 TIMIT 数据集和 IAM 在线手写数据库上使用双向 LSTM，在 JSB Chorales 数据集上使用 LSTM&lt;/li&gt;
&lt;li&gt;在 TIMIT 数据集和 JSB Chorales 上使用交叉熵作为损失函数，在 TIMIT 数据集上则使用 CTC&lt;/li&gt;
&lt;li&gt;对总共 27 个模型各进行 200 次对数尺度上的超参搜索，然后进行训练，共进行 5400 次实验&lt;/li&gt;
&lt;li&gt;每个数据集上的每个变体的 200 次实验中，最好的 20 个实验结果被拿来和 vanilla LSTM 模型的结果对比&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
结论
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;在三个数据集上，移除 forget gate 或 output activation function 都严重损害了模型性能，forget gate 对 LSTM 来说至关重要&lt;/li&gt;
&lt;li&gt;对连续实数数据上的监督学习问题，input gate、output gate 和 input activation function 的存在非常重要&lt;/li&gt;
&lt;li&gt;GRU 和 移除 peephole 的变体相比 vanilla LSTM 没有显著的性能差异，但它们都在一定程度上简化了 LSTM 结构&lt;/li&gt;
&lt;li&gt;full gate recurrence 结构没有改善 LSTM 的性能，相反还在 JSB Chorales 数据集上让结果变差了不少，加上它让 LSTM 更复杂了，不建议使用&lt;/li&gt;
&lt;li&gt;动量项对性能和训练速度都没有提高作用&lt;/li&gt;
&lt;li&gt;梯度裁剪会损害整体性能&lt;/li&gt;
&lt;li&gt;在使用 SGD 进行训练时，动量项对训练没什么显著好处；但在用 BSGD 进行训练时可能会起到一定的作用&lt;/li&gt;
&lt;li&gt;学习率和网络大小是 LSTM 中非常重要的两个超参&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>论文笔记：Hierarchical Memory Networks for Answer Selection on Unknown Words</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/11/10/hmn_for_qa.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2018/11/10/hmn_for_qa</id>
    <published>2018-11-10T00:00:00+00:00</published>
    <updated>2018-11-10T00:00:00+00:00</updated>
    <description>
    
      <p>

</p>
    
    </description>
    <content type="html">
      &lt;hr /&gt;

&lt;p&gt;
这篇论文是中科院自动化研究所(CASIA)在 9 月份发表的一篇论文，收录于 COLING2016。该论文基于 Memmory Network 做了一些改进，使得模型在特定的 QA 任务中能更好地从 memory 中选择答案，并且能一定程度上处理低频词甚至未登录词(unknown words)。论文的数据集以及模型实现已经在 Github 上开源，如果对论文细节没有太多兴趣，可以直接去 &lt;a href=&quot;https://github.com/jacoxu/HMN4QA&quot;&gt;项目地址&lt;/a&gt; 了解项目详情。
&lt;/p&gt;

&lt;p&gt;
论文使用的数据集如下表所示
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/hmn_datasets.png&quot; alt=&quot;hmn_datasets.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
数据集包含机票预订和酒店预订两个领域，而且包含中文的数据集哦，这点很赞，虽然数据量看起来并不是很多。截取中文的机票预订数据中的片段如下:
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
1 下午 好 ， 我 是 机票 预订 服务 代理 ， 需要 什么 服务 ？
2 我要 预订 一张 机票 。
3 请问 先生 您 从 哪里 起飞 ？
4 由 BGI 起飞 的 飞机 。
5 去 到 哪里 ？
6 到 印第安纳 去 。
7 电话 号 ？
8 13228762221 ， 这 是 我 的 号码
9 时间 是 ？
10 2015年09月26日22点 之前 。
11 先生 ， 乘客 的 身份证 是 ？
12 我 的 身份证号 是 110100195352319154 。
13 麻烦 说 下 您 的 名字 ？ 谢谢 先生 。
14 好 的 ， 名字 是 袁磊 。
15 先生 ， 我们 已经 成功 为 您 预订 。
16 这么 快 ， 非常 感谢您
17 订票 人 的 姓名 叫 什么 ？ 袁磊 16
18 出发 城市 是 哪里 ？       BGI 16
19 到达 城市 是 哪里 ？       印第安纳 16
20 出发 时间 是 什么 时候 ？  2015年09月26日22点 16
21 证件号码 是 多少 ？        110100195352319154 16
22 联系电话 是 多少 ？        13228762221 16
&lt;/pre&gt;

&lt;p&gt;
数据集的情况似乎有点像多轮对话，但并不完全是，如上 22 轮对话，其中前 16 轮是客服和客户之间的对话，这段内容被作为 history 输入到模型中储存为 memory，而 17-22 则是问题和对应的答案，每个问题的答案都是一个单独的词，是从 memory 中挑选出来的。所以从数据集上来看，本文的方法适用于一些像机票预订、酒店预订这种流程比较明确的业务。
&lt;/p&gt;

&lt;p&gt;
像这种数据集，如果要我做我会怎么做呢？粗暴点的思路是将 history 和 question 各自 encode，然后将两者一起用于计算来去预测输出，事实上之前不少 QA 方面的工作都是这种思路。论文开头就批评这种做法
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
the memory of these methods, such as Long Short-Term Memory(LSTM) (Hochreiter and Schmidhuber, 1997) and Gated Recurrent Unit (GRU) (Cho et al., 2014) compressing all the external sentences into a fixed-length vector, is typically too small to accurately rememberfacts from the past, and may lose important details for response generation
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
这个也是当前在 sentence representation 讨论得比较多的话题吧，将句子直接 encode 成一个固定长度的向量，是会丢失一些细节的。不过我觉得还是看应用场景，如果是那种一问一答且目的性不是非常强的 QA 场景，encoder-decoder 的框架问题不大，语义漂移(如万能回复)的问题可以在前期进行意图识别、情感分析来得到额外的特征输入到模型里。但像本文的这种数据集就不是简单的一问一答，而是先有了一部分历史信息，然后给定问题从历史信息里寻找答案，有点类似英语的阅读理解题目 —— 因此 PaperWeekly 在 &lt;a href=&quot;http://rsarxiv.github.io/2016/06/18/%E6%95%99%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E9%98%85%E8%AF%BB/&quot;&gt;教机器学习阅读&lt;/a&gt; 中介绍了《End-to-End Memory Networks》这一篇作为本篇论文基础的论文(好绕口呀)。
&lt;/p&gt;

&lt;p&gt;
对于类似本文的 QA 任务，早先的一些相关工作也是可以用上的，比如 Sukhbaatar 提出的端到端的 Memory Networks，文中记为「MemNN」。但是 MemNN 的问题在于它单纯在句子级别进行 &quot;推理&quot;，具体一点是只使用了 sentence level 的 attention 机制，见之前写的笔记: &lt;a href=&quot;end-to-end-memory-networks.html&quot;&gt;End-to-End Memory Networks&lt;/a&gt;。如果能进一步地在词级别进行分析，结果应该会更好一点。事实上也有人这么做了，2015 年俞扬等人的《Empirical study on deep learningmodels for question answering》论文中就提出了一种 &quot;Search-Response&quot; 结构的模型，先使用 MemNN 从 history 中挑选出相关的句子(supporting sentences)，这一步称为 &quot;Search&quot;；然后用 NTM 或者 NMT(Neural Machine Translation) 来从这些 supporting sentences 中生成答案，这一步称为 &quot;Response&quot;。在 &quot;Search-Response&quot; 结构中，Search 和 Response 两个步骤是分别独立训练的，也就是说这其实是一个 pipeline 的方法。
&lt;/p&gt;

&lt;p&gt;
所以本文的基本思想是: 结合 MemNN 和 &quot;Search-Response&quot; 的思想，得到一个端到端的系统。本文的模型结构如下图所示:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/hmn.png&quot; alt=&quot;hmn.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
图中左侧是模型的整体结构，右边的两个小图是左图中两个模块的细节图示。整个模型大体上可以划分为四个部分，分别是:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
sentence level memory and reasoning
&lt;/p&gt;

&lt;p&gt;
这部分将 history 信息转换成内部的 memory，并在 此基础上计算结果，同 MemNN，上图中右下块是这部分的图示，要注意的是这里为了简化画成了类似 RNN 的结构图，但并不是说 \(X\) 中的句子依次输入这个模型，然后更新自连接的 \(u_{r}{(S)}\)，这里的自连接只是表示多层结构(文中使用的层数为 3)，而这种多层结构和 RNN 的结构有共同之处。
&lt;/p&gt;

&lt;p&gt;
在这里，history 也就是 \(X\) 中的每个句子 \(x_{i}\) 和 question 也就是 \(q\) 都要表示成一个向量，使用的是《End-to-End Memory Networks》中的 position encoding 方法，即将句子中每个词的 embedding 加权求和，而这个权值和词在句子中的次序有关。
&lt;/p&gt;

&lt;p&gt;
总之这部分跟《End-to-End Memory Networks》中的内容基本一样，不赘述，详见 &lt;a href=&quot;end-to-end-memory-networks.html&quot;&gt;MemNN 的笔记&lt;/a&gt;。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
k-max pooling
&lt;/p&gt;

&lt;p&gt;
这部分连接 1 和 3，利用 1 输出的 internel state 和 question 一起挑选出 history 中和 question 最相关的 k 个句子。
&lt;/p&gt;

&lt;p&gt;
所谓的 internel state，就是图中的 \(\alpha^{(S)}\)
&lt;/p&gt;

&lt;p&gt;
\[\alpha^{(S)}=softmax(M^{T}u_{1}^{(S)})\]
&lt;/p&gt;

&lt;p&gt;
上式中 \(M\) 为 sentence level memory，\(u_{1}\) 为问题 \(q\) 的 representation。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
word level memory and attention: 使用 2 得到的 k 个句子，进行 word level 的 attention 来得到结果
&lt;/p&gt;

&lt;p&gt;
这部分使用 BiGRU 来得到 attention
&lt;/p&gt;

&lt;p&gt;
\[M^{(W)} = \{m_{t}\}_{t=(1,2,...)}\]
&lt;/p&gt;

&lt;p&gt;
\[m_{t}=\overrightarrow{h_{t}}+\overleftarrow{h_{t}}\]
&lt;/p&gt;

&lt;p&gt;
\[\alpha^{(W)}=softmax(v^{T}\tanh(Wu_{R}^{(S)}+U\hat{m}_{t}))\]
&lt;/p&gt;

&lt;p&gt;
这里的 \(alpha^{(W)}\) 就是 word level 得到的结果，但是这个结果是在 k 个句子中的词上的概率分布，没法直接用于第 4 步的计算，因此要做一次转换，将 \(\alpha^{(W)}\) 扩充为长度为 \(V\) 的向量，\(V\) 是词典的大小，方法是用 0 填充。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
output: 综合 1 和 3 的输出来计算最后的结果
&lt;/p&gt;

&lt;p&gt;
第一步得到的输出记为 \(p^{(S)}\)，第三步得到的输出记为 \(p^{(W)}\)，将这两者直接相加作为最后的输出
&lt;/p&gt;

&lt;p&gt;
\[p = p^{(S)}+p^{(W)}\]
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
如上所述，因为在 sentence level memory network 的基础上加上了 word level memory，作者将这个模型称为「Hierarchical Memmory Networks」，这是一个能够进行端到端训练、能在更细粒度的语言成分上进行&quot;推理&quot;的 QA 模型。
&lt;/p&gt;

&lt;p&gt;
下图是 HMN 和其他模型在给定的数据集上的对比结果
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/hmn_compare_with_others.png&quot; alt=&quot;hmn_compare_with_others.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
以及 HMN 模型使用不同的 word level encoder 时的效果对比
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/hmn_results.png&quot; alt=&quot;hmn_results.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
下面的图显示了模型回答一个问题时的过程
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;表格第一列是 history，这些内容将会被 encode 后储存到 sentence level memory 中&lt;/li&gt;
&lt;li&gt;需要回答的问题是: When does the client depart，正确答案是 history 中第 14 条中的日期&lt;/li&gt;
&lt;li&gt;表格第二列是 sentense level reasoning 的过程，其中的值是每一个 reasoning 层的 internel state 也就是 \(u_{r}^{(S)}\)，可以看到进行三次 reasoning 后正确的 supporting sentence 也就是第 14 条的权重已经非常的高了&lt;/li&gt;
&lt;li&gt;第三列是 k-max pooling，这里的 k 取值为 4，得到的就是 8、10、13、14 这四个候选的句子&lt;/li&gt;
&lt;li&gt;第四列是 word level 部分，使用 attention 来得到每个候选句子中的词作为答案的概率，这里概率最大的就是第 14 条句子中的日期&lt;/li&gt;
&lt;/ol&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/hmn_example.png&quot; alt=&quot;hmn_example.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
以上就是本篇论文的主要内容，至于开头作者提到的未登录词问题的处理，作者就是指着上面的图说：你看， &lt;b&gt;10/13/2018&lt;/b&gt; 这样的词也被找出来了！总之，作者没有提出一种对未登录词的解决办法，我猜他的意思是，在构建 vocabulary 的时候，不要根据词频去除低词频的词，而是照单全收喂给模型，而这个模型是能够将这种词频非常低的词正确地找出来作为答案的。
&lt;/p&gt;

&lt;p&gt;
我觉得这就有点标题党了哈……
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>论文笔记：Empirical Evaluation of Gated Recurrent Neural Networks on Sequence Modeling</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/11/10/evaluation_of_gated_rnn_on_sequence_modeling.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2018/11/10/evaluation_of_gated_rnn_on_sequence_modeling</id>
    <published>2018-11-10T00:00:00+00:00</published>
    <updated>2018-11-10T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


作者
观点
数据集
模型/实验/结论
概念和术语
总结




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org978c74f&quot;&gt;作者&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2c223b1&quot;&gt;观点&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org91bed9a&quot;&gt;数据集&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgcc13f36&quot;&gt;模型/实验/结论&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge0aa3d3&quot;&gt;概念和术语&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org0f12ce6&quot;&gt;总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;hr /&gt;

&lt;div id=&quot;outline-container-org978c74f&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org978c74f&quot;&gt;作者&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org978c74f&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Junyoung Chung&lt;/li&gt;
&lt;li&gt;Caglar Gulcehre&lt;/li&gt;
&lt;li&gt;KyungHyun Cho&lt;/li&gt;
&lt;li&gt;Yoshua Bengio&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2c223b1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org2c223b1&quot;&gt;观点&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org2c223b1&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;RNN 在很多机器学习任务尤其是变长输入输出的任务上效果拔群&lt;/li&gt;
&lt;li&gt;经典 RNN 有两个主要的问题: 梯度消失, 长期记忆急速衰减。&lt;/li&gt;
&lt;li&gt;解决 RNN 难以训练的尝试有两种: 一种是设计更好的学习方法(Bengio 2013)，另外一种是设计更复杂的激活函数&lt;/li&gt;
&lt;li&gt;LSTM 不会每次都重写 memory，而是可以通过 input/forget gate 在需要的时候尽量地保留原来的 memory&lt;/li&gt;
&lt;li&gt;LSTM/GRU 中额外增加的 cell state，让它们能记住较早之前的某些特定输入，同时让误差反向传播时不会衰减地太快&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org91bed9a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org91bed9a&quot;&gt;数据集&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org91bed9a&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;polyphonic music dataset(Boulanger-Lewandowski et al. 2012)

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Nottingham: &lt;a href=&quot;http://abc.sourceforge.net/NMD/&quot;&gt;http://abc.sourceforge.net/NMD/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;JSB Chorales: &lt;a href=&quot;http://www.jsbchorales.net/index.shtml&quot;&gt;http://www.jsbchorales.net/index.shtml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MuseData: &lt;a href=&quot;http://musedata.stanford.edu/&quot;&gt;http://musedata.stanford.edu/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Piano-midi: &lt;a href=&quot;http://www.piano-midi.de/&quot;&gt;http://www.piano-midi.de/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;Ubisoft Datasets&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgcc13f36&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgcc13f36&quot;&gt;模型/实验/结论&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgcc13f36&quot;&gt;
&lt;p&gt;
实验: 在上述几个数据集上，分别使用经典 RNN、LSTM、GRU 进行训练，并记录 NLL 的变化情况。
&lt;/p&gt;

&lt;p&gt;
结论: LSTM/GRU 在收敛速度和最后的结果上，都要比经典 RNN 要好，但 LSTM 和 GRU 在不同的数据集和任务上虽然互有优劣但差异不大，具体使用 LSTM 还是 GRU 还要视情况而定。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge0aa3d3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge0aa3d3&quot;&gt;概念和术语&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge0aa3d3&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
polyphonic music:
&lt;/p&gt;

&lt;p&gt;
(来自维基百科)
&lt;/p&gt;

&lt;p&gt;
复音音乐/复调音乐/和弦，一种“多声部音乐”。作品中含有两条以上（含）独立旋律，通过技术性处理，和谐地结合在一起，这样的音乐就叫做复音音乐。
&lt;/p&gt;

&lt;p&gt;
复音音乐第一个“音”字表示旋律，中国音乐界习惯将“复音音乐”称为“复调音乐”，主要是着眼于曲调一词，但“复调音乐”容易与二十世纪的“复调性音乐”一词混淆。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0f12ce6&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org0f12ce6&quot;&gt;总结&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org0f12ce6&quot;&gt;
&lt;p&gt;
实验很粗暴，结论很简单。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>论文笔记：An Ensemble of Retrieval- and Generation-Based Dialog Systems</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/11/10/ensemble-dialog-systems.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2018/11/10/ensemble-dialog-systems</id>
    <published>2018-11-10T00:00:00+00:00</published>
    <updated>2018-11-10T00:00:00+00:00</updated>
    <description>
    
      <p>

</p>
    
    </description>
    <content type="html">
      &lt;hr /&gt;

&lt;p&gt;
这篇论文在指出基于检索方法(retrieval-based)和基于生成方法(generation-based)的两种对话系统的问题后，提出了一种结合检索方法和生成方法的对话系统，并在 700w 的中文对话数据(来自微博、百度知道、贴吧等)上获得了比两种方法都更好的结果。
&lt;/p&gt;

&lt;p&gt;
检索方法在一些垂直领域的对话系统中比较常见，这是因为特定领域的对话系统中用户的目的性比较明确，多为查询信息或者提供信息(以完成某种「任务」)，通过检索和人工规则一般就能解决问题。而开放域的闲聊类场景下，如果有足够的数据，用生成方法会是一种比较好的选择。作者关注的开放域中的对话系统，这种场景下也可以应用一些检索方法和人工规则，但检索方法只能根据浅层语义来发现关联的回复，而尝试用人工规则覆盖开放域下的种种不同情况将会导致规则数量爆炸增长；生成方法固然可以生成知识库中没有的回答，但很容易抛出类似「呵呵」、「是吗」这种万能回复，这种语义漂移现象已经被很多将生成方法应用于对话系统的人发现并进行研究了。
&lt;/p&gt;

&lt;p&gt;
文本的思路是将检索方法和生成方法结合起来，主要思想有两点:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;使用生成方法时，使用检索到的回复作为额外的信息&lt;/li&gt;
&lt;li&gt;对检索方法和生成方法给出的结果，在最后进行重新排序&lt;/li&gt;
&lt;/ol&gt;



&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/ensemble-dialog-system.png&quot; alt=&quot;ensemble-dialog-system.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
具体一点的话，过程是这样的:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;对给定的 query \(q\)，首先从知识库中进行检索，得到候选的回复 \(r^{\ast}\)，这个 \(r^{\ast}\) 会有很多个&lt;/li&gt;
&lt;li&gt;将每个候选回复 \(r^{\ast}\) 和 \(q\) 一起输入到生成模型也就是图中的「multiseq2seq generator」中，后文又称之为「biseq2seq」&lt;/li&gt;
&lt;li&gt;\(q\) 和 \(r^{\ast}\) 都是一个句子，它们在 biseq2seq 中经过 encoder 被各自编码成一个向量&lt;/li&gt;
&lt;li&gt;将 \(q\) 和 \(r^{\ast}\) 的向量 &lt;b&gt;拼接&lt;/b&gt; 起来，decoder 以其作为输入，生成一个回复 \(r^{​+}\)&lt;/li&gt;
&lt;li&gt;将所有检索出的回复 \(r^{\ast}\) 和生成的回复 \(r^{​+}\) 混合起来，进行重排序，返回最优的一个&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
检索阶段没有太多好说的，就是搜索系统用的那一套东西，先根据 query 内容找到知识库中可能有关联的 &quot;问-答&quot; 对 \((q^{\ast}, r^{\ast})\)，然后进行排序，选出 1000 条最好的结果。需要注意的是，在排序时，\(q\) 和 \(q^{\ast}\) 的关联性、\(q\) 和 \(r^{\ast}\) 的关联性会一起被考虑。
&lt;/p&gt;

&lt;p&gt;
生成阶段，其所谓的「biseq2seq」的结构如下图所示
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/biseq2seq.png&quot; alt=&quot;biseq2seq.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这个模型里有两个 encoder 和一个 decoder，一个 encoder 用来对 \(q\) 进行编码，另一个 encoder 用来对 \(r^{\ast}\) 进行编码。两个 encoder 输出会拼接成一个向量输入到 decoder 中。不过论文没有就 biseq2seq 的具体数学表示和训练做详细说明，从引用文献里看，biseq2seq 的想法是来自 Barret Zoph 和 Kevin Knight 的一篇论文《Multi-source neural translation》，是 2016 年发表的一篇论文，回头再去了解一下。
&lt;/p&gt;

&lt;p&gt;
下表是论文中方法和其他一些方法的实验对比结果。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/ensemble-dialog-system-results.png&quot; alt=&quot;ensemble-dialog-system-results.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
论文中还展示了 biseq2seq 和 seq2seq 在生成回复时的结果对比，从下表来看，biseq2sq 生成的结果确实更有意义一些。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/biseq2seq_vs_seq2seq.png&quot; alt=&quot;biseq2seq_vs_seq2seq.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>论文笔记：End-to-End Memory Networks</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/11/10/end-to-end-memory-networks.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2018/11/10/end-to-end-memory-networks</id>
    <published>2018-11-10T00:00:00+00:00</published>
    <updated>2018-11-10T00:00:00+00:00</updated>
    <description>
    
      <p>

</p>
    
    </description>
    <content type="html">
      &lt;hr /&gt;

&lt;p&gt;
这篇论文是在看 &lt;a href=&quot;hmn_for_qa.html&quot;&gt;Hierarchical Memory Networks for Answer Selection on Unknown Words&lt;/a&gt; 时追过去的 —— 这篇论文里有些东西讲的不明不白，还好它里面说明一些思想来自哪里。
&lt;/p&gt;

&lt;p&gt;
论文标题为 &quot;End-to-End Memory Networks&quot; ，很显然这篇论文是基于 Memory Networks 来做了一些工作，按照惯例，论文在开头说了一些原始的 Memory Networks 的缺点:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Memory Networks 难以进行 BP 训练&lt;/li&gt;
&lt;li&gt;Memory Networks 需要更多的 supervision(这个没太懂，回头把 Memory Networks 再看一下)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
模型的基本结构如下图所示。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/memn2n_single_layer.png&quot; alt=&quot;memn2n_single_layer.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
模型的输入包含两部分，一个是图左端那个「Sentences」，即由多个句子组成的内容，这些句子会被输入到网络中并储存为「memory」，可以认为是在检索/问答时的历史信息或者说上下文；另一部分是 query 或说 question，就是图中下端那个 q，也是一个句子。模型最后的输出也是一个句子。
&lt;/p&gt;

&lt;p&gt;
模型的输出，按照我对这张图的理解，应该是一个经过 softmax 的 d 维向量(d 是 vocabulary 的大小)，但是这样的话就只能输出一个词了？从后面的实验部分来看确实是这样的，总感觉这样的话并不是很适用于常规的 QA 任务了。
&lt;/p&gt;

&lt;p&gt;
输入的 Sentences，首先通过 embedding 矩阵 A 得到 input memory。其实就是将每一个句子 encode 成一个向量，也就是图上的 \(m_{i}\)，这些 \(m_{i}\) 组合起来就得到 input memory，也就是涂上标为 &lt;b&gt;Input&lt;/b&gt; 的那块矩形 M。问题 q 同样通过 embedding 矩阵 B 来 encode 成一个向量 u，然后用 u 和 M 內积得到一个权值向量:
&lt;/p&gt;

&lt;p&gt;
\[p=softmax(u^{T}M)\]
&lt;/p&gt;

&lt;p&gt;
接着，输入的 Sentences 通过另外一个 embedding 矩阵 C 得到另外一个 memory 表示，也就是图上标为 &lt;b&gt;Output&lt;/b&gt; 的那块矩形 C，然后用上一步得到的权值向量来对 C 进行加权求和:
&lt;/p&gt;

&lt;p&gt;
\[o=\sum_{i}p_{i}c_{i}\]
&lt;/p&gt;

&lt;p&gt;
对于这部分，我的理解是，u 和 M 的內积相当于一个 attention，得到 attention 后，就用来在用于输出的 memory 也就是 C 中进行检索得到输出结果。不过还是有些地方不太明白，比如说反映在网络结构上，u 和 M 的內积是怎么体现的？输入连接两个 embedding 矩阵又是怎么体现的？
&lt;/p&gt;

&lt;p&gt;
在得到输出向量 o 后，按理来说直接 softmax 就可以得到结果吧，但是这里却和 question 的向量 u 做了一个加法才进行 softmax，不是很懂，也许和 ResNet 的那个 residual connection 是同样的思想？但是 2015 年 3 月份(这篇论文的发表时间)的时候 ResNet 还没有正式发表吧。
&lt;/p&gt;

&lt;p&gt;
以上就是单层时的情况，多层的时候就用前一层的(未经过 softmax 的)输出作为本层的输入向量 u，即
&lt;/p&gt;

&lt;p&gt;
\[u^{k+1} = o^{k}+u^{k}\]
&lt;/p&gt;

&lt;p&gt;
一图胜千言:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/memn2n_multi_layer.png&quot; alt=&quot;memn2n_multi_layer.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在多层结构的时候，作者又对 &quot;weight typing&quot; 做了不同的尝试 —— 不知道「weight typing」该怎么翻译，且看下文吧。
&lt;/p&gt;

&lt;p&gt;
可以看到，在上面的多层网络结构中，每一层都有一个 A 和 C，对 A 和 C 的处理，有两种方式:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Adjacent: 将前一层的输出 embedding 矩阵 C 作为本层的输入 embedding 矩阵 A: \(A^{k+1}=C^{k}\)&lt;/li&gt;
&lt;li&gt;Layer-wise: 像 RNN 一样，所有输入 embedding 矩阵 A 共享参数: \(A^{1}=A^{2}=...=A^{K}\)，输出矩阵 C 同理&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
在对句子的 encode 上，也有两种不同的处理方式:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;BoW: 简单的将句子中每个词的 embedding 累加起来: \(m_{i}=\sum_{j}Ax_{ij}\)，u 和 \(c_{i}\) 的计算同理&lt;/li&gt;
&lt;li&gt;position encoding: \(m_{i}=\sum_{j}l_{j}\cdot Ax_{ij}\)，这里的 \(l_{j}\) 就是所谓的反映了词序的 position encoding，它和后面的值进行 element-wise 的乘法而不是內积，而这个 position encoding 的计算方法是: \(l_{kj}=(1-j/J)-(k/d)(1-2j/J)\)，其中 j 是词在句子中的位置，J 是句子的长度，k 是这个词的 vocabulary id，d 是 vocabulary 的大小。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
此外就是 Sentences 中的句子之间也是有次序的，为了反映这个次序，又在计算 \(m_{i}\) 和 \(c_{i}\) 时加了一个额外的叫做 temporal encoding 的东西，分别记为 \(T_{A}(i)\) 和 \(T_{C}(i)\):
&lt;/p&gt;

&lt;p&gt;
\[m_{i}=\sum_{j}Axij + T_{A}(i)\]
&lt;/p&gt;

&lt;p&gt;
但是并没有说 \(T_{A}(i)\) 和 \(T_{C}(i)\) 是如何表现的，只是带了一句: Both \(T_{A}\) and \(T_{C}\) are learnd during training。另外，在模型中，句子的次序对真实的次序而言是倒序的。
&lt;/p&gt;

&lt;p&gt;
作者提出这个模型除了用在 QA 上外，还在语言模型上做了实验。在做语言模型时，是没有 question/query 的，所以 u 被设置为一个常量的向量(值都为 0.1)；然后每个 \(m_{i}\) 和 \(c_{i}\) 都是对应一个词而不是一个句子了，因为 LM 是 word-level 的问题嘛。
&lt;/p&gt;

&lt;p&gt;
最后总结一下，本文的主要贡献是增强了原始的 Memory Networks，让其称为一个端到端的模型，能更方便地使用 BP 方法进行训练。
&lt;/p&gt;

&lt;p&gt;
就酱！
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>论文笔记：Decoupled Neural Interfaces using Synthetic Gradients</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/11/10/dni.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2018/11/10/dni</id>
    <published>2018-11-10T00:00:00+00:00</published>
    <updated>2018-11-10T00:00:00+00:00</updated>
    <description>
    
      <p>

</p>
    
    </description>
    <content type="html">
      &lt;hr /&gt;

&lt;p&gt;
这篇论文是 DeepMind 在 2016 年 8 月 18 日发布的，最初是在&lt;a href=&quot;https://zhuanlan.zhihu.com/p/22143664&quot;&gt;智能单元&lt;/a&gt;上看到这个消息的，觉得挺有趣的，就去读了一下。
&lt;/p&gt;

&lt;p&gt;
这篇论文干了什么呢？它在现有的神经网络模型基础上，提出了一种称为 Decoupled Neural Interfaces(后面缩写为 DNI) 的网络层之间的交互方式，用来加速神经网络的训练速度。
&lt;/p&gt;

&lt;p&gt;
作者在开篇指出，在神经网络模型训练中存在几个问题
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Forward Locking: 前一层没有用输入完成计算，后一层无法进行根据输入进行计算&lt;/li&gt;
&lt;li&gt;Update Locking: 如果一个网络层依赖的层没有完成前馈计算，该层无法进行更新&lt;/li&gt;
&lt;li&gt;Backward Locking: 如果一个网络层依赖的层没有完成反向传播，该层无法进行更新&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
刚看到这说不定会想你这不是废话吗，前一层没计算好后一层怎么计算怎么更新？哎，作者表示我就是不信这个邪我就是要上天和太阳肩并肩啊！为什么呢，因为在一些情况下，神经网络的这种计算模式会带来一些问题，这些情况包括:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;由多个异步模块组成的复杂的系统(这个不懂……)&lt;/li&gt;
&lt;li&gt;分布式模型，模型的一部分共享给多个下游客户端使用，最慢的客户端将会成为模型更新速度的短板&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
所以呢，作者就想办法把这种训练时层与层互相依赖的限制干掉咯。
&lt;/p&gt;

&lt;p&gt;
第一个想法，是干掉 Update Locking 和 Backward Locking，让网络的每一层在完成前馈计算后能马上计算出残差，然后立即进行该层的参数更新，而不用等待后一层的前馈计算和误差反向传播。这个是怎么做到的呢？办法就是， &lt;b&gt;增加一个额外的模型&lt;/b&gt; ，去根据当前网络层的输出去预测其残差，并用预测到的残差去计算梯度，这个实际梯度的估计值，被称为「合成梯度(synthetic gradients)」。
&lt;/p&gt;

&lt;p&gt;
先来看看传统的误差反向传播(Backpropagation, BP)算法，我们假设一个有 N 层的神经网络，其第 i 层的激活值即输出为 \(h_{i}\) ，那么对第 i 层，其参数更新式子为:
&lt;/p&gt;

&lt;p&gt;
\[\begin{array}{rcl}
  \theta_{i} &amp;\leftarrow&amp; \theta_{i} - \alpha\delta_{i}\frac{\partial h_{i}}{\partial \theta_{i}} \\
  &amp;\leftarrow&amp; \theta_{i} - \alpha\delta_{N}\frac{\partial h_{i}}{\partial \theta_{i}}\cdot \prod_{j=0}^{N-i-1}\frac{\partial h_{N-j}}{\partial h_{N-j-1}}\end{array}\]
&lt;/p&gt;

&lt;p&gt;
可以看到，需要依赖后面所有层的激活值的计算。作者的思路就是只利用当前层的激活值 \(h_{i}\) 去得到当前层的残差 \(\delta_{i}\) 的估计值 \(\hat{\delta_{i}}\):
&lt;/p&gt;

&lt;p&gt;
\[\begin{array}{rcl}
  \delta_{i} &amp;\sim&amp; \hat{\delta_{i}} \\
             &amp;=&amp; M_{i+1}(h_{i})\end{array}\]
&lt;/p&gt;

&lt;p&gt;
但是可想而知，在初始的时候，这样一个「额外的模型 M」所给出的残差估计值肯定是与实际的残差有很大的偏差的，那么怎么办呢？办法就是用每一层的实际的残差去训练这个额外的模型 M —— 不过这样不就将 BP 的过程转移到另外一个模型里去了么，这不是耍流氓嘛！不过作者在这里又使用了一个技巧，将 BP 过程彻底干掉了。
&lt;/p&gt;

&lt;p&gt;
我们都知道，所谓误差反向传播，是先计算出最后一层的残差，然后用最后一层的残差去计算倒数第二层的残差，依次类推，故称「误差反向传播」。如果在训练模型 M 时依然遵照这个流程，毫无疑问 Update Locking 和 Backward Locking 依然存在，所以作者在计算每一层的“实际残差”时，用的是后一层的“合成残差”，而合成残差的计算是可以立即计算的。这里实际上又做了一次近似，也就是:
&lt;/p&gt;

&lt;p&gt;
\[\delta_{i} = \hat{\delta}_{i+1}\frac{\partial h_{i+1}}{\partial h_{i}}\]
&lt;/p&gt;

&lt;p&gt;
这样用这个近似的 \(\delta_{i}\) ，去评估模型 M 给出的残差估计值 \(\hat{\delta_{i}}\) ，并用两者之间的误差去更新模型 M。由于最后一层是能得到真正的残差的，所以最后一层的模型 M 能较快得到训练，随着最后一层的模型 M 被训练的越来越好，它所估计出的 \(\hat{\delta_{i}}\) 也能越接近真实的 \(\delta_{i}\) 。如下图所示:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dni_update.png&quot; alt=&quot;dni_update.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
再进一步地，作者表示，利用 DNI 的思想，去预测每一层的输入也是可以的，这样就把 Forward Locking 也去掉了。基本思想和合成梯度是一样的，不同之处在于预测每一层的输入时只用到第一层也就是输入层的输入:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dni_unlock_all.png&quot; alt=&quot;dni_unlock_all.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这样 Forward Locking、Update Locking 和 Backward Locking 都被去掉了，通过适当的设计，整个训练可以被很好地并行化、异步化了。
&lt;/p&gt;

&lt;p&gt;
DNI 的思想除了用在前馈神经网络上，也可以用于循环神经网络(Recurrent Neural Network, RNN)的训练上面，因为 RNN 在时间维度上展开后，其实就相当于是一个前馈神经网络了。而且由于应用 DNI 的模型，最多只有两层的网络层依赖，那么在用于 RNN 训练时，可以不用将 RNN 完全展开，而是可以以两个 time step 为最小单元进行展开，即一次只展开两个 time step，这样在存储上的消耗也可以被降低。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/rnn_dni.png&quot; alt=&quot;rnn_dni.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
来看看作者的牛皮
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
Although we have explicitly described the application of DNI for communication between layers in feedforward networks, and between recurrent cores in recurrent networks, thereis nothing to restrict the use of DNI for arbitrary network graphs. The same procedure can be applied toany network or collection of networks, any number of times.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
以上就是 DNI 的理论部分，实际上还有很多东西没有讲清楚，比如:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;那个额外的模型 M 的具体细节？&lt;/li&gt;
&lt;li&gt;增加了额外的模型 M ，相当于增加了参数数量，是不是更容易过拟合了？&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
作者首先在 MNIST 和 CIFAR-10 两个数据集上测试了 DNI 方法和 BP 方法之间的训练效果(只去除 Update Locking 和 Backward Locking)
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dni_every_layer.png&quot; alt=&quot;dni_every_layer.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
需要说明的是，这里用的模型(FCN 和 CNN)层数都不多，实验分别使用了 3-6 的层数，见上图中右侧部分，从该图来看，使用 DNI 的训练方法在训练速度和训练效果上并没有什么优势。这个实验只是表明，使用 DNI ，模型 &lt;b&gt;能够被训练&lt;/b&gt; 。
&lt;/p&gt;

&lt;p&gt;
第二个实验是这样的：对一个四层的前馈网络，以随机的顺序来更新每一层，并且每一层在被选中都是有概率的。在这样的情况下，模型依然是可以被训练的。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dni_sparse_update.png&quot; alt=&quot;dni_sparse_update.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
不过明显能看出来，概率值越大，收敛是越快的，最后在迭代次数达到 50w 次时，不同的概率都达到了接近的精度(2% 的误差)，不过一个四层的网络，真的不是过拟合了么……
&lt;/p&gt;

&lt;p&gt;
第三个实验在第二个实验的基础上，加上了 synthetic inputs ，也就是把 Forward Locking 去掉了，从结果上来看，和第二个实验差不多的样子。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dni_sparse_update_without_locking.png&quot; alt=&quot;dni_sparse_update_without_locking.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
最后在 RNN 上进行了三个实验，分别是:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Copy: 读入 N 个字符，然后将这 N 个字符原样输出，有点类似 char-level language model 和 autoencoder。&lt;/li&gt;
&lt;li&gt;Repeat Copy: 读入 N 个字符，以及一个表示重复次数的数字 R，然后重复输出 R 次这 N 个字符构成的序列。&lt;/li&gt;
&lt;li&gt;char-level language modeling: (持续地)读取一个字符，并预测下一个字符。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
结果如下图所示:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dni_on_rnn.png&quot; alt=&quot;dni_on_rnn.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
上图中 Copy 和 Repeat Copy 两栏中的值表示建模的最大序列长度，越大越好；Penn Treebank 一栏表示语言模型的困惑度(Perplexity，这里用 bits per word 进行度量)，越小越好。从实验结果上来看，在 Copy 和 Repeat Copy 任务上，使用 DNI 的模型能建模更长的序列。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>论文笔记：Ask Me Anyting: Dynamic Memory Networks for NLP</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/11/10/dmn.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2018/11/10/dmn</id>
    <published>2018-11-10T00:00:00+00:00</published>
    <updated>2018-11-10T00:00:00+00:00</updated>
    <description>
    
      <p>

</p>
    
    </description>
    <content type="html">
      &lt;hr /&gt;

&lt;p&gt;
这篇论文的作者来自一家 AI 公司 MetaMind，因此虽然用了「Memory Network」这个概念，但在思路上和 FAIR 提出 Memory Network 的几个人都很不一样。按我的观点，这篇论文里的模型与其说是 Memory Network，不如说是 encoder-decoder + attention。
&lt;/p&gt;

&lt;p&gt;
这篇论文同样是用来处理 QA 任务的，用的是 FAIR 公开的 bAbI 数据集。这个数据集所描述的场景，其实和 reading comprehension 更接近一点，先会有一段话进行描述，然后给出若干个问题，要求根据前面的描述来寻找答案，下面是一个例子:
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
I: Jane went to the hallway.
I: Mary walked to the bathroom.
I: Sandra went to the garden.
I: Daniel went back to the garden.
I: Sandra took the milk there.
Q: Where is the milk?
A: garden
I: It started boring, but then it got interesting.
Q: What’s the sentiment?
A: positive
Q: POS tags?
A: PRP VBD JJ , CC RB PRP VBD JJ .
&lt;/pre&gt;

&lt;p&gt;
其中以 &quot;I&quot; 开头的句子就是描述性句子，被称为上下文（Context）；&quot;Q&quot; 开头的句子则是问题，&quot;A&quot; 开头的句子是回答。在这个场景下，context 有一定的长度，要比 RNN 能处理的信息长度更大，但又是有限的。
&lt;/p&gt;

&lt;p&gt;
与 14 年那提出的 Memory Network 模型和 Neural Turing Maching 模型不同的是，DMN 里没有使用外部的存储空间，而是直接用一个 RNN 的 encoder 对 context 进行编码，将这个过程中输出的 hidden state 作为 memory —— 所以我会认为这个模型更接近 encoder-decoder + attention 而不是 Memory Network 了。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dmn_overview.png&quot; alt=&quot;dmn_overview.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
如上图所示，整个模型分为四个模块，和 Memory Network 里的 I/G/R/O 四个模块一一对应，但刚才也说了，其实这个模型和 Memory Network 并不是很像，所以作者为了对应上 Memory Network 的四个模块而作出类比，搞得有点不太好理解。图中的 Episodic Memory 模块并不对应 Memory Network 里的 memory 存储区域，非要说的话，应该是对应 Memory Network 里的 Response 模块，用来做结果的推理也就是 attention。
&lt;/p&gt;

&lt;p&gt;
接下来我还是按我的理解来梳理这篇论文吧。
&lt;/p&gt;

&lt;p&gt;
模型的 Input Module，其实就是一个 encoder，用来将 context 表示成 hidden state 形式的 &quot;memory&quot;。与 Memory Network 不同的是，各个 context 并不是分开处理的，而是串联成一个长的 sequence，然后喂给 RNN，然后只取每个 context 结束时输出的 hidden state。当然也有一些极端情况，比如说只有一个 context 的句子，这种情况下就直接输出每个 time step 的 hidden state 作为 memory。如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dmn_input_module.png&quot; alt=&quot;dmn_input_module.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
然后同样用一个 RNN encoder 对 quesiton 进行处理，不过这时只取这个 encoder 最后一个 time step 的 hidden state，作为这个 question 的表示。
&lt;/p&gt;

&lt;p&gt;
Episodic Memory Module 其实就是一个 attention 模块，用 question 在 Input Module 产生的 memory 上进行 attention。不过与普通的 attention 不同的是，这里的 attention 不是单纯地用 question 和 memory 进行內积算 softmax，而是再用一个 RNN encoder，将 Input Module 产生的 memory 依次输入到这个 encoder 中，并且每次都将 Question Module 的输出作为额外的信息参与计算，然后取这个 encoder 的最后一个 time step 的 hidden state 作为最后 Answer Module 里的 decoder 的 context vector。除了这点不同外，再就是这个过程可能会进行多遍，用每次计算出来的 context vector 输入到一个 decoder 里，用产生的 hidden state 再参与到 attention 中，这个迭代次数是认为设定的，在论文里作者就迭代了三次。如下图所示:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dmn_memory_module.png&quot; alt=&quot;dmn_memory_module.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
最后，将 Episodic Memory Module 的输出作为 context vector 输入到 Answer Module 的 decoder 里去，来生成最终的答案，这块比较简单，如下图所示。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dmn_answer_module.png&quot; alt=&quot;dmn_answer_module.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
比较有意思的是它里面那个 Episodic Memory Module 多遍迭代的结果，作者可视化后发现，第一遍的时候可能找到的是字面上相关的 context 句子，然后后面在迭代会慢慢定位到真正语义相关的 context 句子上，相当于是在做了推理。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dmn_focus.png&quot; alt=&quot;dmn_focus.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
此外，作者还把模型用在了情感分析上，对句子中词的 attention 结果，在迭代过程中的变化也展现出了类似的现象。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dmn_focus2.png&quot; alt=&quot;dmn_focus2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
以上。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>空洞骑士</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/10/27/hollow-knight.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2018/10/27/hollow-knight</id>
    <published>2018-10-27T00:00:00+00:00</published>
    <updated>2018-10-27T00:00:00+00:00</updated>
    <description>
    
      <p>




</p>
    
    </description>
    <content type="html">
      &lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/hollow_knight.jpg&quot; alt=&quot;hollow_knight.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
手残在神居被打懵，随便写点东西……
&lt;/p&gt;

&lt;p&gt;
《荒野之息》和《空洞骑士》是我入了 NS 后主要玩的两款游戏，刚才去瞄了眼，前者的游戏时间是 250 小时，后者是 75 小时。两款游戏都非常棒，不过给我的感觉是很不一样的。《荒野之息》的游戏引导（包括 NPC 指引、环境暗示）等做得非常好，所以玩起来非常舒服，哪怕是在守护者环绕的平原之塔，也可以避免战斗巧妙地利用障碍物阻挡怪物的视线一路爬上去，整个游戏除了必要的一些战斗外，玩家完全可以当一个和平主义者，爬爬山、做做菜、找找呀哈哈，真的可以当作一个放松心情的方式。《空洞骑士》就不一样了，成天要担心离长椅（存档点）太远死了要跑好长一段路去拣尸，地图上布满各种陷阱和麻烦的小怪，BOSS 战斗节奏和小怪相差极大难以适应，存档点居然还是要花钱买的……
&lt;/p&gt;

&lt;p&gt;
在某些方面，我还是要偏爱《空洞骑士》一些。
&lt;/p&gt;

&lt;p&gt;
开放世界的游戏，往往不会强迫你去完成具体的任务，并且会给玩家在主线剧情外充分多的可玩内容和形式，早几年很喜欢这种类型的游戏，如《Minecraft》、《上古卷轴》之类的。这一类的游戏如果愿意投入足够多的时间在里面，是能够发掘出很多乐趣的，然而工作几年后，我已经没有这么多精力去做这种探索了，与其花大量的时间在《荒野之息》里像做化学实验一样制造不一样的菜谱，我还不如去下厨房多学几个快手菜、家常菜呢。所以对我来说，游戏中故事对我的吸引力渐渐地成为了主要因素。而《荒野之息》的故事实在是有点单薄：远古魔王苏醒，王国发掘出古代遗迹制造四神兽和守护者作为战力，但最终被魔王控制，最后一刻公主觉醒力量封印了魔王，同时把为了保护自己而伤重濒死的护卫（就是主角）送到复苏神庙治疗，一百年后，主角醒来，然后去重新控制四神兽、解救公主。说故事梗概可以扩充更多的细节来进一步丰富，这在《荒野之息》里是通过主角失忆并在特定地点唤醒记忆的形式来得到体现，此外还有一些关键 NPC 的对话，除此以外绝大部分 NPC 的对话、任务都和主线剧情毫无关系。我玩过的游戏不多，开放世界的游戏更少，所以我觉得，这类游戏本来也不是为了讲故事的，它们希望的是玩家能通过游戏来讲自己的故事。
&lt;/p&gt;

&lt;p&gt;
相比之下，《空洞骑士》整个游戏，都在不遗余力地讲着一个故事，所有的 NPC 讲话都在补全着故事背景，甚至玩过一遍游戏后会发现某些 NPC 的讲话里其实暗示了故事中非常核心的部分，同时在游戏进度引导上也是不断地进行着设置悬念、揭晓答案然后设置更多悬念的过程，而且这个游戏讲故事的方式远远不止通过主线剧情、核心 NPC，场景音乐、背景装饰甚至怪物的内心话语，都在为这个过程服务。更要命的是，游戏里没有《荒野之息》里英拉、吟游诗人、回忆这些元素，来直接告诉你一些完整的信息，设定上任何一个角色对完整图景的了解、掌握都很少，更有很多文字是通过诗歌、历史记录、实验记录之类的方式留下来的，这就产生了很大的留白，给玩家带来了巨大的想象空间，甚至在不少地方玩家对故事的理解产生巨大的分歧并彼此争论。这是我喜欢的讲故事的方式，也是我喜欢的故事。
&lt;/p&gt;

&lt;p&gt;
正因为《空洞骑士》这种故事性，让我不能不联想起多年前玩的另外一款独立游戏来。什么游戏呢？那就是《洞窟物语》(Cave Story)，是日本一个独立开发者制作的经典独立游戏，甚至在游戏类型上和《空洞骑士》也接近，也是类银河战士恶魔城的游戏。这游戏是 2004 年发布的，年代有点久远，所以画面没有办法和《空洞骑士》相比（像素风），细节的丰富程度也要逊色不少，但音乐也很不错，作为一款十几年前的游戏，可以说是非常不错了。难度上比《空洞骑士》要低一些，目前在 steam 平台和 NS 上都有售。
&lt;/p&gt;

&lt;p&gt;
在游戏难度上，《空洞骑士》要比《荒野之息》难不少，但随着游戏时间的增加，基本上都能适应过来。而且我认为在这种故事性很强的游戏里，适当的难度是很必要的，如果故事内容太容易得到，那么那种「经过自己的努力挖掘出真相」的感受就会弱很多，毕竟游戏主要还是以视觉互动为主，不可能真的像小说一样用各种写作手法来提升悬念和制造带入感。
&lt;/p&gt;

&lt;p&gt;
最后附上两款游戏的 steam 链接 :)
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;空洞骑士：&lt;a href=&quot;https://store.steampowered.com/app/367520/Hollow_Knight/?l=schinese&amp;amp;cc=ie&quot;&gt;链接&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;洞窟物语：&lt;a href=&quot;https://store.steampowered.com/app/200900/Cave_Story/&quot;&gt;链接&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

    </content>
  </entry>
  
  <entry>
    <title>近况</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/10/20/recent.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2018/10/20/recent</id>
    <published>2018-10-20T00:00:00+00:00</published>
    <updated>2018-10-20T00:00:00+00:00</updated>
    <description>
    
      <p>
近一年来心理、精神状态总体上来说都不佳，一方面是工作上琐事繁多，另外一方面家庭方面的压力也开始上来了。


</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
近一年来心理、精神状态总体上来说都不佳，一方面是工作上琐事繁多，另外一方面家庭方面的压力也开始上来了。
&lt;/p&gt;

&lt;p&gt;
工作上，主要是一直做的都是算法落地的事情，这个过程和学术研究不一样，远不是简单重复调调参就行，会有大量的脏活、定制，繁杂到怀疑人生。这种工作状况也导致我基本上没有精力去在 NLP 本身上做太多沉淀，逐渐有些危机感和厌烦。上半年出了好多次差，在高铁上写代码、在出租车上写代码，也算是难忘的经历吧，但是真的很累。要命的是，我这种忙碌是否真的有价值（无论是对公司还是对自己），我也是持怀疑态度的。渐渐地对工作这件事情本身开始感到厌烦，因为我知道商业公司基本上都是这样的，但我又不是那种有勇气去走自由职业道路的人。
&lt;/p&gt;

&lt;p&gt;
家庭上，父母年纪大了，虽然不想说，但是真的是开始老态显露，开始担心他们的身体。我并不想回家去生活，但没有能力把他们接到身边来，也没有办法做到让他们在家里过得足够好 —— 这件事情一想起就难受，只能尽量不去想这个问题。弟弟还有几年也即将进入社会，也担心他将来的工作、生活。
&lt;/p&gt;

&lt;p&gt;
我的情绪控制能力不太好，压力一大的时候，性格里糟糕的一面就开始暴露出来，并且在长期高压的状况下，这些负面的音素已经开始逐渐地往上浮现，哪怕是在相对轻松的状况下，一些不好的行为也开始更多的出现了。还好公司里有一些同事始终非常耐心、理智，给了我一个锚点，让我能及时通过对比发现自己的问题，另外也感谢他们的包容吧。
&lt;/p&gt;

&lt;p&gt;
这是休完一个较长假期后的一些想法，虽然不是年末，但最近也在做一些新的计划。
&lt;/p&gt;

&lt;p&gt;
回来的第一周，调整了自己的作息，提早了一个小时起床，一方面是让早上有更多的时间去吃早饭、思考或者看点东西，另外一方面也是找点新鲜感吧。
&lt;/p&gt;

&lt;p&gt;
另外 《NLP 哪里跑》这个系列，原来是准备尽量系统化地去谈自己的理解，结果就是一篇文章牵扯内容太多，整理资料、梳理思路的周期有点太长了，那篇《自然语言处理在文学分析中的应用》的草稿已经在我本地躺了两个月了，还处在整理资料的阶段 —— 所以我打算换一个思路，一些小块的内容可以考虑单独发出来，然后有时间再汇总成长文吧。
&lt;/p&gt;

&lt;p&gt;
其他各种事情就不说了，近期我就想多写点东西，这件事情能让我心情舒缓不少。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>NLP哪里跑: Unicode相关的一些小知识和工具</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/10/20/nlp-road-3-unicode.html"/>
    <category term="NLP" scheme="http://www.zmonster.me/categories.html#NLP"/>
    <id>http://www.zmonster.me/2018/10/20/nlp-road-3-unicode</id>
    <published>2018-10-20T00:00:00+00:00</published>
    <updated>2018-10-20T00:00:00+00:00</updated>
    <description>
    
      <p>说一下在做自然语言处理的工作时会涉及到的一些小知识以及相关的工具</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org60c6ab9&quot;&gt;一、Unicode 简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org0a25915&quot;&gt;二、Unicode 在 NLP 中的应用&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgfc9e56a&quot;&gt;根据 Unihan 数据来从文本中筛选中文字符&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org80f5aa7&quot;&gt;用 category 属性判断标点、数字、货币单位等&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
本文是《NLP 哪里跑》系列的第三篇文章，系列文章如下：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zmonster.me/2018/03/26/nlp-thinking-1.html&quot;&gt;NLP哪里跑: 开篇及一些碎碎念 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zmonster.me/2018/06/25/nlp-thinking-2.html&quot;&gt;NLP哪里跑: 什么是自然语言处理 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zmonster.me/2018/10/20/nlp-road-3-unicode.html&quot;&gt;NLP哪里跑: Unicode相关的一些小知识和工具 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zmonster.me/2019/10/20/nlp-thinking-4.html&quot;&gt;NLP哪里跑: 文本分类工具一览 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div id=&quot;outline-container-org60c6ab9&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org60c6ab9&quot;&gt;一、Unicode 简介&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org60c6ab9&quot;&gt;
&lt;p&gt;
我们都知道，所有的数据，在计算机上都是以数字（严格来说是二进制）的形式存在的，文字也是如此，只不过咱们的编辑器、浏览器对这些数字做了特殊处理，将其对应的形状展示出来了而已。在这个基础上，不同的操作系统、平台、应用为了能够正常地交流，就必须约定一个统一的「计算机中的数字」到「实际文字」的对应关系（即编码标准），比方说数字 97 对应小写英文字母「a」、33528 对应「言」字之类的 —— 没错，所谓的编码标准，就相当于一个大的索引表，每个文字在这个索引表里都有一个对应的索引号（也就是我们刚才说到的数字）。
&lt;/p&gt;

&lt;p&gt;
在计算机系统发展早期，其实是并没有这样一个统一的编码系统的，美国一开始就用了 0-127 的值来编码，包括了大小写字母、数字、标点符号以及一些特殊符号，这就是“美国信息交换标准代码(American Standard Code for Information Interchange, &lt;b&gt;ASCII&lt;/b&gt;)”。显然 ASCII 是不适用于中文的，所以后来我国推出过 GB2312 标准，收录了 6763 个汉字，并在之后经过扩展有了 GBK 和 GB18030 多个编码标准；另外一方面，港澳台地区又独立发展出了繁体的 BIG5 编码……这些编码都是互相不兼容的，这就会导致使用编码 A 的网站，被使用编码 B 的计算机访问后显示为乱码的状况，而这里只提到了中英文的编码体系，实际上很多国家都有过自己的标准，而且很多是还在使用的。
&lt;/p&gt;

&lt;p&gt;
基于这种状况，后来计算机领域产生了一个叫做 Unicode 的统一编码，又称「万国码」，收录了世界上各个国家大部分的文字，并且仍然在不断增修，今年六月份发布了第十一个正式版本。目前使用最广泛的是 Unicode 实现是 UTF-8 编码。
&lt;/p&gt;

&lt;p&gt;
本文无意就编码标准和编码实现的关系、不同编码之间的同异这类问题做太多展开，只是说一下在做自然语言处理的工作时会涉及到的一些小知识以及相关的工具。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0a25915&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org0a25915&quot;&gt;二、Unicode 在 NLP 中的应用&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org0a25915&quot;&gt;
&lt;p&gt;
也许读者会疑惑，编码标准不就是字符和索引值的对应嘛，和 NLP 有什么关系呢？
&lt;/p&gt;

&lt;p&gt;
是这样的，Unicode 这个标准，并不是单纯做好所有文字的索引，它还对文字分门别类做了很多的整理，比如说同一个语系的文字会放在索引表的邻近区域，而一个文字是否是数字或标点、数学符号这些信息也都在 Unicode 标准中有记录，并且所有这些数据都是公开的。如果能善加利用这些信息的话，能帮助到咱们在 NLP 工作中对文字进行处理的部分。
&lt;/p&gt;

&lt;p&gt;
这里不准备对 Unicode 数据做系统、全面的说明，如有兴趣，可以前往 &lt;a href=&quot;http://unicode.org/charts/&quot;&gt;http://unicode.org/charts/&lt;/a&gt; 查看完整的 Unicode 数据，这里就以几个例子来讲讲我个人的一些认识和经验吧。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgfc9e56a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgfc9e56a&quot;&gt;根据 Unihan 数据来从文本中筛选中文字符&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgfc9e56a&quot;&gt;
&lt;p&gt;
Unicode 中中文数据的部分被称为「Unihan 数据库」，在&lt;a href=&quot;http://unicode.org/charts/unihangridindex.html&quot;&gt;这个页面&lt;/a&gt;可以看到 Unihan 中数据的范围。根据 Unihan 数据，我们可以得知在 Unicode 编码里，中文的索引值的范围包括以下几部分:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;U+3400 - U+4DB5: 「U+」表示这是 Unicode 编码，3400 是十六进制表示，换算成十进制是 13312，下同&lt;/li&gt;
&lt;li&gt;U+4E00 - U+9FCC&lt;/li&gt;
&lt;li&gt;U+F900 - U+FAD9&lt;/li&gt;
&lt;li&gt;U+20000 - U+2A6D6&lt;/li&gt;
&lt;li&gt;U+2A700 - U+2B734&lt;/li&gt;
&lt;li&gt;U+2B740 - U+2B81D&lt;/li&gt;
&lt;li&gt;U+2B820 - U+2CEA1&lt;/li&gt;
&lt;li&gt;U+2F800 - U+2FA1D&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
根据这个我们能很容易地写出一个检查某个字符是不是中文字符的方法来，如下
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;is_chinese_char&lt;/span&gt;(char):
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;char_idx&lt;/span&gt; = &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;ord&lt;/span&gt;(char)
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; 0x3400 &amp;lt;= char_idx &amp;lt;= 0x4DB5 &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;or&lt;/span&gt; \
       0xF900 &amp;lt;= char_idx &amp;lt;= 0xFAD9 &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;or&lt;/span&gt; \
       0x4E00 &amp;lt;= char_idx &amp;lt;= 0x9FCC &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;or&lt;/span&gt; \
       0x20000 &amp;lt;= char_idx &amp;lt;= 0x2A6D6 &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;or&lt;/span&gt; \
       0x2A700 &amp;lt;= char_idx &amp;lt;= 0x2B734 &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;or&lt;/span&gt; \
       0x2B740 &amp;lt;= char_idx &amp;lt;= 0x2B81D &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;or&lt;/span&gt; \
       0x2B820 &amp;lt;= char_idx &amp;lt;= 0x2CEA1 &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;or&lt;/span&gt; \
       0x2F800 &amp;lt;= char_idx &amp;lt;= 0x2FA1D:
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #6699cc;&quot;&gt;True&lt;/span&gt;

    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #6699cc;&quot;&gt;False&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
或者写个正则
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; re

&lt;span style=&quot;color: #ffcc66;&quot;&gt;CHINESE_CHAR_PAT&lt;/span&gt; = re.&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;compile&lt;/span&gt;(
    r&lt;span style=&quot;color: #66cccc;&quot;&gt;'[\u3400-\u4DB5\u4E00-\u9FCC\uF900-\uFAD9'&lt;/span&gt;
    r&lt;span style=&quot;color: #66cccc;&quot;&gt;'\u20000-\u2A6D6\u2A700-\u2B734\u2B740-\u2B81D'&lt;/span&gt;
    r&lt;span style=&quot;color: #66cccc;&quot;&gt;'\u2B820-\u2CEA1\u2F800-\u2FA1D]'&lt;/span&gt;
)

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;is_chinese_char&lt;/span&gt;(char):
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;bool&lt;/span&gt;(CHINESE_CHAR_PAT.match(char))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
以上都是笨办法，因为实际上我们并不需要去记中文的编码范围，而且由于 Unicode 是在扩展的，如果将来扩充了，那么扩充进来的新的字可能就没有办法用上面的方法检查了。前面提到，Unicode 标准做了多方面的整理，而这些整理结果都作为属性附加到每个 Unicode 字符上了。
&lt;/p&gt;

&lt;p&gt;
首先，每个 Unicode 字符都会被赋予一个名字，下面是一部分对照表
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;Unicode&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;Name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;a&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;LATIN SMALL LETTER A&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;9&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;DIGIT NINE&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;我&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;CJK UNIFIED IDEOGRAPH-6211&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;α&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;GREEK SMALL LETTER ALPHA&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
对于中文，我们只要取其 name，然后判断是否包含 CJK 这个关键词就行了。要怎么获取 Unicode 字符的 name 呢？用 Python 标准库里的 &lt;b&gt;unicodedata&lt;/b&gt; 模块即可
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; unicodedata

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;is_chinese&lt;/span&gt;(char):
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; unicodedata.name(char).startswith(&lt;span style=&quot;color: #66cccc;&quot;&gt;'CJK'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
而除了 name，Unicode 字符还有 block 和 script 两个属性：block 其实就是我们前面提到的连续编码区域，不过会有一个名字；script 是指每个文字的书写体系，可能会包含多个 block，详情见 &lt;a href=&quot;https://www.unicode.org/standard/supported.html&quot;&gt;文档&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
前面提到的汉字的编码区域和 block 名称的对应关系如下表所示
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;Block Name&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;Block Range&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;CJK Unified Ideographs Extension A&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;U+3400 - U+4DB5&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;CJK Unified Ideographs&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;U+4E00 - U+9FCC&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;CJK Compatibility Ideographs&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;U+F900 - U+FAD9&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;CJK Unified Ideographs Extension B&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;U+20000 - U+2A6D6&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;CJK Unified Ideographs Extension C&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;U+2A700 - U+2B734&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;CJK Unified Ideographs Extension D&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;U+2B740 - U+2B81D&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;CJK Unified Ideographs Extension E&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;U+2B820 - U+2CEA1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;CJK Compatibility Ideographs Supplement&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;U+2F800 - U+2FA1D&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
汉字对应的 script 名字是 Han，直接包括了上述所有 block。使用 Python 的 &lt;a href=&quot;https://pypi.org/project/regex/&quot;&gt;regex&lt;/a&gt; 这个工具，可以直接在正则表达式中使用 block 和 script。仍以汉字判断为例，可以这么写
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; regex

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;is_chinese_char&lt;/span&gt;(char):
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;bool&lt;/span&gt;(regex.match(r&lt;span style=&quot;color: #66cccc;&quot;&gt;'\p{script=han}'&lt;/span&gt;, char))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
可惜在标准库 unicodedata 中并没有访问 Unicode 字符的 block、script 等属性的方法。
&lt;/p&gt;

&lt;p&gt;
对于其他语言的文字，将上述方法中的参数（编码区域、script 等）稍作修改也是可行的，不再赘述。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org80f5aa7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org80f5aa7&quot;&gt;用 category 属性判断标点、数字、货币单位等&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org80f5aa7&quot;&gt;
&lt;p&gt;
Unicode 数据中，每个 Unicode 字符还有一个叫做 category 的属性，这个属性和字从属的语言无关。category 一共有 Letter、Mark、Number、Punctuation、Symbol、Seperator、Other 七大类，然后每个大类下还有一些小类，总体上是一个二级分类结构。因此在 Unicode 中有两个字母来组合表示一个 Unicode 字符的类型信息，我们可以用 &lt;b&gt;unicodedata.category&lt;/b&gt; 来得到这个信息
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; unicodedata

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; char &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;'1&amp;#22825;&amp;#12290;'&lt;/span&gt;:
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt;(char, unicodedata.category(char))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果为
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
1 Nd
天 Lo
。 Po

&lt;/pre&gt;

&lt;p&gt;
类型码和分类信息的对照表如下
&lt;/p&gt;
&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;类型码&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;类型信息&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Lu&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Letter, uppercase&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Ll&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Letter, lowercase&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Lt&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Letter, titlecase&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Lm&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Letter, modifier&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Lo&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Letter, other&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Mn&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Mark, nonspacing&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Mc&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Mark, spacing combining&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Me&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Mark, enclosing&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Nd&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Number, decimal digit&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Nl&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Number, letter&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;No&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Number, other&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Pc&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Punctuation, connector&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Pd&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Punctuation, dash&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Ps&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Punctuation, open&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Pe&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Punctuation, close&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Pi&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Punctuation, initial quote (may behave like Ps or Pe depending on usage)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Pf&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Punctuation, final quote (may behave like Ps or Pe depending on usage)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Po&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Punctuation, other&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Sm&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Symbol, math&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Sc&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Symbol, currency&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Sk&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Symbol, modifier&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;So&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Symbol, other&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Zs&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Separator, space&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Zl&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Separator, line&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Zp&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Separator, paragraph&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Cc&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Other, control&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Cf&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Other, format&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Cs&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Other, surrogate&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Co&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Other, private use&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Cn&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Other, not assigned (including noncharacters)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
如上，标点符号的类型码都是 P 开头的，根据这个就能把标点筛出来了
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; unicodedata

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;is_punctuation_char&lt;/span&gt;(char):
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; unicodedata.category(char).startswith(&lt;span style=&quot;color: #66cccc;&quot;&gt;'P'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
类似的，货币单位符号的类型码为 Sc，可以直接判断
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; unicodedata

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;is_currency_char&lt;/span&gt;(char):
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; unicodedata.category(char) == &lt;span style=&quot;color: #66cccc;&quot;&gt;'Sc'&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
类型码 N 开头的是数字字符，除了我们常见的十个阿拉伯数字外，像罗马数字、带圆圈的数字序号等都被涵盖在内。
&lt;/p&gt;

&lt;p&gt;
此外类型信息也可以在 regex 这个工具里使用，例如
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
找到文本中所有数字
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;regex.findall(r&lt;span style=&quot;color: #66cccc;&quot;&gt;'\p{N}'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#31532;&amp;#9321;&amp;#39033;'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
['⑩']

&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
找到各种括号表示开始的那一个
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;regex.findall(r&lt;span style=&quot;color: #66cccc;&quot;&gt;'\p{Ps}'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#12300;Unicode&amp;#12301;&amp;#65288;&amp;#21448;&amp;#21517;&amp;#19975;&amp;#22269;&amp;#30721;&amp;#65289;&amp;#35265;&amp;#12298;&amp;#26631;&amp;#20934;&amp;#12299;'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
['「', '（', '《']

&lt;/pre&gt;

&lt;p&gt;
或找到表示结束那一个
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;regex.findall(r&lt;span style=&quot;color: #66cccc;&quot;&gt;'\p{Pe}'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#12300;Unicode&amp;#12301;&amp;#65288;&amp;#21448;&amp;#21517;&amp;#19975;&amp;#22269;&amp;#30721;&amp;#65289;&amp;#35265;&amp;#12298;&amp;#26631;&amp;#20934;&amp;#12299;'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
['」', '）', '》']

&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
根据这张类型表，我们也可以写出一个用于文本预处理的简单清洗函数来，用来把一些奇奇怪怪的字符都从文本里去掉
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; regex

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;clean_text&lt;/span&gt;(text):
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#21435;&amp;#38500;&amp;#26126;&amp;#30830;&amp;#26080;&amp;#24847;&amp;#20041;&amp;#30340;&amp;#23383;&amp;#31526;&lt;/span&gt;
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;1. Zl: Separator, line&lt;/span&gt;
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;2. Zp: Separator, paragraph&lt;/span&gt;
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;3. Cc, Cf, Cs, Co, Cn&lt;/span&gt;
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;text&lt;/span&gt; = regex.sub(r&lt;span style=&quot;color: #66cccc;&quot;&gt;'[\p{Zl}\p{Zp}\p{C}]'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;''&lt;/span&gt;, text)

    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#23558;&amp;#31354;&amp;#30333;&amp;#31526;&amp;#24402;&amp;#19968;&amp;#21270;&lt;/span&gt;
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;text&lt;/span&gt; = regex.sub(r&lt;span style=&quot;color: #66cccc;&quot;&gt;'\p{Zs}'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;' '&lt;/span&gt;, text)
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; text
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
我们还可以根据数字类型 Unicode 字符的 name 来将其归一化到阿拉伯数字上，先看看数字类型的 Unicode 字符的 name 吧
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; unicodedata

&lt;span style=&quot;color: #ffcc66;&quot;&gt;chars&lt;/span&gt; = [&lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#9321;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'1'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#8546;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#12345;'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#9367;'&lt;/span&gt;]
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; char &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; chars:
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #66cccc;&quot;&gt;'{}: {}'&lt;/span&gt;.&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;format&lt;/span&gt;(char, unicodedata.name(char)))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
⑩: CIRCLED NUMBER TEN
1: DIGIT ONE
Ⅲ: ROMAN NUMERAL THREE
〹: HANGZHOU NUMERAL TWENTY
⒗: NUMBER SIXTEEN FULL STOP

&lt;/pre&gt;

&lt;p&gt;
可以看到，在 NUMBER/DIGIT/NUMERAL 后面的那个单词，就是对应数值的英文单词，只要把这个英文单词提取出来就得到了一个统一的表示，然后再将其转换成阿拉伯数字即可。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>NLP哪里跑: 什么是自然语言处理</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/06/25/nlp-thinking-2.html"/>
    <category term="NLP" scheme="http://www.zmonster.me/categories.html#NLP"/>
    <id>http://www.zmonster.me/2018/06/25/nlp-thinking-2</id>
    <published>2018-06-25T00:00:00+00:00</published>
    <updated>2018-06-25T00:00:00+00:00</updated>
    <description>
    
      <p>自然语言处理是一门旨在利用计算机技术来理解并运用自然语言的学科</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org6509521&quot;&gt;什么是自然语言处理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf872e5a&quot;&gt;自然语言处理的困难和限制&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org81c00b5&quot;&gt;自然语言处理的主要应用和关键技术&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
本文是《NLP 哪里跑》系列的第二篇文章，系列文章如下：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zmonster.me/2018/03/26/nlp-thinking-1.html&quot;&gt;NLP哪里跑: 开篇及一些碎碎念 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zmonster.me/2018/06/25/nlp-thinking-2.html&quot;&gt;NLP哪里跑: 什么是自然语言处理 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zmonster.me/2018/10/20/nlp-road-3-unicode.html&quot;&gt;NLP哪里跑: Unicode相关的一些小知识和工具 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zmonster.me/2019/10/20/nlp-thinking-4.html&quot;&gt;NLP哪里跑: 文本分类工具一览 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;div id=&quot;outline-container-org6509521&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org6509521&quot;&gt;什么是自然语言处理&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org6509521&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;教授：“你笑什么？”&lt;/li&gt;
&lt;li&gt;Z：“老师，学自然语言处理是我从小的梦想，能在这里我很开心！”&lt;/li&gt;
&lt;li&gt;教授：“用不着开心，给自然语言处理下个定义。”&lt;/li&gt;
&lt;li&gt;Z：“能帮助我们理解自然语言的技术就是自然语言处理。”&lt;/li&gt;
&lt;li&gt;教授：“能说详细点吗？”&lt;/li&gt;
&lt;li&gt;Z：“自然语言处理能帮我们理解人类的语言。你写了一篇文章，编辑器告诉你有些字写错了，这是自然语言处理；来了一封邮件，分个类告诉你这是垃圾邮件，这是自然语言处理；在输入框里输入‘香农’两个字，搜索引擎把香农的百科、学术成果展示在你面前，这是自然语言处理；你发了一条微博，说‘我想连任你的男朋友’，被微博自动删掉了，这是自然语言处理；你写论文从英文文献里抄了一段，用谷歌翻译转成中文放到自己论文里，这是自然语言处理；你对着 iPhone 说「hey siri 定 7 点钟的闹钟」，7 点钟 siri 提醒你该起床了，这是自然语言处理……”&lt;/li&gt;
&lt;li&gt;教授（生气）：“净说废话！定义是什么！？”&lt;/li&gt;
&lt;li&gt;Z：“我刚说了呀，老师。”&lt;/li&gt;
&lt;li&gt;教授：“考试你也这样？自然语言处理是，连任你的男朋友？白痴！换个人回答！”&lt;/li&gt;
&lt;li&gt;M：“老师，自然语言处理可以定义为研究在人与人交际中以及在人与计算机交际中的语言问题的一门学科。自然语言处理要研制表示语言能力和语言应用的模型，建立计算框架来实现这样的语言模型，提出相应的方法来不断完善这样的语言模型，根据这样的语言模型设计各种实用系统，并探讨这些实用系统的评测技术。”&lt;/li&gt;
&lt;li&gt;教授：“太棒了！好极了！”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
以上是一则瞎编的小品，套用了&lt;a href=&quot;https://movie.douban.com/subject/3793023/&quot;&gt;《三傻》&lt;/a&gt;中 Rancho 被教授问及“什么是机械装置”的场景。电影里通过这个场景里教授和“优等生”的死板与 Rancho 的灵活风趣之间的对比，来抨击僵硬死板的教育体制。不过电影总归是电影，它批评的问题我们要承认是客观存在的，但 Rancho 的行为是作为与一个极端对立的另一个极端来呈现并强化冲突和矛盾的，在我们认识事物、学习知识时，机械式地死板记忆固然不可取，毫无章法纯凭个人感性认识也不是什么值得鼓励的行为。
&lt;/p&gt;

&lt;p&gt;
那么什么是自然语言处理呢？
&lt;/p&gt;

&lt;p&gt;
自然语言处理，即 Natural Language Processing，简称 &lt;b&gt;NLP&lt;/b&gt; ，是一门旨在利用计算机技术来理解并运用自然语言的学科。在不同的场景下，有时候也称之为计算语言学(Computational Linguistics, &lt;b&gt;CL&lt;/b&gt;)或者自然语言理解(Natural Language Understanding, &lt;b&gt;NLU&lt;/b&gt;)。
&lt;/p&gt;

&lt;p&gt;
要理解 NLP 这个领域，只要紧紧抓住这几个要点就好
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
NLP 主要通过计算机技术来进行
&lt;/p&gt;

&lt;p&gt;
在底层理论层面，NLP 会涉及数学、语言学、认知科学等多个学科，但在最后一般是通过计算机技术来承载这些理论知识并发挥效果的。
&lt;/p&gt;

&lt;p&gt;
看起来好像是废话，但仍然要在此进行强调，计算机和人脑不同，它有其优点也有其缺点，而 NLP 技术也会受到现在计算机技术优缺点的影响。因此不要用我们人脑处理自然语言的过程和效果来要求 NLP 技术 —— 对我们中的绝大部分人来说，使用语言是很自然、很简单的，但不要因此就觉得用计算机来处理也会很简单。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
NLP 要理解和运用的，是自然语言
&lt;/p&gt;

&lt;p&gt;
所谓「自然语言」是指在我们的世界中自然地演变出来的语言，比如说英语、汉语、法语……之所以称之为「自然语言」，是为了和程序设计语言（如 C 语言、Java 语言、Python 语言等）等人造的语言进行区分。
&lt;/p&gt;

&lt;p&gt;
程序设计语言是有非常明确的、固定的语法的，用程序设计语言写出来的每一个句子，都会有唯一确定的含义，因此计算机只需要按照语法规则对其进行解析并执行就好了。
&lt;/p&gt;

&lt;p&gt;
自然语言则不同，它有相对稳定的语法规则，但这些语法规则都会存在例外而且一直在演变，加上其他一些特性，经常会出现歧义。处理歧义是 NLP 中非常核心的一部分内容。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
NLP 试图理解自然语言，但何谓「理解」其实并没有一个确定的标准
&lt;/p&gt;

&lt;p&gt;
理想意义上的「理解」自然语言，是要求 NLP 可以像人脑一样理解自然语言，然而现在脑科学研究上对于我们在使用语言时大脑是如何运作的，并没有一个系统的、全面的认识。因此这也就不能称之为一个标准，实际上在现有的技术框架下，用计算机做到完全理解自然语言，是不可能的。
&lt;/p&gt;

&lt;p&gt;
退而求其次的，我们一般认为只要在特定的场景中，机器能对我们用自然语言表达的要求进行正确的响应，就是理解了自然语言。
&lt;/p&gt;

&lt;p&gt;
注意这里有几个前提
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;「在特定的场景中」：一般我们认为，在限制了场景后，人们的目的以及语言的表达也会受到限制，因此能把语言表达的多样性降低，这样理解才具备可能性&lt;/li&gt;
&lt;li&gt;「进行了正确的响应」：我们认为机器的行为符合预期就是理解了，并不关心这中间的过程是否和人脑的运作机制是否一致、是否真正意义上的理解了语言的内涵&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
当然，这只是现在实际的 NLP 系统所遵循的标准，事实上还是有人从语言学、脑科学等不同角度尝试确定「理解」的过程和标准，让我们保持关注、期待未来吧。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;NLP 在理解自然语言之后还有加以运用，因此凡是有用计算机来处理、分析自然语言的应用，我们都可以说它是一个 NLP 过程 —— 当然有可能不止是 NLP。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
接下来我将根据这几点来讨论一下
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;NLP 有哪些困难和限制&lt;/li&gt;
&lt;li&gt;NLP 有哪些主要的应用&lt;/li&gt;
&lt;li&gt;NLP 有哪些主要的技术&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf872e5a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf872e5a&quot;&gt;自然语言处理的困难和限制&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf872e5a&quot;&gt;
&lt;p&gt;
我们每天都在使用自然语言，并不会对「理解自然语言」这件事情的困难之处有太多认识，但实际上，自然语言自身的一些特性，给计算机理解自然语言这件事情带来了非常多的困难。
&lt;/p&gt;

&lt;p&gt;
第一个特性是自然语言中普遍地存在歧义现象，这种歧义体现在多个层面：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
在语言的最小单元也就是词语的级别，存在多义词、同义词等现象
&lt;/p&gt;

&lt;p&gt;
比较经典的是 20 世纪 60 年代一位早期的机器翻译研究者给出的经典例子
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
The box is in the pen.
&lt;/pre&gt;

&lt;p&gt;
我们虽然可能不太清楚 &lt;b&gt;pen&lt;/b&gt; 的另外一个含义是「围栏」，但肯定能意识到这句话中 &lt;b&gt;pen&lt;/b&gt; 的含义不是「笔」。这个 badcase 从提出到现在已经有 50 多年了，但我们可以看到，仍然没有翻译系统能够在不加特殊处理的情况下解决这个问题（换言之这个 badcase 是可以通过特殊而丑陋的手段来解决的）。
&lt;/p&gt;

&lt;p&gt;
Google 翻译
&lt;img src=&quot;/assets/img/google-translate.png&quot; alt=&quot;google-translate.png&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;
百度翻译
&lt;img src=&quot;/assets/img/baidu-translate.png&quot; alt=&quot;baidu-translate.png&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;
搜狗翻译
&lt;img src=&quot;/assets/img/sogou-translate.png&quot; alt=&quot;sogou-translate.png&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;
与之相对的，中文里有一个例子是「意思」这个词的多义性
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
   他说：“她这个人真有意思(funny)。”她说：“他这个人怪有意思(funny)的。”于是人们认为他们有了意思(wish)，并让他向她意思意思(express)。他火了：“我根本没有那个意思(thought)！”她也生气了：“你们这么说是什么意思(intention)？”事后有人说：“真有意思(funny)。”也有人说：“真没意思(nosense)”。（原文见《生活报》1994.11.13 第六版）
&lt;/pre&gt;

&lt;p&gt;
当然，上述两个例子都是经过人为设计的精巧例子，大部分人们日常活动中使用的语言，并不会这么复杂。
&lt;/p&gt;

&lt;p&gt;
多义词之外，同义词也是非常普遍的语言现象，如：词语的缩写（如「人影办」之于「人工影响天气办公室」）、专有名词的别名（如「感冒」之于「上呼吸道感染」）、网络用语（如「蓝瘦」之于「难受」）、方言（如「包谷」之于「玉米」）、口语和书面语（如「脑袋」之于「头部」）……在 NLP 应用中，对同义词的辨别和处理工作也是非常多的，如：搜索引擎会通过查询改写(Query Rewrite)来将用户的搜索改写为同样含义但表述更为精准的语句；知识图谱里的实体链接技术本质上就是将实体名称（如人名、地名）的不同形式的表达和标准的表达对应起来；智能对话里可以通过同义词来更好地理解用户的问题……
&lt;/p&gt;

&lt;p&gt;
而在多义词、同义词理解上，目前 NLP 领域并没有一劳永逸的解决办法，有靠人工构建的小规模高质量知识库如 WordNet、HowNet、同义词词林，也有靠机器学习方法从大量语料中学习到词语的向量表示来隐式地反映词义 —— 量大但并不足够精确。前者往往质量很好但只能覆盖人们实际语言中很小的一部分，后者依赖于语料的数量、质量和领域，对于语料中较少出现的一些词往往就会得到莫名其妙的结果。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
在句子乃至更高层的语言单元如段落、篇章里，又存在结构性歧义的现象
&lt;/p&gt;

&lt;p&gt;
以句子为例，它是由词组成的，词和词之间有些是有关联的、有些是没有关联的，因此整体会形成一个结构，也就是我们在学习语言时了解到的「语法」。
&lt;/p&gt;

&lt;p&gt;
理想的情况下，任意给定一个句子，如果它的语法结构是唯一、确定的，那么我们只需要把它这个语法结构计算出来，然后再把前面提到的同义词、多义词的问题也解决了，那么这个句子的含义就能确定了。但实际情况是，自然语言的语法规则并不是一个非常严格的规则，在句子比较复杂的时候，往往会造成句子可以有多种不同但都合理的解释。
&lt;/p&gt;

&lt;p&gt;
举一些例子
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;“喜欢乡下的孩子” 可以有下面两种解释

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;[喜欢/乡下]的/孩子: “喜欢乡下的”作为定语修饰“孩子”&lt;/li&gt;
&lt;li&gt;喜欢[乡下/的/孩子]: “乡下的孩子”作为“喜欢”的宾语&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;“他背着总经理和副总经理偷偷地把钱存进了银行” 可以有下面 2 种解释

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;他[背着/总经理/和/副总经理]偷偷地/把/钱/存进/了/银行: “他”独自存钱&lt;/li&gt;
&lt;li&gt;他[背着/总经理]和/副总经理/偷偷地/把/钱/存进/了/银行: “他”和“副总经理”一起存钱&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;“放弃美丽的女人让人心碎” 可以有下面 2 种解释

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;[放弃/美丽/的]女人/让/人/心碎: “女人”让人心碎&lt;/li&gt;
&lt;li&gt;[放弃/美丽/的/女人]让/人/心碎: “放弃”让人心碎&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
再看英文的一个经典例句: &quot;Put the block in the box on the table&quot;。它可以有两种解释:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Put the block [in the box on the table]: &quot;on the table&quot; 修饰 &quot;box&quot;&lt;/li&gt;
&lt;li&gt;Put [the block in the box] on the table: &quot;on the table&quot; 限定 &quot;block&quot;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
如果再加上一个介词短语 &quot;in the kitchen&quot;，那么它可以有 5 种不同的解释；再增加一个的话，将会得到 14 种不同的解释。就这个介词短语导致歧义的情况来说，可能的歧义结构数量基本上是随着介词短语数量的增加而呈指数级上升。「指数级上升」是什么概念？那意味着想要靠枚举所有的可能性来解决歧义是非常低效甚至不可能的。
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
上述两种情况互相组合，又会造成更多、更复杂的歧义情况。
&lt;/p&gt;

&lt;p&gt;
正如前文所说，如何处理歧义并排除歧义，是 NLP 中非常主要的一部分内容，而且是非常困难的一部分，这是因为造成语言歧义的原因多种多样。
&lt;/p&gt;

&lt;p&gt;
造成词语歧义的原因，前面已经说过了一部分，也就是缩写、别名、网络用语、方言、口头语和书面语这几个；除此以外，比喻、拟人、谐音等手法也会使已有的词产生新的含义或和原来不相关的词产生同义；还有省略、指代等依赖上下文的情况也容易造成歧义……总之造成词语歧义的情况是非常多的。
&lt;/p&gt;

&lt;p&gt;
在词义消歧这个问题上，除了造成歧义的情况多种多样外，还有一个困难是消歧经常依赖于文本之外的、海量的「常识」，比如说前面那个机器翻译的例子「The box is in the pen」，我们为什么能判断「pen」的含义不是「笔」，是因为我们具备这些知识
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;盒子是有体积的&lt;/li&gt;
&lt;li&gt;笔不是一个容器&lt;/li&gt;
&lt;li&gt;相对盒子，笔一般都更小&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
并由此推理出：盒子在笔中是不合理的。但是抱歉，这种我们认为是常识的知识，计算机并不具备，它是无法作出这种推理的。我们说的机器学习、深度学习，本质上还是依赖于数据，也就是说，要见过相同的或者相近的数据，它才能理解，对于知识本身则基本没有学习到。
&lt;/p&gt;

&lt;p&gt;
在 NLP 发展历程中，也有人耗费巨大精力和金钱来将我们说的知识和规则整理成计算机可操作的数据，如 &lt;a href=&quot;https://zh.wikipedia.org/zh-hans/Cyc&quot;&gt;Cyc&lt;/a&gt;、&lt;a href=&quot;https://zh.wikipedia.org/zh/DBpedia&quot;&gt;DBpedia&lt;/a&gt;、&lt;a href=&quot;https://zh.wikipedia.org/wiki/Freebase&quot;&gt;Freebase&lt;/a&gt;，并演变成我们现在所说的知识图谱（其实以前就叫「知识库(Knowledge Base)」的，「Knowledge Graph」最早是 Google 的一个知识库的名字），但在 NLP 任务比如说词义消歧中，如何使用这些知识，仍然是一个很大的问题。
&lt;/p&gt;

&lt;p&gt;
至于结构歧义或者说语法歧义，其原因也可能有几方面
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;当其中的词语有歧义时，这个词的不同词义可能具有不同的语法功能，而造成最终的语法结构不同，如前文的例句「放弃美丽的女人让人心碎」的两个不同解释中，「美丽」一词分别作为名词和形容词，而造成了不同的语法解析结果&lt;/li&gt;
&lt;li&gt;自然语言语法本身并不是确定性的，即存在一些情况，哪怕其中每个词的词性、词义都是确定无疑的，可以得到的合理的语法解析结果也会有多个，前面那个「他背着总经理和副总经理偷偷地把钱存进了银行」的例句和那个英文例句就是这种情况&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
再加上语言一直在演变，新的语法规则不断出现，比如原来认为是错误的语法因为被普遍使用而被接受为新的语法规则，比如原有的语法规则被简化称为更简单的语法规则。这就导致很多语法规则都会有例外，而很多例外逐渐又成为了新的语法规则，就造成了「所有规则都有例外，所有例外都是规则」的现象。这就导致如果我们如果想靠语法规则来完成任务的话，最终就会陷入不停补充新的语法规则（或说例外）的境地里。
&lt;/p&gt;

&lt;p&gt;
前面说了歧义这个自然语言的特性，而自然语言还有一个很重要的特性，就是前面提到的语言的动态演变。除了它给带来的歧义现象，更重要的是，由于语言的动态演变，新的知识、语言现象一直在出现，如何捕获、学习到这些新的知识和语言规则，对 NLP 来说，同样是非常大的一个挑战，因为如果不能学习到新的语言知识，那么建立在旧数据上的 NLP 模型，往往连基本的分析都做不到，更别谈去解决歧义并理解了。
&lt;/p&gt;

&lt;p&gt;
此外，对中文、日文等一些语言来说，还有特殊的一点，就是在文字中，词和词不是天然就分隔开的。出于效果和效率等多方面的考虑，现有的 NLP 方法基本都建立在词的基础上，所以对中文这些语言来说，还需要对文字进行额外的、确定词和词之间边界的处理，也就是我们常说的「分词(Word Segmentaion)」。而分词这个过程本身，又存在不确定性，即同一个句子，可能的分词结果不一定是唯一的。
&lt;/p&gt;

&lt;p&gt;
先看看这些例子
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;“梁启超生前住在这里” 可能有两种分词结果
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;梁启超/生前/住/在/这里&lt;/li&gt;
&lt;li&gt;梁启/超生/前/住/在/这里&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;“武汉市长江大桥” 可能有两种分词结果
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;武汉/市长/江大桥&lt;/li&gt;
&lt;li&gt;武汉市/长江/大桥&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;“阿拉斯加遭强暴风雪袭击致多人死亡” 可能有两种分词结果
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;阿拉斯加/遭/强/暴风雪/袭击/致/多人/死亡&lt;/li&gt;
&lt;li&gt;阿拉斯加/遭/强暴/风雪/袭击/致/多人/死亡&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;“已取得文凭的和尚未取得文凭的干部” 可能有两种分词结果
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;已/取得/文凭/的/和/尚未/取得/文凭/的/干部&lt;/li&gt;
&lt;li&gt;已/取得/文凭/的/和尚/未/取得/文凭/的/干部&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;“今后三年中将翻两番” 可能有两种分词结果
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;今后/三年/中将/翻/两番&lt;/li&gt;
&lt;li&gt;今后/三年/中/将/翻/两番&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
可以看到，仅仅是分错一两个词，整个句子的含义就完全不一样了。中文分词的困难在于，如果要正确地进行分词，就要对句子的语义有正确的理解；另一方面，要正确理解句子的语义，又需要正确的分词结果。于是就出现了一个先有鸡还是现有蛋的问题。
&lt;/p&gt;

&lt;p&gt;
虽然有上述诸多困难，但 NLP 领域也形成了相应的应对方法，不过也只能说是「应对」而非「解决」，因为这些方法的目的都是追求解决上述问题在实际应用中常见的一部分，使对应的 NLP 系统能在受限场景中正确处理绝大部分比如 80% 或者 90% 的自然语言；而剩下未能处理的部分，则可以通过系统、产品上的一些设计，根据用户行为把它们找出来，加以研究并更新技术，如此逐渐迭代，来让 NLP 系统逐渐达到令人满意的效果。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org81c00b5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org81c00b5&quot;&gt;自然语言处理的主要应用和关键技术&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org81c00b5&quot;&gt;
&lt;p&gt;
我们比较熟知的一些比较成体系的 NLP 应用，有
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;机器翻译: 将一种自然语言的文字转换成另外一种自然语言的文字&lt;/li&gt;
&lt;li&gt;信息检索: 从海量的文档里检索出我们需要的信息，搜索引擎如 Google/Bing/Baidu 就是非常典型的信息检索系统&lt;/li&gt;
&lt;li&gt;文本摘要: 从较长的文档或文章中生成篇幅更小但内容完整的摘要&lt;/li&gt;
&lt;li&gt;智能对话: 通过对话的形式直接自动回答用户的问题或者执行特定的行为&lt;/li&gt;
&lt;li&gt;垃圾邮件过滤: 将垃圾邮件筛选出来并进行标记&lt;/li&gt;
&lt;li&gt;與情分析: 检测民众对公共事件的意见、态度、情感等倾向&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
当然实际上 NLP 的应用是非常多的，限于篇幅这里只讨论一下上述比较主要的应用。
&lt;/p&gt;

&lt;p&gt;
上面六个 NLP 应用，其实可以划分成两类，一类是需要理解文本的完整语义并作出响应，如机器翻译、文本摘要和智能对话；另一类只需要理解文本中特定的信息就可以，对于文本的完整语义并不太关心，比如信息检索、垃圾邮件过滤和與情分析。当然我这样划分并不太严格，比如说搜索引擎里也会有人用自然语言去描述自己的问题并期望得到正确的结果，而垃圾邮件过滤和與情分析有时候也需要在理解完整语义的基础上再去提炼「特定信息」，但大部分情况下我认为这样划分是没有问题的。
&lt;/p&gt;

&lt;p&gt;
在第一类即机器翻译、文本摘要和智能对话中，前两者都有明确的目标和评估标准，比如机器翻译有 &lt;b&gt;BLEU&lt;/b&gt; 指标，文本摘要有 &lt;b&gt;ROUGE&lt;/b&gt; 指标，而智能对话至今仍没有一个通用的评估标准，要么是借用一下机器翻译的 BLEU，要么是在特定的对话形式和对话任务里制定特殊的标准 —— 比如任务型对话里的槽填充率、检索型问答里的命中率和召回率。一个真正可用的智能对话系统，必然是一个融合系统，既有任务型问答也有检索型问答，说不定还会有开放域闲聊，那么在这样一个融合的系统里，各扫自家门前雪肯定是不行的，所以就现在来说，智能对话会比机器翻译和文本摘要要难一点 —— 倒不是说技术上难，而是难在确定目标和评估标准上。
&lt;/p&gt;

&lt;p&gt;
在第二类即信息检索、垃圾邮件过滤、與情分析这三者中，與情分析除了要分析出情感、态度倾向，还要确定这种倾向针对的是什么对象，所以相比信息检索和垃圾邮件过滤，又会更难一点。
&lt;/p&gt;

&lt;p&gt;
总的来说，在大部分情况下，对于 NLP 的应用，可以按照下面的原则来判断其难易程度
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;需要理解完整语义的任务，要比只需理解部分信息的任务更难&lt;/li&gt;
&lt;li&gt;有确定目标和评估标准的任务，要比没有的更容易&lt;/li&gt;
&lt;li&gt;要做复杂分析的任务，要比只做简单分析的任务更难&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
在技术方面，各个应用会涉及的更底层的关键 NLP 技术如下：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;早期基于规则的翻译系统: 句法分析&lt;/li&gt;
&lt;li&gt;统计机器翻译: 语言模型，隐马尔可夫模型(HMM，早期被广泛用于序列标注)&lt;/li&gt;
&lt;li&gt;神经网络机器翻译: seq2seq，注意力模型&lt;/li&gt;
&lt;li&gt;信息检索: 大量的文本预处理，实体抽取，主题模型，文本相似度量，知识图谱&lt;/li&gt;
&lt;li&gt;检索型的问答系统: 同信息检索，但还需要进行指代消解、省略消解&lt;/li&gt;
&lt;li&gt;任务型的问答系统: 意图识别，实体抽取，指代消解，省略消解，对话状态管理，自然语言生成&lt;/li&gt;
&lt;li&gt;垃圾邮件过滤: 文本分类&lt;/li&gt;
&lt;li&gt;與情分析: 观点词抽取，情感分析，关系抽取，意见挖掘&lt;/li&gt;
&lt;li&gt;文本摘要: (这个不太清楚，略过)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
上面的东西就是罗列一下以便形成整体印象，实际上像机器翻译和文本摘要我都没有做过，所以里面的关键技术我说不了太多，而信息检索、智能对话方面我相对有经验一些因此就写得比较多。
&lt;/p&gt;

&lt;p&gt;
虽然各个应用的目标都不一样，但最后我们会发现它们用到的很多方法都是共通或者干脆是一样的。
&lt;/p&gt;

&lt;p&gt;
最基础的，各个应用在开始前都需要对文本做预处理，不过预处理是一个很宽泛的概念，并没有一个或一套特定的方法，就我个人经验来说，因为处理的都是汉语，所以基本上都会做简繁统一转换，会把全角字符转成半角字符，会做标点的归一化处理(我才不会告诉你希腊字母里的问号在外形上和英文的分号一个样子呢)，会去除一些无效的字符(比如说不可见的零宽度的空白符)；英文里则会做词干提取、词形还原。很多讲 NLP 的文章说到预处理都会说停用词(stopwords)去除 —— 所谓停用词是指在特定领域里使用频率很高且往往不表达语义的词，如「了」、「的」，但实际上不是所有的应用上都需要去停用词、都可以去停用词的，比如说在作者身份鉴别这个应用上，是重度依赖虚词、介词等所谓功能词的，而在 NLP 里，虚词、介词这种词一般都会被视作停用词。
&lt;/p&gt;

&lt;p&gt;
预处理的目的是让文本变得更「干净」，少一些「脏东西」，同时尽量更加地规范，所以有时候也会把预处理形象地称为「清洗」。好的预处理能减少干扰信息，并且保留重要信息，同时一些规范化处理(如繁简统一转换、标点归一化处理、英语的词干提取和词形还原)还能够减少后续步骤需要处理的信息量。
&lt;/p&gt;

&lt;p&gt;
在做完预处理后，一般就是变着花样从文本里提取信息出来，以机器学习的角度来讲就是特征提取。根据不同的应用，这一步可能会非常简单，也可能会非常复杂。
&lt;/p&gt;

&lt;p&gt;
最初始的一个处理，就是从文本里，把词都提取出来，这一步对英文等语言来说很自然，按空格和标点分一下就好了，而对中文来说则需要专门做中文分词，这个是前面提到过的。从计算语言学的角度来讲，分词是「词法分析」的一部分，所谓「词法分析」除了确定词和词之间的边界，还需要确定词性(一个词是动词、名词还是别的什么)、词义(「苹果」是一种水果还是一种电子产品)，通俗一点来说，就是要解决: 哪些是词，有哪些词，各个词都是什么意思。
&lt;/p&gt;

&lt;p&gt;
分词的方法有多种，简单的如准备好一个超大的词表，然后在这个词表里找可能拼成当前这句话的词，然后在多种可能的组合里确定一个最有可能的，看着很粗暴但其实也还可以。不过现在主流上都是将分词当作序列标注问题来处理。所谓序列标注是说，给一个序列，模型能给这个序列上每一个元素都标注成为一个特殊的记号，对分词而言，要标注的记号可以有三种: 是不是词的第一个字，是不是词的最后一个字，是不是词中间的字。
&lt;/p&gt;

&lt;p&gt;
序列标注问题并不是 NLP 中特有的，但有不少 NLP 任务或技术都和序列标注有关，刚才说到的分词和词性标注(确定词性)，基本上都是当作序列标注问题来处理。除此以外，实体抽取或者更复杂的信息抽取，也被视为序列标注问题。所以如果是作为一个 NLP 从业人员，序列标注问题的相关方法，是必须要掌握的，建议 HMM、CRF、RNN 的原理摸熟吃透，掌握一两个好用的序列标注工具，囤点序列标注问题的数据集打磨一下自己的感觉。
&lt;/p&gt;

&lt;p&gt;
虽然说主流的方法都是将分词当作序列标注问题来做，但在实践中，囤点词典还是有益无害的，比如说做做新词挖掘、同义词挖掘、领域实体词的积累等等。至于怎么做这些挖掘、积累，各个应用有各个应用的做法，比如说搜索引擎靠 query 点击日志能把同义词或近义词找出来，原理就是类似两个人用了不同的词去搜索，但最后都点击了同一个链接这种思路；没有搜索引擎这样比较方便的用户反馈的，可以通过一些无监督或半监督的方法来做，会更难一些但总之是有方法的。
&lt;/p&gt;

&lt;p&gt;
做完词法分析后，一般会有一些不同的后续处理
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;区分哪些词是重要的，哪些词是不重要的，可能涉及到关键词提取、实体抽取、停用词去除等&lt;/li&gt;
&lt;li&gt;分析哪些词之间是有关联的，哪些词之间是没有关联的，可能涉及到短语抽取、关系抽取、句法分析等&lt;/li&gt;
&lt;li&gt;基于词对整个文本进行分类得到一个高度抽象的结果，可能涉及情感分析、意图识别、主题分类等&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
实体抽取前面说了，可以当作序列标注问题来做。停用词去除没什么好说的，一般就是在通用的一个停用词表的基础上，统计一下数据中高频的词加进去而已。关键词提取我觉得是很重要的一件事情，不过大部分情况下用 TFIDF 就能提取出不错的关键词来了，在此基础上辅以之前词法分析的一些结果如词性基本上就能把关键词捋得差不多，基本上名词、动词、形容词、实体词拿出来做关键词就差不多了。
&lt;/p&gt;

&lt;p&gt;
这里说到了 TFIDF，这个也是 NLP 里非常经典非常重要的一个技术，思路是很简单的，就是说对一个词，用两个数值来反映其在某篇文档或者某个句子里的重要程度，第一个是所谓词频(Term Frequency, &lt;b&gt;TF&lt;/b&gt;)，即这个词在当前文档/句子中出现的次数；第二个是所谓逆文档频率(Inverse Document Frequency, &lt;b&gt;IDF&lt;/b&gt;)，指出现过这个词的文档/句子的数量的倒数。通俗来说，就是，一个词在其他文档/句子里越少出现(IDF 值比较大)，在当前文档/句子中越多出现，那么它在当前文档/句子中就越重要。很朴素的思想，实际上这个思路最终是可以用信息熵来解释的，总之很实用。
&lt;/p&gt;

&lt;p&gt;
短语抽取、关系抽取和句法分析都是为了得到文本中的层次结构以更好地理解语义。其中短语抽取较简单，因为只需要看前后两个词是否有关系就好了，而关系抽取和句法分析都需要分析不相邻的词之间是否存在关联。这块不太熟，只是用过相关工具。不过我的观点是，句法分析是理解语义非常核心非常重要的一件事情，一个好的句法分析系统或工具，能够大大提高整个系统的效果。
&lt;/p&gt;

&lt;p&gt;
然后是情感分析、意图识别、主题分类这些技术，其实大部分情况下都是文本分类在不同应用场景里的别名而已。文本分类是一个相对简单但应用非常广泛的技术，也是一块值得花精力去好好掌握的内容，逻辑回归、支持向量机、GBDT，然后是深度学习常见的分类模型结构，把这些都好好掌握一下，并且在实际数据中熟练掌握好预处理、特征提取、特征选择的流程和技巧，受用无穷。至于说深度学习不用特征的都是傻蛋，我分类的时候用深度学习一样能把特征加上去，就是比你不加好，爱调不调。
&lt;/p&gt;

&lt;p&gt;
上述技术，基本上就能把任务相关的「理解」做得差不多了。在理解之后，一般还会有涉及应用的更具体的响应处理，如机器翻译、文本摘要、智能对话中会有自然语言生成，信息检索及检索型问答系统会有文本相似度量。
&lt;/p&gt;

&lt;p&gt;
其中自然语言生成(Natural Language Generation, &lt;b&gt;NLG&lt;/b&gt;)至今仍然是一个很困难的问题，在技术上，有基于统计语言模型的生成方法，也有基于神经网络语言模型的生成方法，近几年的变分自编码器(Variational Auto-Encoder, &lt;b&gt;VAE&lt;/b&gt;)和基于强化学习的生成方法使用得也越来越多了。但这里说的 NLG 多是在特定任务中，基于前面已经有的分析结果来生成较短的文本，至于生成小说什么的，看看都没有媒体和公司去吹就知道是多么难的一件事情了。
&lt;/p&gt;

&lt;p&gt;
这里提到了语言模型，也是一块可以好好掌握一下的内容。
&lt;/p&gt;

&lt;p&gt;
然后就是文本相似度量，也是非常重要的一项 NLP 技能。某种意义上来说，它和 NLP 的终极目标是等价的。如果任意给定两个句子，一个 NLP 系统能够准确地判断这两个句子是相似还是不相似，那么它就已经是一个完全理解自然语言的系统了。以机器翻译为例，其 BLEU 指标，就是判断翻译出来的句子，和给定的标准翻译是否相似，但实际上其计算方法很简单只是计算了表面相似，所以 BLEU 指标也并不是非常准确，在实际应用中还是要靠人来评估实际效果，但是这么多年了学术界和业界也并没有找到比 BLEU 更好多少的指标，所以将就用着，倒是也有 AMBER 和 METEOR 这种不光看表面相似的评估标准，但是计算太复杂了，所以并没有成为公认的标准。假如有一天有更好的评估标准能和人为评估效果更加接近，那才是机器翻译的大突破。
&lt;/p&gt;

&lt;p&gt;
文本相似的困难对很多非技术人员或者非 NLP 领域人员来说也经常难以理解，“这两个句子就是一个意思为什么就不理解呢”这样的话也是经常能听到的。理解一下，它真的很难。
&lt;/p&gt;

&lt;p&gt;
简单的、传统的相似度量有 LCS 相似度、Jaccard 系数、余弦相似度等，都是久经考验非常实用的方法，应对一些简单的任务措措有余，当然这些方法基本上都是看表面相似，所以泛化性会差一些，需要不断补充特征才能提高效果。如果有足够数据的话，一些基于深度学习的匹配模型会有非常不错的效果，这个不错不光是指其在固定的测试集上的效果，在集外数据的泛化性上都会很不错，当然前提是要有米。
&lt;/p&gt;

&lt;p&gt;
文本相似度量的应用也是很多的，在机器翻译和文本摘要里可以用来评估系统效果，在信息检索和智能对话里可以用来匹配正确的文档或问题，甚至有些时候一些分类任务也可以用文本相似度量来解决(有 A 类数据 1000 条 B 类数据 1000 条，判断下和 A 类数据更像还是和 B 类数据更像)。
&lt;/p&gt;

&lt;p&gt;
另外一方面，除了给定两个句子判断其相似程度外，相似句子的挖掘和生成，也是很有意思的一件事情。生成相似问题这件事情，专业的说法叫做「复述(Paraphrase)」，它和相似度量是互相促进的，相似度量做的好，那么就可以挖掘出更多的相似句子来做训练复述生成模型；复述生成做的话，反过来又可以给相似度量模型提供训练数据。
&lt;/p&gt;

&lt;p&gt;
对于深度学习在 NLP 中的应用，比较核心的技术有
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;word embedding，也就是我们俗称的词向量，通过大量数据无监督(不需要标注)训练，可以用一个向量来表示一个词的词义，理想情况下如词性、词义、情感、主题等各种信息都可以在这个向量中得到表达 —— 当然这只是一个感性认识，目前对于这个向量实际的含义和解释，我们并不太关心，好用就对了。此外 word embedding 因为能比较好地反映词义，还可以用来做关键词、同义词挖掘，在各项深度学习相关的 NLP 任务中，基本也是标配了&lt;/li&gt;
&lt;li&gt;序列标注方面，BiLSTM+CRF 已经是很主流的做法&lt;/li&gt;
&lt;li&gt;seq2seq 和 attention，这两个技术都是在神经网络机器翻译的研究中被提出来的，然后也被广泛用到如智能问答、文本摘要等重要 NLP 应用上。这两者一般是一起出现的，现在已经演变成了一种计算框架，具体的方法和细节则已经有了很多的变化&lt;/li&gt;
&lt;li&gt;自然语言生成方面前面提到过 VAE 和强化学习，近一年内生成对抗网络(Generative Adversarial Nets, &lt;b&gt;GAN&lt;/b&gt;)也开始有在这方面的应用&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
深度学习相关的技术一般都会需要比较多的数据，但我们会发现在实际的任务中，可能并没有那么多数据来让我们上深度学习，或者数据太多但却包含了太多噪音数据。土豪的办法是用金钱来为所欲为顺便创造点特殊岗位造福社会，对这件事情我是举双脚支持的。比较经济的做法是先使用前面提到的传统的、经典的方法，同时在产品、系统的上设计好良好的反馈渠道，在冷启动后不断进行迭代优化，同时有意识地从日志、用户反馈中积累数据，到达一定的量后开始上深度学习来解决传统模型泛化性不够好的问题。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>NLP哪里跑: 开篇及一些碎碎念</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/03/26/nlp-thinking-1.html"/>
    <category term="NLP" scheme="http://www.zmonster.me/categories.html#NLP"/>
    <id>http://www.zmonster.me/2018/03/26/nlp-thinking-1</id>
    <published>2018-03-26T00:00:00+00:00</published>
    <updated>2018-03-26T00:00:00+00:00</updated>
    <description>
    
      <p>决定开一个系列，专门讲讲 NLP 的东西</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
本文是《NLP 哪里跑》系列的第一篇文章，系列文章如下：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zmonster.me/2018/03/26/nlp-thinking-1.html&quot;&gt;NLP哪里跑: 开篇及一些碎碎念 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zmonster.me/2018/06/25/nlp-thinking-2.html&quot;&gt;NLP哪里跑: 什么是自然语言处理 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zmonster.me/2018/10/20/nlp-road-3-unicode.html&quot;&gt;NLP哪里跑: Unicode相关的一些小知识和工具 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zmonster.me/2019/10/20/nlp-thinking-4.html&quot;&gt;NLP哪里跑: 文本分类工具一览 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
从事算法工作已经有四年多了，回过头来看过去几年自己做的事情，说实话，谈不上优秀和努力，中规中矩平凡普通，仅此而已。去 Crow 家玩，给他在中科院读研即将毕业的妻子梳理 NLP 的脉络，看到的仿佛是刚工作时候的自己 —— 什么概念都有一点，但又仿佛什么概念都没有，不知道该往哪个方向走，但焦虑和欲望又逼迫你不得不往前走。后来懂得越来越多，做得事情也越来越多，心思却越来越浮泛，在重复繁琐机械的工作里寻得一股虚伪的充实感，只有在偶尔写日记的时候、拖着疲惫的身体行走在路上的时候，自省的想法才会一闪而过。
&lt;/p&gt;

&lt;p&gt;
工作呢，说实话有一个靠谱的团队已经是谢天谢地了，倒也没有办法说我一定要做我感兴趣的事情，毕竟团队需要的是分工协作而不是自大狂的我行我素。话是这么说有时候还是会觉得好无趣啊，想做点有趣点的事情呢。
&lt;/p&gt;

&lt;p&gt;
跑题了，总之，我的一些思考、见闻，我想把他们都写出来。正好最近对 NLP 也就是自然语言处理开始有了一些大致上比较体系的想法了，开始在整理，所以决定开一个系列，专门讲讲 NLP 的东西 —— NLP 是什么呀，有什么应用啦什么的，有什么好玩的东西啦……系列名「NLP 哪里跑」是顺手瞎起的哈哈，&quot;Why so serious&quot;，对不？
&lt;/p&gt;

&lt;p&gt;
正经地讲，可能（但不保证）会有以下内容
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;个人对 NLP 的整体性思考，会涉及 NLP 的一些基础概念、技术&lt;/li&gt;

&lt;li&gt;常见 NLP 的一些应用场景和解决思路&lt;/li&gt;

&lt;li&gt;好用的轮子介绍，或者顺手造点轮子&lt;/li&gt;

&lt;li&gt;前沿方向的介绍和踩坑&lt;/li&gt;

&lt;li&gt;NLP 与其他领域结合的好玩的例子 —— 比如去年在公司年会里分享的《NLP 在文学分析及创作中的应用》&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
以上。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>强大的 Org mode(4): 使用 capture 功能快速记录</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/02/28/org-mode-capture.html"/>
    <category term="Emacs" scheme="http://www.zmonster.me/categories.html#Emacs"/>
    <id>http://www.zmonster.me/2018/02/28/org-mode-capture</id>
    <published>2018-02-28T00:00:00+00:00</published>
    <updated>2018-02-28T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


简介
最小配置
capture 模板的五个部分

用于快速选择模板的 key
描述模板的 description
设置新增内容类型的 type
设置新增内...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgbfd201a&quot;&gt;简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org956d738&quot;&gt;最小配置&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1a3d856&quot;&gt;capture 模板的五个部分&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org790881e&quot;&gt;用于快速选择模板的 key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5cd657e&quot;&gt;描述模板的 description&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org0a0d598&quot;&gt;设置新增内容类型的 type&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgbc6c4bb&quot;&gt;设置新增内容写入位置的 target&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8af60bf&quot;&gt;设置新增内容模板的 template&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgaaa3d30&quot;&gt;capture 模板示例&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgb608172&quot;&gt;用 org-capture 来做任务管理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org361d36d&quot;&gt;用 org-capture 来记录日志&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2d1ad24&quot;&gt;用 org-capture 收集灵感、记录笔记&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org12c36ad&quot;&gt;用 org-capture 记录账单&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org0a98a5a&quot;&gt;用 org-capture 来记录联系人信息&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org17ea029&quot;&gt;用 org-capture 来管理密码&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8223868&quot;&gt;用 org-capture 来新建博客文章&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb0f8460&quot;&gt;用 org-capture 来做网页内容收集&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1c39a08&quot;&gt;用 org-capture 来新建 Anki 卡片&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
本文是《强大的 Org mode》系列的第四篇文章，系列文章如下：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2015/07/12/org-mode-introduction.html&quot;&gt;强大的 Org mode(1): 简单介绍与基本使用 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2015/07/15/org-mode-planning.html&quot;&gt;强大的 Org mode(2): 任务管理 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2016/06/03/org-mode-table.html&quot;&gt;强大的 Org mode(3): 表格的基本操作及公式、绘图 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2018/02/28/org-mode-capture.html&quot;&gt;强大的 Org mode(4): 使用 capture 功能快速记录 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div id=&quot;outline-container-orgbfd201a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgbfd201a&quot;&gt;简介&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgbfd201a&quot;&gt;
&lt;p&gt;
&lt;a href=&quot;https://orgmode.org/manual/Capture.html&quot;&gt;Capture&lt;/a&gt; 是 Org mode 中非常重要的一个功能，使用它可以让我们快速地新建内容到特定的 Org mode 文件中去，具体一点，可以有下面这些场景
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
新建一条笔记到 inbox.org 中，将剪贴板中的内容自动插入，并且附上当时的时间
&lt;/p&gt;


&lt;div id=&quot;org0672efa&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-capture-note.gif&quot; alt=&quot;org-capture-note.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
新增一条日志，按照「年-月-日」的层级结构插入到 journal.org 中，如下图所示
&lt;/p&gt;


&lt;div id=&quot;orgcdf8bac&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-capture-journal.gif&quot; alt=&quot;org-capture-journal.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
以表格的形式，新增一条消费支出记录到用于存放备忘信息的 memo.org 中
&lt;/p&gt;


&lt;div id=&quot;orgac9edff&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-capture-2.gif&quot; alt=&quot;org-capture-2.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
新增一条任务到 task.org 中，并且开始计时
&lt;/p&gt;


&lt;div id=&quot;orgb0e513d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-capture-task.gif&quot; alt=&quot;org-capture-task.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
新增一个代码片段到 snippet.org 中
&lt;/p&gt;


&lt;div id=&quot;org28d450a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-capture-snip.gif&quot; alt=&quot;org-capture-snip.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&amp;#x2026;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
上述看似很不一样的操作，只需要在配置里设置不同的 capture 模板即可，模板里支持的元素很多，甚至能在模板里写 elisp 代码来做到已有模板元素不能做到的事情。在写好模板并加载后，我们只需要调用 org-capture 这个函数，就能在弹出的临时 buffer 里选择对应的模板来记录不同的内容，而不用耗费精力去记忆应该打开哪个文件。
&lt;/p&gt;


&lt;div id=&quot;org05d91d3&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-capture-buffer.png&quot; alt=&quot;org-capture-buffer.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
此外，使用 capture 后将会打开一个临时的 buffer，在我们编辑好内容后轻按 C-c C-c，它就会消失无踪，因此对我们原先在做的事情的打断非常轻微。
&lt;/p&gt;

&lt;p&gt;
总结一下就是：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;capture 可以预先设置记录内容的模板和存储入口&lt;/li&gt;
&lt;li&gt;capture 提供统一的输入入口&lt;/li&gt;
&lt;li&gt;capture 用完即走，不干扰当前工作流&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
如果你是一个 Org mode 用户，应该会用 Org mode 来做笔记记录、日志记录、任务管理这些事情，而这些事情，用 capture 来作为输入是非常自然而方便的，我也在这里建议，在 Org mode 环境里时，应当使用 capture 来作为主要的输入方式。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org956d738&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org956d738&quot;&gt;最小配置&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org956d738&quot;&gt;
&lt;p&gt;
capture 功能包含在 org 包里，所以只要安装了 org，那么直接就是能使用 capture 功能的。不过不做配置的话，那么
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;没有快捷键可以触发功能&lt;/li&gt;
&lt;li&gt;默认只有一个用于创建任务的 Task 模板可选，并且存储在变量 org-default-notes-file 指定的文件里&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
默认的模板是在 org-capture-select-template 中定义的，其逻辑是，当执行 org-capture 命令的时候，如果检查到没有配置任何模板，就会使用一个默认的模板来保证不会出错，这个默认的模板如下所示
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;'(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;t&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Task&quot;&lt;/span&gt; entry (file+headline &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Tasks&quot;&lt;/span&gt;) &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* &lt;/span&gt;&lt;span style=&quot;color: #cc9393;&quot;&gt;TODO&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt; %?\n  %u\n  %a&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
但是呢，如果我们连 org-default-notes-file 都没有设置，它会默认存储到 ~/.notes 中去，然后会由于这个文件不是 Org 文件而报错……
&lt;/p&gt;

&lt;p&gt;
所以，假如我们想真正地使用起 org-capture 来，最小的配置工作，应该包含下述事情
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;为 org-capture 命令设置一个快捷键&lt;/li&gt;
&lt;li&gt;设置 org-default-notes-file 变量的值为一个 Org 文件，比如说 ~/org/inbox.org&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
按照这个要求，可以得到最小的 org-capture 的配置如下
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(global-set-key (kbd &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;C-c c&quot;&lt;/span&gt;) 'org-capture)
(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; org-default-notes-file &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/org/inbox.org&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这样，我们就能新建任务到 ~/org/inbox.org 这个文件中了，见下图示例
&lt;/p&gt;


&lt;div id=&quot;orgfdff538&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-capture-minimum.gif&quot; alt=&quot;org-capture-minimum.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1a3d856&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1a3d856&quot;&gt;capture 模板的五个部分&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org1a3d856&quot;&gt;
&lt;p&gt;
上一节讲到，默认的 capture 模板是下面这个样子的
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;'(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;t&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Task&quot;&lt;/span&gt; entry (file+headline &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Tasks&quot;&lt;/span&gt;) &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* &lt;/span&gt;&lt;span style=&quot;color: #cc9393;&quot;&gt;TODO&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt; %?\n  %u\n  %a&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
后面我们要自己添加新的模板，也是这个格式。这个模板包含五个部分，分别是
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;模板组成&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;对应默认模板中的内容&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;key&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&quot;t&quot;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;用来选择模板的字符&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;description&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&quot;Task&quot;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;展示用的模板描述&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;type&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;entry&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;新增内容的类型&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;target&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;(file+headline &quot;&quot; &quot;Tasks&quot;)&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;新增内容的存储位置&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;template&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&quot;* TODO %?\n  %u\n  %a&quot;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;新增内容的模板&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
下面针对这五部分进行详细说明。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org790881e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org790881e&quot;&gt;用于快速选择模板的 key&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org790881e&quot;&gt;
&lt;p&gt;
对应前面默认模板里的 &quot;t&quot;，这个 key 可以是一个或两个字符，用来在执行 org-capture 的时候选择模板 —— 两个字符的情况是用来给模板分组的，第一个字符表示分组名，第二个字符用来选择这个分组下的实际模板。在我们有很多模板的时候，分组是非常有用的，一来可以让执行 org-capture 时显示的可选项更少，而来可以用来组织相近性质的模板以便管理。模板分组稍后一点会做详细说明，此处就先不展开了。
&lt;/p&gt;


&lt;p&gt;
另外，经验证，这里的 key 是支持中文的 XD
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5cd657e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5cd657e&quot;&gt;描述模板的 description&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5cd657e&quot;&gt;
&lt;p&gt;
对应前面默认模板里的 &quot;Task&quot;，这个就是用来对模板进行描述的，方便我们正确地选择模板。
&lt;/p&gt;

&lt;p&gt;
key 和 description 这两部分会在执行 org-capture 进入模板选择 buffer 后，会显示的内容，其他模板内容在模板选择 buffer 中都是不显示的，如下所示：
&lt;/p&gt;


&lt;div id=&quot;org9422bbb&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-capture-buffer.png&quot; alt=&quot;org-capture-buffer.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这两部分，务必要注意
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;不同模板的 key 不能是一样的&lt;/li&gt;
&lt;li&gt;description 应当尽量清晰以减轻自己的记忆负担&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0a0d598&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org0a0d598&quot;&gt;设置新增内容类型的 type&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org0a0d598&quot;&gt;
&lt;p&gt;
对应前面默认模板里的 &quot;entry&quot;，这个用来设置新增内容的类型，可选的类型如下表所示
&lt;/p&gt;
&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;type&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;entry&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;带有 headline 的一个 Org mode 节点&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;item&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;一个列表项&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;checkitem&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;一个 checkbox 列表项&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;table-line&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;一个表格行&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;plain&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;普通文本&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
根据不同的 type，org-capture 会尝试将新增内容添加到文件中不同类型的数据的后面，比如
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;如果 type 是 item/checkitem，那么会找到目标位置后最近的一个列表，并将新增列表项添加到这个列表的后面&lt;/li&gt;
&lt;li&gt;如果 type 是 table-line，那么会找到目标位置后最近的一个表格，并将新增行添加到表格的后面&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
因此对于不同的 type，要求后面的内容模板是按照一定的格式来编写的，下面是不同的 type 对应内容模板的简单示例
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
type 为 entry 时，内容模板示例
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* headline&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
也就是说，template 的形式上必须是一个 headline
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
type 为 item 时
&lt;/p&gt;

&lt;p&gt;
如果内容模板为空，会插入一个普通列表项，并且等待输入；如果有需要自定义的内容，那么才需要去写内容模板。
&lt;/p&gt;

&lt;p&gt;
而此时的内容模板不需要在形式上是一个列表项，也就是说
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;- item&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
和
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;item&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
的效果是一样的，都会在 target 对应的位置里插入下面这样一个列表项
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;- item
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
type 为 checkitem 时
&lt;/p&gt;

&lt;p&gt;
与 type 为 item 时行为大部分一样，仅有一点区别，就是在内容模板为空的时候，它会插入一个 checkbox 列表项。
&lt;/p&gt;

&lt;p&gt;
也就是说，如果内容模板不为空，那么它其实是不保证插入的是 checkbox 列表项的，需要我们自己来保证。
&lt;/p&gt;

&lt;p&gt;
相应的内容模板应该是类似下面的格式
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;[ ] item&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
type 为 table-line，内容模板示例
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;| colum 1 | colum 2 | colum3 |&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
就是说，内容模板必须是一个表格的行
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgbc6c4bb&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgbc6c4bb&quot;&gt;设置新增内容写入位置的 target&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgbc6c4bb&quot;&gt;
&lt;p&gt;
对应前面默认模板里的 &quot;(file+headline &quot;&quot; &quot;Tasks&quot;)&quot;，target 用来指定
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;新增内容要写入到哪个文件&lt;/li&gt;
&lt;li&gt;新增内容要写入到文件的什么地方&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
如前面的默认模板所示，target 部分用一个 list 来表示，其中第一个元素用来表示 target 的类型，可用的类型如下表所示
&lt;/p&gt;
&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;type&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;description&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;file&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;文件&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;(file &quot;path/to/file&quot;)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;id&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;特定 ID 的某个 headline&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;(id &quot;id of existing Org entry&quot;)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;file+headline&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;文件的某个唯一的 headline&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;(file+headline &quot;path/to/file&quot; &quot;node headline&quot;)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;file+olp&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;文件中的 headline 路径&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;(file+olp &quot;path/to/file&quot; &quot;Level 1 heading&quot; &quot;Level 2&quot; &amp;#x2026;)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;file+regexp&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;文件中被正则匹配的 headline&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;(file+regexp  &quot;path/to/file&quot; &quot;regexp to find location&quot;)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;file+datetree&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;文件中当日所在的 datetree&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;(file+datetree &quot;path/to/file&quot;)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;file+datetree+prompt&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;文件中的 datetree，弹出日期选择&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;(file+datetree+prompt &quot;path/to/file&quot;)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;file+weektree&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;文件中当日所在的 weektree&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;(file+weektree &quot;path/to/file&quot;)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;file+weektree+prompt&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;文件中的 weektree，弹出日期选择&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;(file+weektree+prompt &quot;path/to/file&quot;)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;file+function&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;文件中被函数匹配的位置&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;(file+function &quot;path/to/file&quot; function-finding-location)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;clock&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;当前正在计时中的任务所在的位置&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;(clock)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;function&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;自定义函数匹配的位置&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;(function function-finding-location)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
(翻译有点生硬，如有疑惑，请执行 「M-x describe-variable」并输入「org-capture-templates」查看对应的文档)
&lt;/p&gt;

&lt;p&gt;
其中 file+headline 是比较常用的，用来记录笔记、创建任务一般用这个就好了。不过这个要求 headline 在文件中是唯一的，如果不是唯一的话，最好使用 file+olp，指定对应 headline 在文件中的完整路径。
&lt;/p&gt;

&lt;p&gt;
而 file+datetree、file+weektree 这两种用来创建日志是非常合适的，记录的内容能按年-月-日的层级结构组织好，方便回顾和管理。
&lt;/p&gt;

&lt;p&gt;
如果有自己的特殊需求，那么 file+function、function 这两个也提供了极大的自由扩展的空间。
&lt;/p&gt;

&lt;p&gt;
需要注意的是，上述与文件相关的 target 类型，如果指定了文件名，那么将会优先使用这个文件名而不是变量 org-default-notes-file 指定的文件 —— 反之，如果文件部分留空，那么就会默认使用 org-default-notes-file 指定的文件了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8af60bf&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8af60bf&quot;&gt;设置新增内容模板的 template&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8af60bf&quot;&gt;
&lt;p&gt;
对应前面默认模板里的 &quot;* TODO %?\n  %u\n  %a&quot;，这部分的内容是实际上新增内容的模板，通过设置它，我们可以在新增内容时
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;自动插入时间、链接、剪贴板内容、文件内容&lt;/li&gt;
&lt;li&gt;交互式地要求输入特定内容，如 tag、headline 属性或其他自定义的字段&lt;/li&gt;
&lt;li&gt;自动插入外部应用传入的特定信息，如浏览器上当前网页的链接、选中的文本等&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
这部分的配置，其中的内容可以分为两类
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;普通的文本，将会原样出现在新增内容中，如默认模板里的 &quot;* TODO&quot;、&quot;\n&quot;、&quot;  &quot;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
以 % 开头的特殊标记，如 &quot;%?&quot; 和 &quot;%a&quot;，将会在最后根据类型自动扩展成不同的内容
&lt;/p&gt;

&lt;p&gt;
这些特殊标记包括这些
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
时间、日期相关
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;标记&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%&amp;lt;&amp;#x2026;&amp;gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;自定义格式的 timestamp，如: %&amp;lt;%Y-%m-%d&amp;gt;，会得到 &lt;span class=&quot;timestamp-wrapper&quot;&gt;&lt;span class=&quot;timestamp&quot;&gt;&amp;lt;2018-03-04 日&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%t&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;当前仅包含日期的 timestamp，如: &lt;span class=&quot;timestamp-wrapper&quot;&gt;&lt;span class=&quot;timestamp&quot;&gt;&amp;lt;2018-03-04 日&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%T&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;当前包含日期和时间的 timestamp，如: &lt;span class=&quot;timestamp-wrapper&quot;&gt;&lt;span class=&quot;timestamp&quot;&gt;&amp;lt;2018-03-04 日 19:26&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%u&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;当前包含日期的未激活的 timestamp，如: &lt;span class=&quot;timestamp-wrapper&quot;&gt;&lt;span class=&quot;timestamp&quot;&gt;[2018-03-04 日]&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%U&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;当前包含日期和时间的未激活的 timestamp，如: &lt;span class=&quot;timestamp-wrapper&quot;&gt;&lt;span class=&quot;timestamp&quot;&gt;[2018-03-04 日 19:26]&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%^t&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;类似 %t，但是弹出日历让用户选择日期&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%^T&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;类似 %T，但是弹出日历让用户选择日期和时间&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%^u&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;类似 %u，但是弹出日历让用户选择日期&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%^U&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;类似 %U，但是弹出日历让用户选择日期和时间&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
注: 激活(active)和未激活(inactive)的 timestamp 的区别在于，后者不会出现在 agenda 中 —— 所以如果是新建一个 headline 到 org-agenda-files 中并且不希望它出现在 agenda 列表中时，应当使用未激活的 timestamp。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
剪贴板相关
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;标记&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%c&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;当前 kill ring 中的第一条内容&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%x&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;当前系统剪贴板中的内容&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%^C&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;交互式地选择 kill ring 或剪贴板中的内容&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%^L&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;类似 %^C，但是将选中的内容作为链接插入&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
标签相关
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;标记&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%^g&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;交互式地输入标签，并用 target 所在文件中的标签进行补全&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%^G&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;类似 %^g，但用所有 org-agenda-files 涉及文件中的标签进行补全&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
文件相关
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;标记&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%[file]&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;插入文件 &lt;i&gt;file&lt;/i&gt; 中的内容&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%f&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;执行 org-capture 时当前 buffer 对应的文件名&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%F&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;类似 %f，但输入该文件的绝对路径&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
任务相关
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;标记&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%k&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;当前在计时的任务的标题&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%K&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;当前在计时的任务的链接&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
外部链接的信息
&lt;/p&gt;

&lt;p&gt;
这里的链接不仅仅指如 &lt;a href=&quot;http://www.google.com&quot;&gt;http://www.google.com&lt;/a&gt; 这样的网页链接，还包括文件、邮箱、新闻组、IRC 会话等，详情见 Org mode 手册的 &lt;a href=&quot;https://orgmode.org/manual/External-links.html&quot;&gt;External links&lt;/a&gt; 一节。
&lt;/p&gt;

&lt;p&gt;
当然在 capture 里我们用不到所有类型的外部链接，从&lt;a href=&quot;https://orgmode.org/manual/Template-expansion.html&quot;&gt;文档&lt;/a&gt;和 &lt;a href=&quot;https://code.orgmode.org/bzg/org-mode/src/master/lisp/org-capture.el#L321&quot;&gt;docstring&lt;/a&gt; 来看，在 capture 里能用的外部链接只有下面几种
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;link type&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;bbdb&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://www.emacswiki.org/emacs/CategoryBbdb&quot;&gt;BBDB&lt;/a&gt; 联系人数据库记录链接&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;irc&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;IRC 会话链接&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;vm&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://www.emacswiki.org/emacs/CategoryViewMail&quot;&gt;View Mail&lt;/a&gt; 邮件阅读器中的消息、目录链接&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;wl&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://www.emacswiki.org/emacs/WanderLust&quot;&gt;Wunder Lust&lt;/a&gt; 邮件/新闻阅读器中的消息、目录链接&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;mh&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://www.emacswiki.org/emacs/MH-E&quot;&gt;MH-E&lt;/a&gt; 邮件用户代理中的消息、目录链接&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;mew&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;https://www.emacswiki.org/emacs/Mew&quot;&gt;MEW&lt;/a&gt; 邮件阅读器中的消息链接&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;rmail&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;Emacs 的默认邮件阅读器 &lt;a href=&quot;https://www.emacswiki.org/emacs/Rmail&quot;&gt;Rmail&lt;/a&gt; 中的消息链接&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;gnus&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;a href=&quot;http://www.gnus.org/&quot;&gt;GNUS&lt;/a&gt; 邮件/新闻阅读器中的群组、消息等资源链接&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;eww/w3/w3m&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;在eww/w3/w3m 中存储的网页链接&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;calendar&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;日历链接&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;org-protocol&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;遵循 org-protocol 协议的外部应用链接&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
注: &lt;a href=&quot;https://orgmode.org/manual/Template-expansion.html&quot;&gt;文档&lt;/a&gt;的内容来自 &lt;a href=&quot;https://code.orgmode.org/bzg/org-mode&quot;&gt;org-mode 仓库&lt;/a&gt; 中的 doc/org.texi，从 commit 历史来看，可能是过时的；但奇怪的是 org-protocol 明明是支持的，docstring 里却完全没有提及……
&lt;/p&gt;

&lt;p&gt;
这些外部链接，大部分都会在 Emacs 中通过 &lt;b&gt;org-store-link-pros&lt;/b&gt; 记录起来，其中会包含这些链接的各个属性，而在 capture 的模板里面，就支持以 &lt;b&gt;%:keyword&lt;/b&gt; 的形式来访问这些属性，比如 vm/wl/mh/mew/rmail/gnus 消息中的发件人名称、发件人地址之类的。因为邮件阅读器这块我个人不怎么用，需要详细了解的请查阅&lt;a href=&quot;https://orgmode.org/manual/Template-expansion.html&quot;&gt;文档&lt;/a&gt;，而 calendar 完全可以用前面的「时间、日期相关」中的 %t、%T 等标记来替代，因此这里只详细说一下 eww 和 org-protocol。
&lt;/p&gt;

&lt;p&gt;
eww 可用的特殊标记有如下三个
&lt;/p&gt;
&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;标记&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%:type&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;固定值，eww&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%:link&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;页面的链接&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%:description&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;页面的标题，如无则为页面的链接&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
org-protocol 可用的特殊标记有如下六个
&lt;/p&gt;
&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;标记&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%:type&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;链接的类型，如 http/https/ftp 等&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%:link&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;链接地址，在 org-protocol 里的 url 字段&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%:description&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;链接的标题，在 org-protocol 里的 title 字段&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%:annotation&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;靠 url 和 title 完成的 org 格式的链接&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%:initial&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;链接上选中的文本，在 org-protocol 里的 body 字段&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;%:query&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;org-protocol 上除掉开头和子协议部分的剩下部分&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
此外，在内容模板中还支持自定义函数来插入内容，以 &lt;i&gt;%(sexp)&lt;/i&gt; 的形式，比如说我们可以自己写一个 &lt;b&gt;get-current-time&lt;/b&gt; 函数来插入当前的时间，那么内容模板可以是这个样子的
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;org185f444&quot;&gt;
&quot;%(get-current-time)&quot;
&lt;/pre&gt;

&lt;p&gt;
而在内容模板中使用自定义函数时，可以将上面 eww 和 org-protocol 的这些特殊标记作为函数的参数，比如一个场景是，用 org-protocol 捕获的网页 title 中包含中括号，会导致下面这样的内容模板出错
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org6f0f801&quot;&gt;
&quot;[[%:link][%:description]]&quot;
&lt;/pre&gt;

&lt;p&gt;
这个时候可以定一个一个函数来将 %:description 中的中括号替换成下划线
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;replace-bracket-in-title&lt;/span&gt; (title)
  &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;; &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;blablabla&lt;/span&gt;
  )
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
那么上面那个内容模板可以改成这样
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org423e554&quot;&gt;
&quot;[[%:link][%(replace-bracket-in-title \&quot;%:description\&quot;)]]&quot;
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
其他
&lt;/p&gt;

&lt;p&gt;
还有一些特殊标记，不太好归类，就在这里罗列一下。
&lt;/p&gt;

&lt;p&gt;
&quot;%i&quot; 可以插入一段初始化内容，通常是 &lt;b&gt;org-store-link-plist&lt;/b&gt; 中 &quot;initial&quot; 属性的值；如果没有的话，会使用当前 buffer 中被选中的内容；都没有的话就什么也不插入。
&lt;/p&gt;

&lt;p&gt;
&quot;%^{prop}p&quot; 会提示输入内容，这将会在新增内容中插入一个 property 到 target 中，并且这个 property 的名字是 prop，值则是我们输入的文本。
&lt;/p&gt;

&lt;p&gt;
&quot;%^{prompt}&quot; 则会用 prompt 作为提示符要求我们输入，并且用我们输入的文本替换模板中相应的内容。比如说 &quot;%{姓名}&quot; 会用 &quot;姓名&quot; 作为提示符要求输入。当有多个标记时，可以用 &quot;%\N&quot; 来插入第 N 个提示输入标记产生的内容，举个例子，下面的内容模板
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;orgb89291f&quot;&gt;
&quot;- name: %^{姓名}\n- age: %^{年龄}\n\n%\\1的年龄是%\\2&quot;
&lt;/pre&gt;

&lt;p&gt;
(注: 此处的反斜线「\」需要转义，否则「\1」会被视作值为 1 的 ASCII 码特殊字符，感谢 Emacs China 网友 &lt;a href=&quot;https://emacs-china.org/u/slack-py&quot;&gt;slack-py&lt;/a&gt; 指出该问题)
&lt;/p&gt;

&lt;p&gt;
会要求我们输入姓名和年龄，假如我们输入姓名是 &quot;张三&quot;，年龄是 &quot;25&quot;，那么最后得到的内容是
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org977571f&quot;&gt;
- name: 张三
- age: 25

张三的年龄是25
&lt;/pre&gt;

&lt;p&gt;
&quot;%?&quot; 是一个更特殊的标记，它不会产生任何内容，当所有其他的特殊标记都展开完毕或者输入完毕后，光标将会停留在这个标记所在的位置。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgaaa3d30&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgaaa3d30&quot;&gt;capture 模板示例&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgaaa3d30&quot;&gt;
&lt;p&gt;
所有的 capture 模板都应当以 list 的形式记录在变量 &lt;b&gt;org-capture-templates&lt;/b&gt; 中，下面的示例可能会存在模板的 key 冲突的情况，请根据自己的情况来选用或参考示例。
&lt;/p&gt;

&lt;p&gt;
在开始之前，我们先将 org-capture-templates 设置为空
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; org-capture-templates nil)
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb608172&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb608172&quot;&gt;用 org-capture 来做任务管理&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb608172&quot;&gt;
&lt;p&gt;
GTD 一般会有一整套系统的设计，这里只讲一下最一般的新建任务的做法，下面是一个新建书籍阅读任务的示例
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;r&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Book Reading Task&quot;&lt;/span&gt; entry
               (file+olp &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/task.org&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Reading&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Book&quot;&lt;/span&gt;)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* &lt;/span&gt;&lt;span style=&quot;color: #cc9393;&quot;&gt;TODO&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt; %^{&amp;#20070;&amp;#21517;}\n%u\n%a\n&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:clock-in&lt;/span&gt; t &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:clock-resume&lt;/span&gt; t))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上面的两个属性 &quot;:clock-in&quot; 和 &quot;:clock-resume&quot; 在之前没有讲过，是用来对新建内容的行为做一些设置的，不影响内容本身。可用的这些属性一共有 14 个，这里及后面只对涉及到的做说明，其他的请查阅&lt;a href=&quot;https://orgmode.org/manual/Template-elements.html#Template-elements&quot;&gt;文档&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
&quot;:clock-in&quot; 设置为 t 的时候，会在新建内容时开始计时，这在 GTD 这种场景下是挺有用的。但有可能我们在新建内容时，本来就有一个任务在计时，这种情况下原来的计时会中断掉，这个时候将 &quot;:clock-resume&quot; 设置为 t，可以在新任务完成后，自动恢复原来任务的计时状态。
&lt;/p&gt;

&lt;p&gt;
有些时候我们会对我们需要做的任务做分类，比如上面有一个阅读任务，可能还有工作任务、写作任务，这个时候我们可以利用前面说到的模板分组来更好地进行管理。
&lt;/p&gt;

&lt;p&gt;
在做模板分组前，我们的 org-capture 的任务模板可能是这样的
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;r&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Book Reading Task&quot;&lt;/span&gt; entry
               (file+olp &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/task.org&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Reading&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Book&quot;&lt;/span&gt;)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* &lt;/span&gt;&lt;span style=&quot;color: #cc9393;&quot;&gt;TODO&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt; %^{&amp;#20070;&amp;#21517;}\n%u\n%a\n&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:clock-in&lt;/span&gt; t &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:clock-resume&lt;/span&gt; t))
(add-to-list 'org-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;w&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Work Task&quot;&lt;/span&gt; entry
               (file+headline &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/task.org&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Work&quot;&lt;/span&gt;)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* &lt;/span&gt;&lt;span style=&quot;color: #cc9393;&quot;&gt;TODO&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt; %^{&amp;#20219;&amp;#21153;&amp;#21517;}\n%u\n%a\n&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:clock-in&lt;/span&gt; t &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:clock-resume&lt;/span&gt; t))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
在这个基础上，假设我们要添加一个模板，用来记录从网页上收集的资源、文章的时候，遵循使用描述中关键词的首字母作为选择键的原则，我会希望新建这样一个 capture 模板
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;w&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Web Collections&quot;&lt;/span&gt; entry
               (file+headline &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/inbox.org&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Web&quot;&lt;/span&gt;)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* %U %:annotation\n\n%:initial\n\n%?&quot;&lt;/span&gt;))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
但这个时候的模板选择键 &quot;w&quot; 和之前任务里的 &quot;Work Task&quot; 就冲突了，为了解决冲突，我只好在其中一个使用小写的 &quot;w&quot; 字母而在另外一个中使用大写的字母 &quot;W&quot;。当我们的模板数量更多时，这种 capture 模板选择键冲突的情况可能会更多。
&lt;/p&gt;

&lt;p&gt;
虽然并不是非常大的问题，但使用模板分组，能尽量地减少这种情况，让我们的模板更加清爽一些
&lt;/p&gt;

&lt;p&gt;
上述情况，我们可以将任务相关的 capture 模板分到一组里，如下所示：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;t&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Tasks&quot;&lt;/span&gt;))
(add-to-list 'org-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;tr&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Book Reading Task&quot;&lt;/span&gt; entry
               (file+olp &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/task.org&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Reading&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Book&quot;&lt;/span&gt;)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* &lt;/span&gt;&lt;span style=&quot;color: #cc9393;&quot;&gt;TODO&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt; %^{&amp;#20070;&amp;#21517;}\n%u\n%a\n&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:clock-in&lt;/span&gt; t &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:clock-resume&lt;/span&gt; t))
(add-to-list 'org-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;tw&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Work Task&quot;&lt;/span&gt; entry
               (file+headline &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/task.org&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Work&quot;&lt;/span&gt;)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* &lt;/span&gt;&lt;span style=&quot;color: #cc9393;&quot;&gt;TODO&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt; %^{&amp;#20219;&amp;#21153;&amp;#21517;}\n%u\n%a\n&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:clock-in&lt;/span&gt; t &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:clock-resume&lt;/span&gt; t))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
和前面未分组的模板，有两个不同
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
多了一个只有 key 和 description 而没有 entry/target/template 的 capture 模板，也就是
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;t&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Tasks&quot;&lt;/span&gt;))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这个模板至关重要，它设定了一组模板的名称和选择键前缀。如果缺失了这个模板，那么后面两个模板是不会起作用的。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;原来的两个任务模板，其选择键多了一个前缀 &quot;t&quot;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
一图胜千言，在建立分组前，执行 M-x org-capture 时，弹出的模板选择 buffer 是这个样子的
&lt;/p&gt;


&lt;div id=&quot;orgafb2a9b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-capture-buffer-no-group.png&quot; alt=&quot;org-capture-buffer-no-group.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
建立分组后，在模板选择 buffer 里看到的是这个样子
&lt;/p&gt;


&lt;div id=&quot;org10b6174&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-capture-buffer-group-1.png&quot; alt=&quot;org-capture-buffer-group-1.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这里只会显示模板的 group 的 key 和 description，等我们按下 t 后才会出来组内所有模板的列表
&lt;/p&gt;


&lt;div id=&quot;orgcfb6133&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-capture-buffer-group-2.png&quot; alt=&quot;org-capture-buffer-group-2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org361d36d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org361d36d&quot;&gt;用 org-capture 来记录日志&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org361d36d&quot;&gt;
&lt;p&gt;
这个之前也提到过，就是用来做日志记录、日记写作一类的事情，新增的内容和过去的内容都按时间顺序排列，方便我们进行回顾。
&lt;/p&gt;

&lt;p&gt;
做日志记录时，比较推荐用 file+datetree 或者 file+weektree 这两个 target type，当然也不是绝对的，比如说下面这个 capture 模板也是满足基本要求的
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;j&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Journal&quot;&lt;/span&gt; entry (file &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/journal.org&quot;&lt;/span&gt;)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* %U - %^{heading}\n  %?&quot;&lt;/span&gt;))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上述模板在每次执行后，在 journal.org 的尾部插入下面这样的内容
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #cccccc; background-color: #2d2d2d; font-weight: bold; text-decoration: underline;&quot;&gt;* &lt;/span&gt;&lt;span style=&quot;color: #6699cc; text-decoration: underline;&quot;&gt;[2018-03-24 &amp;#20845; 21:42]&lt;/span&gt;&lt;span style=&quot;color: #cccccc; background-color: #2d2d2d; font-weight: bold; text-decoration: underline;&quot;&gt; - &amp;#26576;&amp;#20214;&amp;#20107;&amp;#24773;&amp;#30340;&amp;#35760;&amp;#24405;&lt;/span&gt;

  &amp;#20855;&amp;#20307;&amp;#30340;&amp;#35760;&amp;#24405; blablabla
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
就是如果想要快速地找到某一天或者某一个月的记录，会稍微费力一点，使用 file+datetree 的话，新增的记录会按照「年-月-日」的层次组织起来；而使用 file+weektree 的话，新增的记录会按「年-周-日」的层次组织，下图是两者的对比
&lt;/p&gt;


&lt;div id=&quot;org1f913ba&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-capture-datetree-and-weektree.png&quot; alt=&quot;org-capture-datetree-and-weektree.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
我个人目前是使用 file+datetree 的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2d1ad24&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2d1ad24&quot;&gt;用 org-capture 收集灵感、记录笔记&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2d1ad24&quot;&gt;
&lt;p&gt;
这类模板也比较简单，基本上用 file+headline 的 target，然后视情况而定预先设置 tag 什么的。
&lt;/p&gt;

&lt;p&gt;
我个人有一个 capture 模板，用来快速记录未归类的东西，然后会在后面使用 refile 来将这些东西迁移到任务或者笔记中
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;i&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Inbox&quot;&lt;/span&gt; entry (file &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/inbox.org&quot;&lt;/span&gt;)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* %U - %^{heading} %^g\n %?\n&quot;&lt;/span&gt;))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
笔记则用另外一个 capture 模板
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;n&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Notes&quot;&lt;/span&gt; entry (file &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/notes/inbox.org&quot;&lt;/span&gt;)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* %^{heading} %t %^g\n  %?\n&quot;&lt;/span&gt;))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到两个模板其实差不多，无非就是写入的文件不一样。实际上的不同之处在于，在我的笔记本 ~/Dropbox/org/notes/inbox.org 中，我设置了一些文件级别的 tag，如下所示
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #99cc99;&quot;&gt;#+TITLE:&lt;/span&gt; &lt;span style=&quot;color: #f99157; font-size: 144%; font-weight: bold;&quot;&gt;&amp;#31508;&amp;#35760;&amp;#26412;&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+STARTUP: hideall&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+TAGS: [coding: shell python]&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+TAGS: [shell: grep tail sed ssh]&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+TAGS: [python: ipython pandas numpy]&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这样在特殊标记 %^g 展开的时候，就可以用上面设置的 tag 进行补全。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org12c36ad&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org12c36ad&quot;&gt;用 org-capture 记录账单&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org12c36ad&quot;&gt;
&lt;p&gt;
在 Org mode 中利用表格来记录账单是非常合适的一个方式，记录好后利用表格公式(见我的上一篇文章)可以很方便地进行计算、绘图什么的。
&lt;/p&gt;

&lt;p&gt;
下面是我用来记录账单的 capture 模板，利用自定义的函数，来将同一个月的支出记录在同一张表里
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;b&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Billing&quot;&lt;/span&gt; plain
               (file+function &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/billing.org&quot;&lt;/span&gt; find-month-tree)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot; | %U | %^{&amp;#31867;&amp;#21035;} | %^{&amp;#25551;&amp;#36848;} | %^{&amp;#37329;&amp;#39069;} |&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:kill-buffer&lt;/span&gt; t))))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
其中的函数 find-month-tree，用来做类似 file+datetree 的事情，不过层级结构只到月为止，其实现如下
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;get-year-and-month&lt;/span&gt; ()
  (list (format-time-string &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%Y&amp;#24180;&quot;&lt;/span&gt;) (format-time-string &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%m&amp;#26376;&quot;&lt;/span&gt;)))


(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;find-month-tree&lt;/span&gt; ()
  (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;let*&lt;/span&gt; ((path (get-year-and-month))
         (level 1)
         end)
    (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;unless&lt;/span&gt; (derived-mode-p 'org-mode)
      (&lt;span style=&quot;color: #f2777a; background-color: #ffe4b5; font-weight: bold;&quot;&gt;error&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Target buffer \&quot;%s\&quot; should be in Org mode&quot;&lt;/span&gt; (current-buffer)))
    (goto-char (point-min))             &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#31227;&amp;#21160;&amp;#21040; buffer &amp;#30340;&amp;#24320;&amp;#22987;&amp;#20301;&amp;#32622;&lt;/span&gt;
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;; &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#20808;&amp;#23450;&amp;#20301;&amp;#34920;&amp;#31034;&amp;#24180;&amp;#20221;&amp;#30340; headline&amp;#65292;&amp;#20877;&amp;#23450;&amp;#20301;&amp;#34920;&amp;#31034;&amp;#26376;&amp;#20221;&amp;#30340; headline&lt;/span&gt;
    (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;dolist&lt;/span&gt; (heading path)
      (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;let&lt;/span&gt; ((re (format org-complex-heading-regexp-format
                        (regexp-quote heading)))
            (cnt 0))
        (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;if&lt;/span&gt; (re-search-forward re end t)
            (goto-char (point-at-bol))  &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#22914;&amp;#26524;&amp;#25214;&amp;#21040;&amp;#20102; headline &amp;#23601;&amp;#31227;&amp;#21160;&amp;#21040;&amp;#23545;&amp;#24212;&amp;#30340;&amp;#20301;&amp;#32622;&lt;/span&gt;
          (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;progn&lt;/span&gt;                        &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#21542;&amp;#21017;&amp;#23601;&amp;#26032;&amp;#24314;&amp;#19968;&amp;#20010; headline&lt;/span&gt;
            (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;or&lt;/span&gt; (bolp) (insert &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;\n&quot;&lt;/span&gt;))
            (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;if&lt;/span&gt; (/= (point) (point-min)) (org-end-of-subtree t t))
            (insert (make-string level ?*) &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot; &quot;&lt;/span&gt; heading &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;\n&quot;&lt;/span&gt;))))
      (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; level (1+ level))
      (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; end (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;save-excursion&lt;/span&gt; (org-end-of-subtree t t))))
    (org-end-of-subtree)))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
效果如下图所示
&lt;/p&gt;


&lt;div id=&quot;org8303ae3&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-capture-billing.gif&quot; alt=&quot;org-capture-billing.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org0a98a5a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org0a98a5a&quot;&gt;用 org-capture 来记录联系人信息&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org0a98a5a&quot;&gt;
&lt;p&gt;
联系人会有一些常见的属性比如姓名、手机号、邮箱、住址之类的，简单起见可以用表格来做，比如
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;c&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Contacts&quot;&lt;/span&gt; table-line (file &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/contacts.org&quot;&lt;/span&gt;)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;| %U | %^{&amp;#22995;&amp;#21517;} | %^{&amp;#25163;&amp;#26426;&amp;#21495;}| %^{&amp;#37038;&amp;#31665;} |&quot;&lt;/span&gt;))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
不过在一些场景下用表格来做可能会不太方便，比如说我们想对联系人进行一些细致的描述之类的，这种情况下一个表格行太长就不太方便了。
&lt;/p&gt;

&lt;p&gt;
因此因外一个方案是，将每个联系人的信息记录为一个 headline 中，联系人的具体属性作为 headline 的 property 进行记录，如果要进行什么描述说明的话就作为 headline 下属的内容就好，如下所示：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;c&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Contacts&quot;&lt;/span&gt; entry (file &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/contacts.org&quot;&lt;/span&gt;)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* %^{&amp;#22995;&amp;#21517;} %^{&amp;#25163;&amp;#26426;&amp;#21495;}p %^{&amp;#37038;&amp;#31665;}p %^{&amp;#20303;&amp;#22336;}p\n\n  %?&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:empty-lines&lt;/span&gt; 1))
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org17ea029&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org17ea029&quot;&gt;用 org-capture 来管理密码&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org17ea029&quot;&gt;
&lt;p&gt;
和记录联系人类似，如果只是单纯地记录密码，那么可以直接用表格。不过作为一个密码管理方案，我们可能要考虑以下事情
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;org 文件本质上是文本文件，怎么保证密码的安全性？&lt;/li&gt;
&lt;li&gt;当我需要新建密码时，是否能在 org-capture 中直接来生成密码？&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
以上两点都是可以解决的。安全方面，Org mode 支持对文件、headline、headline 中正文等不同层级的加密，详情见 &lt;a href=&quot;https://orgmode.org/worg/org-tutorials/encrypting-files.html&quot;&gt;Encrypting org Files.&lt;/a&gt;，这里只讲最简单的文件级加密。
&lt;/p&gt;

&lt;p&gt;
首先我们在 Emacs 中先新建好一个后缀为 cpt 的 org 文件，比如 passwords.org.cpt —— 在一个正常的 org 文件后再附加上 cpt 这个后缀，就会被当作一个加密文件，在创建这个文件的时候会要求我们输入加密用的密码，我们只需要把这个主密码记住就好了。
&lt;/p&gt;

&lt;p&gt;
然后我们要写一个函数来要求输入密码，当输入密码为空时，我们就自动生成一个密码 —— 简单起见这里限定生成的密码长度是 16 位，只用字母和数字组成，如下所示。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;random-alphanum&lt;/span&gt; ()
  (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;let*&lt;/span&gt; ((charset &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;abcdefghijklmnopqrstuvwxyz0123456789&quot;&lt;/span&gt;)
         (x (random 36)))
    (char-to-string (elt charset x))))

(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;create-password&lt;/span&gt; ()
  (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;let&lt;/span&gt; ((value &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&quot;&lt;/span&gt;))
    (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;dotimes&lt;/span&gt; (number 16 value)
      (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; value (concat value (random-alphanum))))))


(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;get-or-create-password&lt;/span&gt; ()
  (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; password (read-string &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Password: &quot;&lt;/span&gt;))
  (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;if&lt;/span&gt; (string= password &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&quot;&lt;/span&gt;)
      (create-password)
    password))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后新建一个模板如下就可以了。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;p&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Passwords&quot;&lt;/span&gt; entry (file &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/passwords.org.cpt&quot;&lt;/span&gt;)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* %U - %^{title} %^G\n\n  - &amp;#29992;&amp;#25143;&amp;#21517;: %^{&amp;#29992;&amp;#25143;&amp;#21517;}\n  - &amp;#23494;&amp;#30721;: %(get-or-create-password)&quot;&lt;/span&gt;
               &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:empty-lines&lt;/span&gt; 1 &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:kill-buffer&lt;/span&gt; t))
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8223868&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8223868&quot;&gt;用 org-capture 来新建博客文章&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8223868&quot;&gt;
&lt;p&gt;
我是直接使用 Org mode 的原生支持的 project 来写博客的，写好后将整个 project 导出成 html，放置到配置好的 jekyll 目录下。Org mode 的 project 要求设置一个目录，这个目录下的 org 文件都会被当作 project 中的文章，比如说我的博客对应的 project 设置是这样的
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; org-publish-project-alist
      '((&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;blog-org&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:base-directory&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/blog/&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:base-extension&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;org&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:publishing-directory&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Projects/github-pages/&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:recursive&lt;/span&gt; t
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:htmlized-source&lt;/span&gt; t
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:section-numbers&lt;/span&gt; nil
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:publishing-function&lt;/span&gt; org-html-publish-to-html
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:headline-levels&lt;/span&gt; 4
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:html-extension&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;html&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:body-only&lt;/span&gt; t     &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;Only export section between &amp;lt;body&amp;gt; &amp;lt;/body&amp;gt;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:table-of-contents&lt;/span&gt; nil
         )
        (&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;blog-static&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:base-directory&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/blog/&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:base-extension&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;css&lt;/span&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;js&lt;/span&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;png&lt;/span&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;jpg&lt;/span&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;gif&lt;/span&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;pdf&lt;/span&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;mp3&lt;/span&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;ogg&lt;/span&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;swf&lt;/span&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;php&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:publishing-directory&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Projects/github-pages/&quot;&lt;/span&gt;
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:recursive&lt;/span&gt; t
         &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:publishing-function&lt;/span&gt; org-publish-attachment
         )
        (&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;blog&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:components&lt;/span&gt; (&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;blog-org&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;blog-static&quot;&lt;/span&gt;))))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
那么我每次新写文章的时候，就需要用 C-x C-f(find-file) 去在这个目录下新建一个文件，这个过程，是可以用 org-capture 来优化的。
&lt;/p&gt;

&lt;p&gt;
为了方便示例我们把问题简化一下，我需要的是执行 org-capture 后，自动在一个固定的目录下，产生一个命名类似 2018-03-25.org 的文件，并在文件中写入一些固定的内容。
&lt;/p&gt;

&lt;p&gt;
用 org-capture 我们可以这么做
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates
             `(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;b&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Blog&quot;&lt;/span&gt; plain (file ,(concat &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/blog/&quot;&lt;/span&gt;
                                               (format-time-string &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%Y-%m-%d.org&quot;&lt;/span&gt;)))
               ,(concat &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+startup: showall\n&quot;&lt;/span&gt;
                        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+options: toc:nil\n&quot;&lt;/span&gt;
                        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+begin_export html\n&quot;&lt;/span&gt;
                        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;---\n&quot;&lt;/span&gt;
                        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;layout     : post\n&quot;&lt;/span&gt;
                        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;title      : %^{&amp;#26631;&amp;#39064;}\n&quot;&lt;/span&gt;
                        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;categories : %^{&amp;#31867;&amp;#21035;}\n&quot;&lt;/span&gt;
                        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;tags       : %^{&amp;#26631;&amp;#31614;}\n&quot;&lt;/span&gt;
                        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;---\n&quot;&lt;/span&gt;
                        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+end_export\n&quot;&lt;/span&gt;
                        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+TOC: headlines 2\n&quot;&lt;/span&gt;)))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
注意，这里和前面的模板有一些不同
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;b&gt;`(&quot;b&quot; &quot;Blog&quot;&lt;/b&gt; 这里开头的符号不是单引号&lt;/li&gt;
&lt;li&gt;target 和 template 两部分中有一个 concat 函数的调用，在其前面有一个逗号&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
这里涉及到 emacs-lisp 的一些语法细节，想要详细了解的可以查看相关文档： &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/elisp/Backquote.html&quot;&gt;Backquote - GNU Emacs Lisp Reference Manual&lt;/a&gt;。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb0f8460&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb0f8460&quot;&gt;用 org-capture 来做网页内容收集&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb0f8460&quot;&gt;
&lt;p&gt;
结合 org-protocol，我们可以在外部程序中发送数据到 Emacs 中并触发 org-capture，是非常方便的一个功能。
&lt;/p&gt;

&lt;p&gt;
由于 org-protocol 本身还有很多细节，展开来讲的话内容会很多，这里就只重点讲一下和 org-capture 相关的部分。
&lt;/p&gt;

&lt;p&gt;
首先我们要知道 org-protocol 其实是定义了一个类似通信协议一样的东西，因此我们需要启动 Emacs server 来让外部程序可以访问，在配置文件中加入下面这行配置即可
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(server-start)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
要启用 org-protocol 的话，还需要在 Emacs 之外做一些设置，本文不准备在这里做过多说明，详情可以参考 &lt;a href=&quot;https://github.com/sprig/org-capture-extension&quot;&gt;org-capture-extension&lt;/a&gt; 这个项目，里面对 Linux/OSX/Windows 三个操作系统上的设置都做了详细说明。
&lt;/p&gt;

&lt;p&gt;
在 Emacs 中我们需要加载一下 org-protocol
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;require&lt;/span&gt; '&lt;span style=&quot;color: #6699cc; font-style: italic;&quot;&gt;org-protocol&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
当用 org-protocol 触发 org-capture 时，它会设置 org-store-link-plist 这个变量，根据外部传入的数据设置其中的一些属性。从 &lt;b&gt;org-protocol-do-capture&lt;/b&gt; 这个函数的源代码中，我们可以发现这么一段
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(org-store-link-props &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:type&lt;/span&gt; type
                      &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:link&lt;/span&gt; url
                      &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:description&lt;/span&gt; title
                      &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:annotation&lt;/span&gt; orglink
                      &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:initial&lt;/span&gt; region
                      &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:query&lt;/span&gt; parts)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
也就是说，在 org-store-link-plist 中的属性有六个，分别如下
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;属性&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;type&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;链接的类型，如 http/https/ftp 等，是靠正则 (string-match &quot;^\\([a-z]+\\):&quot; url) 解析出来的&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;link&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;链接地址，在 org-protocol 里的 url 字段&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;description&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;链接的标题，在 org-protocol 里的 title 字段&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;annotation&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;靠 link 和 description 完成的 org 格式的链接&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;initial&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;链接上选中的文本，在 org-protocol 里的 body 字段&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;query&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;org-protocol 上除掉开头和子协议部分的剩下部分&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
这和我们前面「&lt;a href=&quot;#org1a3d856&quot;&gt;capture 模板的五个部分&lt;/a&gt;」中提到的 org-protocol 在内容模板中可用的六个特殊标记，是一一对应的。
&lt;/p&gt;

&lt;p&gt;
利用这六个属性及对应的六个特殊标记，我们就可以方便地做网页内容的收集了。
&lt;/p&gt;

&lt;p&gt;
我们先为 org-protocol 相关的 capture 模板设立一个分组
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;p&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Protocol&quot;&lt;/span&gt;))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
最简单的情况是用 org-capture 来做网页书签管理，相应的 capture 模板会比较简单，只需要记录下网页的标题和链接即可，如下所示：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;pb&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Protocol Bookmarks&quot;&lt;/span&gt; entry
               (file+headline &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/web.org&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Bookmarks&quot;&lt;/span&gt;)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* %U - %:annotation&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:immediate-finish&lt;/span&gt; t &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:kill-buffer&lt;/span&gt; t))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
再进一步的，我们可以选中网页上的内容，通过 org-protocol 和 org-capture 快速记录到笔记中
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;pn&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Protocol Bookmarks&quot;&lt;/span&gt; entry
               (file+headline &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/web.org&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Notes&quot;&lt;/span&gt;)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* %U - %:annotation %^g\n\n  %?&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:empty-lines&lt;/span&gt; 1 &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:kill-buffer&lt;/span&gt; t))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
当然，上面的 capture 模板会有一个问题，假如说一个网页上，有多处我觉得有价值的内容，我都选中了然后通过 org-protocol 调用了 org-capture，那么实际上是会产生多条记录的。这种情况如果能将同一个网页的内容都按顺序放置到同一个 headline 里面，显然是更加合理的。对上面的 capture 模板稍作调整，得到的下面的模板就能满足这个需求：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates
             '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;pa&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Protocol Annotation&quot;&lt;/span&gt; plain
               (file+function &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/web.org&quot;&lt;/span&gt; org-capture-template-goto-link)
               &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;  %U - %?\n\n  %:initial&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:empty-lines&lt;/span&gt; 1))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这里用了 file+function，函数 org-capture-template-goto-link 的定义参考了 reddit 上的&lt;a href=&quot;https://www.reddit.com/r/emacs/comments/7m6nwo/file_orgcapture_item_under_existing_heading_if_it/&quot;&gt;这篇帖子&lt;/a&gt;。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;org-capture-template-goto-link&lt;/span&gt; ()
  (org-capture-put &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:target&lt;/span&gt; (list 'file+headline
                                 (nth 1 (org-capture-get &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:target&lt;/span&gt;))
                                 (org-capture-get &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:annotation&lt;/span&gt;)))
  (org-capture-put-target-region-and-position)
  (widen)
  (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;let&lt;/span&gt; ((hd (nth 2 (org-capture-get &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:target&lt;/span&gt;))))
    (goto-char (point-min))
    (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;if&lt;/span&gt; (re-search-forward
         (format org-complex-heading-regexp-format (regexp-quote hd)) nil t)
        (org-end-of-subtree)
      (goto-char (point-max))
      (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;or&lt;/span&gt; (bolp) (insert &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;\n&quot;&lt;/span&gt;))
      (insert &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* &quot;&lt;/span&gt; hd &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;\n&quot;&lt;/span&gt;))))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
此外，结合 abo-abo 的 &lt;a href=&quot;https://github.com/abo-abo/orca&quot;&gt;orca&lt;/a&gt; 工具，我们还可以针对不同的网站域名，来自动地将网页收集内容进行归类，可以应用的场景有
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;在 arxiv、google scholar 上用 org-protocol 触发 org-capture 时，自动新增内容到记录待读论文列表的 papers.org 中&lt;/li&gt;
&lt;li&gt;在淘宝、京东、亚马逊网站上用 org-protocol 触发 org-capture 时，自动新增内容到记录心愿单列表的 wishlist.org 中&lt;/li&gt;
&lt;li&gt;&amp;#x2026;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
而结合 &lt;a href=&quot;https://github.com/alphapapa/org-protocol-capture-html&quot;&gt;org-protocol-capture-html&lt;/a&gt; 这个工具，我们可以在用 org-protocol 触发 org-capture 时，将网页内容全文转换成 org 文件存储到特定目录中，打造一个类似&lt;a href=&quot;https://baike.baidu.com/item/%25E7%25A8%258D%25E5%2590%258E%25E9%2598%2585%25E8%25AF%25BB&quot;&gt;稍后阅读&lt;/a&gt;的工具。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org1c39a08&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1c39a08&quot;&gt;用 org-capture 来新建 Anki 卡片&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1c39a08&quot;&gt;
&lt;p&gt;
利用 &lt;a href=&quot;https://github.com/louietan/anki-editor&quot;&gt;anki-editor&lt;/a&gt;，我们可以在 org 文件中创建卡片并同步到 Anki 软件中。这里就以 anki-editor 中的卡片结构，来展示如何用 org-capture 创建 Anki 卡片。
&lt;/p&gt;

&lt;p&gt;
最简单的例子，是新建单词卡，用来辅助记忆我们学习到的一些新的单词。那么对应的 capture 模板是这个样子的：
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'org-capture-templates
             `(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;v&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Vocabulary&quot;&lt;/span&gt; entry
               (file+headline &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/Dropbox/org/anki.org&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Vocabulary&quot;&lt;/span&gt;)
               ,(concat &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;* %^{heading} :note:\n&quot;&lt;/span&gt;
                        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%(generate-anki-note-body)\n&quot;&lt;/span&gt;)))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
其中的 generate-anki-note-body 函数如下
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;generate-anki-note-body&lt;/span&gt; ()
  (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;interactive&lt;/span&gt;)
  (message &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Fetching note types...&quot;&lt;/span&gt;)
  (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;let&lt;/span&gt; ((note-types (sort (anki-editor-note-types) #'string-lessp))
        (decks (sort (anki-editor-deck-names) #'string-lessp))
        deck note-type fields)
    (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; deck (completing-read &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Choose a deck: &quot;&lt;/span&gt; decks))
    (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; note-type (completing-read &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Choose a note type: &quot;&lt;/span&gt; note-types))
    (message &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Fetching note fields...&quot;&lt;/span&gt;)
    (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; fields (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;anki-editor--anki-connect-invoke-result&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;modelFieldNames&quot;&lt;/span&gt; `((modelName . ,note-type))))
    (concat &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;  :PROPERTIES:\n&quot;&lt;/span&gt;
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;  :ANKI_DECK: &quot;&lt;/span&gt; deck &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;\n&quot;&lt;/span&gt;
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;  :ANKI_&lt;/span&gt;&lt;span style=&quot;color: #d0bf8f;&quot;&gt;NOTE&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;_TYPE: &quot;&lt;/span&gt; note-type &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;\n&quot;&lt;/span&gt;
            &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;  :END:\n\n&quot;&lt;/span&gt;
            (mapconcat (&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;lambda&lt;/span&gt; (str) (concat &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;** &quot;&lt;/span&gt; str))
                       fields
                       &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;\n\n&quot;&lt;/span&gt;))))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这个函数的定义是抄了 anki-editor(version:20180729) 中的代码，做了一些修改得到的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>PyTorch 初体验</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2018/01/07/pytorch-note.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2018/01/07/pytorch-note</id>
    <published>2018-01-07T00:00:00+00:00</published>
    <updated>2018-01-07T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


基础模块构成
其他




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgc9e33e4&quot;&gt;基础模块构成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org08971c3&quot;&gt;其他&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
这两周简单看了下 &lt;a href=&quot;http://pytorch.org/&quot;&gt;pytorch&lt;/a&gt;，虽然说还没有非常系统的、全方面的认识，但姑且总结一下好了。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgc9e33e4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgc9e33e4&quot;&gt;基础模块构成&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgc9e33e4&quot;&gt;
&lt;p&gt;
最核心的模型组件都在 torch.nn 这个模块里，这个模块里包含了
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;不同类型的网络结构，如：Embedding, LSTM, Conv1d, MaxPool1d, Linear&lt;/li&gt;
&lt;li&gt;不同类型的激活函数，如：RELU, SELU, Sigmoid, Tanh&lt;/li&gt;
&lt;li&gt;不同类型的目标函数，如：CrossEntropyLoss, MSELoss, HingeEmbeddingLoss&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
不一一列举，总之，如果是想构建起一个网络，不考虑训练的话，那么只用 torch.nn 这个模块里的东西就足够了。
&lt;/p&gt;

&lt;p&gt;
比较重要的是 torch.nn.Module 这个类，上述的网络结构、激活函数、目标函数都继承自这个类，如果是想自定义模型、激活函数、目标函数的话，继承这个类就好。所以这个类的行为和内在机制有必要好好了解一下。
&lt;/p&gt;

&lt;p&gt;
其次就是 torch.autograd 这个模块，其中的 Variable 是 torch 里的输入、输出数据的标准类型，也就是说，我们定义好一个模型后，如果想输入东西，就得把数据都转成 Variable 类型的值。
&lt;/p&gt;

&lt;p&gt;
torch.optim 里则定义了常用的一些优化方法，不多，罗列如下
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Adadelta&lt;/li&gt;
&lt;li&gt;Adagrad&lt;/li&gt;
&lt;li&gt;Adam&lt;/li&gt;
&lt;li&gt;SparseAdam&lt;/li&gt;
&lt;li&gt;Adamax&lt;/li&gt;
&lt;li&gt;ASGD&lt;/li&gt;
&lt;li&gt;SGD&lt;/li&gt;
&lt;li&gt;Rprop&lt;/li&gt;
&lt;li&gt;RMSprop&lt;/li&gt;
&lt;li&gt;Optimizer&lt;/li&gt;
&lt;li&gt;LBFGS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
差不多就是这个样子。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org08971c3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org08971c3&quot;&gt;其他&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org08971c3&quot;&gt;
&lt;p&gt;
暂时了解还不多，就不长篇大论了，这里随便写写。
&lt;/p&gt;

&lt;p&gt;
在模型层面，pytorch 使用起来确实舒服很多。主要的点有这些
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;不需要管 session、graph 这些东西，定义好的网络结构，直接就能接受输入并得到输出&lt;/li&gt;
&lt;li&gt;模块都继承自 torch.nn.Module 这个类，而这个类被设计成了 picklable 的，我们直接用 pickle.dump 和 pickle.load 就能对模型进行保存和加载，相比之下，tensorflow 默认将模型拆成若干个文件然后通过 saver 的方式来保存和加载一直让我非常抗拒 —— 倒不是说我认为模型存成多个文件就不好，但至少提供让我不存成多个文件的选项吧？在 tensorflow 里想要自己去把模型结构和模型参数拿出来按自己的想法存储这件事情，我是一直都没有成功过……&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
torch.nn.Module 类有一个 bool 类型的 training 成员，如果将其设置成 False，那么 Dropout、BatchNorm 之类的层就会失效，这个虽然是个很小的点但也是非常让人舒服的一点，tensorflow 里为了解决这个问题，通常就得自己来设置选项来保证在训练和预测的时候产生两张不同的图，贼恶心
&lt;/p&gt;

&lt;p&gt;
详情见 &lt;a href=&quot;https://discuss.pytorch.org/t/what-does-nn-modules-train-true-train-false-do/4004&quot;&gt;这个帖子&lt;/a&gt; 和 &lt;a href=&quot;https://discuss.pytorch.org/t/dropout-changing-between-training-mode-and-eval-mode/6833&quot;&gt;这个帖子&lt;/a&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
当然，也有一些坑，或者说我觉得不太满意的地方吧
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;目前 pypi 上的版本落后于官网版本，按照官网上的安装方法要下几百兆的东西……吐血……&lt;/li&gt;
&lt;li&gt;没有对整个项目结构和机制的总体介绍，当然，毕竟版本还在 0.3.0……&lt;/li&gt;
&lt;li&gt;模型内部的数据类型好像有不一致的地方，我在默认行为下，遇到过什么 DoubleTensor 的错误，可能和这个 &lt;a href=&quot;https://github.com/pytorch/pytorch/issues/1498&quot;&gt;issue&lt;/a&gt; 有关&lt;/li&gt;
&lt;li&gt;需要手动选择是否使用 CUDA，但是我明明看到 torch.cuda 下有个 is_available 的方法&lt;/li&gt;
&lt;li&gt;RNN 的输入和输出，默认第二个维度是 batch，如果想让第一个维度表示 batch，就得手动把 batch_first 设置成 True，挺奇怪的&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>Emacs 的 Python3 开发环境配置</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2017/09/16/emacs-python-configuration.html"/>
    <category term="Emacs" scheme="http://www.zmonster.me/categories.html#Emacs"/>
    <id>http://www.zmonster.me/2017/09/16/emacs-python-configuration</id>
    <published>2017-09-16T00:00:00+00:00</published>
    <updated>2017-09-16T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


基础配置
Emacs + Python3 的问题
company + jedi-core 的 Python3 配置
结合 virtualenv 来使用 f...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org17ae8b4&quot;&gt;基础配置&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgdee9213&quot;&gt;Emacs + Python3 的问题&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org56179ba&quot;&gt;company + jedi-core 的 Python3 配置&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org10dd21d&quot;&gt;结合 virtualenv 来使用 flycheck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org27ebd7d&quot;&gt;PEP8 的支持&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org17ae8b4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org17ae8b4&quot;&gt;基础配置&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org17ae8b4&quot;&gt;
&lt;p&gt;
基础配置就没啥好说的了，就是缩进宽度啦，各种 minor-mode 的添加啦之类的，直接上配置
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;my-python-mode-config&lt;/span&gt; ()
  (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; python-indent-offset 4
        python-indent 4
        indent-tabs-mode nil
        default-tab-width 4

        &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;; &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#35774;&amp;#32622; run-python &amp;#30340;&amp;#21442;&amp;#25968;&lt;/span&gt;
        python-shell-interpreter &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;ipython&quot;&lt;/span&gt;
        python-shell-interpreter-args &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;-i&quot;&lt;/span&gt;
        python-shell-prompt-regexp &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;In \\[[0-9]+\\]: &quot;&lt;/span&gt;
        python-shell-prompt-output-regexp &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Out\\[[0-9]+\\]: &quot;&lt;/span&gt;
        python-shell-completion-setup-code &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;from IPython.core.completerlib import module_completion&quot;&lt;/span&gt;
        python-shell-completion-module-string-code &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;';'.join(module_completion('''%s'''))\n&quot;&lt;/span&gt;
        python-shell-completion-string-code &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;';'.join(get_ipython().Completer.all_completions('''%s'''))\n&quot;&lt;/span&gt;)

  (add-to-list 'auto-mode-alist '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;\\.py\\'&quot;&lt;/span&gt; . python-mode))
  (hs-minor-mode t)                     &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#24320;&amp;#21551; hs-minor-mode &amp;#20197;&amp;#25903;&amp;#25345;&amp;#20195;&amp;#30721;&amp;#25240;&amp;#21472;&lt;/span&gt;
  (auto-fill-mode 0)                    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#20851;&amp;#38381; auto-fill-mode&amp;#65292;&amp;#25298;&amp;#32477;&amp;#33258;&amp;#21160;&amp;#25240;&amp;#34892;&lt;/span&gt;
  (whitespace-mode t)                   &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#24320;&amp;#21551; whitespace-mode &amp;#23545;&amp;#21046;&amp;#34920;&amp;#31526;&amp;#21644;&amp;#34892;&amp;#20026;&amp;#31354;&amp;#26684;&amp;#39640;&amp;#20142;&lt;/span&gt;
  (hl-line-mode t)                      &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#24320;&amp;#21551; hl-line-mode &amp;#23545;&amp;#24403;&amp;#21069;&amp;#34892;&amp;#36827;&amp;#34892;&amp;#39640;&amp;#20142;&lt;/span&gt;
  (pretty-symbols-mode t)               &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#24320;&amp;#21551; pretty-symbols-mode &amp;#23558; lambda &amp;#26174;&amp;#31034;&amp;#25104;&amp;#24076;&amp;#33098;&amp;#23383;&amp;#31526; &amp;#955;&lt;/span&gt;
  (set (make-local-variable 'electric-indent-mode) nil)) &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#20851;&amp;#38381;&amp;#33258;&amp;#21160;&amp;#32553;&amp;#36827;&lt;/span&gt;

(add-hook 'python-mode-hook 'my-python-mode-config)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
另外如果是 Emacs 25.1 的话，有一个已知 &lt;a href=&quot;https://lists.gnu.org/archive/html/bug-gnu-emacs/2016-08/msg00230.html&quot;&gt;bug&lt;/a&gt;，会导致执行 &lt;b&gt;run-python&lt;/b&gt; 的时候，python shell 里显示一堆乱码，下面的方法能够解决
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(setenv &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;IPY_TEST_SIMPLE_PROMPT&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;1&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgdee9213&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgdee9213&quot;&gt;Emacs + Python3 的问题&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgdee9213&quot;&gt;
&lt;p&gt;
从去年开始，因为工作的原因，日常的开发环境从 Python2 切换成了 Python3，一开始还是有一点不太习惯的，其中 Python 本身的语法差异倒真没有带来太多的不适应，一开始的抗拒主要还是因为不少 Python 的库在对 Python3 的支持上多少有点问题。
&lt;/p&gt;

&lt;p&gt;
当然，因为公司是用 Python3 的，碰到上述问题的时候就会去找替代方案了，加上主流的一些库也有了对 Python3 的支持，所以现在已经习惯了用 Python3，而且本身是从事 NLP 相关的工作，读写文本的时候不用每次都 encode/decode，还是挺舒服的。
&lt;/p&gt;

&lt;p&gt;
Python2 还是 Python3 这个就不想讨论了，网上相关的讨论也不少了。我这边的问题主要是，切换成 Python3 后，原来 Python 的配置多少都有点问题，比如语法检查、自动补全等默认都是用系统的 Python 环境的，要处理 Python3 的代码就需要额外做点事情，我这个人实在是懒于是去掉了语法检查、自动补全这些功能，将就着用着最基础的一些功能，倒也不是不能过日子。
&lt;/p&gt;

&lt;p&gt;
有时候也有考虑重新配置一下 Python 环境，但是一看到 elpy 啊 projectile 这些稍微复杂点的 package 就犯懒，倒是这阵子用一些更小的 package 一点一点地加新功能，貌似倒是已经解决了自己的需求了，加上有些时间没写东西了，想着写点东西，顺便分享下踩到的坑吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org56179ba&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org56179ba&quot;&gt;company + jedi-core 的 Python3 配置&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org56179ba&quot;&gt;
&lt;p&gt;
首先是自动补全了，一开始是用 &lt;b&gt;auto-complete&lt;/b&gt; 的，不过被 auto-complete 坑过太多次了， &lt;b&gt;company&lt;/b&gt; 算是后起之秀，配置起来也挺方便的。
&lt;/p&gt;

&lt;p&gt;
把 company 装上
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;when&lt;/span&gt; (not (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;require&lt;/span&gt; '&lt;span style=&quot;color: #6699cc;&quot;&gt;company&lt;/span&gt; nil &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:noerror&lt;/span&gt;))
  (message &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;install company now...&quot;&lt;/span&gt;)
  (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; url-http-attempt-keepalives nil)
  (package-refresh-contents)
  (package-install 'company))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后在启动 Emacs 的时候开启全局的 company-mode
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-hook 'after-init-hook 'global-company-mode)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
company-mode 默认已经配置好了多个语言的 backends，基本上是开箱即用的，查看变量 company-backends 可以看它当前使用的 backends，默认是
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(company-bbdb
 company-nxml
 company-css
 company-eclim
 company-semantic
 company-clang
 company-xcode
 company-cmake
 company-capf
 company-files
 (company-dabbrev-code company-gtags company-etags company-keywords)
 company-oddmuse company-dabbrev)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这些应付一些简单的场景足够用了。
&lt;/p&gt;

&lt;p&gt;
然后是安装 &lt;b&gt;company-jedi&lt;/b&gt;
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;when&lt;/span&gt; (not (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;require&lt;/span&gt; '&lt;span style=&quot;color: #6699cc;&quot;&gt;company-jedi&lt;/span&gt; nil &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:noerror&lt;/span&gt;))
  (message &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;install company-jedi now...&quot;&lt;/span&gt;)
  (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; url-http-attempt-keepalives nil)
  (package-refresh-contents)
  (package-install 'company-jedi))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
company-jedi 是 company 的一个 backend，使用 jedi 这个 Python 的自动补全和静态分析工具。需要注意的是，使用 package-install 安装 company-jedi 就好了，它会安装 &lt;b&gt;jedi-core&lt;/b&gt; 这个 package，里面有对 jedi 的封装。说这个是因为用户如果没有看 company-jedi 的说明，有可能会去安装 jedi 这个 Emacs package，但实际上这个 package 是一个 auto-complete 的后端，完全不用。
&lt;/p&gt;

&lt;p&gt;
到目前为止的操作都是通用的，和 Python2/Python3 都没有关系，但要知道，jedi 的工作原理是根据一个 Python 环境里的标准库及安装的非标准库来进行补全的，也就是说，它需要依赖一个外部的 Python 环境，如果去看 emacs-jedi 的文档，会看到要求用户执行 jedi:install-server 来建立一个 Python 环境，而这个命令实际上会在 ~/.emacs.d/.python-environments 这个目录下建立一个 virtualenv 环境，默认用的是 Python2.7。
&lt;/p&gt;

&lt;p&gt;
所以如果想为 Python3 配置 jedi，请注意 &lt;b&gt;不要使用 jedi:install-server 这种方式&lt;/b&gt; 。
&lt;/p&gt;

&lt;p&gt;
既然知道了 emacs-jedi 的工作原理，那就好办了，那我就自己在 ~/.emacs.d/.python-environments 这个目录下建立一个 Python3 的 virtualenv 环境呗。
&lt;/p&gt;

&lt;p&gt;
首先建立 ~/.emacs.d/.python-environments/ 这个目录
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;mkdir -p ~/.emacs.d/.python-environments/
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后在其中创建 virtualenv 环境，下面的示例中为这个 virtualenv 环境命名为 jedi，取别的名字都可以的
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;cd&lt;/span&gt; ~/.emacs.d/.python-environments/
virtualenv -p /usr/bin/python3  --prompt=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;lt;venv:jedi&amp;gt;&quot;&lt;/span&gt; jedi
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后在这个 virtualenv 环境中安装需要的 Python 依赖，依赖分两部分，一部分是 jedi 相关的几个 Python 包，是自动补全必须的，这些东西都在 jedi-core 这个 Emacs package 里的 setup.py 里写好了，其内容如下
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;setup(
    name=&lt;span style=&quot;color: #66cccc;&quot;&gt;'jediepcserver'&lt;/span&gt;,
    version=&lt;span style=&quot;color: #66cccc;&quot;&gt;'0.2.7'&lt;/span&gt;,
    py_modules=[&lt;span style=&quot;color: #66cccc;&quot;&gt;'jediepcserver'&lt;/span&gt;],
    install_requires=[
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;jedi&amp;gt;=0.8.1&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;epc&amp;gt;=0.0.4&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;argparse&quot;&lt;/span&gt;,
    ],
    entry_points={
        &lt;span style=&quot;color: #66cccc;&quot;&gt;'console_scripts'&lt;/span&gt;: [&lt;span style=&quot;color: #66cccc;&quot;&gt;'jediepcserver = jediepcserver:main'&lt;/span&gt;],
    },
    **args
)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到，依赖的是 jedi 和 epc 两个 Python 包，我们可以手动安装它们
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;~/.emacs.d/.python-environments/jedi/bin/pip install jedi&amp;gt;=0.8.1 epc&amp;gt;=0.0.4 argparse
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
也可以直接使用这个 setup.py 来安装
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;~/.emacs.d/.python-environments/jedi/bin/pip install --upgrade ~/.emacs.d/elpa/jedi-core-20170319.2107/
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
其次是需要用于补全的 Python 的非标准库，比如说我经常用 sklearn、tensorflow 之类的工具，我想在写相关的代码的时候能补全，那么要在我们刚才建立好的 virtualenv 环境里安装好这些 Python 包。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;~/.emacs.d/.python-environments/jedi/bin/pip install &lt;span style=&quot;color: #ffcc66;&quot;&gt;tensorflow&lt;/span&gt;==1.3.0 &lt;span style=&quot;color: #ffcc66;&quot;&gt;scipy&lt;/span&gt;==0.19.1 &lt;span style=&quot;color: #ffcc66;&quot;&gt;numy&lt;/span&gt;==1.13.1 scikit-learn==0.19.0
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
至此外部的设置都已经好了，然后就是要在 Emacs 里设置来使用我们刚才建立好的这个 virtualenv 环境
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; jedi:environment-root &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;jedi&quot;&lt;/span&gt;)
(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; jedi:server-command (jedi:-env-server-command))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后设置当打开 Python 代码文件的时候，启动 jedi
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;config/enable-jedi&lt;/span&gt; ()
  (add-to-list 'company-backends 'company-jedi))
(add-hook 'python-mode-hook 'jedi:setup)
(add-hook 'python-mode-hook 'config/enable-jedi)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
还有一些补全的细节可以设置，如
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
输入句点符号 &quot;.&quot; 的时候自动弹出补全列表，这个主要是方便用来选择 Python package 的子模块或者方法
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; jedi:complete-on-dot t)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
补全时能识别简写，这个是说如果我写了 &quot;import tensorflow as tf&quot; ，那么我再输入 &quot;tf.&quot; 的时候能自动补全
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; jedi:use-shortcuts t)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
设置补全时需要的最小字数(默认就是 3)
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; compandy-minimum-prefix-length 3)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
设置弹出的补全列表的外观
&lt;/p&gt;

&lt;p&gt;
让补全列表里的各项左右对齐
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; company-tooltip-align-annotations t)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
如果开启这个，那么补全列表会是下面这个样子
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/company-aligned-tooltip.png&quot; alt=&quot;company-aligned-tooltip.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
默认是这个样子
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/company-default-tooltip.png&quot; alt=&quot;company-default-tooltip.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
补全列表里的项按照使用的频次排序，这样经常使用到的会放在前面，减少按键次数
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; company-transformers '(company-sort-by-occurrence))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
在弹出的补全列表里移动时可以前后循环，默认如果移动到了最后一个是没有办法再往下移动的
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; company-selection-wrap-around t)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
对默认快捷键做一些修改
&lt;/p&gt;

&lt;p&gt;
默认使用 M-n 和 M-p 来在补全列表里移动，改成 C-n 和 C-p
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(define-key company-active-map (kbd &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;M-n&quot;&lt;/span&gt;) nil)
(define-key company-active-map (kbd &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;M-p&quot;&lt;/span&gt;) nil)
(define-key company-active-map (kbd &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;C-n&quot;&lt;/span&gt;) 'company-select-next)
(define-key company-active-map (kbd &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;C-p&quot;&lt;/span&gt;) 'company-select-previous)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
设置让 TAB 也具备相同的功能
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(define-key company-active-map (kbd &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;TAB&quot;&lt;/span&gt;) 'company-complete-common-or-cycle)
(define-key company-active-map (kbd &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;lt;tab&amp;gt;&quot;&lt;/span&gt;) 'company-complete-common-or-cycle)
(define-key company-active-map (kbd &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;S-TAB&quot;&lt;/span&gt;) 'company-select-previous)
(define-key company-active-map (kbd &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;lt;backtab&amp;gt;&quot;&lt;/span&gt;) 'company-select-previous)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org10dd21d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org10dd21d&quot;&gt;结合 virtualenv 来使用 flycheck&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org10dd21d&quot;&gt;
&lt;p&gt;
首先我们要安装 &lt;b&gt;flycheck&lt;/b&gt; 这个实时语法检查工具
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;when&lt;/span&gt; (not (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;require&lt;/span&gt; '&lt;span style=&quot;color: #6699cc;&quot;&gt;flycheck&lt;/span&gt; nil &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:noerror&lt;/span&gt;))
  (message &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;install flycheck now...&quot;&lt;/span&gt;)
  (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; url-http-attempt-keepalives nil)
  (package-refresh-contents)
  (package-install 'flycheck))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
在 python-mode 里启用也很简单
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;config/enable-flycheck&lt;/span&gt; ()
  (flycheck-mode t))
(add-hook 'python-mode-hook 'config/enable-flycheck)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
flycheck 使用 pylint 来对代码进行语法和代码规范的检查，实际上会使用 &lt;b&gt;executable-find&lt;/b&gt; 这个方法来确定使用的 pylint
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;defcustom&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;flycheck-executable-find&lt;/span&gt; #'executable-find
  &lt;span style=&quot;color: #cc99cc;&quot;&gt;&quot;Function to search for executables.&lt;/span&gt;

&lt;span style=&quot;color: #cc99cc;&quot;&gt;The value of this option is a function which is given the name or&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;path of an executable and shall return the full path to the&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;executable, or nil if the executable does not exit.&lt;/span&gt;

&lt;span style=&quot;color: #cc99cc;&quot;&gt;The default is the standard `&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;executable-find&lt;/span&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;' function which&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;searches `&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;exec-path&lt;/span&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;'.  You can customize this option to search&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;for checkers in other environments such as bundle or NixOS&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;sandboxes.&quot;&lt;/span&gt;
  &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:group&lt;/span&gt; 'flycheck
  &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:type&lt;/span&gt; '(choice (const &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:tag&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Search executables in `&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;exec-path&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;'&quot;&lt;/span&gt; executable-find)
                 (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:tag&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Search executables with a custom function&quot;&lt;/span&gt;))
  &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:package-version&lt;/span&gt; '(flycheck . &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;0.25&quot;&lt;/span&gt;)
  &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:risky&lt;/span&gt; t)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
而 executable-find 的工作原理是从 exec-path 这个变量里包含的的路径下寻找对应的可执行程序
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;executable-find&lt;/span&gt; (command)
  &lt;span style=&quot;color: #cc99cc;&quot;&gt;&quot;Search for COMMAND in `&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;exec-path&lt;/span&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;' and return the absolute file name.&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;Return nil if COMMAND is not found anywhere in `&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;exec-path&lt;/span&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;'.&quot;&lt;/span&gt;
  &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;; &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;Use 1 rather than file-executable-p to better match the behavior of&lt;/span&gt;
  &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;; &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;call-process.&lt;/span&gt;
  (locate-file command exec-path exec-suffixes 1))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
如果只是为了支持 Python3，那么我们可以自己建立一个 Python3 的 virtualenv，然后将其路径加到 exec-path 的最前面
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;push&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;lt;YOUR PYTHON3 VENV&amp;gt;/bin/&quot;&lt;/span&gt; exec-path)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
当然记得在里面安装 pylint，不然还是会用系统环境也就是 Python2 环境里的 pylint。
&lt;/p&gt;

&lt;p&gt;
这种方法可以 work，但是会有不方便的地方，比如说我有时候也有可能会写 Python2 代码，遇到 Python3 已经不兼容的语法，上述方法会导致 flycheck 认为是语法错误。另外一个就是，比较良好的开发习惯，是用 virtualenv 隔离开每个项目的依赖，不同项目的同一个依赖可能会版本不一样，这样的话 flycheck 如果只使用静态的环境就没有办法应付。
&lt;/p&gt;

&lt;p&gt;
当然，上一节的自动补全用的是一个统一的 virtualenv 环境，也会有类似的问题，不过要改起来会麻烦一些，所以先略过。
&lt;/p&gt;

&lt;p&gt;
flycheck 的这个问题倒是好解决，既然我每个项目都会有一个独立的 virtualenv，那么能不能做到我打开对应项目的代码的时候就使用对应的 virtualenv 环境呢，比如说将对应的路径添加到 exec-path 这个列表的前面？
&lt;/p&gt;

&lt;p&gt;
答案是可以的，方法是使用 &lt;b&gt;auto-virtualenvwrapper&lt;/b&gt;,这个 package 可以根据当前的文件寻找当前目录或者上级目录中的 virtualenv 环境，然后启用。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;when&lt;/span&gt; (not (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;require&lt;/span&gt; '&lt;span style=&quot;color: #6699cc;&quot;&gt;auto-virtualenvwrapper&lt;/span&gt; nil &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:noerror&lt;/span&gt;))
  (message &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;install auto-virtualenvwrapper now...&quot;&lt;/span&gt;)
  (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; url-http-attempt-keepalives nil)
  (package-refresh-contents)
  (package-install 'auto-virtualenvwrapper))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后设置一下在 python-mode 里启用它
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-hook 'python-mode-hook #'auto-virtualenvwrapper-activate)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
可以做到切换 buffer 的时候自动切换对应的 virtualenv 环境
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-hook 'window-configuration-change-hook #'auto-virtualenvwrapper-activate)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后我们要保证 flycheck 会在这个 virtualenv 环境里去寻找 pylint，也就是说，我们要临时修改一下 exec-path 的值
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;declare-function&lt;/span&gt; python-shell-calculate-exec-path &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;python&quot;&lt;/span&gt;)

(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;flycheck-virtualenv-executable-find&lt;/span&gt; (executable)
  &lt;span style=&quot;color: #cc99cc;&quot;&gt;&quot;Find an EXECUTABLE in the current virtualenv if any.&quot;&lt;/span&gt;
  (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;bound-and-true-p&lt;/span&gt; python-shell-virtualenv-root)
      (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;let&lt;/span&gt; ((exec-path (python-shell-calculate-exec-path)))
        (executable-find executable))
    (executable-find executable)))

(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;flycheck-virtualenv-setup&lt;/span&gt; ()
  &lt;span style=&quot;color: #cc99cc;&quot;&gt;&quot;Setup Flycheck for the current virtualenv.&quot;&lt;/span&gt;
  (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq-local&lt;/span&gt; flycheck-executable-find #'flycheck-virtualenv-executable-find))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
注：上述代码来自&lt;a href=&quot;https://github.com/lunaryorn/old-emacs-configuration/blob/master/lisp/flycheck-virtualenv.el&quot;&gt;lunaryorn 的配置&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org27ebd7d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org27ebd7d&quot;&gt;PEP8 的支持&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org27ebd7d&quot;&gt;
&lt;p&gt;
上面配置好的 flycheck 所做的语法检查和静态分析，对于不符合 PEP8 规范的语句已经会做一些提示了，不过说实话，一些东西我们可能并不想在上面化太多精力，运算符前后一个空格啦、函数之间空两行啦、类内方法之间空一行啦之类的，其实可以靠 &lt;b&gt;py-autopep8&lt;/b&gt; 来格式化代码自动完成。
&lt;/p&gt;

&lt;p&gt;
安装相应的 Emacs package
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;when&lt;/span&gt; (not (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;require&lt;/span&gt; '&lt;span style=&quot;color: #6699cc;&quot;&gt;py-autopep8&lt;/span&gt; nil &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:noerror&lt;/span&gt;))
  (message &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;install autopep8 now...&quot;&lt;/span&gt;)
  (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; url-http-attempt-keepalives nil)
  (package-refresh-contents)
  (package-install 'py-autopep8))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
当然它其实是使用的 Python 的 autopep8 这个外部工具，所以也需要安装它
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;pip install autopep8
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后在 python-mode 里启用就好了，下面的配置会让 Emacs 每次在保存 Python 文件的时候自动调用 autopep8 进行格式化
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-hook 'python-mode-hook 'py-autopep8-enable-on-save)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
当然我们也可以额外设置一些参数，比如默认的一个标准是每行最大字符数为 80，如果超过了，格式化的时候会将该行折行。下面的配置可以设置为 100
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;setq&lt;/span&gt; py-autopep8-options '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;--max-line-length=100&quot;&lt;/span&gt;))
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>深度学习在自然语言处理中的应用: 集智俱乐部活动笔记</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/12/14/dl_in_nlp.html"/>
    <category term="Deep Learning" scheme="http://www.zmonster.me/categories.html#Deep Learning"/>
    <id>http://www.zmonster.me/2016/12/14/dl_in_nlp</id>
    <published>2016-12-14T00:00:00+00:00</published>
    <updated>2016-12-14T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


简介
深度学习在自然语言处理中的应用
可微数据结构(Differentiable Data-structure)
语言学习的范式




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org2f60bfd&quot;&gt;简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org12c012f&quot;&gt;深度学习在自然语言处理中的应用&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org889346e&quot;&gt;可微数据结构(Differentiable Data-structure)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6baef5e&quot;&gt;语言学习的范式&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;hr  /&gt;

&lt;div id=&quot;outline-container-org2f60bfd&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org2f60bfd&quot;&gt;简介&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org2f60bfd&quot;&gt;
&lt;p&gt;
本文为对 2016 年 12 月 10 日集智俱乐部公开活动「深度学习与自然语言处理」进行的总结。
&lt;/p&gt;

&lt;p&gt;
活动主讲人是自然语言处理领域的知名学者吕正东，他先后在 MSRA 和华为诺亚方舟实验室担任过研究员，在顶级会议、期刊上发表过 40 余篇论文，并长期担任一些会议、期刊的审稿人。微博上的「&lt;a href=&quot;http://weibo.com/u/2141767181?topnav=1&amp;amp;wvr=6&amp;amp;topsug=1&quot;&gt;鲁东东胖&lt;/a&gt;」就是他啦，最近他创办了一家人工智能公司，正在进行招聘。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org12c012f&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org12c012f&quot;&gt;深度学习在自然语言处理中的应用&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org12c012f&quot;&gt;
&lt;p&gt;
自然语言处理(Natural Language Processing, &lt;b&gt;NLP&lt;/b&gt;)是人工智能中的一个重要分支，从人工智能这个领域刚发展起来的时候就一直是一个重要的研究方向，到现在也发展出了很多的细分领域和非常多的方法，大致上来说，我们可以认为是在 2013 年的时候，伴随着 word2vec 这个 word embedding 的开源工具的出现，正式地将深度学习引进了 NLP 的研究中 —— 当然要认真考据的话，word embedding 的思想早在上世纪 80 年代的时候就已经初露端倪&lt;sup&gt;&lt;a id=&quot;fnr.1&quot; class=&quot;footref&quot; href=&quot;#fn.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;，用神经网络来建模语言的工作也可以追溯到现为 IDL 科学家的徐伟在 2001 年的工作&lt;sup&gt;&lt;a id=&quot;fnr.2&quot; class=&quot;footref&quot; href=&quot;#fn.2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;以及 2003 年 Bengio 在 JMLR 上发表的著名论文《A Neural Probabilistic Language Model》，大家去了解 word2vec/word embedding 的时候经常会见到的一张经典的模型图(见图&lt;a href=&quot;#org1975290&quot;&gt;1&lt;/a&gt;)就来自 Bengio 的这篇论文。
&lt;/p&gt;


&lt;div id=&quot;org1975290&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/nplm_structure.png&quot; alt=&quot;nplm_structure.png&quot; width=&quot;60%&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;1&amp;nbsp; &lt;/span&gt;Bengio 的 NPLM&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
从不那么严格的大众的角度来看，可以说 word2vec 的出现是深度学习进入 NLP 领域的一个标志性事件，其中的 word embedding 思想带来了更好的文本的表示方法，也催生了各种在更高层级做 embedding 的工作，比如 sentence embedding，比如知识图谱中实体和关系的 embedding(TransE/TransR等)；而 sequence to sequence 思想的提出以及 attention 机制的出现，则在机器翻译(Machine Translation, &lt;b&gt;MT&lt;/b&gt;)领域产生了重要的作用。当然除此以外，CNN 和 GAN 乃至强化学习等最开始并不是用于 NLP 的方法，也被引入到 NLP 领域当中，并且取得了不错的结果。
&lt;/p&gt;

&lt;p&gt;
总得来说，深度学习给 NLP 研究带来的新方法可以列举如下:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;以 embedding 为代表的表示学习&lt;/li&gt;
&lt;li&gt;sequence to sequence 模型/encoder-decoder 框架&lt;/li&gt;
&lt;li&gt;注意力机制(Attention Mechanism)&lt;/li&gt;
&lt;li&gt;记忆网络(Memory Network)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
在 embedding 思想出现前，在各种 NLP 处理中都是用一个离散的值来表示每个词的，这种表示方法称为 one-hot 表示，是一种难以扩展、难以表达语义的方法。embedding 将一个词表示为多维空间中的一个连续实数向量，能在一定程度上反映语义乃至上下位关系。word embedding 的价值不在于它能得出的「男人 - 女人 = 国王 - 王后」这种类比关系，而在于它作为 NLP 中基本处理单元的一个基础表示，可以用来构建更高层级文本单元(句子、段落、篇章)的表示(见图&lt;a href=&quot;#orgc5b62c2&quot;&gt;2&lt;/a&gt;)，用来支撑更为复杂的上层操作如文本分类、机器翻译。
&lt;/p&gt;


&lt;div id=&quot;orgc5b62c2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/sentence_embedding_similarity.png&quot; alt=&quot;sentence_embedding_similarity.png&quot; width=&quot;60%&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;2&amp;nbsp; &lt;/span&gt;句子的 embedding 表示&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这种思想还能拓展到其他领域如知识图谱(见图&lt;a href=&quot;#orga16d437&quot;&gt;3&lt;/a&gt;)、复杂系统中。
&lt;/p&gt;


&lt;div id=&quot;orga16d437&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/transr.png&quot; alt=&quot;transr.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;3&amp;nbsp; &lt;/span&gt;知识图谱中的 TransR 模型&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
当然 word embedding 称不上完美，它还做不到完美地表达语义，但不用对这些问题太过刻薄纠结。我非常同意吕正东老师以及很多 NLP 学者的观点: word embedding 的效果在语言学层面还有尚待改进的地步，在留意这些问题的同时，还应该积极地去使用它去推动更复杂的 NLP 的研究和应用。
&lt;/p&gt;

&lt;p&gt;
sequence to sequence 或说 encoder-decoder 框架最初是在机器翻译中提出来的，以机器翻译为例，其基本思想是:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;将输入的句子经过一个 RNN 生成一个能反映句子语义的向量，类似计算 sentence embedding 的过程，&lt;/li&gt;
&lt;li&gt;用另一个 RNN ，从输入句子的向量表达中解码出另一个句子&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
第一个过程称之为 encoding，第二个过程称之为 decoding，整个模型非常的简单优雅，不需要词对齐，不需要额外的语言模型，输入英语，直接得到法语，这样便成了一个端到端(end-to-end)的模型，如图&lt;a href=&quot;#org7ca6f98&quot;&gt;4&lt;/a&gt;所示。
&lt;/p&gt;


&lt;div id=&quot;org7ca6f98&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/seq2seq.png&quot; alt=&quot;seq2seq.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;4&amp;nbsp; &lt;/span&gt;sequence to sequence 框架&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
之所以称其为「框架」而不是模型，在于它提出了一种通用的、可扩展的模型设计方式，其中的 encoder 和 decoder 都可以换成其他类型的神经网络结构，从而被广泛应用到不同的领域中，比如语音识别、OCR、自动驾驶、机器翻译、对话、image caption……而在 encoder-decoder 的基础上，为了改进机器翻译系统，attention 机制又被提了出来。
&lt;/p&gt;

&lt;p&gt;
attention 是一种在根据模型内部状态动态聚焦于输入或输出不同部分的一种机制，比如说做机器翻译时在不同时刻关注源语言文本中不同的词，如图&lt;a href=&quot;#org8a1df1d&quot;&gt;5&lt;/a&gt;所示。
&lt;/p&gt;


&lt;div id=&quot;org8a1df1d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/attention_alignment.png&quot; alt=&quot;attention_alignment.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;5&amp;nbsp; &lt;/span&gt;神经机器翻译中的 attention 矩阵&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在 image caption 任务中，要为一张图片生成描述性文字，在这里，attention 会根据当前要生成的词去聚焦于图片的不同区域，见图&lt;a href=&quot;#org099abf6&quot;&gt;6&lt;/a&gt;。
&lt;/p&gt;


&lt;div id=&quot;org099abf6&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/attention_in_image_caption.png&quot; alt=&quot;attention_in_image_caption.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;6&amp;nbsp; &lt;/span&gt;Image Caption 中的 attention&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
memory network 则是一种附带额外存储结构的神经网络模型，通过这个额外的存储结构来记忆更丰富的信息，使得模型具有更强的表达能力和学习能力。在这之中，对这个存储结构中信息的访问，使用的就是 attention 机制；相应的，在机器翻译和 image caption 这些任务中使用 encoder-decoder 模型时，也可以把 encoder 产生的输入的表达当作是 memory，attention 机制是在这个 memory 上挑选合适的内容。总之，在相关的场景中，我们可以认为 memory 是一个可以容纳有用信息的数据结构，而 attention 则是操作这个数据结构的一种方式，这也是这次活动中最主要讨论的内容。
&lt;/p&gt;

&lt;p&gt;
从应用上来说，深度学习给以下 NLP 任务带来了比较大的推动作用:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;机器翻译&lt;/li&gt;
&lt;li&gt;对话系统(Dialogue/Chatbot/Question Answering)&lt;/li&gt;
&lt;li&gt;自动推理&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
当然，这其中最受关注的就是机器翻译和对话系统了，毕竟语言的最终目的是用于进行交流，机器翻译能够让原来语言不同的两个人能够互相交流，而对话系统则能让人和机器以人类熟悉的方式进行交流，备受关注都是理所当然的。机器翻译在 NLP 领域中一直都是比较重要的一个方向，从应用意义上来说是一件能极大提高人类交流效率的事情，从学术意义上来说是一个数据相对充足且定义相对良好的研究问题，在神经机器翻译(Neural Machine Translation, &lt;b&gt;NMT&lt;/b&gt;)突破前，就已经有基于统计学方法的统计机器翻译(Statistical Machine Translation, &lt;b&gt;SMT&lt;/b&gt;)并且得到广泛应用。随着 encoder-decoder 框架和 attention 机制的提出，NMT 已经大幅超越了传统 SMT，并且在翻译问题上对 attention 机制的改进仍然在继续。
&lt;/p&gt;

&lt;p&gt;
谈到 NMT，当然离不开 Google 的翻译系统，图&lt;a href=&quot;#org109704b&quot;&gt;7&lt;/a&gt;就是 Google 神经机器翻译系统(Google Neural Machine Translation, &lt;b&gt;GNMT&lt;/b&gt;) 的模型结构，看起来有点复杂，其实就是 encoder-decoder 结构：左侧框图是 encoder 部分，右侧框图是 decoder 部分，它们之间靠 attention 机制联系起来。
&lt;/p&gt;


&lt;div id=&quot;org109704b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gnmt.png&quot; alt=&quot;gnmt.png&quot; width=&quot;80%&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;7&amp;nbsp; &lt;/span&gt;GNMT 模型结构&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
Google 在 NMT 方面的翻译效果，一方面固然来源于新的方法，另一方面也在于 Google 庞大的数据积累和强大的工程能力。数据是深度学习中很重要的成分，我在 Quora 上看到有人用「without data, it's nothing」来评论 NLP 的 Python 工具包 NLTK，在深度学习这块，我觉得也可以这样讲 —— 当然这么讲是强调数据的重要性，并不是说深度学习就不重要了，「巧妇难为无米之炊 」，要做好一桌可口的饭菜，原材料、烹饪工具和厨艺是缺一不可的。
&lt;/p&gt;

&lt;p&gt;
在对话方面，我们现在已经可以很简单地使用基于 encoder-decoder 的模型来得到一个用于对话的生成模型，在处理单轮对话和某些特定领域的多轮对话上取得不错的结果。最简单的办法，是将 encoder-decoder 框架用到对话领域，仿照机器翻译的方法，将对话看作是一个翻译问题，根据用户的话语来生成对应的回应。区别于传统的基于检索和基于规则、模板的方法，生成模型可以完全是数据驱动的， &lt;b&gt;在有足够丰富数据的情况下&lt;/b&gt; ，可以几乎不需要人工介入学习过程内部。图&lt;a href=&quot;#orgb82e77a&quot;&gt;8&lt;/a&gt;是一个例子。
&lt;/p&gt;


&lt;div id=&quot;orgb82e77a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/nrm.png&quot; alt=&quot;nrm.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;8&amp;nbsp; &lt;/span&gt;Neural Responding Machine&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
但我们能看出来，对话和翻译本质上是两个不同的事情，翻译是在两个不同语言但具有相同语义的文本之间做转换，对话则不是这样的，它是一个持续的过程，我们会希望它能记忆上下文、能识别实体、能辨别细微的感情等等等等。再加上在对话这个领域，数据的积累还不够，健全的评价标准还有待建立和完善。按照吕老师的看法，对话是比翻译复杂一到两个量级的任务，在真正得到突破前，可能还需要一定时间去提高我们对对话这个任务的认识。基本上来说，这两年在对话任务上所做的工作，也经常使用 encoder-decoder 框架，attention 机制基本也是标配，在多轮对话需要处理上下文时则还会使用如 memory network 之类带额外存储结构的模型来记忆上下文。除此以外，学术界还尝试了很多其他方法来用在对话任务上，比如整合知识图谱来提供精确的回答，比如应用强化学习来让优化对话结果&lt;sup&gt;&lt;a id=&quot;fnr.3&quot; class=&quot;footref&quot; href=&quot;#fn.3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;(见图&lt;a href=&quot;#orgeab07f6&quot;&gt;9&lt;/a&gt;)。
&lt;/p&gt;


&lt;div id=&quot;orgeab07f6&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dialogue_with_rl.png&quot; alt=&quot;dialogue_with_rl.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;9&amp;nbsp; &lt;/span&gt;强化学习在对话中的应用&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在另外一个应用「自动推理」上，按我的看法，可以分为两部分。我们谈推理的时候，可以是在谈形式逻辑的推理，也可以是自然语言层面的事实、因果、关系的推理，形式逻辑的推理可以用来做定理证明、类比归纳等各种事情，也是人工智能中的一个重要研究领域，这一块的定义是比较明确的；而自然语言推理则很难给出一个公认的定义，对此吕老师的观点是，如果我们在处理一个 NLP 任务时，需要对输入进行多遍处理，那么这个 NLP 任务就可以被认为是一个自然语言推理的任务。比如说 Facebook AI Research(FAIR) 用 memory network 在 bAbI 数据集(见图&lt;a href=&quot;#orgcc2e080&quot;&gt;10&lt;/a&gt;)做的问答&lt;sup&gt;&lt;a id=&quot;fnr.4&quot; class=&quot;footref&quot; href=&quot;#fn.4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;，就可以认为是一个推理过程。
&lt;/p&gt;


&lt;div id=&quot;orgcc2e080&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/fair_babi.png&quot; alt=&quot;fair_babi.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;10&amp;nbsp; &lt;/span&gt;FAIR 的 bAbI 数据集&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
bAbI 数据集是 FAIR 设计的用来考察对话系统个方面能力的一个数据集，包含了十几种从易到难的推理任务，此后有不少做对话或者推理的工作都通过这个数据集来评判模型的表达能力，比如 15 年 8 月香港中文大学 Baolin Peng 的 Neural Reasoner&lt;sup&gt;&lt;a id=&quot;fnr.5&quot; class=&quot;footref&quot; href=&quot;#fn.5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;，图&lt;a href=&quot;#orgc9ec6aa&quot;&gt;11&lt;/a&gt;是 Neural Reasoner 的模型结构，很显然也可以看作是一个 encoder-decoder 的模型。
&lt;/p&gt;


&lt;div id=&quot;orgc9ec6aa&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/neural_reasoner.png&quot; alt=&quot;neural_reasoner.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;11&amp;nbsp; &lt;/span&gt;Neural Reasoner&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
不管是形式逻辑的推理，还是自然语言推理，它都是在一定的知识基础上去做推理的，特别是自然语言推理，对于何谓知识何谓推理，都得是在一个具体的场景下才能界定清楚。据吕老师讲，他创立的「深度好奇」就是尝试将自然语言推理的技术应用到法律领域上，比如去做法律条文的理解和推断，想一想还是蛮酷的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org889346e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org889346e&quot;&gt;可微数据结构(Differentiable Data-structure)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org889346e&quot;&gt;
&lt;p&gt;
吕老师提出一个新的概念「可微数据结构」，其实并不是一个新的东西，而是对已有的各种模型中具有相同性质的模块或成分的一个统称。前面我们提到了 attention 和 memory network 两个重要的技术，讲到在 NMT 中 attention 其实就是在 encoder 输出的 hidden state 序列上根据当前要计算的输出选取有用的信息，这里这个 hidden state 序列在性质上和 memory network 或者神经元图灵机(Neural Turing Machine, &lt;b&gt;NTM&lt;/b&gt;)&lt;sup&gt;&lt;a id=&quot;fnr.6&quot; class=&quot;footref&quot; href=&quot;#fn.6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;增加的那个额外的存储结构其实是一样的，它们都保留了历史输入的信息并在输出时被反复读取，并且都是以一种模糊、可微的操作来进行处理。回过头来看 LSTM 的 cell state 也是这样的，forget gate 和 input gate 对它进行读写，output gate 则根据 cell state 得到输出。NMT 中的 hidden state 序列、memory network 和 NTM 中的额外存储结构，这就是吕老师称之为可微数据结构的事物 —— 当然，我个人觉得 LSTM 中的 cell state 也算。
&lt;/p&gt;

&lt;p&gt;
LSTM 中的 cell state 的操作相对还是比较简单，但毫无疑问它是现在这些 memory 一类思想的起源 —— 当然更早还可以追溯到 Hopfield Network，这里就不展开了 —— 我们不妨先从 LSTM 来讨论一下可微数据结构。首先的一点也是最关键的一点，作为一个「数据结构」，它提供了更强的信息存储能力，然后极大地增强了神经网络模型的表达能力和学习能力。LSTM 为什么能大幅地缓解 RNN 的梯度下降问题，提高长程依赖能力？从优化角度来说，是因为其中类似 residual network 中 skip connection 的 constant error flow，使得梯度不再是指数级衰减的，但只有 constant error flow 也不行呀，一味地记住过去的信息不加区分显然也不是合理的，而 forget gate 和 input gate 就起到了对过去信息选择性增强和丢弃的作用。这是我对可微数据结构的认识，它不仅能存储可用的信息，还能在此基础上用来做对信息的筛选，我们说得很多的 attention 机制，其实就是起这个作用的。
&lt;/p&gt;

&lt;p&gt;
当然，既然说 &lt;b&gt;可微&lt;/b&gt; ，那么对这个数据结构的操作，还必须是连续可微的才行。这个限制是为了保证这个数据结构和神经网络模型整合在一起时，不会破坏模型整体可微的的特性，我们都知道，现在大部分的神经网络模型，基本上都是用误差反向传播算法来进行训练的。
&lt;/p&gt;

&lt;p&gt;
对于可微数据结构，其实我更习惯叫它 memory，虽然是个容易和认知科学、心理学、物理学等各个领域中类似概念混淆的词。一图胜千言，神经元图灵机的结构示意图可以当作是对可微数据结构的一个普适的描述，如图&lt;a href=&quot;#orgc0dc152&quot;&gt;12&lt;/a&gt;所示。
&lt;/p&gt;


&lt;div id=&quot;orgc0dc152&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/ntm.png&quot; alt=&quot;ntm.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;12&amp;nbsp; &lt;/span&gt;神经元图灵机&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
我们可以按照其持续作用时间，将可微数据结构或说 memory 粗略地划分成短期记忆(Short Term Memory, &lt;b&gt;STM&lt;/b&gt;)、中间记忆(Intermediate Memory)和长期记忆(Long Term Memory, &lt;b&gt;LTM&lt;/b&gt;)，我们可以在感性上把它们和心理学上的瞬时记忆、工作记忆和长期记忆类比，当然其中的对应是否合理就不是本篇要讨论的内容了。encoder-decoder 模型中 encoder 产生的 hidden state 序列，是我们所说的短期记忆；而在问答中，模型会在 memory 中存储前几轮对话的信息，这个信息我们可以叫做中间记忆；而在一些基于知识图谱的推理问答任务中，还需要从知识图谱中进行知识的查找和推导，这个知识图谱，我们也可以将其视为 memory，这种独立于具体输入的信息，则叫做长期记忆。如图&lt;a href=&quot;#org0004791&quot;&gt;13&lt;/a&gt;所示。
&lt;/p&gt;


&lt;div id=&quot;org0004791&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/memory_types.png&quot; alt=&quot;memory_types.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;13&amp;nbsp; &lt;/span&gt;可微数据结构: 按持续时间分类&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
当然，也可以从结构上来对可微数据结构来分类，比如有像 NTM 中 memory 一样固定大小的 memory，也有像 Neural Stack Machine 这样大小可扩展的 memory&lt;sup&gt;&lt;a id=&quot;fnr.7&quot; class=&quot;footref&quot; href=&quot;#fn.7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;(见图&lt;a href=&quot;#orgd0856a7&quot;&gt;14&lt;/a&gt;)，再复杂一点的还有像 Deep Memory 这样的层次化的 memory&lt;sup&gt;&lt;a id=&quot;fnr.8&quot; class=&quot;footref&quot; href=&quot;#fn.8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;(见图&lt;a href=&quot;#org2b23aa3&quot;&gt;15&lt;/a&gt;)。使用什么样结构的 memory ，当然也要视具体任务而定。
&lt;/p&gt;


&lt;div id=&quot;orgd0856a7&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/neural_stack_machine.png&quot; alt=&quot;neural_stack_machine.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;14&amp;nbsp; &lt;/span&gt;Neural Stack Machine&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org2b23aa3&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/deep_memory.png&quot; alt=&quot;deep_memory.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;15&amp;nbsp; &lt;/span&gt;Deep Memory&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
借鉴计算机概念，我们可以说读写操作的基础是寻址操作，对可微数据结构的寻址是模糊的，我们称之为 soft addressing；而计算机寻址最后得到的是一个精确的地址值，我们称之为 hard addressing。所谓 soft addressing，得到的不是一个精确的地址，而是得到在所有地址上的权重，其中权重高的地址中的数据就是对当前计算更有价值的信息。我们前面说得很多的 attention，本质上就是一种寻址操作，对应的也有所谓 soft attention 和 hard attention。
&lt;/p&gt;

&lt;p&gt;
我们可以用 Python 代码来进一步解释一下 soft/hard addressing 的区别。假设我们有一个列表
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ff7800; font-weight: bold;&quot;&gt;import&lt;/span&gt; random

&lt;span style=&quot;color: #671ebb;&quot;&gt;x&lt;/span&gt; = [0, 1, 2, 3, 4, 5, 6]
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
以读取操作为例，所谓 hard addressing，是直接按下标来取一个元素
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #671ebb;&quot;&gt;hard_address&lt;/span&gt; = random.randint(0, &lt;span style=&quot;color: #000000; background-color: #f8f8ff;&quot;&gt;len&lt;/span&gt;(x))
&lt;span style=&quot;color: #671ebb;&quot;&gt;hard_value&lt;/span&gt; = x[hard_address]

&lt;span style=&quot;color: #409b1c;&quot;&gt;&quot;Hard addressing: {}&quot;&lt;/span&gt;.&lt;span style=&quot;color: #000000; background-color: #f8f8ff;&quot;&gt;format&lt;/span&gt;(hard_value)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
Hard addressing: 6
&lt;/pre&gt;

&lt;p&gt;
所谓 soft addressing，是先计算出一个权重向量，再按这个权重向量去计算
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ff7800; font-weight: bold;&quot;&gt;from&lt;/span&gt; operator &lt;span style=&quot;color: #ff7800; font-weight: bold;&quot;&gt;import&lt;/span&gt; mul

&lt;span style=&quot;color: #ff7800; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #000000; background-color: #f8f8ff; font-weight: bold;&quot;&gt;gen_weights&lt;/span&gt;(length):
    &lt;span style=&quot;color: #671ebb;&quot;&gt;weights&lt;/span&gt; = [random.random() &lt;span style=&quot;color: #ff7800; font-weight: bold;&quot;&gt;for&lt;/span&gt; _ &lt;span style=&quot;color: #ff7800; font-weight: bold;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #000000; background-color: #f8f8ff;&quot;&gt;range&lt;/span&gt;(length)]
    &lt;span style=&quot;color: #671ebb;&quot;&gt;weights_sum&lt;/span&gt; = &lt;span style=&quot;color: #000000; background-color: #f8f8ff;&quot;&gt;sum&lt;/span&gt;(weights)
    &lt;span style=&quot;color: #ff7800; font-weight: bold;&quot;&gt;return&lt;/span&gt; [w / weights_sum &lt;span style=&quot;color: #ff7800; font-weight: bold;&quot;&gt;for&lt;/span&gt; w &lt;span style=&quot;color: #ff7800; font-weight: bold;&quot;&gt;in&lt;/span&gt; weights]

&lt;span style=&quot;color: #671ebb;&quot;&gt;soft_addresses&lt;/span&gt; = gen_weights(&lt;span style=&quot;color: #000000; background-color: #f8f8ff;&quot;&gt;len&lt;/span&gt;(x))
&lt;span style=&quot;color: #671ebb;&quot;&gt;soft_value&lt;/span&gt; = &lt;span style=&quot;color: #000000; background-color: #f8f8ff;&quot;&gt;sum&lt;/span&gt;(&lt;span style=&quot;color: #000000; background-color: #f8f8ff;&quot;&gt;map&lt;/span&gt;(mul, soft_addresses, x))

&lt;span style=&quot;color: #409b1c;&quot;&gt;&quot;Soft addressing: {}&quot;&lt;/span&gt;.&lt;span style=&quot;color: #000000; background-color: #f8f8ff;&quot;&gt;format&lt;/span&gt;(soft_value)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
Soft addressing: 2.49246559272
&lt;/pre&gt;

&lt;p&gt;
当然，上面的寻址都是随机产生的，实际我们在做 attention 的时候是，一般来说，寻址可以分为按内容寻址和按地址寻址，在大部分场景中，我们使用按内容寻址的方式来对可微数据结构进行读写。需要注意的是，在做 soft addressing/attention 的时候，模型要学习的是「计算权重的函数」即上面代码中的 &lt;code&gt;gen_weights&lt;/code&gt; 方法，而不是 &lt;code&gt;soft_addresses&lt;/code&gt; 所代表的「每个时刻实际的权重」，以 NMT 为例，decoder 在每个 time step 时计算 attention 时用 decoder 的 hidden state 和 encoder 的 hidden state 做內积然后经过一个非线性变换得到 attention 权重，这里的这个非线性变换的参数就是学习到的，见图&lt;a href=&quot;#orgd019ca7&quot;&gt;16&lt;/a&gt;。在可微性得到保证的前提下，学习到的寻址方法应当是能增大更有用信息的权重、降低无关信息权重的。
&lt;/p&gt;


&lt;div id=&quot;orgd019ca7&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/attention_as_addressing.png&quot; alt=&quot;attention_as_addressing.png&quot; width=&quot;80%&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;16&amp;nbsp; &lt;/span&gt;Attention 与 Addressing&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
和 word embedding 的意义近似，可微数据结构和寻址方法的存在，可以作为更高层级操作的基础构成，想想图灵机吧，在纸带和读写头的基础上所产生出来的复杂计算，和这个是可以类比的。
&lt;/p&gt;

&lt;p&gt;
最开始在 NMT 中提出来的 attention 方法，只是对 encoder 的 hidden state 序列进行读操作，今年的 NMT 工作在为了解决 under-translation 和 over-translation 的问题，也开始提出了一些更复杂的 attention 方法，比如将 encoder 的 hidden state 存起来，然后每次不仅去读它们，还会去修改它们&lt;sup&gt;&lt;a id=&quot;fnr.9&quot; class=&quot;footref&quot; href=&quot;#fn.9&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;，这对 NMT 的结果有显著提高。图&lt;a href=&quot;#orgdb555be&quot;&gt;17&lt;/a&gt;是一个应用了改进的 attention 方法的模型。
&lt;/p&gt;


&lt;div id=&quot;orgdb555be&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/interactive_attention.png&quot; alt=&quot;interactive_attention.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;17&amp;nbsp; &lt;/span&gt;Interactive Attention&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
我们前面说可微数据结构对提高神经网络模型的表达能力和学习能力有很大的增强作用，但须知有一利必有一弊，在具体的场景下，该选择什么粒度的 memory 表示、该如何对其进行读写操作、该如何用这些基本操作来表达更复杂操作，都是需要去思考的；再比如 attention 计算的复杂度和 memory 的大小是正相关的，那么具体场景下，肯定是要在表达能力和训练效率之间折衷；另外可微性的要求也是对模型设计和训练的一个挑战，因此也有用 hard attention 加强化学习来设计模型的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6baef5e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org6baef5e&quot;&gt;语言学习的范式&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org6baef5e&quot;&gt;
&lt;p&gt;
这里说的「语言学习」，当然是指机器的「语言学习」。首先来看看我们人类的学习过程：我们会有老师或父母教我们字词和语法，这帮助我们学会最基本的表达和理解，这可以算作是监督学习；在有一定的词汇量并掌握基本语法后，我们可以通过大量阅读来更好地理解语言的使用，这是无监督学习；同时我们的学习过程是通过不停地试错来进行的，环境会给予我们各种反馈，比如说你说了一句在用词和语法方面都很糟糕的奇怪的语句，别人会表达出不理解或诧异，因此也可以将我们的学习过程视作强化学习；此外我们可以在掌握常识后基于常识来去对我们未接触过的语言现象或者知识进行快速的掌握，这是基于解释的学习，和最近的 zero-shot 学习类似？
&lt;/p&gt;

&lt;p&gt;
对于机器的「语言学习」范式，吕老师从不同的方面对其进行了划分：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
学习过程是 end-to-end 还是 step-by-step 的
&lt;/p&gt;

&lt;p&gt;
所谓端到端，是指整个学习过程直接从最后的输出中得到反馈来进行调整，而 step-by-step 则要对显式地对学习过程中的中间步骤进行调整。以机器翻译为例，神经机器翻译是端到端的，在 encoder-decoder 框架下，输入一个语言，直接去学习另外一个语言的输出，中间过程我们不用做人工干涉；而在统计机器翻译里，我们要得到两个语言之间的语言单元(词或短语)的翻译统计，要统计两个语言各自的词语搭配频率(语言模型)，最后还要学习对齐过程，这些都是分开进行的，只不过最后组合在一起而已。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;学习目标是连续可微的还是离散的&lt;/li&gt;
&lt;li&gt;学习过程中接受的 supervision，是来自人类的标注，还是来自环境的反馈&lt;/li&gt;
&lt;li&gt;是监督学习还是强化学习&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
2、3、4 讲的都是更高层级的对比，我们主要关心的还是 end-to-end 和 step-by-step 的对比。对于大部分问题，如果允许的话，我们都会希望整个学习过程是端到端的，喂进去一头猪，出来一堆火腿肠，这样多好！
&lt;/p&gt;

&lt;p&gt;
NLP 的学习任务，我们基本上可以将它们划分三个层级，即语法(syntax)、语义(semantics)和语用(pragmatics)，如图&lt;a href=&quot;#org5a793e2&quot;&gt;18&lt;/a&gt;所示。
&lt;/p&gt;


&lt;div id=&quot;org5a793e2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/nlp_phrases.png&quot; alt=&quot;nlp_phrases.png&quot; width=&quot;80%&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;18&amp;nbsp; &lt;/span&gt;NLP 层级&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
语用对应着真实的、具体的任务场景，从中我们可以得到反馈信息，这反馈信息向下层传递，调整整个学习过程(见图&lt;a href=&quot;#org869bc24&quot;&gt;19&lt;/a&gt;)，根据这个我们可以为很多 NLP 任务设计端到端的模型，比如基于 encoder-decoder 的 NMT 和单轮对话，都算是比较成功的案例，以及在复杂情况下的多轮对话，也有通过设计更复杂的模型来做到了端到端的学习，这个前文已经提过了。
&lt;/p&gt;


&lt;div id=&quot;org869bc24&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/nlp_phrases2.png&quot; alt=&quot;nlp_phrases2.png&quot; width=&quot;80%&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;19&amp;nbsp; &lt;/span&gt;NLP 层级(2)&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
但我们前面也说过了，端到端的学习过程当然是很好的，但它也有一些问题，它对模型设计的要求会比较高，如果模型设计地不好，导致信息在模型中间传递时出现问题，那么这个模型很可能就不能有效地学习。吕老师提到一个例子，给定一个俄罗斯方块的图像，最后要学习一个模型，预测其中俄罗斯方块类型的数量是偶数还是奇数，设计了一个端到端的模型如图&lt;a href=&quot;#orgad47db2&quot;&gt;20&lt;/a&gt;所示。
&lt;/p&gt;


&lt;div id=&quot;orgad47db2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/failed_end2end_task.png&quot; alt=&quot;failed_end2end_task.png&quot; width=&quot;80%&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;figure-number&quot;&gt;&amp;#22270;20&amp;nbsp; &lt;/span&gt;俄罗斯方块类型奇偶预测&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
看起来是很简单的问题，但是结果非常差，是一个失败的例子。对于这种端到端失败的情况，可能的原因有两个，一个是路径很长(比如说模型很深)，另外一个是信息在某一层的时候传递很困难。
&lt;/p&gt;

&lt;p&gt;
再就是，从我们自身的角度出发，人类的学习过程并不是端到端的，我们一味地在机器的语言学习过程中追求端到端地方式，未必是正确的。
&lt;/p&gt;

&lt;p&gt;
针对这些问题，吕老师提出，所谓语言学习的新范式，应该是
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
监督学习与强化学习的结合
&lt;/p&gt;

&lt;p&gt;
如果我们能放下对「端到端」的执念，应用强化学习的思想来让机器进行语言学习，我们前文提到的模型设计的困难会减轻很多。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;更具有可解释性的学习&lt;/li&gt;
&lt;li&gt;前文中我们提到的基于解释的学习&lt;/li&gt;
&lt;li&gt;无监督学习和其他方法的结合&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;&amp;#33050;&amp;#27880;: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.1&quot; class=&quot;footnum&quot; href=&quot;#fnr.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Elman, Jeffrey L. &quot;Finding structure in time.&quot; Cognitive science 14.2 (1990): 179-211.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.2&quot; class=&quot;footnum&quot; href=&quot;#fnr.2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Xu, Wei, and Alexander I. Rudnicky. &quot;Can artificial neural networks learn language models?.&quot; (2000).
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.3&quot; class=&quot;footnum&quot; href=&quot;#fnr.3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Li, Jiwei, et al. &quot;Deep Reinforcement Learning for Dialogue Generation.&quot; arXiv preprint arXiv:1606.01541 (2016).
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.4&quot; class=&quot;footnum&quot; href=&quot;#fnr.4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Weston, Jason, et al. &quot;Towards ai-complete question answering: A set of prerequisite toy tasks.&quot; arXiv preprint arXiv:1502.05698 (2015).
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.5&quot; class=&quot;footnum&quot; href=&quot;#fnr.5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Peng, Baolin, et al. &quot;Towards neural network-based reasoning.&quot; arXiv preprint arXiv:1508.05508 (2015).
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.6&quot; class=&quot;footnum&quot; href=&quot;#fnr.6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Graves, Alex, Greg Wayne, and Ivo Danihelka. &quot;Neural turing machines.&quot; arXiv preprint arXiv:1410.5401 (2014).
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.7&quot; class=&quot;footnum&quot; href=&quot;#fnr.7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Grefenstette, Edward, et al. &quot;Learning to transduce with unbounded memory.&quot; Advances in Neural Information Processing Systems. 2015.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.8&quot; class=&quot;footnum&quot; href=&quot;#fnr.8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Meng, Fandong, et al. &quot;A Deep Memory-based Architecture for Sequence-to-Sequence Learning.&quot; arXiv preprint arXiv:1506.06442 (2015).
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.9&quot; class=&quot;footnum&quot; href=&quot;#fnr.9&quot;&gt;9&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Meng, Fandong, et al. &quot;Interactive Attention for Neural Machine Translation.&quot; arXiv preprint arXiv:1610.05011 (2016).
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>个人知识管理系统(二): 信息的取舍与收集</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/10/22/pkm-information-collection.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2016/10/22/pkm-information-collection</id>
    <published>2016-10-22T00:00:00+00:00</published>
    <updated>2016-10-22T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


信息的取舍
信息的收集

RSS 和「即刻」
Feed43: 从静态网站生成 RSS 输出
微广场: 从微信公众号、知乎、简书、百度百家生成 RSS 输出...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org519d91e&quot;&gt;信息的取舍&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org263dff2&quot;&gt;信息的收集&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org7f79f5c&quot;&gt;RSS 和「即刻」&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org604dd48&quot;&gt;Feed43: 从静态网站生成 RSS 输出&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org845e4c0&quot;&gt;微广场: 从微信公众号、知乎、简书、百度百家生成 RSS 输出&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org56e1826&quot;&gt;微博看看: 从微博用户的 feed 流生成 RSS 输出&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge5f5ea8&quot;&gt;Huginn: 从任意网站生成 RSS 输出&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;
接上一篇 &lt;a href=&quot;http://www.zmonster.me/2016/10/11/pkm-design-overview.html&quot;&gt;《个人知识管理系统(一): 概述》&lt;/a&gt; ，本篇主要谈一下我是如何对信息进行取舍和收集的。
&lt;/p&gt;

&lt;div id=&quot;outline-container-org519d91e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org519d91e&quot;&gt;信息的取舍&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org519d91e&quot;&gt;
&lt;p&gt;
前文已经提过，信息的取舍是建立整个系统的第一步。而信息取舍也是分阶段的: 最初的阶段，剔除对个人来说无用的信息；第二个阶段，区分有用信息的重要程度，只保留重要的信息。
&lt;/p&gt;

&lt;p&gt;
第一个阶段是对信息的初步过滤，这个阶段可以发生在很多地方，不一定说是要整合在 PKM 之中。比如说屏蔽实际上不熟悉的微信好友的朋友圈，这是在系统之外；比如说在 RSS 阅读器中设置过滤规则将一些不感兴趣的信息自动标记为已读，这是在系统内。这个步骤是比较容易做到的。
&lt;/p&gt;

&lt;p&gt;
第二个阶段是按照信息的重要程度来进行取舍，相比第一个阶段要难得多，很多信息看起来都是有用的而让我们难以舍弃。但事实上低优先级的信息可能会在接收到的信息中占据很大的比利，如果不进行取舍，那么将大量时间花费在低质量信息的处理上，那只会事倍功半。
&lt;/p&gt;

&lt;p&gt;
需要说一下的是，系统外的信息取舍同样重要，因为如果被系统外的信息耗费了太多精力，在系统中的注意力就会减少，刷微博、刷知乎就是很典型的事例。
&lt;/p&gt;

&lt;p&gt;
对于信息的重要程度的区分，我按采铜的「收益值-半衰期」四象限法来进行区分。以下是采铜在知乎问题「&lt;a href=&quot;https://www.zhihu.com/question/22238159&quot;&gt;你有什么相见恨晚的知识推荐给年轻人？&lt;/a&gt;」的回答中对这个概念的描述:
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
当我们评价一个事情值不值得去做、应该花多少精力去做的时候，应该抛弃单一的视角，而是分从两个不同的维度来看，一是该事件将给我带来的收益大小（认知、情感、物质、身体方面的收益皆可计入），即「收益值」；二是该收益随时间衰减的速度，我称为「收益半衰期」，半衰期长的事件，对我们的影响会持续地较久较长。
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
以半衰期长为优先条件，不同的信息按照重要程度衰减的顺序，可以这样划分:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
高收益值长半衰期的信息
&lt;/p&gt;

&lt;p&gt;
如:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;深度学习和自然语言处理方面的论文&lt;/li&gt;
&lt;li&gt;像「阡陌的自留地」、「战隼的学习探索」这样的方法论博客&lt;/li&gt;
&lt;li&gt;深度学习和自然语言处理方面的深度文章&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
低收益值长半衰期的信息
&lt;/p&gt;

&lt;p&gt;
如:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;神话学、哲学、历史等方面的专著&lt;/li&gt;
&lt;li&gt;数学、计算机科学等学科的系统性知识&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
高收益短半衰期的信息
&lt;/p&gt;

&lt;p&gt;
如:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;段子、笑话之类的「趣味性」信息&lt;/li&gt;
&lt;li&gt;休闲小说&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
低收益短半衰期的信息
&lt;/p&gt;

&lt;p&gt;
如:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;微信、微博及其他社区或社交平台上的信息&lt;/li&gt;
&lt;li&gt;社会/行业的热点资讯&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
长半衰期的信息，基本上都需要深度的阅读，因此需要养成在固定的时间段内进行处理的习惯，这样从心理上和环境上都能保持比较稳定的状态，有利于快速进入阅读状态；短半衰期的信息，多半具有时效性，且数量庞大，因此需要进行筛选以减少数量，同时利用各种碎片化时间快速处理。
&lt;/p&gt;

&lt;p&gt;
结合前面的「两个阶段」，我的总体的取舍方法是这样的:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;减少社交平台上的信息量: 微信上屏蔽「不熟悉好友」的朋友圈，微博和知乎上限制关注数量&lt;/li&gt;
&lt;li&gt;减少资讯类信息的数量，只对每日的热点做大概了解，比如使用「即刻」而不是订阅一堆资讯类信息源&lt;/li&gt;
&lt;li&gt;降低信息冗余，删除不同渠道的相同信息源(比如同一个人的知乎专栏和微信公众号)，删除只做信息转发的信息源&lt;/li&gt;
&lt;li&gt;按照自己的兴趣和规划，对信息源进行分类，删除无法分类的信息源&lt;/li&gt;
&lt;li&gt;维护一个关键词列表，在信息汇总的地方进行二次过滤&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
此外，尽量避免使用「稍后阅读」类工具，也不要在浏览器书签或者笔记工具中上收藏一大堆文章 —— 对此有些人可能会有异议，但就我而言，信息的收集只是为后续的知识提炼准备材料，我的目的 &lt;b&gt;不是建立一个可供快速搜索的庞大资料库&lt;/b&gt; 。所有收集到的信息，都应该在一定时间内被消化然后清除掉，如果有哪些信息一直滞留在收集阶段，那么这样的信息对我来说是无用甚至有害的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org263dff2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org263dff2&quot;&gt;信息的收集&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org263dff2&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org7f79f5c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org7f79f5c&quot;&gt;RSS 和「即刻」&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org7f79f5c&quot;&gt;
&lt;p&gt;
我主要使用 RSS 阅读器来收集、汇总不同的信息源。
&lt;/p&gt;

&lt;p&gt;
首先介绍一下 RSS，它是「简单信息聚合(Really Simple Syndication)」的简称，是一种标准化的信息格式，允许人们将不同的信息来源以统一的格式进行聚合和处理。RSS 最初用来整合不同新闻站点的内容，后来在博客上被广泛使用。需要明确的是，RSS 只是一种「信息标准」，包括以特定结构和格式来存储信息，以及对信息的更新，而 RSS 阅读器则是支持这种信息标准的一个整合工具，用来接收不同信息源的 RSS 输出，然后在统一的界面中进行呈现。
&lt;/p&gt;

&lt;p&gt;
RSS 阅读器的好处是保证阅读环境和交互的统一，以及基于统一信息标准上的丰富的扩展操作。某种程度上来说，像 Pocket 等稍后阅读工具或者 Evernote/为知笔记 等笔记手机工具，也能做到「阅读环境和交互的统一」，但是这些工具只提供环境，不提供「信息的自动收集」这个功能。RSS 阅读器会定时去检查信息源的 RSS 输出，发现更新后就呈现出来 —— 当然也可以用 IFTTT 一类的工具来监听信息源然后自动化地添加内容到 Pocket/Evernote 里，但这样稍显麻烦一些。
&lt;/p&gt;

&lt;p&gt;
在 RSS 阅读器中，我可以对信息源进行分类整理，RSS 阅读器帮我进行定时的更新同步，我则定期打开 RSS 阅读器，选择某个类别一口气读完而不用在乎它是从哪个来源产生的。这种阅读体验很难在别的地方获得 —— 有点类似微博的 feed 流，但是社交平台上的内容质量相对还是太低了。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/inoreader.png&quot; alt=&quot;inoreader.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
然而使用 RSS 阅读器会碰到一个问题，那就是一个信息源是否提供 RSS 格式的输出是由信息源自己控制的，它如果不愿意提供 RSS 输出，那么似乎就没有办法获得其中的信息了。当然实际上是有解决办法的，稍后再谈。
&lt;/p&gt;

&lt;p&gt;
除了 RSS 阅读器，我还使用手机 App 「即刻」来接收资讯类信息。前文也说了，资讯类信息往往具有短时效性，且数量庞大，如果用 RSS 阅读器接收，很容易造成信息过载，对我来说，我只要知道每一天发生了哪些大事件即可，即刻上的「今天微博都在热议什么」和「一觉醒来世界发生了什么」很好地满足了我这个需求。
&lt;/p&gt;

&lt;p&gt;
RSS 阅读器我用 Inoreader，再加上即刻，这就是我使用且仅使用的两个在线的信息收集工具。书籍阅读我要么用 Kindle，要么直接买实体书，书籍阅读笔记的收集属于知识的提炼部分，因此在本文不进行讨论。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org604dd48&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org604dd48&quot;&gt;Feed43: 从静态网站生成 RSS 输出&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org604dd48&quot;&gt;
&lt;p&gt;
前文也说了，RSS 只是一种信息标准，信息源如果有提供 RSS 输出，那当然是最好的，如果没有，那么只要用一些方法将内容从信息源中「抽取」出来，然后按照 RSS 的格式组织好，不就生成了一个 RSS 输出结果吗？没错，任何一个可以公开访问的信息源，理论上都能转换为 RSS 输出，基本步骤就是「内容抽取-格式转换」两个步骤，由于 RSS 的格式是标准的，格式转换这一步没有太多难度，因此将一个网站的内容转换成 RSS 输出，主要的难度在内容抽取上。
&lt;/p&gt;

&lt;p&gt;
最简单的一种情况是静态网站，所谓静态网站，是指访问的网页内容就是一个对不同的人来说内容不变的网页文件，这种网站上的内容访问不受限制，比如说不需要登录啊之类的，因此可以很简单地完成内容抽取这一步。而 &lt;a href=&quot;http://feed43.com&quot;&gt;Feed43&lt;/a&gt; 就是这样一个用来从静态网站中生成 RSS 输出的工具。
&lt;/p&gt;

&lt;p&gt;
Feed43 的使用需要一点 HTML/CSS 的知识，稍微有点门槛，如果没有这方面知识的需要先了解一下。接下来以简书用户「计算士」的简书首页为例演示一下如何整个过程。
&lt;/p&gt;

&lt;p&gt;
进入 Feed43 的页面后，点击「Create Feed」进入操作页。首先填入要处理的网页地址，在这里填入要解析的网页: &lt;a href=&quot;http://www.jianshu.com/users/2e2954a2be81/latest_articles&quot;&gt;http://www.jianshu.com/users/2e2954a2be81/latest_articles&lt;/a&gt; ，然后点击「Reload」来载入网页内容，如下图所示:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/feed43_step1.png&quot; alt=&quot;feed43_step1.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
其实每一步 Feed43 都给出了简洁但友好的提示，如果懂 HTML/CSS ，按照提示一步一步进行就可以了。在载入网页内容后，Feed43 会要求填写提取规则，包含两部分
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Global Search Pattern: 用来定位内容的总体区域所在&lt;/li&gt;
&lt;li&gt;Item(repeatable) Search Pattern: 用来定位每一条内容的具体位置&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
提取规则会有一些简单的语法，可以通过点击界面上的小问号来查看了解。
&lt;/p&gt;

&lt;p&gt;
提取规则填写好后，点击「Extract」可以看到提取内容，如果提取规则写得不对，那么提取结果会给出反馈，回去继续修改直到能正确提取即可。
&lt;img src=&quot;/assets/img/feed43_step2.png&quot; alt=&quot;feed43_step2.png&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;
提取出内容后，再定义好 RSS 输出的内容，其实就是填写 title 是什么，url 是什么之类的。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/feed43_step3.png&quot; alt=&quot;feed43_step3.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
然后点击 preview 可以预览生成的 RSS 输出
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/feed43_step4.png&quot; alt=&quot;feed43_step4.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
如果 preview 没有问题，Feed43 会生成可用的 RSS 链接，比如上述「计算士」的简书页面，生成的 RSS 链接为: &lt;a href=&quot;http://feed43.com/5507461252042782.xml&quot;&gt;http://feed43.com/5507461252042782.xml&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org845e4c0&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org845e4c0&quot;&gt;微广场: 从微信公众号、知乎、简书、百度百家生成 RSS 输出&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org845e4c0&quot;&gt;
&lt;p&gt;
微信公众号是一个封闭的内容平台，对于想使用 RSS 阅读器来聚合信息的人来说可能是一个难以割舍的信息来源。而微广场对此提供服务，从微信公众号、知乎、简书等站点生成 RSS 输出，这样就可以把订阅的一堆微信公众号以及知乎上关注的很多专栏都整合进 RSS 阅读器里了。
&lt;/p&gt;

&lt;p&gt;
简书在 Feed43 一节讲了，由于是静态网站，是可以用一些简单的工具来转换的，不过有现成的服务自然是乐得轻松了。微信公众号其实是一个很封闭的平台，不过好在后面搜狗提供了微信公众号的搜索，所以也有办法进行转换了。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/iwgc.png&quot; alt=&quot;iwgc.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
由于免费用户只能订阅 10 个站点，我购买了一年的会员，除了没有订阅数量上限外，会员还能提交微广场没有收录的站点。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org56e1826&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org56e1826&quot;&gt;微博看看: 从微博用户的 feed 流生成 RSS 输出&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org56e1826&quot;&gt;
&lt;p&gt;
「微博看看」原名「微博档案」，是一个微博备份工具，同时提供 RSS 输出。我原先在微博上关注了不少做机器学习、深度学习方面的微博用户，但他们的 feed 流经常被我关注的其他微博用户的 feed 流打乱，有了微博看看后我就取关了这些微博用户，在 RSS 阅读器里看他们输出的内容了，目前只对「爱可可-爱生活」老师的 feed 流做了转换。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/weibo_rss.png&quot; alt=&quot;weibo_rss.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge5f5ea8&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge5f5ea8&quot;&gt;Huginn: 从任意网站生成 RSS 输出&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge5f5ea8&quot;&gt;

&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/huginn.png&quot; alt=&quot;huginn.png&quot; width=&quot;30%&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;a href=&quot;https://github.com/cantino/huginn&quot;&gt;Huginn&lt;/a&gt; 是一个 Ruby 编写的自动化工具，在理念上类似 IFTTT 和天国的 Yahoo! Pipes，即进行事件的监听然后根据预先设定的规则自动化地进行后续操作。
&lt;/p&gt;

&lt;p&gt;
Huginn 的 wiki 上列举了一些典型的使用场景，如:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Never Forget Your Umbrella Again: 下雨提醒&lt;/li&gt;
&lt;li&gt;Adding RSS Feeds to Any Site: 为任意网站生成 RSS 输出&lt;/li&gt;
&lt;li&gt;Follow stock prices: 监听股票价格&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
在 Huginn 中，主要有 event 和 agent 两个概念，agent 类似 IFTTT 里的 channel，event 则是 agent 的输出。在 Huginn 中可以将一个 agent 的输出作为另外一个 agent 的输入，由此产生复杂的自动化操作。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/huginn_diagram.png&quot; alt=&quot;huginn_diagram.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
上图来自 &lt;a href=&quot;https://web.archive.org/web/20170315013204/http://www.jianshu.com/p/4a47e452abc9&quot;&gt;Huginn:烧录RSS的神器&lt;/a&gt; 一文，该文对 Huginn 的使用做了很详细的介绍。
&lt;/p&gt;

&lt;p&gt;
和 IFTTT 不同的是，Huginn 需要自己部署，很多细节需要自己定制，因此在使用门槛上会高很多。
&lt;/p&gt;

&lt;p&gt;
目前我用 Huginn 来将 Google Scholar 关键词搜索结果输出为 RSS，这样我在 RSS 阅读器里就能看到我关心的一些深度学习的主题的论文更新情况了。此外，前文提到的提供微信公众号「微广场」，因为内容生产方的一些防护策略，可能会不稳定，替代方案是用 Huginn 从搜狗的微信公众号搜索结果中生成 RSS 输出。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>个人知识管理系统(一): 概述</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/10/11/pkm-design-overview.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2016/10/11/pkm-design-overview</id>
    <published>2016-10-11T00:00:00+00:00</published>
    <updated>2016-10-11T00:00:00+00:00</updated>
    <description>
    
      <p>

</p>
    
    </description>
    <content type="html">
      &lt;hr  /&gt;

&lt;p&gt;
浏览器上堆满了书签、收藏的网址，知乎和微博的 feed 流奔涌从无休止，摘抄本里这一页还是宋时买房的趣事、下一页就堆满了产品经理必知必会的几大模型。微信公众号里有好多有深度的文章，知乎里学到了好多知识，简书上以文会友真让人羡慕，豆瓣读书上有人在某本书下坚持不懈地记着笔记 —— 「P81 如果我们想增强自控力……」…… 我还能数出好多非常棒的阅读应用，「单读」、「Mono」、「豌豆荚·一览」、「豆瓣·一刻」、「好奇心日报」、「ONE」、「界面」……
&lt;/p&gt;

&lt;p&gt;
我曾沉溺其中，你们呢？
&lt;/p&gt;

&lt;p&gt;
浏览器上千来个书签，有多少是当时觉得很有价值而收藏下来，此后再也没有打开过的呢？手机上安装的一堆阅读应用，上次打开时是什么时候呢？看到公众号更新的小红点、feed 流里「有 xx 条新动态」，是不是忍不住去看看发生了什么？
&lt;/p&gt;

&lt;p&gt;
在这个信息爆炸的年代，我们的注意力时时刻刻被卷入信息流中，有人乐在其中，有人干净利落地脱离。我呢，稍微有点贪心，我不想彻底地离开信息的洪流，但又想在其中保持足够的理智 —— 当然了，这是我希望的方式，但并非我追求的结果，关乎选择，没有对错。
&lt;/p&gt;

&lt;p&gt;
我所追求的，是「知识」，而非信息。信息，只是一段接受到的有价值或无价值的数据；知识，是「我」对这个世界的认识，是外界信息在我身上的内化。信息引发我的思考、行动，知识决定我思考、行动的方式和方向。
&lt;/p&gt;

&lt;p&gt;
首先，要对信息有所取舍，将那些无休止地耗费注意力、但对于个人心智成长毫无意义的内容从视野中彻底剔除。得到对自己有用的信息后，要从中提炼出知识碎屑，将这些零散的知识梳理、系统化，这些知识就成了自己的东西。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/pkm_overview.png&quot; alt=&quot;pkm_overview.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
为了这个目的，我一直尝试建立一套高效的流程，即标题所谓「个人知识管理(Personal Knowledge Management)」，当然，专业的知识管理定义和我的表述未必相符，知识管理和信息管理之间的区别，我也不是很明了，姑且这么用着。
&lt;/p&gt;

&lt;p&gt;
我对这套 PKM 流程/系统有以下期待:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;有足够的信息来源，但这些信息来源能集中汇总到一处&lt;/li&gt;
&lt;li&gt;信息的筛选和过滤由我自己来进行，我不需要推荐，不需要「智能处理」&lt;/li&gt;
&lt;li&gt;尽量少的干扰，尽量与社交行为隔绝&lt;/li&gt;
&lt;li&gt;从信息中提炼的知识能集中汇总到一处&lt;/li&gt;
&lt;li&gt;梳理、系统化的过程能使用我最舒服的编辑环境&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
对于第一点，其实信息来源一直是很多的，但是这些信息来源有很多种类型，关注的博客、知乎专栏、微信公众号、阅读 App 等，每个我都需要在不同的地方用不同的方式接收，在不同的环境之间切换将导致效率的极大损耗，这是我不能忍受的，我希望我只在一个环境中接收信息。
&lt;/p&gt;

&lt;p&gt;
对于第二点，我不信赖大多数的推荐功能，加之我对业界的推荐算法有所了解，我知道这些推荐算法是无法满足我的需求的，至于「人工智能」，有多少「智能」就有多少人工，我觉得某些方面还是我自己聪明一点。从另外的角度来讲，自己控制自己的信息源也是很重要的，这能保证自己得到的不是别人刻意筛选过的结果，保证自己接收到的不是片面的信息。
&lt;/p&gt;

&lt;p&gt;
对于第三点，我认为阅读是一件需要沉浸其中的事情，即使是「碎片化阅读」，也要保证当我开始阅读的时候不会被打断，而微信公众号、微博、知乎这种带有社交属性的平台，很难做到这一点。当我阅读时，我只想阅读时；当我打开微信时，我只关心社交和通信 —— 两者应当泾渭分明。
&lt;/p&gt;

&lt;p&gt;
对于第四点，与汇总信息源的动机同理，如果提炼的知识分散在不同的地方，如便签、纸质笔记本、网络上的笔记应用，那么将影响后续梳理、系统化的效率。在这个问题上，已经有了一些比较成熟的方案，比如用 evernote/印象笔记/为知笔记来管理自己的笔记，但对我来说，我最终需要的输出自己生产的系统化的知识，而不是维护一个庞大的可供快速搜索的「知识库」 —— 从这点来说，为知笔记其实是一个不错的选择，但是它不满足我的第五点需求。
&lt;/p&gt;

&lt;p&gt;
最后一点，我是一个 Emacs 用户，是 org-mode 的重度用户，我的写作行为 —— 博客、笔记、工作日志，都是在 org-mode 中进行的，甚至在浏览器上的很多需要输入的地方，我都通过 Chrome 插件调用 Emacs 来进行编辑。org-mode 天生的大纲式的组织方式让我能很好地梳理思路；内置的 babel 模块能让我不脱离编辑环境就能得到代码片段的结果 —— 本文所有附图就是在同一个文件内使用 babel 对编写的 graphviz dot 代码求值得到的输出；强大的导出功能让我能在 org-mode 里写的 LaTeX 数学表达式在导出成 HTML 的时候以漂亮的形式展现，比如「\(e^{i\pi}+1=0\)」；capture 功能能让我快速地新建笔记、日程、灵感……我是已经无法脱离 org-mode 的，markdown 简陋的功能在我看来就是一个玩具，但即使这样 markdown 也比网上各种编辑环境强太多了。前面也说过为知笔记其实是一个很好的知识管理工具，但是它仍然是基于 markdown 的，虽然有 org-mode 插件但只能在 Windows 下使用 —— 但即使在 Linux 下为知笔记能使用 org-mode 插件，想来也是阉割过的 org-mode，毕竟 org-mode 的语法是一个很庞大的体系，不是谁都有精力去完全支持它，而没有了 babel 和 LaTeX 支持的 org-mode，对我来说无异于废物。这是因为我自身经历而比较特殊的一点。
&lt;/p&gt;

&lt;p&gt;
最后我将我的 PKM 系统设计为如下形式
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/pkm_design.png&quot; alt=&quot;pkm_design.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
基本的思路是:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;将所有自己关心的信息源 RSS 化，对于完全没有办法 RSS 化的信息源，直接丢弃 —— 而将信息源 RSS 化的理由是，这是目前唯一一个允许我自己管理信息来源的方式，也是和后续许多其他工具进行整合的前提条件&lt;/li&gt;
&lt;li&gt;将信息源的 RSS 收集到一个统一的地方，以便进行后续处理&lt;/li&gt;
&lt;li&gt;汇总信息流后，使用一些工具来对其进行过滤，主要出于两个考虑

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;即使是优质的信息源，也会有我不关心的内容&lt;/li&gt;
&lt;li&gt;不同的信息源之间会出现重复的内容&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;对于信息收集器里未被过滤的信息，我会定期阅读、清空，并且从中产生笔记、摘抄，而这些笔记也会被收集到一个统一的地方&lt;/li&gt;
&lt;li&gt;笔记收集起来后，会按照领域、用途梳理好，有些会转换为任务，有些则被系统地整理成特定领域的知识体系&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
为了实现上述系统，有几个问题要去解决:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;如何取舍信息源，毕竟信息源是如此的多&lt;/li&gt;
&lt;li&gt;如何将信息源 RSS 化，像微信公众号这样的封闭信息是没有提供 RSS 输出的&lt;/li&gt;
&lt;li&gt;如何对信息进行过滤&lt;/li&gt;
&lt;li&gt;除开 RSS 化信息源外，我还有纸质书和 Kindle，从其中产生的笔记该如何和从 RSS 信息源中产生的笔记汇集到一处呢?&lt;/li&gt;
&lt;li&gt;笔记又该如何管理和输出呢&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
(待续)
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>2016 年第三季度总结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/10/03/2016-q3-review.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2016/10/03/2016-q3-review</id>
    <published>2016-10-03T00:00:00+00:00</published>
    <updated>2016-10-03T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


生活方面
专业能力方面
个人修养方面




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;生活方面&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;专业能力方面&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;个人修养方面&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;hr  /&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;生活方面&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
计划内容有:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;开始晨跑&lt;/li&gt;
&lt;li&gt;改造卧室&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
第一个计划，嗯，没有执行 —— 懒惰如我……事实上这和以前制定然后没有执行的计划具有同样的问题，那就是不具体。当然根本原因是，我在心理上，并没有在这方面进行改变的强烈欲望。第二个计划倒是完成了，拆掉并且扔掉了笨重的衣柜，把我的床变了一下形 —— 我的床其实是那种储物床，相当于由两个大储物箱拼接起来的，我把其中一个旋转了 90 度，这样就能把房间尽头暖气片附近那点空间利用上了，如下图所示。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/my_bed.jpg&quot; alt=&quot;my_bed.jpg&quot; width=&quot;50%&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
然后把大量暂时没有看的书、冬天的衣服全塞进了床底下，就把夏天的一些衣服挂在了外面。
&lt;/p&gt;

&lt;p&gt;
第三季度的生活状态，稍微有点乱。六月份离开前公司后，花了挺多的时间面试想尝试一些新的机会，直到八月份才安稳下来，并且决定以后就在 NLP 这个方向上走下去 —— 其实我在这个方向上并没有什么积累，但是已经毕业三年了，我想我必须要专注在某个特定的方向上。此外就是集智俱乐部在这期间开始了「自然语言处理与深度学习读书会」，我自告奋勇上去主讲了三期，倒是感觉自己收获非常大。
&lt;/p&gt;

&lt;p&gt;
目前已经工作快两个月了，同事老板都很 nice，我对目前的境况是感到比较满意的。
&lt;/p&gt;

&lt;p&gt;
Q4 就是秋冬时期了，除了有雾霾和静电，是我比较喜欢的时期：有风，温度比较低。我也就不提晨跑什么的啦，内心没有在这方面改变的想法，制定了计划也是白搭。外出锻炼、健身对我来说还是比较大的改变，我想我可以先从做一些更小的改变开始，比如早睡早起，比如吃早饭。
&lt;/p&gt;

&lt;p&gt;
所以 Q4 的计划是:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;至少 60 天 11 点半前睡觉, 6 点半前起床&lt;/li&gt;
&lt;li&gt;至少 60 天去吃早饭&lt;/li&gt;
&lt;li&gt;至少 60 天不玩游戏&lt;/li&gt;
&lt;li&gt;看 30 部电影&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
是很小的计划，所以我会坚持去做好。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;专业能力方面&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
计划内容有:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;在 panic-notebook 中增加 Theano 的笔记&lt;/li&gt;
&lt;li&gt;使用 Keras 在 Kaggle 上完成一些至少十个任务&lt;/li&gt;
&lt;li&gt;完成集智俱乐部 NLP 线上读书会(其中 RNN 的部分由我主讲)&lt;/li&gt;
&lt;li&gt;掌握 Dialogue/QA 的技术，实现一个对话系统&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
第一项和第二项未完成，第三和第四项完成。Theano 笔记未完成的原因是因为我对 Theano 并没有真正很熟悉，所以要写的时候不知道要写什么，就搁置了；kaggle 任务未完成的原因，在于我的动手能力太弱，每次一动手写什么东西，我就想在一开始尽善尽美，考虑效率考虑扩展性考虑代码的美观 —— 这种习惯在某些场景下可能是好事，但在有些时候并不是，而我设定这个任务的目的，本来就是为了对抗自己这种习性，希望能在快速的练习里提高自己的解决问题的能力和效率。
&lt;/p&gt;

&lt;p&gt;
第三项之所以完成，是因为这是一个受到别人监督的任务，尽管如此，在这期间我仍然一再拖延。第四项因为是和现在工作内容紧密相关的，不过完成度不算高。
&lt;/p&gt;

&lt;p&gt;
Q4 的话，我会更加专注在 NLP 上，但是这块内容很多，我可能更多地会跟着工作内容走。除此以外，我还会去了解一下网络信息抽取和爬虫，以及 Docker。根据以上目标，暂时设定 Q4 的计划为:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;熟练掌握句法分析: 能用之进行句法成分地提取、句型的检测和转换等任务&lt;/li&gt;
&lt;li&gt;熟练掌握 Scrapy、PhantomJS 和 Selenium: 完成至少 5 个爬虫&lt;/li&gt;
&lt;li&gt;熟练掌握使用 Docker 进行项目部署、测试的流程&lt;/li&gt;
&lt;li&gt;阅读 40 篇以上的 paper(大概两天一篇)，主题不限，做了笔记并发布到博客或公众号上的记为有效结果&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
除此以外，还买了几本 NLP 相关的书，也计划在 Q4 把它们读完。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;个人修养方面&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
计划内容:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;读完《中国神话传说》、《神话与诗》、《失落的天书：山海经与古代华夏世界观》、《中国小说史略》、《雪人》和《火星崛起》六本书&lt;/li&gt;
&lt;li&gt;坚持每天日记&lt;/li&gt;
&lt;li&gt;坚持每周输出论文阅读笔记或书籍阅读笔记&lt;/li&gt;
&lt;li&gt;建立起自己的 PKM 系统&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
阅读方面，《中国小说史略》和《神话与诗》尚未读完，其他四本都完成了。其中刘宗迪的《失落的天书》给了我很多惊喜，特别是其中对「龙星纪时」的论述，因此 Q4 会追着读过的几本中国古代神话、山海经相关著作的参考文献深入下去，《中国小说史略》暂时搁置，Q4 也不打算去阅读。闻一多的《神话与诗》打算快速翻一遍，然后之前买的顾颉刚的《三皇考》也快速翻一遍，再挑一本讲稷下学宫的书和一本讲中国天文学史的书看一看。小说就比较随意了，但作为一个科幻爱好者，我决定还是多读一点科幻小说，保持自己在这方面的触感。
&lt;/p&gt;

&lt;p&gt;
每天日记这个没有坚持，大部分时间是靠自己自觉，我想还是需要靠自动提醒的一些手段来帮助加固这个习惯。
&lt;/p&gt;

&lt;p&gt;
至于写作，九月共计有三篇博客输出和一篇论文笔记输出，并不达标。我写博客或笔记的一个自我限制是，总想把事情表达地很全面细致，这就要求我为之付出很多考证和查漏补缺的功夫，后面可以考虑稍微牺牲一下完整性和系统性来加快输出速度。另外之前尝试在公众号中进行写作，但是公众号里的写作体验很糟糕，后面决定还是统一发布到自己的博客上，然后挑选一些对别人有意义的文章放到公众号上去，就当给博客引流了。
&lt;/p&gt;

&lt;p&gt;
第四项是我为之付出了大量精力的一项任务，并在这几天完成了收尾工作。
&lt;/p&gt;

&lt;p&gt;
我所设想中的 PKM 系统，总的来说包含两个部分:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;信息收集、筛选部分&lt;/li&gt;
&lt;li&gt;知识提取、归纳和输出部分&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
第一部分一开始想用 &lt;a href=&quot;https://github.com/cantino/huginn&quot;&gt;Huginn&lt;/a&gt; 来完成，但是它并没有自己想象中那么好用，而且和我在使用的其他工具整合度不高，所以后来放弃了以 Huginn 作为核心工具，转而购买了 Inoreader 专业版，用 Inoreader 来进行信息的汇总和过滤，然后通过 &lt;a href=&quot;https://ifttt.com/&quot;&gt;IFTTT&lt;/a&gt; 来进行二次过滤和中转。如下图所示。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/information_collect.jpg&quot; alt=&quot;information_collect.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
第二部分通过 Emacs 的 org-mode 来进行 —— 之前也是一直使用 org-mode 来进行知识的整理，但是尚未形成自洽的系统。系统的大致结构如下图所示。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/knowledge_process.jpg&quot; alt=&quot;knowledge_process.jpg&quot; width=&quot;50%&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
除此以外，发现自己房间空白的墙相当于一块大白板，我现在会把自己在家时的一些读书笔记、杂乱的一些想法写到便签上然后贴在墙上，感觉很不错。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/stickynotes_on_wall.jpg&quot; alt=&quot;stickynotes_on_wall.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
关于 PKM 的设计，后面我会单独写一篇文章来讲。
&lt;/p&gt;

&lt;p&gt;
所以 Q4 的计划是:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;至少写 70 篇日记&lt;/li&gt;
&lt;li&gt;早起后手抄一篇古诗文，至少完成 70 次&lt;/li&gt;
&lt;li&gt;阅读完这几本书籍:

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;顾颉刚《三皇考》&lt;/li&gt;
&lt;li&gt;闻一多《神话与诗》&lt;/li&gt;
&lt;li&gt;《稷下学研究》(要去三联买耶……)&lt;/li&gt;
&lt;li&gt;冯时《中国天文考古学》&lt;/li&gt;
&lt;li&gt;迟卉《荆棘双翼》&lt;/li&gt;
&lt;li&gt;《上帝的图书馆》&lt;/li&gt;
&lt;li&gt;《6号泵》&lt;/li&gt;
&lt;li&gt;《献给阿尔吉侬的花束》&lt;/li&gt;
&lt;li&gt;《24个比利》&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
然后，不再对自己的输出设立目标，因为实际上我的输出效果和效率是受我的 PKM 系统影响的，所以让自己的 PKM 系统真正地运转起来后，自然就能达到自己的期望了！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>博客启用新域名</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/09/18/rename-blog.html"/>
    <category term="博客" scheme="http://www.zmonster.me/categories.html#博客"/>
    <id>http://www.zmonster.me/2016/09/18/rename-blog</id>
    <published>2016-09-18T00:00:00+00:00</published>
    <updated>2016-09-18T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


Linux, Lisp: ID &quot;Linusp&quot; 的由来
异或门, 邮件人和「电子怪兽」




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;Linux, Lisp: ID &quot;Linusp&quot; 的由来&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;异或门, 邮件人和「电子怪兽」&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
中秋的时候，在 Namesilo 上买了个域名，然后解析到了这个博客上，以后也会逐渐地把网络上的 ID 换成对应的 ID。
&lt;/p&gt;

&lt;p&gt;
然后，讲点过去的小故事。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;Linux, Lisp: ID &quot;Linusp&quot; 的由来&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
基本上每个人初看到我这个 ID，都会问这个 ID 和 Linus Torvalds 是不是有什么关系，或者我是不是崇拜 Linus 之类的。实际上这个 ID 和 Linus Torvalds 没有什么关系，我也不崇拜这个人(事实上我不崇拜任何人)。
&lt;/p&gt;

&lt;p&gt;
事情的最初，是在 2010 年 9 月份，我去参加了学院社团组织的「自由软件日」或者什么活动，时间久远，不太记得清了。活动大致就是宣传了一下开源精神啦之类的东西，理所当然地也介绍了 Linux，然后现场演示了一下 Ubuntu 系统的使用，用 Compiz 展示了一番桌面特效，什么窗口最小化动画啦、桌面立方体啦、火焰特效啦，当时作为一个刚接触编程才半年不到只会在 Windows 下用 Turbo C 傻傻地写 C 代码的吃瓜群众，一下就被震惊到了。临走的时候从组织者那里领了一张 Ubuntu 的光盘，现在想想，那个光盘好像是从 Ubuntu 官方申请到的呢，可惜后来被我弄丢了。
&lt;/p&gt;

&lt;p&gt;
光盘拿回去后，折腾了一阵子装上了双系统，那个 Ubuntu 是 10.04，还不赖。装好以后呢，大部分的时候是在进行各种桌面美化、特效配置，并没有做太多深入了解。后来美化、特效什么地玩腻了，就渐渐地不怎么碰了。
&lt;/p&gt;

&lt;p&gt;
然后学期结束的时候，去图书馆借了几本书，准备带回家过冬。现在是想不起来当时的心情了，借了本&lt;a href=&quot;https://book.douban.com/subject/3119946/&quot;&gt;《程序设计语言原理》&lt;/a&gt;，本来以为是本讲怎么编程的书，结果是本讲语言本身原理的书，大半我都没看懂。但这本书让我了解到了 Lisp 语言。当时觉得 Lisp 和 Prolog 有意思极了，于是回学校后就把尘封的 Ubuntu 系统捡起来了，开始在上面练习 Lisp 的编程。然后又因为 Lisp 了解到 Emacs 慢慢成为了 Emacs 用户。想想还是蛮奇妙的。
&lt;/p&gt;

&lt;p&gt;
我接触电脑是在初二的时候，接触网络则是在高一，但高中那些年主要都是在玩网游和聊 QQ，到大学的时候才知道还有贴吧啊、微博啊好多好多东西。也是在那个时候开始在网络上活跃起来，注册了贴吧、微博帐号，逛各种社区、论坛。最开始的时候在各个地方会用不同的 ID，后来想着要有一个独特的个人标识，就把自己喜欢的 Linux 和 Lisp 两个词混合起来，得到了 Linusp 这个 ID，如果硬要说 Linus 是 Linux 之父那我也没办法，但我一向是个吃鸡蛋不问母鸡的人，另外 Linus 有些行为我也是不喜欢的 —— 嗯，但我不反对。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;异或门, 邮件人和「电子怪兽」&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
刚学编程的时候，最搞不明白的就是异或运算了 —— 当然异或运算本身是很简单的，但是经常会有一些用异或运算来组合起来的复杂运算，当时感觉就像黑魔法一样，即使是现在我还是没法很好地操控这种「黑魔法」。再后来学电路，了解到异或门也是复杂芯片中的不可或缺的部分，事实上在 CPU 的最基础的部件加法器中，异或门就是核心的逻辑门。再后来了解到人工智能(Artificial Intelligence, &lt;b&gt;AI&lt;/b&gt;)，发现异或门又在第一次 AI 之冬中发挥了很大的影响(当然实际上并不是的)。
&lt;/p&gt;

&lt;p&gt;
异或门是不进位的加法器，是非线性的逻辑单元。
&lt;/p&gt;

&lt;p&gt;
在此之前，还在高中的时候，在《科幻世界》上看过一个小短篇，讲计算机上的逻辑单元因为故障衍生出智能的故事。不知道什么时候起，模模糊糊地在心里把 AI 和异或门联系起来了 —— 这当然不是说我认为异或门会产生智能，只是一种从科幻爱好者的视角产生的「它们之间好像有点什么共性」这样的想法。
&lt;/p&gt;

&lt;p&gt;
说到科幻，其实我在七八岁的时候就开始看科幻了。小时候是个好奇宝宝，什么都想问一问一探究竟，但是父母长时间不在家，加上很多问题就算父母在身边也并不一定能回答上来，而书本给了我很好地了解世界的途径。刚开始的时候，是什么都看，武侠小说、科幻小说、知音、读者、故事会、半月谈……捡到什么看什么，大部分都是我父母的书或者父母的朋友的书，偶尔赶集买两本书就高兴坏了。印象里最开始读的一本小说是讲农民起义的《红袄军》，第一本科幻小说我记得是《2001 太空历险记》，不过后面查了一下是克拉克的书，和我印象中的剧情好像不太一样。之后的四五年小学生涯，主要是在读各种武侠小说，初中的时候读到了王晋康的《水星播种》和《终极爆炸》，印象中还读过阿西莫夫的一个短篇，但好像是讲双重人格的。自那以后，武侠小说和科幻小说就成了我的主要阅读对象。高一和高三的时候，有持续地买《今古传奇》和《科幻世界》，毕业的时候这些杂志都能摞成几堆一米多高的书堆了。
&lt;/p&gt;

&lt;p&gt;
到大学的时候，能看到的书更多了，也了解到了更多的科幻作家和作品。在网上读过弗诺·文奇的《循环》和《天渊》后，对他的作品印象很深刻，后来就去读了《真名实姓》，非常棒。在《真名实姓》的故事里，有一个具有自我意识的程序在 Cyber Space 里活动，就叫做「邮件人」。另外，《真名实姓》成书比《神经浪游者》更早，可以说是赛博朋克的最早作品(比《攻壳机动队》、《黑客帝国》要早啦)。弗诺·文奇后面写的《彩虹尽头》也很棒。
&lt;/p&gt;

&lt;p&gt;
所有这些混杂在一起，产生了「电子怪兽」这样一个 ID。从一名科幻爱好者的角度来看，我认为所谓的「强人工智能」会是从巨量的冗余信息里涌现出来的模式，就像「邮件人」一样，它是赛博空间中的异类，电子元件中的怪兽；从一名算法工程师的角度来看，「强人工智能」是镜中花水中月，所谓「人工智能」，能处理现实中的大部分的非线性映射，就已经是极大的进步了，而异或门就是一个最简单的非线性问题。
&lt;/p&gt;

&lt;p&gt;
所以呢，本来是想换成 emonster 这个 ID 的，但是 Github 上这个 ID 已经被使用了，相应的域名也被买走了。退而求其次，把 &quot;e&quot; 换成我的姓的首字母，就是这样啦！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>Github Pages 升级 Jekyll 版本造成博客构建失败</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/09/11/github-pages-build-error-with-jekyll-3.2.1.html"/>
    <category term="博客" scheme="http://www.zmonster.me/categories.html#博客"/>
    <id>http://www.zmonster.me/2016/09/11/github-pages-build-error-with-jekyll-3.2.1</id>
    <published>2016-09-11T00:00:00+00:00</published>
    <updated>2016-09-11T00:00:00+00:00</updated>
    <description>
    
      <p>

</p>
    
    </description>
    <content type="html">
      &lt;hr  /&gt;


&lt;p&gt;
8 月底的时候写了一篇在 Windows 下建立 Python 开发环境的文章(嗯，其实是应一些朋友的要求写的)，然后照常 push ，结果收到了一封邮件，告诉我博客构建失败了。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/page_build_failure.png&quot; alt=&quot;page_build_failure.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
点击邮件给出的&lt;a href=&quot;https://help.github.com/articles/troubleshooting-jekyll-builds&quot;&gt;链接&lt;/a&gt;，里面都是一些常规的排错建议，并没有给我相应的错误信息，看完还是一头雾水。为了确定是不是最近一次 commit 提交的文章内容有什么问题，我把 repo 回滚到了出错前的一个 commit 上，然后 'push -f' ，一秒钟之后又收到了相同的邮件。
&lt;/p&gt;

&lt;p&gt;
当时感觉有点懵，但是因为手头还有别的事情，于是就丢在那里不管了。直到昨天，我才给 Github 发了封邮件，说了一下我的情况。很快就收到了回复。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/page_build_failure_2.png&quot; alt=&quot;page_build_failure_2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
原来是 Github Pages 将 Jekyll 升级到了 3.2.1 ，而在 Jekyll 3.2.1 中，配置文件 _config.yml 中的 &quot;theme&quot; 字段，现在被用作设置 &quot;gem-based theme&quot;，不能用于用户的自定义使用了。
&lt;/p&gt;

&lt;p&gt;
按照邮件的建议，我把 _config.yml 中原先的 theme 字段改写为 theme_settings ，并将相应的模板文件中的名称也改过来，重新 push 之后没有再报错。
&lt;/p&gt;

&lt;p&gt;
但我翻了下 Jekyll 的&lt;a href=&quot;https://jekyllrb.com/news/releases/&quot;&gt;发布历史&lt;/a&gt;，并没有找到对这件事情的详细说明……
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>Windows 上 Python 开发环境搭建</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/09/10/use-python-on-windows.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2016/09/10/use-python-on-windows</id>
    <published>2016-09-10T00:00:00+00:00</published>
    <updated>2016-09-10T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


前言
Cygwin 的安装
Cygwin 的界面设置
Python 的安装和使用

安装 Python/Python3
安装 pip
使用 virtual...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;前言&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;Cygwin 的安装&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;Cygwin 的界面设置&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;Python 的安装和使用&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;安装 Python/Python3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline6&quot;&gt;安装 pip&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline7&quot;&gt;使用 virtualenv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline8&quot;&gt;Theano/TensorFlow 的安装和使用&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline9&quot;&gt;Theano&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline10&quot;&gt;TensorFlow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline11&quot;&gt;其他方案&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;hr  /&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;前言&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
本文会涉及:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Windows 上 Python 开发环境的建立(基于 Cygwin)&lt;/li&gt;
&lt;li&gt;Python 开发的一些基础知识&lt;/li&gt;
&lt;li&gt;深度学习框架 Theano 在 Windows 环境下的安装和使用&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
简单介绍一下 Cygwin: &lt;a href=&quot;https://www.cygwin.com/&quot;&gt;Cygwin&lt;/a&gt; 是一个旨在提供 Windows 上的类 Linux 环境的软件，包含了提供 POSIX API 的底层 library 以及大量建立在 POSIX API 上的 GNU 软件和其他开源软件的集合。通过 Cygwin ，可以在不脱离 Windows 环境的情况下获得与 Linux 上一致的开发体验，当然也包括 Python。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;Cygwin 的安装&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
从 &lt;a href=&quot;https://www.cygwin.com/&quot;&gt;Cygwin 的官网&lt;/a&gt; 上下载对应的安装程序，32 位系统就下载 setup-x86.exe，64 位就下载 setup-x86_64.exe —— 现在应该都是 64 位系统了吧。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cygwin_download.png&quot; alt=&quot;cygwin_download.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
安装过程很简单，大部分情况下点击下一步进行下去即可。
&lt;/p&gt;

&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;img src=&quot;/assets/img/cygwin_installation_1.png&quot; alt=&quot;cygwin_installation_1.png&quot; /&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;img src=&quot;/assets/img/cygwin_installation_2.png&quot; alt=&quot;cygwin_installation_2.png&quot; /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;
这里可以按自己的需要设置一下 Cygwin 的安装目录，同时在安装完成后，Cygwin 会将这个目录当作根目录(Linux 上的 /)。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cygwin_installation_3.png&quot; alt=&quot;cygwin_installation_3.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
安装过程中会从网络上下载各种东西，这里可以设置用于存放这些东西的 &lt;b&gt;临时目录&lt;/b&gt; :
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cygwin_installation_4.png&quot; alt=&quot;cygwin_installation_4.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
到下面这一步需要选择下载站点，大致上来说选国内的站点速度会快一些，教育网的建议选中科大的源(&lt;a href=&quot;http://mirrors.ustc.cn/&quot;&gt;http://mirrors.ustc.cn/&lt;/a&gt;)，如图；非教育网的话可以在下面那个「User URL」输入框中填入网易的源(&lt;a href=&quot;http://mirrors.163.com/cygwin/&quot;&gt;http://mirrors.163.com/cygwin/&lt;/a&gt;)，点击 Add 后网易的源就会出现在列表中，选中即可。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cygwin_installation_5.png&quot; alt=&quot;cygwin_installation_5.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
然后会进入一个更详细的安装页面，一些基础的、必须的软件包已经默认选中了,可以按自己的需要选择一些额外的软件包。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cygwin_installation_6.png&quot; alt=&quot;cygwin_installation_6.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
点下一步继续，会开始下载、安装选中的软件包，如无意外，就可以顺利安装上 Cygwin 了。
&lt;/p&gt;

&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;img src=&quot;/assets/img/cygwin_installation_7.png&quot; alt=&quot;cygwin_installation_7.png&quot; /&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;img src=&quot;/assets/img/cygwin_installation_8.png&quot; alt=&quot;cygwin_installation_8.png&quot; /&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;img src=&quot;/assets/img/cygwin_installation_9.png&quot; alt=&quot;cygwin_installation_9.png&quot; /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
至此安装结束，会在桌面上生成 Cygwin 的快捷方式，双击即可打开，正常的话，应该会看到下面这样一个黑乎乎的窗口，其实就是个终端啦。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cygwin_face.png&quot; alt=&quot;cygwin_face.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;Cygwin 的界面设置&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
刚安装好时的 Cygwin 默认外观并不是很好看(当然比 cmd 还是好看一点的……)，我们可以通过调整设置来获得一个更让人舒适的外观。
&lt;/p&gt;

&lt;p&gt;
首先是字体，在 Cygwin 的窗口区域右键，选择 Options 会弹出 Cygwin 的设置，如下所示进行字体设置:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cygwin_font_setting.png&quot; alt=&quot;cygwin_font_setting.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这里我选择了 DejaVu Sans Mono 这一款字体，这是我常用的编程字体 —— 以我的标准而言，一款编程用的字体，最低要求是要能区分出一些形状相似的字符，如下图所示:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cygwin_face_2.png&quot; alt=&quot;cygwin_face_2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
注: 这个字体并不是 Windows 自带的，需要自己下载和安装。
&lt;/p&gt;

&lt;p&gt;
然后，如下图所示，在 Looks 一栏可以设置窗口的透明度
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cygwin_ui_setting.png&quot; alt=&quot;cygwin_ui_setting.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这是选择透明等级 Med (中等)后的效果
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cygwin_med_transparency.png&quot; alt=&quot;cygwin_med_transparency.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到右边还有一个 &quot;Glass&quot; 可以选，选择后的效果为
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cygwin_glass.png&quot; alt=&quot;cygwin_glass.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
注意，这里我为了配合透明和 Glass 效果，把窗口的滚动栏去掉了，见设置页面的 Window 一栏。
&lt;/p&gt;

&lt;p&gt;
最后一项，我们设置一下 Cygwin 里的终端提示符。终端提示符一般通过环境变量 &quot;PS1&quot; 来进行设置，由于这个是 Cygwin(Linux) 特有的环境变量，就不在 Windows 的系统设置里设置这个环境变量了。我们可以新建一个名为 &quot;.bash_profile&quot; 的文件，Cygwin(严格来说是 shell) 启动时会读取这个文件并进行初始化。由于 Windows 下不允许直接以 &quot;.&quot; 符号起始的文件，这个文件只能在 Cygwin 中创建，用 vi 命令直接创建并编辑即可(注意是 vi 而不是 vim)，写入内容
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_RESET&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[00m'&lt;/span&gt;

&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_BLACK&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[0;30m'&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_RED&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[0;31m'&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_GREEN&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[0;32m'&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_BROWN&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[0;33m'&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_BLUE&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[0;34m'&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_PURPLE&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[0;35m'&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_CYAN&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[0;36m'&lt;/span&gt;

&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_LIGHT_GRAY&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[0;37m'&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_DARK_GRAY&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[1;30m'&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_LIGHT_RED&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[1;31m'&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_LIGHT_GREEN&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[1;32m'&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_YELLOW&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[1;33m'&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_LIGHT_BLUE&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[1;34m'&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_LIGHT_PURPLE&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[1;35m'&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_LIGHT_CYAN&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[1;36m'&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;CC_WHITE&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'[1;37m'&lt;/span&gt;

&lt;span style=&quot;color: #eeeeec;&quot;&gt;force_color_prompt&lt;/span&gt;=yes
&lt;span style=&quot;color: #729fcf;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;PS1&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'\[\e${CC_WHITE}\][\[\e${CC_RESET}\]\&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;\[\e${CC_LIGHT_BLUE}\]\w\&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;\[\e${CC_RESET}\]\[\e${CC_WHITE}\]]\[\e${CC_RESET}\]\n\&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;\[\e${CC_LIGHT_GREEN}\]\u \[\e${CC_RESET}\]\&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;\[\e${CC_LIGHT_RED}\]\$\[\e${CC_RESET}\] '&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
效果如下:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cygwin_bash_prompt.png&quot; alt=&quot;cygwin_bash_prompt.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline4&quot;&gt;Python 的安装和使用&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline5&quot;&gt;安装 Python/Python3&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;p&gt;
默认情况下，Cygwin 中没有安装 Python ，不过它会读取 Windows 系统中的环境变量，如果自己有单独安装 Python，且已经配置好环境变量，在 Cygwin 中也可以运行 Python 。但建议还是安装 Cygwin 自身软件仓库中的 Python。
&lt;/p&gt;

&lt;p&gt;
首先下载一个 Cygwin 的软件包管理工具: &lt;a href=&quot;https://github.com/transcode-open/apt-cyg&quot;&gt;apt-cyg&lt;/a&gt; 。这是一个类似 Debian/Ubuntu 中的 apt-get 的工具，可以让我们在 Cygwin 中查找、安装、卸载软件包，非常的方便。依次在 Cygwin 中执行下面两条命令即可安装 apt-cyg:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;lynx -source rawgit.com/transcode-open/apt-cyg/master/apt-cyg &amp;gt; apt-cyg
install apt-cyg /bin
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
由于 apt-cyg 使用 wget 来访问服务器上的数据，建议先安装一下 wget (不安装的话会用 lynx 替代)，同时一些常用的工具也先安装一下
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;apt-cyg install wget vim gcc-core tmux sl
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
apt-cyg 的几个子命令:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;install &amp;lt;package&amp;gt;: 安装软件包&lt;/li&gt;
&lt;li&gt;remove &amp;lt;package&amp;gt;: 卸载软件包&lt;/li&gt;
&lt;li&gt;listall &amp;lt;keyword&amp;gt;: 以指定的关键词搜索相关的软件包&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
apt-cyg 安装好后就可以用来安装 Python 的基本环境了:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;apt-cyg install python python3
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
美中不足的是 Cygwin 中的 Python 3 版本为 3.4.3 ，这对需要使用 Python 3.5 的朋友来说可能是一个比较大的问题。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline6&quot;&gt;安装 pip&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline6&quot;&gt;
&lt;p&gt;
在安装好 Python 后，通过下面的命令安装 pip 和 pip3:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;python -m ensurepip
python3 -m ensurepip
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
鉴于国内访问 pip 官方的源速度有点慢，可以考虑修改 pip 的配置，使用国内的源，比如:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;V2EX: &lt;a href=&quot;http://pypi.v2ex.com/simple/&quot;&gt;http://pypi.v2ex.com/simple/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;豆瓣: &lt;a href=&quot;http://pypi.douban.com/simple/&quot;&gt;http://pypi.douban.com/simple/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;阿里云: &lt;a href=&quot;http://mirrors.aliyun.com/pypi/simple/&quot;&gt;http://mirrors.aliyun.com/pypi/simple/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;中科大: &lt;a href=&quot;https://pypi.mirrors.ustc.edu.cn/simple&quot;&gt;https://pypi.mirrors.ustc.edu.cn/simple&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
首先在 Cygwin 的 HOME 目录中新建配置文件:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;mkdir ~/.pip/ &amp;amp;&amp;amp; touch ~/.pip/pip.conf
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后往里写入以下配置(以使用豆瓣源为例):
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-conf&quot;&gt;[&lt;span style=&quot;color: #8ae234;&quot;&gt;global&lt;/span&gt;]
&lt;span style=&quot;color: #eeeeec;&quot;&gt;trusted-host&lt;/span&gt;=pypi.douban.com
&lt;span style=&quot;color: #eeeeec;&quot;&gt;index-url&lt;/span&gt;=http://pypi.douban.com/simple/
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
建议配置好后也更新一下 pip 本身
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;pip install pip --upgrade
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后就可以直接安装自己想要使用的各种软件包了:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;pip install numpy pandas nltk jieba
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline7&quot;&gt;使用 virtualenv&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline7&quot;&gt;
&lt;p&gt;
在实际进行 Python 开发的时候，通常会使用 virtualenv 来进行环境的隔离，什么意思呢？举个例子，我们有两个项目，分别称之为项目 A 和项目 B，它们使用的 Python 版本和 Python 包的版本都不同，如下
&lt;/p&gt;

&lt;p&gt;
项目 A:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Python 版本: 2.7&lt;/li&gt;
&lt;li&gt;Python 包依赖:

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;jieba 0.37&lt;/li&gt;
&lt;li&gt;nltk 3.1&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
项目 B:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Python 版本: 3.4&lt;/li&gt;
&lt;li&gt;Python 包依赖:

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;jieba 0.38&lt;/li&gt;
&lt;li&gt;nltk 3.2&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
由于系统上的同一个 Python 包是没法安装两个不同版本的，如果使用系统中的 Python 包，是不能满足以上这种情况的。virtualenv 的作用就是为每个单独的项目建立独立的环境。要使用 virtualenv ，在 Cygwin 上只能通过 pip 来安装:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;pip install virtualenv
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
对项目 A ，按如下步骤建立环境:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
首先用 virtualenv 为项目 A 建立一个环境:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;virtualenv venv_for_a -p /usr/bin/python2.7
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
这一步会建立目录 venv_for_a ，并将 python2.7 和 pip 拷贝到其中，形成一个最小的 Python2 运行环境。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
用 source 然后激活这个环境:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;source&lt;/span&gt; venv_for_a/bin/activate
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
然后安装依赖
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;pip install &lt;span style=&quot;color: #eeeeec;&quot;&gt;jieba&lt;/span&gt;==0.37 &lt;span style=&quot;color: #eeeeec;&quot;&gt;nltk&lt;/span&gt;==3.1
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
对项目 B 同样如此:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
建立环境
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;virtualenv venv_for_b -p /usr/bin/python3.4
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
激活环境
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;source&lt;/span&gt; venv_for_b/bin/activate
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
安装依赖
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;pip install &lt;span style=&quot;color: #eeeeec;&quot;&gt;jieba&lt;/span&gt;==0.38 &lt;span style=&quot;color: #eeeeec;&quot;&gt;nltk&lt;/span&gt;==3.2
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline8&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline8&quot;&gt;Theano/TensorFlow 的安装和使用&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline8&quot;&gt;
&lt;p&gt;
本节将在之前搭建好的 Python 开发环境基础上，展示 Windows 下深度学习框架 Theano的安装和使用。
&lt;/p&gt;

&lt;p&gt;
下面的内容都在以下环境下进行:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Cygwin PC x86_64&lt;/li&gt;
&lt;li&gt;python2.7&lt;/li&gt;
&lt;li&gt;pip 8.1.2&lt;/li&gt;
&lt;li&gt;ipythohn 5.1.0&lt;/li&gt;
&lt;li&gt;Theano 0.8.2&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
注: 我也尝试了在 Windows 上安装 TensorFlow ，但是以失败告终，详见后叙。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline9&quot;&gt;Theano&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline9&quot;&gt;
&lt;p&gt;
theano 的安装比较简单，直接用 pip 进行安装即可:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;pip install theano --upgrade
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Theano 还依赖 Numpy、Scipy，然后在安装 Scipy 的时候报错，错误信息为:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
no lapack/blas resources found
&lt;/pre&gt;

&lt;p&gt;
LAPACK/BLAS 是提供线性代数相关计算的 C 库，既然缺失的话，用 apt-cyg 搜索看看:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;apt-cyg listall lapack blas
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果为
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
lapack
lapack-debuginfo
liblapack-devel
liblapack-doc
liblapack0

liblasem0.4-devel
liblasem0.4-doc
liblasem0.4_4
libopenblas
openblas
&lt;/pre&gt;

&lt;p&gt;
把 liblapack-devel, libopenblas 和 openblas 装上
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;apt-cyg install liblapack-devel libopenblas openblas
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
重试安装，仍然发生错误，相应的错误信息如下：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
error: library dfftpack has Fortran sources but no Fortran compiler found
&lt;/pre&gt;

&lt;p&gt;
这是因为缺少 fortran 编译器导致的，安装上 gcc-fortran 即可，但仍然报错，说找不到 g++ ，那把 g++ 也装上
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;apt-cyg install gcc-fortran gcc-g++
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
安装之后，尝试在 Python 交互环境中执行 &lt;code&gt;import theano&lt;/code&gt; 出错，出错信息为
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
File &quot;theano/gof/cmodule.py&quot;, line 2014, in compile_str
  return dlimport(lib_filename)
File &quot;theano/gof/cmodule.py&quot;, line 289, in dlimport
    rval = __import__(module_name, {}, {}, [module_name])
ImportError: No module named cutils_ext
&lt;/pre&gt;

&lt;p&gt;
在 HOME 中的 .theano 目录下找到了 cutils，我的系统上是: ~/.theano/compiledir_CYGWIN_NT-6.1-2.2.1-0.289-5-3-x86_64-64bit&amp;#x2013;2.7.10-64/cutils_ext/。按照 &lt;a href=&quot;https://github.com/Theano/Theano/issues/2253&quot;&gt;这里&lt;/a&gt; 和 &lt;a href=&quot;http://josephlemley.com/blog/installing-theano-on-windows-with-cygwin/&quot;&gt;这里&lt;/a&gt; 给出的信息，这个错误的原因在于里面一个名为 cutils_ext.pyd 的文件，它是 Python 生成的编译后的模块，实际上是一个动态链接库(Dynamic Link Library, DLL)，见 &lt;a href=&quot;https://docs.python.org/2/faq/windows.html#is-a-pyd-file-the-same-as-a-dll&quot;&gt;Python 官方文档&lt;/a&gt; 。由于它是一个 DLL，Cygwin 在加载它的时候会希望它的后缀是 dll ，所以出错了，一种暂时的办法是修改一下它的后缀名
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;cd&lt;/span&gt; ~/.theano/compiledir_CYGWIN_NT-6.1-2.2.1-0.289-5-3-x86_64-64bit--2.7.10-64/cutils_ext/
cp cutils_ext.pyd cutils_ext.dll
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这样在 import 时是可以成功的，但在执行下面这段代码时依然会出错
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy
&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; theano
&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; theano.tensor &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; T
&lt;span style=&quot;color: #729fcf;&quot;&gt;from&lt;/span&gt; theano &lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; function


&lt;span style=&quot;color: #eeeeec;&quot;&gt;x&lt;/span&gt; = T.scalar(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'x'&lt;/span&gt;)
&lt;span style=&quot;color: #eeeeec;&quot;&gt;y&lt;/span&gt; = T.scalar(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'y'&lt;/span&gt;)
&lt;span style=&quot;color: #eeeeec;&quot;&gt;z&lt;/span&gt; = x + y

&lt;span style=&quot;color: #eeeeec;&quot;&gt;f&lt;/span&gt; = function([x, y], z)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; f(3, 4)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这是因为用 Theano 定义的符号计算过程，最后也要编译成实际的模块，和前面的 cutils_ext.pyd 的问题是一样的，编译生成的模块后缀为 pyd ，但 Cygwin 加载时希望后缀是 dll 。所以要彻底解决这个问题，需要修改 Theano 中生成编译后模块的代码，让其生成的模块后缀为 dll 而不是 pyd。相关的代码在 Theano 代码中的 cmodule.py 中，在我的机器上，其路径为 &quot;/usr/lib/python2.7/site-packages/theano/gof/cmodule.py&quot;。其中有一个名为 &lt;code&gt;get_lib_extension&lt;/code&gt; 的函数，其内容为:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;get_lib_extension&lt;/span&gt;():
    &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    Return the platform-dependent extension for compiled modules.&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; sys.platform &lt;span style=&quot;color: #729fcf;&quot;&gt;in&lt;/span&gt; [&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'win32'&lt;/span&gt;, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'cygwin'&lt;/span&gt;]:
        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'pyd'&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt;:
        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'so'&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
将它改为:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;get_lib_extension&lt;/span&gt;():
    &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    Return the platform-dependent extension for compiled modules.&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; sys.platform == &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'win32'&lt;/span&gt;:
        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'pyd'&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;elif&lt;/span&gt; sys.platform == &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'cygwin'&lt;/span&gt;:
        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'dll'&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt;:
        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'so'&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
修改后可以尝试把 ~/.theano 这个目录删除，然后重新在 Python 交互环境中执行 &lt;code&gt;import theano&lt;/code&gt; ，成功后会重新生成 ~/.theano/compiledir_CYGWIN_NT-6.1-2.2.1-0.289-5-3-x86_64-64bit&amp;#x2013;2.7.10-64/cutils_ext/ 这个目录，不出意外的话，里面应该只有一个 cutils_ext.dll 而没有 cutils_ext.pyd 了。
&lt;/p&gt;

&lt;p&gt;
至此便可以在 Cygwin 中正常使用 Theano 了，如下图所示。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cygwin_run_theano.png&quot; alt=&quot;cygwin_run_theano.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline10&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline10&quot;&gt;TensorFlow&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline10&quot;&gt;
&lt;p&gt;
在 TensorFlow 的 &lt;a href=&quot;https://github.com/tensorflow/tensorflow/blob/master/tensorflow/g3doc/get_started/os_setup.md&quot;&gt;Download and Setup&lt;/a&gt; 中，介绍了在 Linux 和 Mac OS 平台上安装 TensorFlow 的详细过程，但并没有提供 Windows 的相关内容。不过其中的 &lt;a href=&quot;https://github.com/tensorflow/tensorflow/blob/master/tensorflow/g3doc/get_started/os_setup.md#docker-installation&quot;&gt;Docker installation&lt;/a&gt; 一节给出的解决方案是一个在 Windows 上运行 TensorFlow 的折衷办法，但是仅仅为了安装一个 37MB 的 Python 包，而要下载 180 多 MB 的 &lt;a href=&quot;https://www.docker.com/products/docker-toolbox&quot;&gt;Docker Toolbox&lt;/a&gt;，不太能接受。
&lt;/p&gt;

&lt;p&gt;
目前在 Windows 上运行 TensorFlow 的方案有以下两种：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;在 Windows 上安装 Docker 或者虚拟机，然后在其中安装 TensorFlow，参考: &lt;a href=&quot;http://bbs.makercollider.com/?/article/11&quot;&gt;TensorFlow在Windows上的安装&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;使用 Windows 10 上的 &lt;a href=&quot;https://msdn.microsoft.com/en-us/commandline/wsl/about&quot;&gt;Bash On Windows&lt;/a&gt; 安装 TensorFlow，有 Windows 10 的朋友可以自己尝试下&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
(这两种方法我也懒得去试验了，有兴趣和条件(我还用着 Windows 7 呢)的朋友自己再去折腾吧～)
&lt;/p&gt;

&lt;p&gt;
事实上 TensorFlow 目前并没有对 Windows 的原生支持，不过对 Windows 平台的支持已经提上议程，见 &lt;a href=&quot;https://github.com/tensorflow/tensorflow/blob/master/tensorflow/g3doc/resources/roadmap.md&quot;&gt;Roadmap&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
在 Github 上有一个 &lt;a href=&quot;https://github.com/tensorflow/tensorflow/issues/17&quot;&gt;Issue&lt;/a&gt;，从 2015 年年底至今，一直在讨论 TensorFlow 对 Windows 的原生支持这件事情，希望在 Windows 平台上使用 TensorFlow 的朋友可以关注一下这个 Issue。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline11&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline11&quot;&gt;其他方案&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline11&quot;&gt;
&lt;p&gt;
使用 &lt;a href=&quot;https://www.continuum.io/downloads&quot;&gt;Anaconda&lt;/a&gt; 是另外一个在 Windows 下建立 Python 编程环境的好主意，Anaconda 是一个基于 Python 的「数据科学平台」，内置了许多用于数据科学、机器学习的 Python 包，并有自己的软件包管理工具，也是很推荐的。
&lt;/p&gt;

&lt;p&gt;
Anaconda 在 Windows 上的使用稍微尝试了一下，但没有对其细节做太多了解，所以就不罗嗦了。有需要的话后面再为 Anaconda 单独写一篇吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>2016 年第二季度总结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/08/01/2016-q2-review.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2016/08/01/2016-q2-review</id>
    <published>2016-08-01T00:00:00+00:00</published>
    <updated>2016-08-01T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


计划及总结

生活方面的计划
专业能力方面的计划
个人修养方面的计划


计划之外




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;计划及总结&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;生活方面的计划&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;专业能力方面的计划&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;个人修养方面的计划&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;计划之外&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;hr  /&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;计划及总结&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline2&quot;&gt;生活方面的计划&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
计划内容有:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;每周两次走路上下班，目的是保持良好的身体和精神状态&lt;/li&gt;
&lt;li&gt;每两周参加一次活动，目的是保持与人交流&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
第一个计划，因为在 4 月份购买了自行车，所以改成了骑车上下班，确实对身体状态有帮助，早上到公司的时候感觉精神很多。车是在某次步行下班的时候在路边随便进了家自行车店，花了 300 多块钱买的，刚开始的时候不适应拥挤的车流，一路胆战心惊。周末晚上没事的时候会在上地南路到上地七街这片区域转悠，这一带有很多公司，平时是人很多的，但到周末特别是晚上基本是空荡荡的，很安静，到七街附近的时候经常能见到一些老人在昏黄的路灯灯光中下象棋，偶尔能看到情侣安静地散步，间或有一些车辆和其他零星的行人，除此以外便只有风和树影。心情苦闷的时候也会在这一块夜骑，效果不错。不过自从入夏后，天气炎热，慢慢地不怎么骑车上班了。
&lt;/p&gt;

&lt;p&gt;
每两周参加一次活动这个计划我觉得后面还是终止吧，参加过不少愚蠢的活动了，大致上人多的活动都很愚蠢。最初订立定期参加活动这个计划，是为了结识优秀的朋友，以及开阔视野，但现在逐渐明白，自己必须优秀才能被其他优秀的人认可，而开阔视野这一点并没有从活动中有多大收获，因为参加的都是自己领域相关的活动，内容大部分都是已知的 —— 倒是可以考虑去参加一些其他领域的活动。
&lt;/p&gt;

&lt;p&gt;
写这篇总结的时候第三季度已然过去三分之一。重新调整一下计划吧。
&lt;/p&gt;

&lt;p&gt;
第三季度天气都会比较热，所以走路上班就算了，稍微凉快的时候骑车上班应该问题不大，就不列入具体计划中了。现在倒是想去晨跑，所以把这个加入到计划中吧！至于参加活动的计划就算了，还是那句话，「大致上人多的活动都很愚蠢」。
&lt;/p&gt;

&lt;p&gt;
所以 Q3 计划如下:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;开始晨跑(目前无具体计划)&lt;/li&gt;
&lt;li&gt;改造卧室！&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline3&quot;&gt;专业能力方面的计划&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
计划内容有:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;系统学习 Theano&lt;/li&gt;
&lt;li&gt;掌握一些 DL 的框架的使用&lt;/li&gt;
&lt;li&gt;系统掌握 RNN 的相关知识，包括其理论及历史发展概况，后面可能会专门写一个 RNN 的系列文章&lt;/li&gt;
&lt;li&gt;完成线性代数的学习&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
第四条没有完成，其他三条进行地都还可以。第三季度的话，计划做这些事情:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;在 &lt;a href=&quot;https://github.com/Linusp/panic-notebook&quot;&gt;panic-notebook&lt;/a&gt; 中增加 Theano 的笔记&lt;/li&gt;
&lt;li&gt;使用 Keras 在 Kaggle 上完成一些至少十个任务&lt;/li&gt;
&lt;li&gt;完成集智俱乐部 NLP 线上读书会(其中 RNN 的部分由我主讲)&lt;/li&gt;
&lt;li&gt;掌握 Dialogue/QA 的技术，实现一个对话系统&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
除此以外，现在决定在 NLP 方向深入探索，但是现在并没有比较清晰的路线，暂时不做具体计划。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline4&quot;&gt;个人修养方面的计划&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
计划内容有:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;坚持每日阅读&lt;/li&gt;
&lt;li&gt;坚持写日记&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
阅读方面的话，主要读了两本神话学的书以及几本小说，第三季度会继续神话学方面的阅读。暂定要阅读
&lt;/p&gt;

&lt;p&gt;
第三季度暂定要阅读的书有:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;袁珂《中国神话传说》&lt;/li&gt;
&lt;li&gt;闻一多《神话与诗》&lt;/li&gt;
&lt;li&gt;刘宗迪《失落的天书:山海经与古代华夏世界观》&lt;/li&gt;
&lt;li&gt;鲁迅《中国小说史略》&lt;/li&gt;
&lt;li&gt;《雪人》&lt;/li&gt;
&lt;li&gt;《火星崛起》&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
所以第三季度的计划如下:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;读完上述六本书籍&lt;/li&gt;
&lt;li&gt;坚持每天日记&lt;/li&gt;
&lt;li&gt;坚持每周输出论文阅读笔记或书籍阅读笔记&lt;/li&gt;
&lt;li&gt;建立起自己的「个人知识管理(Personal Knowledge Management, &lt;b&gt;PKM&lt;/b&gt;)」系统&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline5&quot;&gt;计划之外&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;公司散伙了，所以换了份工作&lt;/li&gt;
&lt;li&gt;体检检出颈椎骨质增生&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
(完)
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>自然语言处理与深度学习: 集智俱乐部活动笔记</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/07/04/dl_and_nlp.html"/>
    <category term="NLP" scheme="http://www.zmonster.me/categories.html#NLP"/>
    <id>http://www.zmonster.me/2016/07/04/dl_and_nlp</id>
    <published>2016-07-04T00:00:00+00:00</published>
    <updated>2016-07-04T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


简介
自然语言处理的基本任务
对语言进行建模的若干方法

语言模型简介
N-gram 语言模型
基于神经网络的语言模型


语言的表示方法

词的表示: ...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;自然语言处理的基本任务&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;对语言进行建模的若干方法&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;语言模型简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;N-gram 语言模型&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline6&quot;&gt;基于神经网络的语言模型&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline7&quot;&gt;语言的表示方法&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline8&quot;&gt;词的表示: one-hot 与 embedding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline9&quot;&gt;句子及更高层级数据的表示: VSM 和 embedding&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline10&quot;&gt;机器翻译: 从 SMT 到 end-to-end&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline11&quot;&gt;统计机器翻译(Statistical Machine Translation, &lt;b&gt;SMT&lt;/b&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline12&quot;&gt;端到端(end-to-end)的新方法&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline13&quot;&gt;自然语言生成(Natural Language Generation, NLG)&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline14&quot;&gt;从模板方法到 encoder-decoder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline15&quot;&gt;对话系统中的自然语言生成&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline16&quot;&gt;后记&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;hr  /&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;简介&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
本文为对 2016 年 7 月 3 日集智俱乐部活动「自然语言处理与深度学习」进行的总结。
&lt;/p&gt;

&lt;p&gt;
集智俱乐部是张江在 2008 年建立的一个从事学术研究、享受科学乐趣的开放团体，它倡导以平等开放的态度、科学实证的精神，进行跨学科的研究与交流，力图搭建一个中国的 ”没有围墙的研究所”。我于 2014 年结缘集智俱乐部，从中结识到不少优秀又有趣的人。
&lt;/p&gt;

&lt;p&gt;
集智会不定期地以读书会、讲座等形式进行线下活动，并且这两年的活动主要都聚焦于互联网和人工智能前沿技术上，7 月 3 日这期活动就是如此。
&lt;/p&gt;

&lt;p&gt;
活动主讲人是是香港理工大学的在读博士李嫣然，其主要研究方向为自然语言的语义表达和语言生成。同时她还是微信公众号「程序媛的日常」的维护者之一小 S，这个公众号提供了高质量的关于机器学习和自然语言处理的文章，从事这方面工作或研究的朋友不妨关注一下。另，后文为了方便，一律用「小 S」来指代「李嫣然」。
&lt;/p&gt;

&lt;p&gt;
下面是两个公众号的二维码，有兴趣的可以关注一下:
&lt;/p&gt;
&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;集智俱乐部&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;程序媛的日常&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;img src=&quot;/assets/img/qrcode_swarmagents.jpg&quot; alt=&quot;qrcode_swarmagents.jpg&quot; /&gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&lt;img src=&quot;/assets/img/qrcode_girlswhocode.jpg&quot; alt=&quot;qrcode_girlswhocode.jpg&quot; /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;自然语言处理的基本任务&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
自然语言是我们日常用于互相沟通的最常见方式，结合个人的观点以及小 S 讲述的内容，「用自然语言进行沟通」可以分解为以下几个步骤:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;对于接收到的信息，判断是否是自然语言&lt;/li&gt;
&lt;li&gt;在确定接收到自然语言数据后，对其进行理解&lt;/li&gt;
&lt;li&gt;在理解接收的自然语言数据后，组织好要回复的内容并将其传达给另一方&lt;/li&gt;
&lt;/ol&gt;



&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/slap.jpg&quot; alt=&quot;slap.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
好好好，我说人话，别打脸！
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;场景一: 接收到非自然语言&lt;/b&gt;
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
—— 小明: 汪汪汪汪喵喵喵
—— 小红: (说人话，不然滚犊子)
&lt;/pre&gt;

&lt;p&gt;
&lt;b&gt;场景二: 接收到自然语言，但理解不能&lt;/b&gt;
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
—— 小明: 苟利国家生死已，岂因祸福避趋之，小红你有没有一种钦定的感觉？
—— 小红: (这个人在说什么……)
&lt;/pre&gt;

&lt;p&gt;
&lt;b&gt;场景三: 接收到自然语言，理解并回复&lt;/b&gt;
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
—— 小红: 小明，下午放学后你把教室的窗户玻璃擦一擦吧!
—— 小明: 我擦，我不擦！
&lt;/pre&gt;

&lt;p&gt;
小 S 将这个过程划分为 Perceive、Understand 和 Communicate 三部分，并为 NLP 主要的研究或应用方向和这三部分进行对应，如下图所示:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/nlp_task.png&quot; alt=&quot;nlp_task.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
Perceive、Understand 和 Communicate 和我之前总结的那三个步骤一一对应，或者说，之前我所说的那三个步骤，是我对 Perceive、Understand 和 Communicate 的理解吧。
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Language Modeling: 对语言的建模是对整个语言或者特定场景下的语言的特性的一个刻画，所得到的结果通常被称之为「语言模型(Language Model, LM)」&lt;/li&gt;
&lt;li&gt;Representation: 所谓表示一般是对具体的文本的语义、语法上的刻画，比如一个具体的词、一个具体的句子等等&lt;/li&gt;
&lt;li&gt;Machine Translation: 机器翻译，无须多说&lt;/li&gt;
&lt;li&gt;Language Generation: 即根据语义、语法生成有符合自然语言语法并能表达正确语义的文本&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
语言建模用来刻画整个语言的特性，所得到的语言模型有很多的应用，其中之一就是用来计算某个「给定句子」在这个语言的出现的概率以判别这个句子是不是一个「合理」的句子。而具体的词和句子等元素的表示，一方面是能用来分析这些元素的语义，另一方面也还反映了其所属语言的一些特性，因而是与 Perceive 和 Understand 都相关。
&lt;/p&gt;

&lt;p&gt;
Language Generation 则是在理解之后进行的结果的组织，组织成自然语言当然是要给人看的，这是它和 Communicate 之间的关系所在。Machine Translation 作为一个重要的 NLP 应用方向，需要确保源语言句子和目标语言句子具备同样的语义，从目的上来说本身就是为了提高人与人之间的沟通效率的，因此和 Understand、Communicate 的关系也是很明白的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;对语言进行建模的若干方法&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline4&quot;&gt;语言模型简介&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
语言模型是对语言整体特性的一个刻画，理想情况下，我们当然希望这个模型能够完全刻画「语言整体」，但有几个问题:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;从时间角度来看，语言整体一直是在变化的，我们无法建立一个能刻画过去、现在和未来所有时刻语言特性的模型，因此一般的做法是对某个时段的语言数据进行采样&lt;/li&gt;
&lt;li&gt;从语言本身来看，在不同的场景、人群中，同一种语言，其特性也会稍有不同，我们也无法建立一个能刻画所有可能的子语言特性的模型，尽管有人为建立「通用语言模型」而努力，但这种通用性本身也是相对的，绝对通用的语言模型不存在。换言之，在进行语言数据的采样时，按自己的需要，可能还需要将采样范围限制在某些特定的场景或人群中&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
按上述两个条件得到的语言数据，被称之为「语料(Corpus)」，理想的情况下，我们希望:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;语料中不同时间的语言数据的特性基本稳定&lt;/li&gt;
&lt;li&gt;在限制在特定场景或人群中时，希望数据能尽量涵盖受限条件下语言的各种情况&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
第一点要求语料的质量，第二点要求语料的规模，但实际情况中这两者很难一起得到保证。
&lt;/p&gt;

&lt;p&gt;
有了语料后，我们怎么去得到语言模型呢？换言之，所谓的「特性」该如何量化？
&lt;/p&gt;

&lt;p&gt;
首先，我们要知道，这个语言模型都涵盖了哪些基本元素，所谓「基本元素」，以英文为例，一般是单词，当然实际上也可以是词组或者字符，但单词是我们认识语言(至少是英文)的比较基本的单元。
&lt;/p&gt;

&lt;p&gt;
然后呢，对任意的这些基本元素组成的序列，一般来说，就是句子，这个模型能给出其置信度(Confidence)，用来判断这个句子在这个语言下的合理性，通常表现为一个概率。在语音识别以及其他一些应用中，通常会在最后有若干个候选的句子结果，此时就要用置信度来从中选择最合理的结果。比如说下面两个句子，他们的发音基本上是一样的，但我们是可以知道第一个句子其实是更合理的。
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;It's hard to recognize speech&lt;/li&gt;
&lt;li&gt;It's hard to wreck a nice beach&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
总结一下，从给定的语料中可以得到一个语言模型，语言模型包含两部分:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;包含语料中出现的基本元素的一个有限集合: \(V = \{ e_{1},e_{2}, ..., e_{n} \}\)&lt;/li&gt;
&lt;li&gt;一个概率分布，对给定的序列 \(W = w_{1}w_{2}...w_{m}\)，可以得到概率 \(P(W)\)，其中 \(w_{i} \in V\)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
也许我们会想，是不是需要考虑语法结构？毕竟一个合理的句子，应该是大致符合自然语言的语法结构的，但首先我们的自然语言并没有一个精确的、无歧义的语法规则，其次语法规则本身已经是一个更高抽象级别的概念了 —— 简单的就是好的，我们更愿意去寻找一些简单的方法，N-gram 语言模型和神经网络语言模型(Neural Network Language Model, &lt;b&gt;NNLM&lt;/b&gt;)就是这样。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline5&quot;&gt;N-gram 语言模型&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;p&gt;
基于马尔可夫假设，我们可以认为，在句子中每个「基本元素」出现的概率只和其前面的元素有关，这样，对给定句子 \(W=w_{1}w_{2}...w_{m}\)，可以得到其概率为:
&lt;/p&gt;

&lt;p&gt;
\[P(W) = P(w_{1})\cdot P(w_{2}|w_{1})\cdot P(w_{3}|w_{1}w_{2})... P(w_{m}|w_{1}w_{2}...w_{m-1})\]
&lt;/p&gt;

&lt;p&gt;
但是这样的条件概率仍然难以计算，因此我们再进一步地假设: 每个「基本元素」只和其前面 \(N-1\) 个元素有关。在这样的假设即 N-1 阶马尔可夫假设下，前面的式子可以进行近似简化(以 \(N=3\) 为例):
&lt;/p&gt;

&lt;p&gt;
\[\begin{eqnarray}
     P(W) &amp;=&amp; P(w_{1})\cdot P(w_{2}|w_{1})\cdot P(w_{3}|w_{1}w_{2})\cdot P(w_{4}|w_{1}w_{2}w_{3})... P(w_{m}|w_{1}w_{2}...w_{m-1}) \\
          &amp;\approx&amp; P(w_{1})\cdot P(w_{2}|w_{1})\cdot P(w_{3}|w_{1}w_{2})\cdot P(w_{4}|w_{2}w_{3})... P(w_{m}|w_{m-2}w_{m-1}))
  \end{eqnarray}\]
&lt;/p&gt;

&lt;p&gt;
这样我们就得到了一个 3 阶的「N-gram 语言模型」，又称「Trigram 语言模型」，相应的，1 阶 N-gram 语言模型被称为「Unigram 语言模型」，2 阶 N-gram 语言模型被称为「Bigram 语言模型」，4 阶语言模型则可以简称为「4-gram 语言模型」，依次类推。除了能得到我们期望的概率分布外，大于 1 阶的 N-gram 语言模型还隐式地通过上下文信息一定程度上反映了语言的语法结构。
&lt;/p&gt;

&lt;p&gt;
这里的「gram」是一个抽象的概念，在不同的粒度下它可以对应不同的单元，比如说我们如果基于字符来建模，这个 gram 就是字符；如果基于词来建模，这个 gram 就是词。一般情况下我们使用词作为 gram ，后文一些示例或讨论，如无特殊说明，默认使用词作为 gram。
&lt;/p&gt;

&lt;p&gt;
根据上面的式子，我们要做的，就是从语料中得到每个「N-gram」的概率，最简单的办法是用「极大似然估计(Maximum Likelihood Estimation, &lt;b&gt;MLE&lt;/b&gt;)」—— 即直接统计每个 N-gram 的在语料中的频次然后除以频次之和作为概率值。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;from&lt;/span&gt; __future__ &lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; division
&lt;span style=&quot;color: #729fcf;&quot;&gt;from&lt;/span&gt; collections &lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; Counter

&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;build_ngram&lt;/span&gt;(corpus, gram_level):
    &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    :param corpus: list of sentence&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    :param gram_level: as it says&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;freqs&lt;/span&gt; = Counter()
    &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; sentence &lt;span style=&quot;color: #729fcf;&quot;&gt;in&lt;/span&gt; corpus:
        &lt;span style=&quot;color: #eeeeec;&quot;&gt;seq&lt;/span&gt; = sentence.strip().split()
        &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; index &lt;span style=&quot;color: #729fcf;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;xrange&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;len&lt;/span&gt;(seq) - gram_level + 1):
            &lt;span style=&quot;color: #eeeeec;&quot;&gt;gram&lt;/span&gt; = &lt;span style=&quot;color: #729fcf;&quot;&gt;tuple&lt;/span&gt;(seq[index:index+gram_level])
            &lt;span style=&quot;color: #eeeeec;&quot;&gt;freqs&lt;/span&gt;[gram] += 1

    &lt;span style=&quot;color: #eeeeec;&quot;&gt;total_count&lt;/span&gt; = &lt;span style=&quot;color: #729fcf;&quot;&gt;sum&lt;/span&gt;(freqs.itervalues())
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; {gram: freq / total_count &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; gram, freq &lt;span style=&quot;color: #729fcf;&quot;&gt;in&lt;/span&gt; freqs.iteritems()}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
但这样的简单的计算方式是有问题的，在实际应用中，往往因为语料的规模不够，导致一些低频的 N-gram 在语料中未出现，这样在计算句子概率的时候，一个概率为 0 的 N-gram 将导致整个句子的概率为 0，此即「零概率问题」。随着 N 的增大，这个问题会越发的明显。
&lt;/p&gt;

&lt;p&gt;
零概率问题的解决办法是将语料中一些有的 N-gram 的频次「分」一点给这些未出现的 N-gram，这个叫 「折扣(discount)」；或者用这个未出现的 N-gram 的低阶形式的概率来估计，这个叫做「backoff」。这些方法统称为「平滑(smoothing)」方法。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline6&quot;&gt;基于神经网络的语言模型&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline6&quot;&gt;
&lt;p&gt;
Bengio 在 2003 年提出的神经概率语言模型(Neural Probabilistic Language Model, &lt;b&gt;NPLM&lt;/b&gt;)是影响较大的基于神经网络的语言模型&lt;sup&gt;&lt;a id=&quot;fnr.1&quot; class=&quot;footref&quot; href=&quot;#fn.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;。其模型思想其实和 N-gram 语言模型还是同出一源，即基于 N-1 阶马尔可夫假设，认为句子中某个词是由其前面的 N-1 个词决定的。模型使用的网络结构如下图所示。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/nplm_structure.png&quot; alt=&quot;nplm_structure.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这个模型将 N-1 个词的表示拼接起来作为输入，然后去预测下一个词最有可能是哪个。输出层会是一个很大的向量，每一维的值就是每一个可能的词的条件概率，这样要计算一个句子的概率也就没问题了。
&lt;/p&gt;

&lt;p&gt;
这样基于神经网络的语言模型有什么好处呢？
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;N-gram 需要显式存储每个 N-gram 的内容和概率，于是模型体积会随着语料的扩充而膨胀，但 NPLM 没有这个问题&lt;/li&gt;
&lt;li&gt;N-gram 需要应用各种平滑方法来解决零概率问题，但 NPLM 不存在这个问题，即使是语料中没出现的 N-gram ，依然能给出非 0 的概率值&lt;/li&gt;
&lt;li&gt;模型中会学习一个固定长度的向量来表示一个词，且向量中各维度的值都是连续实值而非离散的 0/1 ，此即「Word Embedding」的较早形式&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
Bengio 还在论文中提到可以用「循环神经网络(Recurrent Neural Network, &lt;b&gt;RNN&lt;/b&gt;)」来减少模型参数数量和捕获更远距离的上下文信息(longer term context)，这些观点无疑是非常具有前瞻性的。
&lt;/p&gt;

&lt;p&gt;
当然，值得一提的是，现为「IDL 杰出科学家」的徐伟曾在 2000 年独立提出用神经网络构建 Bigram 语言模型的思路&lt;sup&gt;&lt;a id=&quot;fnr.2&quot; class=&quot;footref&quot; href=&quot;#fn.2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;。
&lt;/p&gt;

&lt;p&gt;
在这之后，Tomas Mikolov 于 2010 年提出基于 RNN 的语言模型(Recurrent Neural Network Language Model, &lt;b&gt;RNNLM&lt;/b&gt;)&lt;sup&gt;&lt;a id=&quot;fnr.3&quot; class=&quot;footref&quot; href=&quot;#fn.3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;，并且顺着这个方向一直发论文发到博士毕业，Bengio 还是厉害啊 —— 话说 Google Scholar 上 Tomas Mikolov 的照片一头长发害近视眼的我以为他是个姑娘呢 :)
&lt;/p&gt;

&lt;p&gt;
RNNLM 的根本思想和 NPLM 是共通的，不同的地方在于词是逐个输入到模型中的，然后隐藏层有一个具有「记忆功能」的单元将之前的词的信息都记录了下来，然后在输出层去预测下一个词。如果把其中的记忆单元拿掉就变成了一个学习 Bigram 语言模型的前馈神经网络了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline7&quot;&gt;语言的表示方法&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline7&quot;&gt;
&lt;p&gt;
在 NLP 的应用场景里，无论我们是要做分类、聚类、摘要、机器翻译，首先我们要将要处理的具体文本转换成模型能够处理的数学形式，并且要求这种表示能够反映文本的独特信息。这就是所谓「Representation」，其实也就是特征提取了。
&lt;/p&gt;

&lt;p&gt;
说 representation 是 NLP 的核心应该不为过吧，事实上在其他机器学习相关的领域，特征表达都是非常重要的，特征设计、特征筛选在以前甚至现在依然是非常重要的一个学术和应用问题。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline8&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline8&quot;&gt;词的表示: one-hot 与 embedding&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline8&quot;&gt;
&lt;p&gt;
单个字符因为不具有语义，所以一般不对其表示方法作过多探讨(暂不考虑汉语)。词作为我们认识语言的基本单元，表示它们的最简单方法，就是为词进行编号，比如说我有一个包含 1 万个词的词典，第一个词就记为「1」，第二个记为「2」，依次类推。
&lt;/p&gt;

&lt;p&gt;
这样当然是可以的，在一些简单的任务，比如文本分类上，问题不大，比如说我们可以统计不同 id 的词在两个文本中出现的频次来判断两个文本的相似程度。但问题在于 id 是一个类别变量值，它的值是不能用于比较、不能用于计算的，假想一下我们要构造一个简单的 NNLM ，某次输入的 N-gram 中包含了 id 为 10000 的词，如果直接输入到模型中，这个巨大的值会导致网络产生严重的偏差。
&lt;/p&gt;

&lt;p&gt;
为了解决这个问题，我们一般用所谓「one-hot representation」来表示一个词，具体做法是，每个词都表示为一个向量，这个向量只有一个维度的值为 1，其他维度的值全为 0，且不同词值为 1 的维度都不同。比如说我们要处理的问题中只包含 5 个词，将这 5 个词编号后，可以分别表示为:
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
第一个词: [1 0 0 0 0]
第二个词: [0 1 0 0 0]
第三个词: [0 0 1 0 0]
第四个词: [0 0 0 1 0]
第四个词: [0 0 0 0 1]
&lt;/pre&gt;

&lt;p&gt;
这就是 one-hot 的含义所在，每个词的向量表示中，只有一个位置是「激活的」。
&lt;/p&gt;

&lt;p&gt;
one-hot 表示应用广泛，但它本身有几个问题:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;数据稀疏，一个包含 10000 个词的问题，每个词都要表示为长度 10000 的向量，但只有一个位置是有值的，这将会造成很大的存储开销&lt;/li&gt;
&lt;li&gt;缺乏语义信息，两个词之间无法进行相似性比较&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
2003 年 Bengio 提出 NPLM 的时候，在模型中去学习每个词的一个连续向量表示，并经过 Tomas Mikolov 等人的发展&lt;sup&gt;&lt;a id=&quot;fnr.4&quot; class=&quot;footref&quot; href=&quot;#fn.4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;，发展出「Word Embedding」这一表示方法。比如说前面那五个词的表示，用 word embedding 表示后，可能是这样子的:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
第一个词: [0.2 0.3 0.5]
第二个词: [0.7 0.1 0.2]
第三个词: [0.1 0.2 0.3]
第四个词: [0.2 0.3 0.4]
第四个词: [0.3 0.4 0.6]
&lt;/pre&gt;

&lt;p&gt;
这样两个词之间就可以比较了——当然，这种表示下相似值高的两个词，并不一定是具有相同语义的，它只能反映两者经常在相近的上下文环境中出现。但无论如何，one-hot 表示的两大问题，word embedding 都给出了一个解决方案。
&lt;/p&gt;

&lt;p&gt;
word embedding 反映的词与词之间的相似性，可能在语义层面并不能说是真正的相似(取决于如何定义「相似」了)，但「两个 word embedding 接近的词，它们是相关的」这一点是毋庸置疑的，如下图所示。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/word_embedding_similarity.png&quot; alt=&quot;word_embedding_similarity.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
除了能反映同一语言的词之间的关系之外，不同语言之间语义近似或相关的词的 word embedding 也将这种关系反映了出来。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/word_embedding_multilingual.png&quot; alt=&quot;word_embedding_multilingual.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
此外，word embedding 还能一定程度上反映语言的内在规律(linguistic regularity)，比如说 'king - man + woman = queen' 之类的，当然这个特定在实际应用场景里是很少用到的，而且我没记错的话主题模型也可以做到类似的事情，所以也并不是什么新东西了。
&lt;/p&gt;

&lt;p&gt;
以上都是从 word embedding 本身来看的一些特点，但根据后来的一些讨论，word embedding 所反映的「相似性」其实要在具体的应用场景下才有确切的意义，像上面提到的 multi-lingual 的相似甚至 multi-modal 的相似，以及 linguistic regularity ，在实际应用中使用得还是较少的。引用小 S 的话，word embedding 更大的意义在于「它已经成为了各种后续或者更高级别粒度的语言表达的基础，这是完全超出相似度的一件事，也是词向量带来的最大贡献」。
&lt;/p&gt;

&lt;p&gt;
当然除了 one-hot 和 word embedding 外，也还有其他的一些特征表示方法，比如说词性、语法结构等信息，都可以附加到词的特征上去。
&lt;/p&gt;

&lt;p&gt;
更深入的关于 word embedding 的讨论，推荐这篇文章: &lt;a href=&quot;http://yanran.li/peppypapers/2015/08/17/post-word-embedding.html&quot;&gt;“后 Word Embedding” 的热点会在哪里？&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline9&quot;&gt;句子及更高层级数据的表示: VSM 和 embedding&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline9&quot;&gt;
&lt;p&gt;
句子、段落和文章，我们都可以把它们视为是词的序列，因此在很多场景下可以用统一的方式来进行表示。当然，在涉及句法结构分析时，基本是以句子为单位的，这里暂时不考虑这种情况。作为词的序列，我们该如何去表示它们呢？理想情况下当然是希望词的顺序啊、语义啊、语法结构啊都能够表达出来，但如果要将这些都反映出来，所使用的特征会比较复杂，光是语义和语法结构就够我们喝一壶了。
&lt;/p&gt;

&lt;p&gt;
在文本分类、文本相似度量等一些主要的应用场景中，我们使用向量空间模型(Vector Space Model, &lt;b&gt;VSM&lt;/b&gt;)来表示一段文本。VSM 经常和词袋模型(Bag Of Words, &lt;b&gt;BOW&lt;/b&gt;)联系在一起。而 BOW 假设词和词之间是互相独立的，认为词和词之间的位置信息是不重要的，可以算作是 VSM 的一个前提、假设。
&lt;/p&gt;

&lt;p&gt;
BOW 的解释也很形象，它假想我们有一个袋子，每遇到一个词就将其丢进袋子中，直到处理完所有文本。在此基础上， VSM 要求用一个向量来表示各个文档，这个向量的长度要与词袋中不同的词的数量一致。比如说我们有下面两段文本:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
(1) John likes to watch movies. Mary likes movies too.
(2) John also likes to watch football games.
&lt;/pre&gt;

&lt;p&gt;
那么我们得到的词袋中包含的词就是 (John, likes, to, watch, movies, also, football, games, Mary, too) 共 10 个词，这样两段文本可以分别表示为:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
(1) [1, 2, 1, 1, 2, 0, 0, 0, 1, 1]
(2) [1, 1, 1, 1, 0, 1, 1, 1, 0, 0]
&lt;/pre&gt;

&lt;p&gt;
如上所示，不同位置的值为对应的词在文本中的权重，这里使用的是词频。这样两段文本之间的相似程度可以简单地通过算余弦距离来得到。当然在实际中，我们希望不同维度的值是能反映对应的词在文本中的「重要程度」的，而直接使用词频并不能达到这个目的，事实上有一些常用的词会在很多的文本里都具有较高的频次，但它们本身并不包含重要的信息。所以一般用 TF-IDF(词频-逆文档频率)来作为词的权重。
&lt;/p&gt;

&lt;p&gt;
VSM 的一个问题是，其特征表示往往会很稀疏(想象一个包含了 100,000 个不同词汇的文本集合)，解决这个问题的一个方法是将一些文档频率很高的词去除，因为这样的词不能为文本与文本之间的区分性作出贡献，这样的方法能有效地降低向量的维度并保留有效的信息。
&lt;/p&gt;

&lt;p&gt;
VSM 的另外一个问题是缺乏语义信息。比如说下面两个句子，它们表达的意义是不一样的，但在 VSM 中，两者的表示会一模一样
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
(1) Mary loves John
(2) John loves Mary
&lt;/pre&gt;

&lt;p&gt;
这个问题的一个解决办法是使用 N-gram 而非 word 来作为基本单元，比如用 Bigram，上述两句话得到的词袋会是: (Mary loves, loves John, John loves, loves Mary)，对应的，两个句子可以表示为:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
(1) [1, 1, 0, 0]
(2) [0, 0, 1, 1]
&lt;/pre&gt;

&lt;p&gt;
另外一个办法就是，使用句子级别的 embedding 表示。常用的方法有 RNN 和 CNN 两种。
&lt;/p&gt;

&lt;p&gt;
RNN 的话比较简单，将句子中的词逐个输入到模型中，结束时取隐藏层的输出即可。这是因为 RNN 隐藏层的输出是由之前的「记忆」和当前的输入计算得到的，可以认为是「整个句子的记忆」，也就是一个句子的特征表示了。如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/sentence_embedding_rnn.png&quot; alt=&quot;sentence_embedding_rnn.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
CNN 的话是将句子中的词的向量表示拼接成一个矩阵，然后在上面进行卷积，最后得到一个向量表示，如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/sentence_embedding_cnn.png&quot; alt=&quot;sentence_embedding_cnn.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
CNN 和 RNN 得到的 sentence embedding，同 word embedding 一样，可以进行相似性的对比，语义相近的句子，其向量表示在空间中也会比较接近，如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/sentence_embedding_similarity.png&quot; alt=&quot;sentence_embedding_similarity.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
所以，既然可以得到 sentence embedding，能不能得到 paragraph embedding 乃至 document embedding 呢？对于前者，Tomas Mikolov 在 2014 年提出了「Paragraph Vector」&lt;sup&gt;&lt;a id=&quot;fnr.5&quot; class=&quot;footref&quot; href=&quot;#fn.5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;，后者的话似乎还没见到过。在 Mikolov 的实验中，paragraph vector 在情感分析上和信息检索两个任务上都取得了比其他模型更好的结果。不过和 word embedding 一样，sentence embedding 和 paragraph embedding 的可解释性仍然存在问题。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline10&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline10&quot;&gt;机器翻译: 从 SMT 到 end-to-end&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline10&quot;&gt;
&lt;p&gt;
沟通是人类的本能，所以将一种语言翻译成另外一种语言的需求，早在 17 世纪就有人提出来了，但我相信在更早之前，在不同语言的人群交界的地方，就已经有人在尝试做这个事情了。不过直到 1903 年，「机器翻译」这个词才被正式提出来。
&lt;/p&gt;

&lt;p&gt;
1953 年的时候，Weaver 等人发表了一篇名为《Translation》的文章&lt;sup&gt;&lt;a id=&quot;fnr.6&quot; class=&quot;footref&quot; href=&quot;#fn.6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;，并在其中提出两个基本的思想:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;翻译类似于密码解读的过程&lt;/li&gt;
&lt;li&gt;原文与译文表达的是相同的意思，翻译可以通过将源语言转换成一个「通用语言」，然后再转换为目标语言&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
这里提到的「通用语言」是一种虚构的语言，假定为全人类共同的。这个思想其实和后面要讲到的 Encoder-Decoder 的思想有一些共通之处呢！
&lt;/p&gt;

&lt;p&gt;
从方法上来说，最早使用的是基于规则的方法，后面出现了基于实例的方法，然后在大概 1999 年，在 IBM 推出了 5 种「基于词的统计翻译模型」并取得非常好的成绩后，统计机器翻译(Statistical Machine Translation, &lt;b&gt;SMT&lt;/b&gt;)成为了机器翻译的主流方法，直到现在依然如此，Google、Bing、百度等几家的在线翻译系统，都是基于统计方法的。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline11&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline11&quot;&gt;统计机器翻译(Statistical Machine Translation, &lt;b&gt;SMT&lt;/b&gt;)&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline11&quot;&gt;
&lt;p&gt;
目前主流的机器翻译系统，其基本思想来源于「噪声信道模型」，即认为源语言的句子 \(f\) 是目标语言 \(e\) 经过含噪声的信道编码后得到的，翻译的过程就是要求解出 \(\hat{e}\)
&lt;/p&gt;

&lt;p&gt;
\[\hat{e} = \mathop{arg\,max}_{e}p(e|f)\]
&lt;/p&gt;

&lt;p&gt;
然后利用贝叶斯公式，转换为
&lt;/p&gt;

&lt;p&gt;
\[\hat{e} = \mathop{arg\,max}_{e}p(f|e)p(e)\]
&lt;/p&gt;

&lt;p&gt;
其中 \(p(f|e)\) 被称为「翻译模型」，\(p(e)\) 则是语言模型。后者可以通过收集目标语言的语料训练得到，但前者怎么办呢？一个简单的思路是，将源语言句子中的每个词都翻译成目标语言对应的词，然后通过重新排列这些词得到符合目标语言语法的句子 —— 后面这个过程称为「词对齐(word alignment)」。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/word_alignment.png&quot; alt=&quot;word_alignment.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
所以翻译模型会由两部分组成，一部分是词到词的映射，另一部分是对结果进行对齐。整个系统要在所有可能的对齐结果中找到最好的那个。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/phrase_based_smt.png&quot; alt=&quot;phrase_based_smt.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这就是传统的统计机器翻译模型的基本原理。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline12&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline12&quot;&gt;端到端(end-to-end)的新方法&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline12&quot;&gt;
&lt;p&gt;
2014 年的时候，Kyunghyun Cho&lt;sup&gt;&lt;a id=&quot;fnr.7&quot; class=&quot;footref&quot; href=&quot;#fn.7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; 和 Sutskever&lt;sup&gt;&lt;a id=&quot;fnr.8&quot; class=&quot;footref&quot; href=&quot;#fn.8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt; 先后提出了一种 End-to-End 即所谓「端到端」的模型，在英语到法语的翻译实验上取得了很好的成绩，前者将其模型命名为 Encoder-Decoder 模型，后者则将其命名为 Sequence-to-Sequence 模型，不过两者其实在结构上基本是一样的。其核心思想都是:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;将输入的句子经过一个 RNN 生成一个能反映句子语义的向量，类似计算 sentence embedding 的过程，&lt;/li&gt;
&lt;li&gt;用另一个 RNN ，从输入句子的向量表达中解码出另一个句子&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
第一个过程称之为 encoding，第二个过程称之为 decoding，整个模型非常的简单优雅，不需要词对齐，不需要额外的语言模型，输入英语，直接得到法语，这就是所谓「端到端」。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/seq2seq.png&quot; alt=&quot;seq2seq.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
Encoder-Decoder 模型虽然在结构上很简单，但它有很重要的两个特点：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;大部分序列到序列的预测问题，都可以使用该模型，这个序列甚至没有必要是文本，语音、图像同样可以&lt;/li&gt;
&lt;li&gt;先 encoding 再 decoding 的 encoder-decoder 的结构，可以推广到非 RNN 的模型上去&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
当然，虽然 encoder-decoder 的模型结构简单优美，在一些问题上也还不错，它仍然是有缺点的，回到机器翻译问题上来，将一个句子 encode 成一个向量，真的是合适的么？一方面这个过程相当于进行数据压缩，肯定是会有信息损耗的，而且这种损耗随着句子长度的提高会越来越大；另一方面，翻译的时候并不一定需要完全理解整个句子的含义后才能进行，比如可能在看完句子的前半部分以后就可以进行部分的翻译，每个翻译结果中的词的生成都使用整个句子的语义的话，无疑准确度也会受到限制。
&lt;/p&gt;

&lt;p&gt;
在这之后，Dzmitry Bahdanau 在 encoder-decoder 模型的基础上增加 attention 机制来解决这个问题&lt;sup&gt;&lt;a id=&quot;fnr.9&quot; class=&quot;footref&quot; href=&quot;#fn.9&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;，通过双向 RNN 来在 decoder 时得到不同时刻的上下文信息。
&lt;/p&gt;

&lt;p&gt;
其中 decoder 在每一个 time step 用下面的式子计算条件概率以判断该输出什么词。
&lt;/p&gt;

&lt;p&gt;
\[p(y_{i}|y_{1}, ..., y_{i-1}, x) = g(y_{i-1}, s_{i}, c_{i})\]
&lt;/p&gt;

&lt;p&gt;
其中 \(s_{i}\) 是 decoder 的隐藏状态
&lt;/p&gt;

&lt;p&gt;
\[s_{i}=f(s_{i-1}, y_{i-1}, c_{i})\]
&lt;/p&gt;

&lt;p&gt;
而 \(c_{i}\) 则是根据从 encoder 中不同时刻的隐藏状态得到的上下文信息，用来决定输出时该聚焦于输入序列的哪些部分。
&lt;/p&gt;

&lt;p&gt;
\[c_{i}=\sum_{j=1}^{T_{x}}\alpha_{ij}h_{j}\]
&lt;/p&gt;

&lt;p&gt;
上式中的 \(\alpha_{ij}\) 构成的权值矩阵就是最核心的内容，将其可视化的话，能发现高亮的部分其实相当于是源语言句子和目标语言句子之间的对齐路径
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/attention_alignment.png&quot; alt=&quot;attention_alignment.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
对照传统的统计机器翻译系统，在 encoder-decoder 模型中，模型本身相当于隐含了语言模型和词到词翻译的两个部分，但却缺乏词对齐部分，而 attention 机制的加入弥补了这个缺陷。
&lt;/p&gt;

&lt;p&gt;
另外要说的是，attention 机制和 encoder-decoder 一样，更大意义上在于它提供了一种解决问题的思路，而不是说某个具体的模型结构，事实上 attention 机制的实现是多种多样的，不一定要使用 RNN。在应用上，attention 机制在图像、视频上也有很大的应用空间，比如在目标识别时用来聚焦于不同的图像区域。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/attention_image.png&quot; alt=&quot;attention_image.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;p&gt;
2016 年， Kyunghyun Cho 又提出结合了 encoder-decoder 和 attention 的多语言翻译模型&lt;sup&gt;&lt;a id=&quot;fnr.10&quot; class=&quot;footref&quot; href=&quot;#fn.10&quot;&gt;10&lt;/a&gt;&lt;/sup&gt;，能够接收多用语言的输入，并翻译成多种不同的语言。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/language_transfer.png&quot; alt=&quot;language_transfer.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline13&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline13&quot;&gt;自然语言生成(Natural Language Generation, NLG)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline13&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline14&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline14&quot;&gt;从模板方法到 encoder-decoder&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline14&quot;&gt;
&lt;p&gt;
说到自然语言生成，我的第一反应是大刘的《诗云》，以及他制作的一款名为「电子诗人」的自动作诗软件。来看一看用电子诗人生成的一首「现代诗」:
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
作品第75509号——
&lt;/p&gt;

&lt;p&gt;
我面对着黑色的艺术家和荆棘丛生的波浪
&lt;/p&gt;

&lt;p&gt;
我看到，剌眼的心灵在午睡，程序代码在猛击着操场
&lt;/p&gt;

&lt;p&gt;
在这橄榄绿的操场中，没有货车，只有蝴蝶
&lt;/p&gt;

&lt;p&gt;
我想吸毒，我想软弱地变黄
&lt;/p&gt;

&lt;p&gt;
我面对着光灿灿的冬雪和双曲线形的霞光
&lt;/p&gt;

&lt;p&gt;
我看到，青色的乳房在漂荡，肥皂在聆听着海象
&lt;/p&gt;

&lt;p&gt;
在这弱小的春雨中，没有贝多芬，只有母亲
&lt;/p&gt;

&lt;p&gt;
我想上升，我想呼吸着歌唱
&lt;/p&gt;

&lt;p&gt;
我面对着宽大的小船和透明的微波束
&lt;/p&gt;

&lt;p&gt;
我看到，枯死的渔船在叫，蒸馏水在铲起羊
&lt;/p&gt;

&lt;p&gt;
在这多孔的青苔中，没有夏娃，只有老师
&lt;/p&gt;

&lt;p&gt;
我想冬眠，我想可恶地发光
&lt;/p&gt;

&lt;p&gt;
我面对着多血的史诗和悠远的大火
&lt;/p&gt;

&lt;p&gt;
我看到，生机勃勃的战舰在沉默，透明裙在爱抚着操场
&lt;/p&gt;

&lt;p&gt;
在这曲线形的奋斗者中，没有月光舞会，只有风沙 我想摆动，我想粗糙地惊慌
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
自然语言生成除了上述这种娱乐性质的作用外，目前在自动天气预报、机器翻译、Image Caption 和对话系统中都有应用。
&lt;/p&gt;

&lt;p&gt;
说到自然语言生成，如果要我们自己实现的话，能很快想到的一个基础的办法，就是模板生成方法。在一些受限环境下，需要返回的文本形式可能比较简单，用模板方法还是可以取得能用的结果的。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/nlg_with_template.png&quot; alt=&quot;nlg_with_template.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
不过模板方法的缺点也是显而易见的:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;泛化性极低，换一个场景就要重新设计一个不同的模板，如果要进行通用领域的自然语言生成，模板数量将会多到爆炸&lt;/li&gt;
&lt;li&gt;输出非常死板僵硬，如果是在对话这样的场景下，用户很快就会发现得到的文本是由机器生成的&lt;/li&gt;
&lt;li&gt;并没有真正「理解文本」&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
怎么样才算是理想的「自然语言生成」呢？
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
Once aware of the communicative goals, machines can understand the meaning of the content (what is important, what is what), and automatically generate natural, meaningful and plausible language.  —— By 小 S
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
几个重点是：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;理解得到的输入(根据不同的场景，可能是文本会图像)&lt;/li&gt;
&lt;li&gt;要生成自然的语言表达，就算是胡说八道，也要一本正经&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
对于一本正经地胡说八道这件事情，其实是可以用语言模型来，用 N-gram 模型的话，随机选一个词，然后找到关联的概率最高的几个 N-gram ，依次类推。另外一种办法是在已有特定语言的「基本句法规则」的情况下，先生成句法结构，然后往里面填充词语。当然，这两种方法都是很简单的，如果直接使用的话生成的文本其实本身没有什么意义，要放到具体的应用场景里的话，这样的方法还必须和其他一些方法结合才行。
&lt;/p&gt;

&lt;p&gt;
而使用之前提到的 encoder-decoder 框架，在一些场景下，能够做到 end-to-end 的生成，比如 Image Caption。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/image_caption_seq2seq.png&quot; alt=&quot;image_caption_seq2seq.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
所以说 encoder-decoder 这个想法真的是非常好用的呀！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline15&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline15&quot;&gt;对话系统中的自然语言生成&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline15&quot;&gt;
&lt;p&gt;
对话系统中使用到的技术，大致上可以分成三部分:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;基于知识库的检索方法&lt;/li&gt;
&lt;li&gt;基于知识图谱的简单推理&lt;/li&gt;
&lt;li&gt;基于生成模型的自然语言生成方法&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
第一部分是在知识库中直接找到「合适的」现成的文本返回给用户，和自然语言生成基本没什么关系；第二部分涉及到对用户意图的分析，可能会有一些基于模板、规则的生成过程；第三部分，据我所知，好几家做问答的公司，都在尝试用 encoder-decoder 的模型。
&lt;/p&gt;

&lt;p&gt;
没做过问答，以上都是我瞎编的 :)
&lt;/p&gt;

&lt;p&gt;
前两部分就不谈了，第三部分使用 encoder-decoder 模型，基本都是基于 RNN 来去实现。这种生成模型虽然能够「理解」用户的问题并且一本正经的胡说八道，但仍然存在一些需要解决的问题。
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;语义漂移(semantic drift)，直观点来说就是答非所问&lt;/li&gt;
&lt;li&gt;生成的文本在语法上有时并不符合自然语言特性(这真是在胡说八道了……)&lt;/li&gt;
&lt;li&gt;训练语料中的高频句式会频繁出现，典型的如「万能回复」问题，其实也算是语义漂移的一个表现&lt;/li&gt;
&lt;li&gt;生成的文本语言风格可能与实际场景不符合&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
本质上 encoder-decoder 也可以认为是一种检索办法，只不过相比基于知识库的检索方法，它是一种模糊的、更细粒度的检索，语义漂移的问题其实就是模型在其巨大的解空间中迷路了，要解决这个问题，一方面是提高方向感，一方面也可以将解空间进行限制。Google 的 Allo 就被设计成使用混合响应策略来解决这个问题。
&lt;/p&gt;

&lt;p&gt;
所谓的「混合响应策略」，其实就是通过其他的方法来辅助咯，比如获取用户的个人信息作为辅助特征，比如通过知识图谱并将推理结果输入到模型中，再比如确定用户的地理位置和环境因素作为额外的特征。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/allo_mixed_response_strategy.png&quot; alt=&quot;allo_mixed_response_strategy.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
至于语言风格的问题，可以通过情感分析等手段来获取用户的情绪状态，然后输入到模型中以得到不同风格的响应。
&lt;/p&gt;

&lt;p&gt;
此外，在对话系统中，一个很典型的问题是「多轮对话问题」—— 大部分对话系统都是「一问一答」的，很少考虑前几轮对话的内容，也就是我们常说的「上下文」。对于这个问题，小 S 的回答是，目前在一块的研究中提到的方法大概有这么几种:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;将前几轮的历史对话信息作为额外的输入&lt;/li&gt;
&lt;li&gt;设计多层次的对话系统&lt;/li&gt;
&lt;li&gt;结合用户画像(user profile)来生成文本，取 top-5 的答案再进一步筛选&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
综上，encoder-decoder 模型虽然简单强大，但仍然有自身固有的问题，如果要设计一个良好的对话系统，以目前的情况，还是需要和传统方法进行结合。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline16&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline16&quot;&gt;后记&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline16&quot;&gt;
&lt;p&gt;
这应该是我参加集智的活动之中质量最高的一次了，75 页的 slides，覆盖 NLP 几大基本问题的内容和展开，加上小 S 本身在 NLP 这块的造诣，给我带来了很大的收获。又因为自己对 NLP 兴趣浓厚，参加完活动后就兴起了写一个完整笔记的念头，历时五天，查阅了很多的论文，把个中尚未明白的一些细节搞清楚，总算是完成了这篇 1 万多字的笔记。
&lt;/p&gt;

&lt;p&gt;
希望以后能看到更多这样高质量的活动！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;&amp;#33050;&amp;#27880;: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.1&quot; class=&quot;footnum&quot; href=&quot;#fnr.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Bengio, Yoshua, et al. &quot;A neural probabilistic language model.&quot; journal of machine learning research 3.Feb (2003): 1137-1155.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.2&quot; class=&quot;footnum&quot; href=&quot;#fnr.2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Xu, Wei, and Alexander I. Rudnicky. &quot;Can artificial neural networks learn language models?.&quot; (2000).
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.3&quot; class=&quot;footnum&quot; href=&quot;#fnr.3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Mikolov, Tomas, et al. &quot;Recurrent neural network based language model.&quot; Interspeech. Vol. 2. 2010.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.4&quot; class=&quot;footnum&quot; href=&quot;#fnr.4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Mikolov, Tomas, et al. &quot;Distributed representations of words and phrases and their compositionality.&quot; Advances in neural information processing systems. 2013.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.5&quot; class=&quot;footnum&quot; href=&quot;#fnr.5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Le, Quoc V., and Tomas Mikolov. &quot;Distributed Representations of Sentences and Documents.&quot; ICML. Vol. 14. 2014.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.6&quot; class=&quot;footnum&quot; href=&quot;#fnr.6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Weaver, Warren. &quot;Translation.&quot; Machine translation of languages 14 (1955): 15-23.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.7&quot; class=&quot;footnum&quot; href=&quot;#fnr.7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Sutskever, Ilya, Oriol Vinyals, and Quoc V. Le. &quot;Sequence to sequence learning with neural networks.&quot; Advances in neural information processing systems. 2014.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.8&quot; class=&quot;footnum&quot; href=&quot;#fnr.8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Cho, Kyunghyun, et al. &quot;Learning phrase representations using RNN encoder-decoder for statistical machine translation.&quot; arXiv preprint arXiv:1406.1078 (2014).
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.9&quot; class=&quot;footnum&quot; href=&quot;#fnr.9&quot;&gt;9&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Bahdanau, Dzmitry, Kyunghyun Cho, and Yoshua Bengio. &quot;Neural machine translation by jointly learning to align and translate.&quot; arXiv preprint arXiv:1409.0473 (2014).
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.10&quot; class=&quot;footnum&quot; href=&quot;#fnr.10&quot;&gt;10&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
Firat, Orhan, Kyunghyun Cho, and Yoshua Bengio. &quot;Multi-way, multilingual neural machine translation with a shared attention mechanism.&quot; arXiv preprint arXiv:1601.01073 (2016).
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>在 NLTK 中使用 Stanford NLP 工具包</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/06/08/use-stanford-nlp-package-in-nltk.html"/>
    <category term="NLP" scheme="http://www.zmonster.me/categories.html#NLP"/>
    <id>http://www.zmonster.me/2016/06/08/use-stanford-nlp-package-in-nltk</id>
    <published>2016-06-08T00:00:00+00:00</published>
    <updated>2016-06-08T00:00:00+00:00</updated>
    <description>
    
      <p>注意：本文仅适用于 nltk&lt;3.2.5 及 2016-10-31 之前的 Stanford 工具包，在 nltk 3.2.5 及之后的版本中，StanfordSegmenter 等接口相当于已经被废弃，按照官方建议，应当转为使用 nltk.parse.CoreNLPParser 这个接口</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org41c2012&quot;&gt;NLTK 与 Stanford NLP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgfd01eb6&quot;&gt;安装和配置&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org7b691ca&quot;&gt;注意事项&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2ef10c1&quot;&gt;StanfordSegmenter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org739e6d8&quot;&gt;StanfordTokenizer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org60ef4fc&quot;&gt;StanfordNERTagger 和 StanfordPOSTagger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4d4e736&quot;&gt;StanfordParser, StanfordDependencyParser&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org26cbf24&quot;&gt;StanfordNeuralDependencyParser&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge518db9&quot;&gt;基本使用&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org054e3c8&quot;&gt;使用 StanfordSegmenter 和 StanfordTokenizer 进行分词&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org964bac5&quot;&gt;使用 StanfordNERTagger 进行命名实体识别&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org18aa32e&quot;&gt;使用 StanfordPOSTagger 进行词性标注&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org52fb103&quot;&gt;使用 StanfordParser 进行句法分析&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org20dbdb8&quot;&gt;使用 StanfordDependencyParser 进行依存句法分析&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;
&lt;b&gt;注意：本文仅适用于 nltk&amp;lt;3.2.5 及 2016-10-31 之前的 Stanford 工具包，在 nltk 3.2.5 及之后的版本中，StanfordSegmenter 等接口相当于已经被废弃，按照官方建议，应当转为使用 nltk.parse.CoreNLPParser 这个接口，详情见 &lt;a href=&quot;https://github.com/nltk/nltk/wiki/Stanford-CoreNLP-API-in-NLTK&quot;&gt;wiki&lt;/a&gt;，感谢网友 &lt;a href=&quot;https://disqus.com/by/vickyding/&quot;&gt;Vicky Ding&lt;/a&gt; 指出问题所在。&lt;/b&gt;
&lt;/p&gt;

&lt;div id=&quot;outline-container-org41c2012&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org41c2012&quot;&gt;NLTK 与 Stanford NLP&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org41c2012&quot;&gt;
&lt;p&gt;
NLTK 是一款著名的 Python 自然语言处理(Natural Language Processing, NLP)工具包，在其收集的大量公开数据集、模型上提供了全面、易用的接口，涵盖了分词、词性标注(Part-Of-Speech tag, POS-tag)、命名实体识别(Named Entity Recognition, NER)、句法分析(Syntactic Parse)等各项 NLP 领域的功能。
&lt;/p&gt;

&lt;p&gt;
Stanford NLP 是由斯坦福大学的 NLP 小组开源的 Java 实现的 NLP 工具包，同样对 NLP 领域的各个问题提供了解决办法。
&lt;/p&gt;

&lt;p&gt;
斯坦福大学的 NLP 小组是世界知名的研究小组，如果能将 NLTK 和 Stanford NLP 这两个工具包结合起来使用，那自然是极好的！在 2004 年 Steve Bird 在 NLTK 中加上了对 Stanford NLP 工具包的支持，通过调用外部的 jar 文件来使用 Stanford NLP 工具包的功能。
&lt;/p&gt;

&lt;p&gt;
从 NLTK 的 commit 历史中可以找到相应的提交记录:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
commit e1372fef56bfb88d02fdb6c0ea88474d5f414a38
Author: Steven Bird &amp;lt;stevenbird1@gmail.com&amp;gt;
Date:   Tue Aug 3 12:20:20 2004 +0000

    added Stanford

    svn/trunk@2088
&lt;/pre&gt;

&lt;p&gt;
现在的 NLTK 中，通过封装提供了 Stanford NLP 中的以下几个功能:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;分词&lt;/li&gt;
&lt;li&gt;词性标注&lt;/li&gt;
&lt;li&gt;命名实体识别&lt;/li&gt;
&lt;li&gt;句法分析，依存句法分析&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgfd01eb6&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgfd01eb6&quot;&gt;安装和配置&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgfd01eb6&quot;&gt;
&lt;p&gt;
NLTK 3.2 之后加入了用于中文分词的 StanfordSegmenter 这个类，作者是知名 NLP 博主 52nlp，见 &lt;a href=&quot;http://www.52nlp.cn/python%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%A4%84%E7%90%86%E5%AE%9E%E8%B7%B5-%E5%9C%A8nltk%E4%B8%AD%E4%BD%BF%E7%94%A8%E6%96%AF%E5%9D%A6%E7%A6%8F%E4%B8%AD%E6%96%87%E5%88%86%E8%AF%8D%E5%99%A8&quot;&gt;相关文章&lt;/a&gt;。而 NLTK 3.1 及之前则只有以下几个类:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;分词: StanfordTokenizer&lt;/li&gt;
&lt;li&gt;词性标注: StanfordPOSTagger&lt;/li&gt;
&lt;li&gt;命名实体识别: StanfordNERTagger&lt;/li&gt;
&lt;li&gt;句法分析: StanfordParser&lt;/li&gt;
&lt;li&gt;依存句法分析: StanfordDependencyParser, StanfordNeuralDependencyParser&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
方便起见，本文以 NLTK 3.2 这个版本来说明如何进行相关的安装和配置，3.1 及之前的版本基本相同。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org7b691ca&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org7b691ca&quot;&gt;注意事项&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org7b691ca&quot;&gt;
&lt;p&gt;
需要注意这么几点:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Stanford NLP 工具包自 2014 年 10 月后(大概是 version 3.5.0)需要 Java 8 及之后的版本，如果出错请检查 Java 版本&lt;/li&gt;
&lt;li&gt;下面的配置过程都以 Stanford NLP 3.6.0 为例，如果使用的是其他版本，请注意替换相应的文件名&lt;/li&gt;
&lt;li&gt;下面的配置过程以 NLTK 3.2 为例，如果使用 NLTK 3.1，需要注意该旧版本中 StanfordSegmenter 未实现，其余大致相同&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
下面的配置过程是针对不同的接口分别讲述各自如何配置，根据来自 NLTK 的源代码，分别是
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;nltk/tokenize/stanford.py&lt;/li&gt;
&lt;li&gt;nltk/tag/stanford.py&lt;/li&gt;
&lt;li&gt;nltk/parse/stanford.py&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
如果不想了解这些细节，可以参考 NLTK 官方 &lt;a href=&quot;https://github.com/nltk/nltk/wiki/Installing-Third-Party-Software#stanford-tagger-ner-tokenizer-and-parser&quot;&gt;wiki 页面&lt;/a&gt;上的内容，但需要注意的是，StanfordSegmenter 和 StanfordNeuralDependencyParser 这两者的配置和其他的都不一样，而 wiki 页面上并未覆盖到这部分内容。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;事实上，也可以完全不进行环境变量设置，但这就需要在每次调用的时候手动指定参数&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2ef10c1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2ef10c1&quot;&gt;StanfordSegmenter&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2ef10c1&quot;&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;从 &lt;a href=&quot;http://nlp.stanford.edu/software/segmenter.html&quot;&gt;http://nlp.stanford.edu/software/segmenter.html&lt;/a&gt; 处下载 &lt;i&gt;stanford-segmenter-2015-12-09.zip&lt;/i&gt; (version 3.6.0)&lt;/li&gt;
&lt;li&gt;将 stanford-segmenter-2015-12-09.zip 解压, 并将解压目录中的 &lt;i&gt;stanford-segmenter-3.6.0.jar&lt;/i&gt; 拷贝为 &lt;i&gt;stanford-segmenter.jar&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
将 &lt;i&gt;stanford-segmenter.jar&lt;/i&gt; 和 &lt;i&gt;slf4j-api.jar&lt;/i&gt; 加入到 CLASSPATH 中去
&lt;/p&gt;

&lt;p&gt;
例:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;STANFORD_SEGMENTER_PATH&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;$HOME/stanford/segmenter&quot;&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;CLASSPATH&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;$CLASSPATH:$STANFORD_SEGMENTER_PATH/stanford-segmenter.jar:$STANFORD_SEGMENTER_PATH/slf4j-api.jar&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
之所以要将 &lt;i&gt;stanford-segmenter.jar&lt;/i&gt; 和 &lt;i&gt;slf4j-api.jar&lt;/i&gt; 加入到 CLASSPATH 中，是因为在 StanfordSegmenter 的实现中显式依赖了这两个文件，并且优先在 CLASSPATH 中寻找这两个文件。如果在 CLASSPATH 中找不到 &lt;i&gt;stanford-segmenter.jar&lt;/i&gt; ，则会在环境变量 STANFORD_SEGMENTER 指定的路径中寻找；同样的，如果找不到 &lt;i&gt;slf4j-api.jar&lt;/i&gt; ，则会在环境变量 SLF4J 指定的路径中寻找。其他几个类也有同样的依赖设置，为了统一管理，可以将所有依赖的 jar 文件都加入到 CLASSPATH 中去，当然分别为不同的 jar 文件设置不同的环境变量也是可以的。
&lt;/p&gt;

&lt;p&gt;
除了设置环境变量，也可以通过函数参数来传入依赖的 jar 文件的准确路径，此时将会忽略环境变量设置。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org739e6d8&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org739e6d8&quot;&gt;StanfordTokenizer&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org739e6d8&quot;&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;从 &lt;a href=&quot;http://nlp.stanford.edu/software/tagger.html&quot;&gt;http://nlp.stanford.edu/software/tagger.html&lt;/a&gt; 中下载 &lt;i&gt;stanford-postagger-full-2015-12-09.zip&lt;/i&gt; (version 3.6.0)&lt;/li&gt;
&lt;li&gt;将 &lt;i&gt;stanford-postagger-full-2015-12-09.zip&lt;/i&gt; 解压&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
将解压目录中的 &lt;i&gt;stanford-postagger.jar&lt;/i&gt; 加入到 CLASSPATH 中，或者设置到环境变量 STANFORD_POSTAGGER 中
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;STANFORD_POSTAGGER_PATH&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;$HOME/stanford/postagger&quot;&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;CLASSPATH&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;$CLASSPATH:$STANFORD_POSTAGGER_PATH/stanford-postagger.jar&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
或
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;STANFORD_POSTAGGER&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;$HOME/stanford/postagger/stanford-postagger.jar&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org60ef4fc&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org60ef4fc&quot;&gt;StanfordNERTagger 和 StanfordPOSTagger&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org60ef4fc&quot;&gt;
&lt;p&gt;
在 NLTK 里，StanfordNERTagger 和 StanfordPOSTagger 都继承自 StanfordTagger ，在设置上有共同之处，因此放到一起来讲一下。
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;从 &lt;a href=&quot;http://nlp.stanford.edu/software/CRF-NER.html&quot;&gt;http://nlp.stanford.edu/software/CRF-NER.html&lt;/a&gt; 处下载 &lt;i&gt;stanford-ner-2015-12-09.zip&lt;/i&gt; (version 3.6.0)&lt;/li&gt;
&lt;li&gt;从 &lt;a href=&quot;http://nlp.stanford.edu/software/tagger.html&quot;&gt;http://nlp.stanford.edu/software/tagger.html&lt;/a&gt; 中下载 &lt;i&gt;stanford-postagger-full-2015-12-09.zip&lt;/i&gt; (version 3.6.0)&lt;/li&gt;
&lt;li&gt;将 &lt;i&gt;stanford-ner-2015-12-09.zip&lt;/i&gt; 和 &lt;i&gt;stanford-postagger-full-2015-12-09.zip&lt;/i&gt; 都解压&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
将解压后目录中的 &lt;i&gt;stanford-ner.jar&lt;/i&gt; 和 &lt;i&gt;stanford-postagger.jar&lt;/i&gt; 加入到 CLASSPATH 中去，和 StanfordTokenizer 不一样，这两个类都只从 CLASSPATH 中寻找对应的 jar 文件(所以为了统一我建议都添加到 CLASSPATH 中去)
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;STANFORD_NER_PATH&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;$HOME/stanford/ner&quot;&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;STANFORD_POSTAGGER_PATH&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;$HOME/stanford/postagger&quot;&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;CLASSPATH&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;$CLASSPATH:$STANFORD_NER_PATH/stanford-ner.jar:$STANFORD_POSTAGGER_PATH/stanford-postagger.jar&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
同时将 &lt;i&gt;stanford-ner-2015-12-09.zip&lt;/i&gt; 解压后目录中的 &lt;i&gt;classifiers&lt;/i&gt; 目录和 &lt;i&gt;stanford-postagger-full-2015-12-09.zip&lt;/i&gt; 解压后目录中的 &lt;i&gt;models&lt;/i&gt; 目录加入到环境变量 STANFORD_MODELS 中去
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;STANFORD_MODELS&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;$STANFORD_NER_PATH/classifiers:$STANFORD_POSTAGGER_PATH/models&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4d4e736&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4d4e736&quot;&gt;StanfordParser, StanfordDependencyParser&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4d4e736&quot;&gt;
&lt;p&gt;
StanfordParser 和 StanfordDependencyParser 都继承自 GenericStanfordParser ，使用 stanford-parser.jar 来提供句法分析功能。
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;从 &lt;a href=&quot;http://nlp.stanford.edu/software/lex-parser.html&quot;&gt;http://nlp.stanford.edu/software/lex-parser.html&lt;/a&gt; 处下载 &lt;i&gt;stanford-parser-full-2015-12-09.zip&lt;/i&gt; (version 3.6.0)&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
将下载的压缩包解压，并将其中的 &lt;i&gt;stanford-parser.jar&lt;/i&gt; 和 &lt;i&gt;stanford-parser-3.6.0-models.jar&lt;/i&gt; (这个在不同版本中名称会不一样) 都加入到 CLASSPATH 中
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;STANFORD_PARSER_PATH&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;$HOME/stanford/parser&quot;&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;CLASSPATH&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;$CLASSPATH:$STANFORD_PARSER_PATH/stanford-parser.jar:$STANFORD_PARSER_PATH/stanford-parser-3.6.0-models.jar&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
或者将 &lt;i&gt;stanford-parser.jar&lt;/i&gt; 加入到环境变量 STANFORD_PARSER 中，将 &lt;i&gt;stanford-parser-3.6.0-models.jar&lt;/i&gt; 加入到环境变量 STANFORD_MODELS 中
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;STANFORD_PARSER&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;$STANFORD_PARSER_PATH/stanford-parser.jar&quot;&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;STANFORD_MODELS&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;$STANFORD_MODELS:$STANFORD_PARSER_PATH/stanford-parser-3.6.0.models.jar&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org26cbf24&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org26cbf24&quot;&gt;StanfordNeuralDependencyParser&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org26cbf24&quot;&gt;
&lt;p&gt;
StanfordNeuralDependencyParser 虽然也继承自 GenericStanfordParser，并且用来进行句法分析，但它使用的 Stanford CoreNLP 中的功能和模型，不依赖 Stanford Parser 这个(子)工具包。
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;从 &lt;a href=&quot;http://stanfordnlp.github.io/CoreNLP/&quot;&gt;http://stanfordnlp.github.io/CoreNLP/&lt;/a&gt; 处下载 &lt;i&gt;stanford-corenlp-full-2015-12-09.zip&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
将下载的压缩包解压，并将其中的 &lt;i&gt;stanford-corenlp-3.6.0.jar&lt;/i&gt; 和 &lt;i&gt;stanford-corenlp-3.6.0-models.jar&lt;/i&gt; 加入到 CLASSPATH 中去
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;STANFORD_CORENLP_PATH&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;$HOME/stanford-corenlp-full-2015-12-09&quot;&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;CLASSPATH&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;$CLASSPATH:$STANFORD_CORENLP_PATH/stanford-corenlp-3.6.0.jar:$STANFORD_CORENLP_PATH/stanford-corenlp-3.6.0-models.jar&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
或者可以更简单地将解压目录设置为环境变量 STANFORD_CORENLP 的值
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;STANFORD_CORENLP&lt;/span&gt;=$&lt;span style=&quot;color: #ffcc66;&quot;&gt;STANFORD_CORENLP_PATH&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge518db9&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge518db9&quot;&gt;基本使用&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge518db9&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org054e3c8&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org054e3c8&quot;&gt;使用 StanfordSegmenter 和 StanfordTokenizer 进行分词&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org054e3c8&quot;&gt;
&lt;p&gt;
StanfordSegmenter 是 52nlp 实现的对 Stanford Segmenter 的封装，用来进行中文分词。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;coding: utf-8&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; nltk.tokenize &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; StanfordSegmenter

&lt;span style=&quot;color: #ffcc66;&quot;&gt;segmenter&lt;/span&gt; = StanfordSegmenter(
    path_to_sihan_corpora_dict=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;/home/linusp/stanford/segmenter/data/&quot;&lt;/span&gt;,
    path_to_model=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;/home/linusp/stanford/segmenter/data/pku.gz&quot;&lt;/span&gt;,
    path_to_dict=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;/home/linusp/stanford/segmenter/data/dict-chris6.ser.gz&quot;&lt;/span&gt;
)
&lt;span style=&quot;color: #ffcc66;&quot;&gt;res&lt;/span&gt; = segmenter.segment(u&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#21271;&amp;#28023;&amp;#24050;&amp;#25104;&amp;#20026;&amp;#20013;&amp;#22269;&amp;#23545;&amp;#22806;&amp;#24320;&amp;#25918;&amp;#20013;&amp;#21319;&amp;#36215;&amp;#30340;&amp;#19968;&amp;#39063;&amp;#26126;&amp;#26143;&quot;&lt;/span&gt;)
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;type&lt;/span&gt;(res)
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; res.encode(&lt;span style=&quot;color: #66cccc;&quot;&gt;'utf-8'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
StanfordSegmenter 的初始化参数说明:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
&lt;i&gt;path_to_jar&lt;/i&gt;: 用来定位 &lt;i&gt;stanford-segmenter.jar&lt;/i&gt; ，在设置了 CLASSPATH 的情况下，该参数可留空
&lt;/p&gt;

&lt;p&gt;
注: 其他所有 Stanford NLP 接口都有 &lt;i&gt;path_to_jar&lt;/i&gt; 这个参数，同样在设置了环境变量的情况下可以留空，后面不再另加说明。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;i&gt;path_to_slf4j&lt;/i&gt;: 用来定位 &lt;i&gt;slf4j-api.jar&lt;/i&gt; ，在设置了 CLASSPATH 或者 SLF4J 这个环境变量的情况下，该参数可留空&lt;/li&gt;
&lt;li&gt;&lt;i&gt;path_to_sihan_corpora_dict&lt;/i&gt;: 设定为 &lt;i&gt;stanford-segmenter-2015-12-09.zip&lt;/i&gt; 解压后目录中的 data 目录，话说这个参数名真是让人摸不着头脑&lt;/li&gt;
&lt;li&gt;&lt;i&gt;path_to_model&lt;/i&gt;: 用来指定用于中文分词的模型，在 &lt;i&gt;stanford-segmenter-2015-12-09&lt;/i&gt; 的 data 目录下，有两个可用模型 &lt;i&gt;pkg.gz&lt;/i&gt; 和 &lt;i&gt;ctb.gz&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
需要注意的是，使用 StanfordSegmenter 进行中文分词后，其返回结果并不是 list ，而是一个字符串，各个汉语词汇在其中被空格分隔开。
&lt;/p&gt;

&lt;p&gt;
StanfordTokenizer 可以用来进行英文的分词，使用起来比较简单
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;coding: utf-8&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; nltk.tokenize &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; StanfordTokenizer

&lt;span style=&quot;color: #ffcc66;&quot;&gt;tokenizer&lt;/span&gt; = StanfordTokenizer()
&lt;span style=&quot;color: #ffcc66;&quot;&gt;sent&lt;/span&gt; = &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Good muffins cost $3.88\nin New York.  Please buy me\ntwo of them.\nThanks.&quot;&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; tokenizer.tokenize(sent)
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org964bac5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org964bac5&quot;&gt;使用 StanfordNERTagger 进行命名实体识别&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org964bac5&quot;&gt;
&lt;p&gt;
所谓命名实体识别，是用来识别并标注文本中的人名、地名、组织机构名等单元，这些单元既是 &quot;命名实体&quot;。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;coding: utf-8&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; nltk.tag &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; StanfordNERTagger

&lt;span style=&quot;color: #ffcc66;&quot;&gt;eng_tagger&lt;/span&gt; = StanfordNERTagger(&lt;span style=&quot;color: #66cccc;&quot;&gt;'english.all.3class.distsim.crf.ser.gz'&lt;/span&gt;)
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; eng_tagger.tag(&lt;span style=&quot;color: #66cccc;&quot;&gt;'Rami Eid is studying at Stony Brook University in NY'&lt;/span&gt;.split())
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
StanfordNERTagger 在初始化时需要指定所使用的模型，在 &lt;i&gt;stanford-ner-2015-12-09.zip&lt;/i&gt; 解压后的 &lt;i&gt;classifiers&lt;/i&gt; 目录中，有几个可用的英语 NER 模型:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
/home/linusp/stanford/ner/classifiers/
├── english.all.3class.distsim.crf.ser.gz
├── english.all.3class.distsim.prop
├── english.conll.4class.distsim.crf.ser.gz
├── english.conll.4class.distsim.prop
├── english.muc.7class.distsim.crf.ser.gz
├── english.muc.7class.distsim.prop
├── example.serialized.ncc.ncc.ser.gz
└── example.serialized.ncc.prop
&lt;/pre&gt;

&lt;p&gt;
如果需要进行中文的命名实体识别，则可以在 &lt;a href=&quot;http://nlp.stanford.edu/software/CRF-NER.shtml&quot;&gt;Stanford Named Entity Recognizer&lt;/a&gt; 页面的 Models 一节找到中文模型的下载链接，下载得到 &lt;i&gt;stanford-chinese-corenlp-2015-12-08-models.jar&lt;/i&gt; ，解压后将 edu/stanford/nlp/models/ner/ 目录下的 chinese.misc.distsim.crf.ser.gz 和 chinese.misc.distsim.prop 复制到模型目录下(&lt;i&gt;stanford-ner-2015-12-09/classifiers&lt;/i&gt;)即可。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;coding: utf-8&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; nltk.tag &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; StanfordNERTagger

&lt;span style=&quot;color: #ffcc66;&quot;&gt;chi_tagger&lt;/span&gt; = StanfordNERTagger(&lt;span style=&quot;color: #66cccc;&quot;&gt;'chinese.misc.distsim.crf.ser.gz'&lt;/span&gt;)
&lt;span style=&quot;color: #ffcc66;&quot;&gt;sent&lt;/span&gt; = u&lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#21271;&amp;#28023; &amp;#24050; &amp;#25104;&amp;#20026; &amp;#20013;&amp;#22269; &amp;#23545;&amp;#22806;&amp;#24320;&amp;#25918; &amp;#20013; &amp;#21319;&amp;#36215; &amp;#30340; &amp;#19968; &amp;#39063; &amp;#26126;&amp;#26143;'&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; word, tag &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt;  chi_tagger.tag(sent.split()):
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; word.encode(&lt;span style=&quot;color: #66cccc;&quot;&gt;'utf-8'&lt;/span&gt;), tag
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org18aa32e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org18aa32e&quot;&gt;使用 StanfordPOSTagger 进行词性标注&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org18aa32e&quot;&gt;
&lt;p&gt;
所谓词性标注，是根据句子中的上下文信息，给句中每个词确定一个最为合适的词性标记，比如动词、名词、人称代词等。
&lt;/p&gt;

&lt;p&gt;
和 StanfordNERTagger 一样，StanfordPOSTagger 需要的输入也是一个已经分好词的句子，下面是一个英文的词性标注实例:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; nltk.tag &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; StanfordPOSTagger

&lt;span style=&quot;color: #ffcc66;&quot;&gt;eng_tagger&lt;/span&gt; = StanfordPOSTagger(&lt;span style=&quot;color: #66cccc;&quot;&gt;'english-bidirectional-distsim.tagger'&lt;/span&gt;)
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; eng_tagger.tag(&lt;span style=&quot;color: #66cccc;&quot;&gt;'What is the airspeed of an unladen swallow ?'&lt;/span&gt;.split())
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
如果之前配置时下载的是 &lt;i&gt;stanford-postagger-full-xxxx-xx-xx.zip&lt;/i&gt; ，在解压后，其中的 models 目录是包含有两个中文模型的，分别是 &lt;i&gt;chinese-distsim.tagger&lt;/i&gt; 和 &lt;i&gt;chinese-nodistsim.tagger&lt;/i&gt; ，可以直接使用。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;coding: utf-8&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; nltk.tag &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; StanfordPOSTagger

&lt;span style=&quot;color: #ffcc66;&quot;&gt;chi_tagger&lt;/span&gt; = StanfordPOSTagger(&lt;span style=&quot;color: #66cccc;&quot;&gt;'chinese-distsim.tagger'&lt;/span&gt;)
&lt;span style=&quot;color: #ffcc66;&quot;&gt;sent&lt;/span&gt; = u&lt;span style=&quot;color: #66cccc;&quot;&gt;'&amp;#21271;&amp;#28023; &amp;#24050; &amp;#25104;&amp;#20026; &amp;#20013;&amp;#22269; &amp;#23545;&amp;#22806;&amp;#24320;&amp;#25918; &amp;#20013; &amp;#21319;&amp;#36215; &amp;#30340; &amp;#19968; &amp;#39063; &amp;#26126;&amp;#26143;'&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; _, word_and_tag &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt;  chi_tagger.tag(sent.split()):
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;word&lt;/span&gt;, &lt;span style=&quot;color: #ffcc66;&quot;&gt;tag&lt;/span&gt; = word_and_tag.split(&lt;span style=&quot;color: #66cccc;&quot;&gt;'#'&lt;/span&gt;)
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; word.encode(&lt;span style=&quot;color: #66cccc;&quot;&gt;'utf-8'&lt;/span&gt;), tag
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这个中文的词性标注输出的结果有点奇怪……
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org52fb103&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org52fb103&quot;&gt;使用 StanfordParser 进行句法分析&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org52fb103&quot;&gt;
&lt;p&gt;
句法分析在分析单个词的词性的基础上，尝试分析词与词之间的关系，并用这种关系来表示句子的结构。实际上，句法结构可以分为两种，一种是短语结构，另一种是依存结构。前者按句子顺序来提取句法结构，后者则按词与词之间的句法关系来提取句子结构。这里说的句法分析得到的是短语结构。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; nltk.parse.stanford &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; StanfordParser

&lt;span style=&quot;color: #ffcc66;&quot;&gt;eng_parser&lt;/span&gt; = StanfordParser(model_path=u&lt;span style=&quot;color: #66cccc;&quot;&gt;'edu/stanford/nlp/models/lexparser/englishPCFG.ser.gz'&lt;/span&gt;)
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;list&lt;/span&gt;(eng_parser.parse(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;the quick brown fox jumps over the lazy dog&quot;&lt;/span&gt;.split()))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
得到的结果是一个 list, 其中的元素是 Tree 类型的，在上面这个例子中，这个 list 的长度是 1 ，调用 Tree 的 draw 方法可以将句法树绘制出来。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/eng_parse_tree.png&quot; alt=&quot;eng_parse_tree.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
要进行中文的句法分析，只要指定好中文的模型就好，可用的中文模型有两个，分别是 'edu/stanford/nlp/models/lexparser/chinesePCFG.ser.gz' 和 'edu/stanford/nlp/models/lexparser/chineseFactored.ser.gz'，依然拿 &quot;_北海 已 成为 中国 对外开放 中 升起 的 一 颗 明星_&quot; 这句话作为例子，得到的句法树如下所示。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/chi_parse_tree.png&quot; alt=&quot;chi_parse_tree.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org20dbdb8&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org20dbdb8&quot;&gt;使用 StanfordDependencyParser 进行依存句法分析&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org20dbdb8&quot;&gt;
&lt;p&gt;
见上一节，依存句法分析得到的是句子的依存结构。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; nltk.parse.stanford &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; StanfordDependencyParser

&lt;span style=&quot;color: #ffcc66;&quot;&gt;eng_parser&lt;/span&gt; = StanfordDependencyParser(model_path=u&lt;span style=&quot;color: #66cccc;&quot;&gt;'edu/stanford/nlp/models/lexparser/englishPCFG.ser.gz'&lt;/span&gt;)
&lt;span style=&quot;color: #ffcc66;&quot;&gt;res&lt;/span&gt; = &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;list&lt;/span&gt;(eng_parser.parse(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;the quick brown fox jumps over the lazy dog&quot;&lt;/span&gt;.split()))
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; row &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; res[0].triples():
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; row
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
绘制出来的依存句法结构如下图所示。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/dep_parse_tree.png&quot; alt=&quot;dep_parse_tree.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
中文的依存句法分析同理，在初始化时使用中文模型即可，不再赘述。
&lt;/p&gt;

&lt;p&gt;
StanfordNeuralDependencyParser 的使用与 StanfordDependencyParser 一样，但是在本人的机器上执行非常耗时，即使是对一些简单句子，所以这里就不略过不讲了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>强大的 Org mode(3): 表格的基本操作及公式、绘图</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/06/03/org-mode-table.html"/>
    <category term="Emacs" scheme="http://www.zmonster.me/categories.html#Emacs"/>
    <id>http://www.zmonster.me/2016/06/03/org-mode-table</id>
    <published>2016-06-03T00:00:00+00:00</published>
    <updated>2016-06-03T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


Org mode 中的表格
表格的创建
表格的基本操作
表格公式
表格绘图

org-plot/gnuplot
With source block


总...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgd207dde&quot;&gt;Org mode 中的表格&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgfec45f4&quot;&gt;表格的创建&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org22e5907&quot;&gt;表格的基本操作&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org700966f&quot;&gt;表格公式&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org95037c7&quot;&gt;表格绘图&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgb471e17&quot;&gt;org-plot/gnuplot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5ac4422&quot;&gt;With source block&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org0ada646&quot;&gt;总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;
本文是《强大的 Org mode》系列的第三篇文章，系列文章如下：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2015/07/12/org-mode-introduction.html&quot;&gt;强大的 Org mode(1): 简单介绍与基本使用 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2015/07/15/org-mode-planning.html&quot;&gt;强大的 Org mode(2): 任务管理 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2016/06/03/org-mode-table.html&quot;&gt;强大的 Org mode(3): 表格的基本操作及公式、绘图 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2018/02/28/org-mode-capture.html&quot;&gt;强大的 Org mode(4): 使用 capture 功能快速记录 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div id=&quot;outline-container-orgd207dde&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgd207dde&quot;&gt;Org mode 中的表格&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgd207dde&quot;&gt;
&lt;p&gt;
Org mode 原生支持表格，这是 rst 或者 markdown 所不具备的特点。一个表格的例子如下所示:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;| Name  | Phone | Age |&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;|-------+-------+-----|&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;| Peter |  1234 |  17 |&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;| Anna  |  4321 |  25 |&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
表格用 &quot;|&quot; 符号作为列分隔符，而在 Org mode 中，如果某一行文字的 &lt;b&gt;第一个非空白符号&lt;/b&gt; 是 &quot;|&quot; 的话，就会被视作是一个表格，而 '-' 符号组成的分隔线之上的部分则被认为是各列的名称(不过列名并不是必须的)。
&lt;/p&gt;

&lt;p&gt;
Org mode 中的表格除了用来展示数据，还支持表格公式，能在表格中原有数据的基础上进行计算；还能直接提供数据给诸如 gnuplot 这样的程序来绘制图像；此外在 source block 中还可以读取指定表格中的数据用于更复杂的计算。
&lt;/p&gt;

&lt;p&gt;
除了表格本身的功能外，基于 Org mode 的日程和任务管理功能，可以对任务完成情况进行定期统计，并将统计结果输出成表格。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgfec45f4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgfec45f4&quot;&gt;表格的创建&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgfec45f4&quot;&gt;
&lt;p&gt;
利用 &quot;第一个非空白符号是 | 的行被视作表格行&quot; 这个特性，手动创建表格也是非常方便的。首先手动完成第一行，确定表格有多少列，然后按下 TAB 键就能自动在下一行插入新一行表格行了，如下图所示。
&lt;/p&gt;


&lt;div id=&quot;orge44e0b6&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-table-create-1.gif&quot; alt=&quot;org-table-create-1.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
当然，一个完整的表格一般是有 header (就是表示列名那一行)的，要有 header 的话就需要 &quot;-&quot; 组成的分隔线，有两种方式可以插入分隔线。
&lt;/p&gt;

&lt;p&gt;
一种办法是新起一行，对齐后输入 &quot;|-&quot; ，即一个列分隔附跟一个连字符，如下所示:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;| &amp;#21333;&amp;#20803;&amp;#26684; | &amp;#21333;&amp;#20803;&amp;#26684; | &amp;#21333;&amp;#20803;&amp;#26684; |&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;|-&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后按 TAB 键，就会补全成为这样的样式了
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #cc99cc;&quot;&gt;| &amp;#21333;&amp;#20803;&amp;#26684; | &amp;#21333;&amp;#20803;&amp;#26684; | &amp;#21333;&amp;#20803;&amp;#26684; |&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;|-------+-------+-------|&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
第二种办法是使用 &quot;C-c -&quot; 这个快捷键来快速插入，如下图所示。
&lt;/p&gt;


&lt;div id=&quot;org8d58290&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-table-create-2.gif&quot; alt=&quot;org-table-create-2.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
除了手动创建表格，还可以通过 &quot;C-c |&quot; 这个快捷键来快速创建指定大小的表格。使用这个快捷键后，会提示输入创建的表格的大小，默认是5x2也就是5列2行的，且其中一行是 header，如下图所示。
&lt;/p&gt;


&lt;div id=&quot;org8414362&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-table-create-3.gif&quot; alt=&quot;org-table-create-3.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
第三种创建方法是直接将 buffer 上已有的数据格式化成表格，比如如果是以逗号(,)分隔的 CSV 格式的数据，可以将其拷贝到当前在编辑的 Org mode 文档中，选中，然后使用 &quot;C-c |&quot; 这个快捷键，就能将其转换成表格形式，如下图所示。
&lt;/p&gt;


&lt;div id=&quot;org3625525&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-table-create-4.gif&quot; alt=&quot;org-table-create-4.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这种方法不会自动插入水平分隔线，所以在完成后，可按自己的需要选择添加或者不添加。
&lt;/p&gt;

&lt;p&gt;
如果数据之间是用空格分隔的，该如何转换呢?选中后使用快捷键&quot;C-u 1 C-c |&quot;即可。
&lt;/p&gt;

&lt;p&gt;
更进一步的，Org mode 提供了 &quot;org-table-import&quot; 这个命令来将外部文件导入到 Org mode 文档中并用它来创建表格，与之对应的，命令 &quot;org-table-export&quot; 则能将Org mode 文档中的表格导出成文件。文件格式可以是 CSV 的，也可以是以制表符(TAB)或空白字符作为分隔符的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org22e5907&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org22e5907&quot;&gt;表格的基本操作&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org22e5907&quot;&gt;
&lt;p&gt;
下表是表格常用操作的快捷键:
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;快捷键&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;TAB&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;切换到下一个单元格，如已是最后一个单元格，则新建一行并跳到该行第一个单元格&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-S-right&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;在当前列前插入一列&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-S-left&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;删除当前列&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-S-down&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;在当前行前插入一行&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-S-up&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;删除当前行&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;C-m&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;移动到下一行，或新建一行&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-up/M-down&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;将当前行往上/下移动&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-left/M-right&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;将当前列往左/右移动&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;C-c `&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;编辑当前单元格&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;C-c C-x C-w&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;剪切某个区域的表格内容&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;C-c C-x C-y&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;拷贝复制的内容到表格&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;S-return&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;当单元格无内容时，将其上方第一个非空内容拷贝过来;否则拷贝当前内容到下一行并随之移动&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;C-c C-c&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;强制表格重新排列&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;C-c ^&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;表格排序&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
这些操作就不再进行图示了，希望读者自行实践。
&lt;/p&gt;

&lt;p&gt;
快捷键注释(以 Linux 系统为例):
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;b&gt;M&lt;/b&gt; 表示 Alt 键&lt;/li&gt;
&lt;li&gt;&lt;b&gt;S&lt;/b&gt; 表示 Shift 键&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C&lt;/b&gt; 表示 Ctrl 键&lt;/li&gt;
&lt;li&gt;up/down/left/right 分别表示 上/下/左/右 四个方向键&lt;/li&gt;
&lt;li&gt;return 表示回车键&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org700966f&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org700966f&quot;&gt;表格公式&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org700966f&quot;&gt;
&lt;p&gt;
Org mode 中的表格的另外一个强大之处，在于它支持公式。在表格区域使用快捷键 &quot;C-c '&quot;，就可以对表格公式进行编辑，完成后公式会显示在表格下方，以 &quot;#+TBLFM:&quot; 开头，如下图所示。
&lt;/p&gt;


&lt;div id=&quot;orgf8e0035&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-table-edit-formula.gif&quot; alt=&quot;org-table-edit-formula.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
使用 &quot;C-c '&quot; 后能在一个独立的、临时的 buffer 中编辑公式，但我们也可以在表格下方手工添加以 &quot;+TBLFM:&quot; 开头的行，然后直接添加公式。
&lt;/p&gt;

&lt;p&gt;
上面这个公式表示将第四列的值设为第二列的值与第三列的值的乘积。在编辑好公式并保存后，将光标移动到公式所在行然后使用 &quot;C-c C-c&quot;，就可以应用公式到表格中。如下图所示:
&lt;/p&gt;


&lt;div id=&quot;orgdb0a7c2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-table-formula-eval.gif&quot; alt=&quot;org-table-formula-eval.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在Org mode的表格公式中，用 &quot;@&quot; 来表示行，用 &quot;$&quot; 来表示列，最简单的，&quot;@3$2&quot; 表示的是第三行第二列的位置。使用快捷键 &quot;C-c }&quot; 可以开启表格的横纵坐标显示——若要关闭的话也是用它。如果是用 &quot;C-c '&quot; 来进行公式编辑，在输入表格位置时，会看到表格上对应的位置会在当时高亮，所以建议用这种方式进行编辑。
&lt;/p&gt;

&lt;p&gt;
如果只给一个坐标，则另一个坐标会被设为&quot;当前行&quot;或者&quot;当前列&quot;，这在批量处理表格内容时会有用。
&lt;/p&gt;

&lt;p&gt;
如果想表示一个区域的话，用 &quot;..&quot; 来表示。
&lt;/p&gt;

&lt;p&gt;
下面这个表示左上角为第二行第一列单元格、右下角为第四行第三列单元格的区域，共包含 9 个单元格。
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org1df168c&quot;&gt;
@2$1..@4$3
&lt;/pre&gt;

&lt;p&gt;
下面这个则表示&quot;当前行&quot;的第一列到第三列的区域:
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org26b9e56&quot;&gt;
$1..$3
&lt;/pre&gt;

&lt;p&gt;
在公式中，可以用 &quot;@#&quot; 表示当前行的行号，用 &quot;$#&quot; 表示当前列的列号，在一些稍复杂点的公式里会有用。
&lt;/p&gt;

&lt;p&gt;
此外，还可以定义常量、变量，或者给某个单元格命名，然后引用它们。假设其名字为 &quot;name&quot;，那么 &quot;$name&quot; 就可以引用它了。常量的定义可以通过 &quot;org-table-formula-constants&quot;  来进行，这样定义的常量是全局的；如果要定义局部的常量，可以在org文件中添加诸如这样的行:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+CONSTANTS: pi=3.14 eps=2.4e-6&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
还可以在当前表格引用其他表格的域，这需要其他表格被命名为某个名字，如&quot;FOO&quot;，我们要在另一个表格中使用其第三行第四列的域，将其值赋给当前表格的第五行第二列，则可以这样写:
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;orgc221a7f&quot;&gt;
@5$2=remote(FOO, @3$4)
&lt;/pre&gt;

&lt;p&gt;
下图将被命名为 &quot;fruit_expend&quot; 的表格的第 6 行第 4 列的数据插入到新表格的第二行第二列中:
&lt;img src=&quot;/assets/img/org-table-formula-example-1.gif&quot; alt=&quot;org-table-formula-example-1.gif&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;
Org mode 的表格公式中，四则运算符都能正常使用，不过略有不同——乘号 &quot;*&quot; 的优先级要比除号 &quot;/&quot; 要高，因此
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;orga9a55bb&quot;&gt;
$3 / $2 * $1
&lt;/pre&gt;

&lt;p&gt;
会被解释为
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;orgda6c6e6&quot;&gt;
$3 / ($2 * $1)
&lt;/pre&gt;

&lt;p&gt;
Org mode 默认使用的是 Emacs 中自带的 Calc 这个 package 来进行计算，而 Calc 中提供了相当丰富的计算方法，这里列举一二:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;基础算术方法: abs, sign, inv, sqrt, min, max，详见 &lt;a href=&quot;http://www.gnu.org/software/emacs/manual/html_mono/calc.html#Arithmetic&quot;&gt;Arithmetic Functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;对数方法: ln, exp, log，详见 &lt;a href=&quot;http://www.gnu.org/software/emacs/manual/html_mono/calc.html#Logarithmic-Functions&quot;&gt;Logarithmic Functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;三角函数: sin, cos, tahn，详见 &lt;a href=&quot;http://www.gnu.org/software/emacs/manual/html_mono/calc.html#Trigonometric-and-Hyperbolic-Functions&quot;&gt;Trigonometric/Hyperbolic Functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;随机数方法: random&lt;/li&gt;
&lt;li&gt;向量/矩阵方法: vunion, vint, vsum, vmean, vmax, vmin, vmedian，详见 &lt;a href=&quot;http://www.gnu.org/software/emacs/manual/html_mono/calc.html#Matrix-Functions&quot;&gt;Vector/Matrix Functions&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
Calc 的内容比较多，这里不做深入展开，有需要的话可以参考 &lt;a href=&quot;http://www.gnu.org/software/emacs/manual/html_mono/calc.html&quot;&gt;GNU Emacs Calc Manual&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
此外，表格公式还能以 Emacs Lisp 的形式来进行编写，不过要在这种形式的公式前加上单引号 &quot;'&quot;，才能正确求值。在 Emacs Lisp 形式的公式表达式中，传入的参数会被当作字符串，所有需要用格式化选项 &quot;N&quot; 来指明参数类型都是数值。如下图，在不加格式化选项时，公式计算出错，加上 &quot;;N&quot; 后才得到了正确的结果。
&lt;/p&gt;


&lt;div id=&quot;org80f657b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-table-formula-with-lisp.gif&quot; alt=&quot;org-table-formula-with-lisp.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
所有的格式化选项，必须通过分号 &quot;;&quot; 和公式进行分隔并跟随在公式后面，可用的选项有:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;p: 设置计算精度&lt;/li&gt;
&lt;li&gt;n/s/e/f: 设置结果的输出格式
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;n3: 输出结果为3位有效数字(1.45)&lt;/li&gt;
&lt;li&gt;s3: 输出结果为科学计数法，3位有效数字(1.45e0)&lt;/li&gt;
&lt;li&gt;e3: 输出结果为工程计数法，3位有效数字(0.145e1)&lt;/li&gt;
&lt;li&gt;f3: 输出结果精确至小数点后3位&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;D/R: 计算时使用角度制还是弧度制(如三角函数)&lt;/li&gt;
&lt;li&gt;F/S: 分数还是符号(当为 S 时，若结果不为整数，则显示式子本身，如: sqrt(6))&lt;/li&gt;
&lt;li&gt;T/t: 时间计算，要求用于计算的值是&quot;HH:MM[:SS]&quot;的形式，当使用 T 时，输出结果是 &quot;HH:MM:SS&quot; 形式；使用 &quot;t&quot; 时，结果显示为一个数值，默认情况下单位是小时，可以通过变量 org-table-duration-custome-format 来设置&lt;/li&gt;
&lt;li&gt;E: 不使用时，所有空白单元格都会被跳过，不会包含在计算过程中;当使用时，如果还使用了 N ，则用 &quot;0&quot; 填充；否则，在普通公式中，用 &quot;nan&quot; 填充，在 emacs lisp 公式中，用空字符串填充&lt;/li&gt;
&lt;li&gt;N: 使用时，将所有域的值视为数字，对于非数值型，用 0 替代&lt;/li&gt;
&lt;li&gt;L: 只用于 emacs lisp 公式，后续&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
如果需要对表格公式的求值进行调试，可以通过快捷键&quot;C-c {&quot;来开启调试模式(或者关闭它)。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org95037c7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org95037c7&quot;&gt;表格绘图&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org95037c7&quot;&gt;
&lt;p&gt;
使用 Org mode 文档中的表格数据进行绘图有两种方式，一种是使用 Org mode 提供的 &quot;org-plot/gnuplot&quot; 命令直接绘制图像，另外一种是通过在 source block 中读取表格数据来绘图。前者胜在方便快捷，但需要对 gnuplot 有一定的了解；后者胜在灵活，可以选用自己擅长的可视化方法，而且可以绘制复杂的图形。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb471e17&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb471e17&quot;&gt;org-plot/gnuplot&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb471e17&quot;&gt;
&lt;p&gt;
第一种方法依赖 gnuplot 这个外部绘图工具，以及 gnuplot-mode 这个 Emacs 插件。
&lt;/p&gt;

&lt;p&gt;
在依赖满足的情况下，只需要在表格上方添加 &quot;#+PLOT:&quot;， 然后在后面填写要传递给 gnuplot 的参数即可:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+PLOT: title:&quot;Citas&quot; ind:1 deps:(3) type:2d with:histograms set:&quot;yrange [0:]&quot; &lt;a href=&quot;file:&amp;quot;./plot.png&quot;&gt;file:&quot;./plot.png&lt;/a&gt;&quot;&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;| Sede      | Max cites | H-index |&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;|-----------+-----------+---------|&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;| Chile     |    257.72 |   21.39 |&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;| Leeds     |    165.77 |   19.68 |&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;| Sao Paolo |     71.00 |   11.50 |&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;| Stockholm |    134.19 |   14.33 |&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;| Morelia   |    257.56 |   17.67 |&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
得到的结果如下图所示：
&lt;/p&gt;


&lt;div id=&quot;orgac87e31&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-plot-example.png&quot; alt=&quot;org-plot-example.png&quot; width=&quot;80%&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
使用这种 Org mode 自带的绘图方式，除了简便以外，还有一个好处就是表格的 header 能被正确地识别做列名，并在图中用来作为各列数据的 label。
&lt;/p&gt;

&lt;p&gt;
以下是可在 &quot;#+PLOT:&quot; 后面设置的绘图参数
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;title: 设置图像的标题&lt;/li&gt;
&lt;li&gt;ind: 用于绘制 x 轴的表中的列&lt;/li&gt;
&lt;li&gt;deps: 除 x 轴以外的其他数据在表中的列，若有多列，用括号括起，如 &quot;deps:(2, 3)&quot;&lt;/li&gt;
&lt;li&gt;type: 2d, 3d, or grid&lt;/li&gt;
&lt;li&gt;with: 设置绘制类型，如 lines, points, boxes, impulses, histograms&lt;/li&gt;
&lt;li&gt;file: 如果需要将绘制的图像保存为文件，则使用该属性&lt;/li&gt;
&lt;li&gt;labels: 给定 deps 的标签，默认为表格 header&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
详见: &lt;a href=&quot;http://orgmode.org/worg/org-tutorials/org-plot.html&quot;&gt;Plotting tables in Org-Mode using org-plot&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5ac4422&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5ac4422&quot;&gt;With source block&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5ac4422&quot;&gt;
&lt;p&gt;
Org mode 有一个非常强大的功能就是可以插入各种语言的 source block，并且能去执行 source block 里的代码，接着将结果插入到当前的 Org mode 文档中来。
&lt;/p&gt;

&lt;p&gt;
下图展示了在 Org mode 中插入 C++ 的 source block 并执行得到结果的过程:
&lt;/p&gt;


&lt;div id=&quot;org90de954&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-src-block-evaluate.gif&quot; alt=&quot;org-src-block-evaluate.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
同时，Org mode 中的表格数据是可以作为变量传递到 source block 中的，如下图所示:
&lt;/p&gt;


&lt;div id=&quot;org114194c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-src-block-read-tbl.gif&quot; alt=&quot;org-src-block-read-tbl.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
如上图所示，要将表格数据传递给 source block ，需要两个步骤
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;用 &quot;#+NAME&quot; 将表格命名为 &quot;citas-data&quot;&lt;/li&gt;
&lt;li&gt;在 source block 的选项中，用 &quot;:var tbl_data=citas-data&quot; 将表格数据赋值给变量 &quot;tbl_data&quot;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
对于下面这个表格，我可以可以用这个方法将数据传递给 source block ，然后用 matplotlib 来绘制图像。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+NAME: citas-data&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;| Sede      | Max cites | H-index |&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;|-----------+-----------+---------|&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;| Chile     |    257.72 |   21.39 |&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;| Leeds     |    165.77 |   19.68 |&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;| Sao Paolo |     71.00 |   11.50 |&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;| Stockholm |    134.19 |   14.33 |&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc;&quot;&gt;| Morelia   |    257.56 |   17.67 |&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
相应的 source block 为
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+BEGIN_SRC python :results file :var tbl_data=citas-data filename=&quot;./org-plot-example2.png&quot;&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; numpy &lt;/span&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; np&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; matplotlib&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; matplotlib.pyplot &lt;/span&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; plt&lt;/span&gt;

&lt;span style=&quot;color: #f99157;&quot;&gt;plt.style.use(&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;'ggplot'&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt;)&lt;/span&gt;


&lt;span style=&quot;color: #ffcc66;&quot;&gt;bar_names&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; = [row[0] &lt;/span&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; row &lt;/span&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; tbl_data]&lt;/span&gt;
&lt;span style=&quot;color: #ffcc66;&quot;&gt;h_index&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; = [row[2] &lt;/span&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; row &lt;/span&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; tbl_data]&lt;/span&gt;
&lt;span style=&quot;color: #ffcc66;&quot;&gt;ind&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; = np.arange(&lt;/span&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt;(tbl_data))&lt;/span&gt;
&lt;span style=&quot;color: #ffcc66;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; = 0.5&lt;/span&gt;

&lt;span style=&quot;color: #f99157;&quot;&gt;plt.bar(ind, h_index, width)&lt;/span&gt;
&lt;span style=&quot;color: #f99157;&quot;&gt;plt.title(&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;'Citas'&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color: #f99157;&quot;&gt;plt.xlabel(&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;'Sede'&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color: #f99157;&quot;&gt;plt.ylabel(&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;'H-index'&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color: #f99157;&quot;&gt;plt.xticks(ind + width/2., bar_names)&lt;/span&gt;

&lt;span style=&quot;color: #f99157;&quot;&gt;plt.savefig(filename)&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt;(filename)&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+END_SRC&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
执行后得到的结果为:
&lt;/p&gt;


&lt;div id=&quot;org3e8ecab&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-plot-example2.png&quot; alt=&quot;org-plot-example2.png&quot; width=&quot;80%&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org0ada646&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org0ada646&quot;&gt;总结&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org0ada646&quot;&gt;
&lt;p&gt;
同 Org mode 中的其他功能一样，表格能很好地和 Org mode 的其他功能一起工作，利用 Org mode ，能够很容易地进行可重现研究(Reproducible Research)，数据、处理过程、结果展示，都可以在 Org mode 中一起呵成，而且比起 IPython Notebook，Org mode 拥有丰富得多的功能，表格就是其中一例。
&lt;/p&gt;

&lt;p&gt;
以数据分析为例，工作流程可以是这样的:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;将收集到的数据整理成 CSV 格式(比如从 excel 中导出)&lt;/li&gt;
&lt;li&gt;在 Org mode 中将 CSV 格式的数据导入并创建一个表格，为其命名&lt;/li&gt;
&lt;li&gt;新建一个 Python 的 source block, 对数据进行清洗、去重，并将结果输出，在 Org mode 中产生一个新的表格，同时将新的表格导出为 CSV 备份&lt;/li&gt;
&lt;li&gt;对清洗后的数据进行分析，新建一个 Python 的 source block，使用 matplotlib 将分析结果绘制成图像并在 Org mode 文档中展示&lt;/li&gt;
&lt;li&gt;对分析结果进行归纳总结&lt;/li&gt;
&lt;li&gt;根据需要，使用 Org mode 自带的功能将文档导出为 HTML 或 PDF 格式，以供他人阅读&lt;/li&gt;
&lt;li&gt;(可选)将该 Org mode 文档分享给其他 Org mode 用户&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
Org mode 真的是太棒啦！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>使用 Keras 实现简单的 Sequence to Sequence 模型</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/05/29/sequence_to_sequence_with_keras.html"/>
    <category term="论文笔记" scheme="http://www.zmonster.me/categories.html#论文笔记"/>
    <id>http://www.zmonster.me/2016/05/29/sequence_to_sequence_with_keras</id>
    <published>2016-05-29T00:00:00+00:00</published>
    <updated>2016-05-29T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


Sequence to Sequence Model
Keras 简介
Pig Latin: Sequence to Sequence 实践




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org3363afb&quot;&gt;Sequence to Sequence Model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5f25482&quot;&gt;Keras 简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org321a34e&quot;&gt;Pig Latin: Sequence to Sequence 实践&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;hr /&gt;

&lt;div id=&quot;outline-container-org3363afb&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3363afb&quot;&gt;Sequence to Sequence Model&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3363afb&quot;&gt;
&lt;p&gt;
Sequence to Sequence 模型是近几年来比较热门的一个基于 RNN 的模型，现在被广泛运用于机器翻译、自动问答系统等领域，并且取得了不错的效果。该模型最早在 2014 年被 Cho 和 Sutskever 先后提出，前者将该模型命名为 &quot;Encoder-Decoder Model&quot;，后者将其命名为 &quot;Sequence to Sequence Model&quot;，两者有一些细节上的差异，但总体思想大致相同，所以后文不做区分，并简称为 &quot;seq2seq 模型&quot;。
&lt;/p&gt;

&lt;p&gt;
seq2seq 模型利用了 RNN 对时序序列天然的处理能力，试图建立一个能 &lt;b&gt;直接处理变长输入与变长输出&lt;/b&gt; 的模型——机器翻译是一个非常好的例子。传统的机器翻译系统当然也能根据变长的输入得到变长的输出，但这种处理能力是通过很多零碎的设置、规则和技巧来达成的，而 seq2seq 模型不一样，它结构简单而自然，对变长输入和变长输出的支持也是简单直接的。来看一下它的结构:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/seq2seq.png&quot; alt=&quot;seq2seq.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
上图是一个已经在时间维度上展开(unroll)的 seq2seq 模型，其输入序列是 &quot;ABC&quot; ，其输出序列是 &quot;WXYZ&quot; 。模型由两个 RNN 组成：第一个 RNN 接受输入，并将其表示成一个语义向量，在上面这个例子中，A、B、C 和表示序列结束的特殊符号 &amp;lt;EOS&amp;gt; 依次输入，并在读取到 &amp;lt;EOS&amp;gt; 时终止接收输入，并输出一个向量作为 &quot;ABC&quot; 这个输入向量的语义表示，因此也被称作 &quot;Encoder&quot;；第二个 RNN 接受第一个 RNN 产生的输入序列的语义向量，然后从中产生出输出序列，因此也被称作 &quot;Decoder&quot;。
&lt;/p&gt;

&lt;p&gt;
更多的细节见我的两篇论文阅读笔记:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://linusp.github.io/notes/sequence_to_sequence_learning.html&quot;&gt;&quot;Sequence to Sequence Learning with Neural Networks&quot; 阅读笔记&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://linusp.github.io/notes/phrase_representation_using_rnn_encoder_decoder.html&quot;&gt;&quot;Learning Phrase Representation using RNN Encoder-Decoder&quot; 笔记&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5f25482&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org5f25482&quot;&gt;Keras 简介&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org5f25482&quot;&gt;
&lt;p&gt;
Keras 是一个 Python 的深度学习框架，它提供一些深度学习方法的高层抽象，后端则被设计成可切换式的(目前支持 Theano 和 TensorFlow)。4 月份 Keras 发布了 1.0 版本，意味着 Keras 的基础特性已经基本稳定下来，不用担心其中的方法会发生剧烈的变化了。
&lt;/p&gt;

&lt;p&gt;
(注: 因为发布 1.0 版本时间还比较短，网上的一些例子有不少还使用的旧版本的方法，建议多多查阅文档)
&lt;/p&gt;

&lt;p&gt;
在 Keras 中实现神经网络模型的方法很简单，首先实例化一个 &quot;Sequential&quot; 类型的模型，然后往其中添加不同类型的 layer 就可以了。比如要实现一个三层的 MLP，可以这样:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; keras.models &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; Sequential
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; keras.layers &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; Dense

&lt;span style=&quot;color: #ffcc66;&quot;&gt;model&lt;/span&gt; = Sequential()
model.add(Dense(input_dim=4, output_dim=9, activation=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;relu&quot;&lt;/span&gt;))
model.add(Dense(output_dim=3, activation=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;softmax&quot;&lt;/span&gt;))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
其中的 &quot;Dense&quot; 是经典的全连接层(在 Caffe 中被称为 InnerProduct)。每个网络层的输入、输出参数和激活函数都可以方便地直接设置。
&lt;/p&gt;

&lt;p&gt;
另外，由于目前使用的后端 Theano 和 TensorFlow 都是基于符号计算的，上述模型定义后只是产生了一个符号计算的图，并不能直接用来训练和识别，所以需要进行一次转换，调用 &quot;Sequential&quot; 的 compile 方法即可:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;model.&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;compile&lt;/span&gt;(loss=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;categorical_crossentropy&quot;&lt;/span&gt;, optimizer=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;sgd&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
compile 时需要设定训练时的目标函数和优化方法，而 Keras 中已经实现了目前常用的目标函数和优化方法，详情见:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://keras.io/objectives/&quot;&gt;Keras Document: Objectives&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://keras.io/optimizers/&quot;&gt;Keras Document: Optimizers&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
训练时则要求数据是 Numpy 的多维数组形式，保证这一点的情况下使用 &quot;Sequential&quot; 的 &quot;fit&quot; 方法即可，如:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;model.fit(IRIS_X, IRIS_Y, nb_epoch=300)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
如果需要进行交叉验证，不用自己手工去分割训练数据，只需要使用 &quot;fit&quot; 方法的 &quot;validation_split&quot; 参数即可，其值应为 0-1 的浮点数，表示将训练数据用于交叉验证的比例，如:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;model.fit(IRIS_X, IRIS_Y, nb_epoch=300, validation_split=0.1)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
训练过程中会将 loss 打印出来，方便了解模型训练情况:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
Epoch 1/100
1024000/1024000 [==============================] - 725s - loss: 0.7274 - val_loss: 0.6810
Epoch 2/100
1024000/1024000 [==============================] - 725s - loss: 0.6770 - val_loss: 0.6711
Epoch 3/100
1024000/1024000 [==============================] - 723s - loss: 0.6723 - val_loss: 0.6680
&lt;/pre&gt;

&lt;p&gt;
在 Keras 中也提供模型的持久化方法，通过 &quot;Sequential.to_json&quot; 方法可以将模型结构保存为 json 然后写入到文件中，通过 &quot;Sequential.save_weights&quot; 方法可以直接将模型参数写入文件，结合这两者就可以将一个模型完整地保存下来:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;save_model_to_file&lt;/span&gt;(model, struct_file, weights_file):
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;save model structure&lt;/span&gt;
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;model_struct&lt;/span&gt; = model.to_json()
    &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;open&lt;/span&gt;(struct_file, &lt;span style=&quot;color: #66cccc;&quot;&gt;'w'&lt;/span&gt;).write(model_struct)

    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;save model weights&lt;/span&gt;
    model.save_weights(weights_file, overwrite=&lt;span style=&quot;color: #6699cc;&quot;&gt;True&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
对于保存下来的模型，当然也有对应的方法来进行读取:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; keras.models &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; model_from_json

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;load_model&lt;/span&gt;(struct_file, weights_file):
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;model&lt;/span&gt; = model_from_json(&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;open&lt;/span&gt;(struct_file, &lt;span style=&quot;color: #66cccc;&quot;&gt;'r'&lt;/span&gt;).read())
    model.&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;compile&lt;/span&gt;(loss=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;categorical_crossentropy&quot;&lt;/span&gt;, optimizer=&lt;span style=&quot;color: #66cccc;&quot;&gt;'sgd'&lt;/span&gt;)
    model.load_weights(weights_file)

    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; model
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org321a34e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org321a34e&quot;&gt;Pig Latin: Sequence to Sequence 实践&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org321a34e&quot;&gt;
&lt;p&gt;
Pig Latin 的一种翻译叫做 “儿童黑话”，罗嗦一点的意译是 “故意颠倒英语字母顺序拼凑而成的黑话”，它有很多种变种规则，这里只取其原始的、最简单的两条规则:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
如果单词起始的字母是 元音 ，那么在单词后面添加一个 'yay'
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
'other' -&amp;gt; 'otheryay'
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
如果单词起始的字母是 辅音 ，那么将起始到第一个元音之前所有的辅音字母从单词首部挪到尾部，然后添加一个 'ay'
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
'book' -&amp;gt; 'ookbay'
&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
Pig Latin 是一个典型的输入和输出都是变长序列的问题，我们通过它来了解一下基于 Keras 的简单 seq2seq 模型。
&lt;/p&gt;

&lt;p&gt;
首先我们需要准备训练数据，在这个问题中，由于规则是确定的，我们可以来生成大量的数据，如下所示，简单几行代码就可以啦:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; itertools &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; dropwhile

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;is_vowel&lt;/span&gt;(char):
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; char &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; (&lt;span style=&quot;color: #66cccc;&quot;&gt;'a'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'e'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'i'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'o'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'u'&lt;/span&gt;)

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;is_consonant&lt;/span&gt;(char):
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;not&lt;/span&gt; is_vowel(char)

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;pig_latin&lt;/span&gt;(word):
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; is_vowel(word[0]):
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; word + &lt;span style=&quot;color: #66cccc;&quot;&gt;'yay'&lt;/span&gt;
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;else&lt;/span&gt;:
        &lt;span style=&quot;color: #ffcc66;&quot;&gt;remain&lt;/span&gt; = &lt;span style=&quot;color: #66cccc;&quot;&gt;''&lt;/span&gt;.join(dropwhile(is_consonant, word))
        &lt;span style=&quot;color: #ffcc66;&quot;&gt;removed&lt;/span&gt; = word[:&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;len&lt;/span&gt;(word)-&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;len&lt;/span&gt;(remain)]
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; remain + removed + &lt;span style=&quot;color: #66cccc;&quot;&gt;'ay'&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后需要实现一个简单的 seq2seq 模型
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; keras.models &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; Sequential
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; keras.layers.recurrent &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; LSTM
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; keras.layers.wrappers &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; TimeDistributed
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; keras.layers.core &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; Dense, RepeatVector

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;build_model&lt;/span&gt;(input_size, max_out_seq_len, hidden_size):
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;model&lt;/span&gt; = Sequential()
    model.add(LSTM(input_dim=input_size, output_dim=hidden_size, return_sequences=&lt;span style=&quot;color: #6699cc;&quot;&gt;False&lt;/span&gt;))
    model.add(Dense(hidden_size, activation=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;relu&quot;&lt;/span&gt;))
    model.add(RepeatVector(max_out_seq_len))
    model.add(LSTM(hidden_size, return_sequences=&lt;span style=&quot;color: #6699cc;&quot;&gt;True&lt;/span&gt;))
    model.add(TimeDistributed(Dense(output_dim=input_size, activation=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;linear&quot;&lt;/span&gt;)))
    model.&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;compile&lt;/span&gt;(loss=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;mse&quot;&lt;/span&gt;, optimizer=&lt;span style=&quot;color: #66cccc;&quot;&gt;'adam'&lt;/span&gt;)

    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; model
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
对上述代码作一点解释:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Encoder(即第一个 LSTM) 只在序列结束时输出一个语义向量，所以其 &quot;return_sequences&quot; 参数设置为 &quot;False&quot;&lt;/li&gt;
&lt;li&gt;Decoder(即第二个 LSTM) 需要在每一个 time step 都输出，所以其 &quot;return_sequences&quot; 参数设置为 &quot;True&quot;&lt;/li&gt;
&lt;li&gt;使用 &quot;RepeatVector&quot; 将 Encoder 的输出(最后一个 time step)复制 N 份作为 Decoder 的 N 次输入&lt;/li&gt;
&lt;li&gt;TimeDistributed 是为了保证 Dense 和 Decoder 之间的一致，可以不用太关心&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
之所以说是 &quot;简单的 seq2seq 模型&quot;，就在于第 3 点其实并不符合两篇论文的模型要求，不过要将 Decoder 的每一个时刻的输出作为下一个时刻的输入，会麻烦很多，所以这里对其进行简化，但用来处理 Pig Latin 这样的简单问题，这种简化问题是不大的。
&lt;/p&gt;

&lt;p&gt;
另外，虽然 seq2seq 模型在理论上是能学习 &quot;变长输入序列-变长输出序列&quot; 的映射关系，但在实际训练中，Keras 的模型要求数据以 Numpy 的多维数组形式传入，这就要求训练数据中每一条数据的大小都必须是一样的。针对这个问题，现在的常规做法是设定一个最大长度，对于长度不足的输入以及输出序列，用特殊的符号进行填充，使所有输入序列的长度保持一致(所有输出序列长度也一致)。
&lt;/p&gt;

&lt;p&gt;
在 Pig Latin 这个问题上，用收集的 2043 个长度在 3-6 的常用英文单词作为原始数据，去除其中包含非 a-z 的字母的单词，最后得到了 2013 个有效单词。然后根据的规则将这些单词改写为 Pig Latin 形式的单词，作为对应的输出。然后在单词前都添加开始符 BEGIN_SYMBOL、在单词后都添加结束符 END_SYMBOL，并用 END_SYMBOL 填充 使其长度为 15 ，并将每一个字符用 one-hot 形式进行向量化(向量化时用于填充的空白符用全 0 向量表示)，最后得到大小都为 2013x10x28 的输入和输出。
&lt;/p&gt;

&lt;p&gt;
训练的话，batch_size 设置为 128, 在 100 个 epoch 后模型收敛到了一个令人满意的程度。
&lt;/p&gt;

&lt;p&gt;
在一些训练集之外的数据上，能看到网络给出了正确的结果:
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
ok -&amp;gt; okyay
sin -&amp;gt; insay
cos -&amp;gt; oscay
master -&amp;gt; astermay
hanting -&amp;gt; antinghay
&lt;/pre&gt;

&lt;p&gt;
当然，也有一些反例:
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
dddodd -&amp;gt; oddddray
mxnet -&amp;gt; inetlay
zzzm -&amp;gt; omhmay
&lt;/pre&gt;

&lt;p&gt;
但是无论结果错误程度如何，能看到结果总是以 'ay' 结尾的！
&lt;/p&gt;

&lt;p&gt;
完整代码见: &lt;a href=&quot;https://github.com/Linusp/soph/blob/master/demos/pig_latin.py&quot;&gt;soph/demos/pig_latin.py&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>2016 年第一季度总结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/05/04/2016-q1-summary.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2016/05/04/2016-q1-summary</id>
    <published>2016-05-04T00:00:00+00:00</published>
    <updated>2016-05-04T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


计划及总结

生活方面的计划
专业能力方面的计划
个人修养方面的计划


计划之外




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;计划及总结&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;生活方面的计划&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;专业能力方面的计划&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;个人修养方面的计划&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;计划之外&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;hr  /&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;计划及总结&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline2&quot;&gt;生活方面的计划&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
计划内容有:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;每周两次走路上下班，目的是保持良好的身体和精神状态&lt;/li&gt;
&lt;li&gt;每两周参加一次活动，目的是保持与人交流&lt;/li&gt;
&lt;li&gt;每周末出门，目的是保持心灵的敏锐&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
走路上下班这个事情坚持的蛮好的，那个时候天气还冷，有太阳和风的时候走一走非常舒服，走在路上观察迎面走来的人也蛮有趣的。不过进入 4 月后就没怎么走了，天气渐暖，计划买一辆自行车。
&lt;/p&gt;

&lt;p&gt;
活动确实也没少参加，不过每两周一次大概没能做到。比较遗憾的是，除了集智的活动，其他的活动人都比较多，互相之间的交流讨论比较少，渐渐对这些活动有些厌烦。倒是自己现在在一些问题上钻进去有了一些系统的看法，估摸着也许可以在集智里面由我来发起一次活动。
&lt;/p&gt;

&lt;p&gt;
至于每周末出门这个说法，除开出门参加活动，基本没怎么执行过，以后也不用再去执行了吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline3&quot;&gt;专业能力方面的计划&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
计划内容有:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;了解 &quot;产品-后端-前端-移动端&quot; 整个产品开发链中的技术&lt;/li&gt;
&lt;li&gt;掌握 Numpy、Pandas、Theano 这些强力工具&lt;/li&gt;
&lt;li&gt;学习完 《Deep Learning Tutorials》，能应用当前的一些 DL 技术解决一些应用问题&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
第一点被我直接放弃，并且在 2016 年的其他时间也不再准备涉及。随着自己在阅读和 DL 方面花的时间越来越多，已经没有精力再去了解这些自己不喜欢也没什么兴趣的技术栈。业余时间也还会看看，但都是看看一些基础的东西而已了。
&lt;/p&gt;

&lt;p&gt;
Numpy、Pandas 已经在日常的工作中用起来了，确实是对工作效率和幸福感有提升的。Theano 的话因为一直没什么实际需求，因此在上面没太花时间，不过近来已经开始尝试用来做一些练习，比如我的 &lt;a href=&quot;https://github.com/Linusp/connections&quot;&gt;connections 项目&lt;/a&gt;和 &lt;a href=&quot;https://github.com/Linusp/thea&quot;&gt;thea 项目&lt;/a&gt; —— 虽然说在这两个项目中用上 Theano 的时间是不在第一季度的范围内的。至于《Deep Learning Tutorials》，也没有去看 —— 一个原因是我觉得其中的代码实现给我造成的困惑很多，其中一些 Theano 的用法直到最近自己去练习了之后才理解。
&lt;/p&gt;

&lt;p&gt;
第一季度在机器学习这一块并没有太多进展(不过第二季度有)；数学方面的话把《线性代数及其应用》阅读了一半，不过各章节后面的练习题做得少。至于说第二季度想要完成概率论和统计学的学习，目前看来是够呛。
&lt;/p&gt;

&lt;p&gt;
总之第二季度大概会做这样一些事情吧:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;系统学习 Theano&lt;/li&gt;
&lt;li&gt;掌握一些 DL 的框架的使用，目前的目标是 Keras，而且已经用 Keras 做了一些事情了，见 &lt;a href=&quot;https://github.com/Linusp/soph&quot;&gt;Soph 项目&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;系统掌握 RNN 的相关知识，包括其理论及历史发展概况，后面可能会专门写一个 RNN 的系列文章&lt;/li&gt;
&lt;li&gt;完成线性代数的学习&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline4&quot;&gt;个人修养方面的计划&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
计划内容有:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;坚持每日阅读&lt;/li&gt;
&lt;li&gt;坚持写日记&lt;/li&gt;
&lt;li&gt;坚持每周进行非日记写作&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
阅读方面在第一季度做得不太好，唯一读完的大概是吕思哲的《中国通史》，后面的文化史有意思一点，前半部分的政治史 &quot;直相斫书耳&quot;，只觉枯燥无聊。
&lt;/p&gt;

&lt;p&gt;
日记有一阵没一阵的写，要求每日都写怕是有点困难，毕竟不是每天都有事可写的。至于非日记写作，唉，暂时先从计划表里挪走吧。
&lt;/p&gt;

&lt;p&gt;
第二季度的话，目前的阅读状况比较良好，读完了《中国古代神话研究》、《中国哲学简史》、《中国散文五十年》几本书，尤其惊喜的是《中国古代神话研究》，让我对古代神话有了系统性的认识 —— 以前虽然读过一些阐释《山海经》的书，但都着眼于从一些特定的方面，比如地理和历法，层次较深对我来说有点困难，而这本书则将散落于《山海经》、《淮南子》等各处中的相关记录串联了起来并从中发掘出了清晰的脉络，对我来说意义重大。这个季度会把更多的重心往神话学方面偏移，估计会打破我之前下的 &quot;偿还完阅读债务前不再购买新书&quot; 的决定了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline5&quot;&gt;计划之外&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;认识了一些有趣的朋友&lt;/li&gt;
&lt;li&gt;读了大量 paper (相对以往)&lt;/li&gt;
&lt;li&gt;吃了好多面&lt;/li&gt;
&lt;li&gt;大概又长胖了&lt;/li&gt;
&lt;li&gt;炉石 AFK&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
(完)
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>文本相似度量方法(2): LCS 和编辑距离</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/03/31/text-similarity-character-based-1.html"/>
    <category term="NLP" scheme="http://www.zmonster.me/categories.html#NLP"/>
    <id>http://www.zmonster.me/2016/03/31/text-similarity-character-based-1</id>
    <published>2016-03-31T00:00:00+00:00</published>
    <updated>2016-03-31T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


最长公共子序列

问题定义
求解方法
数学表示与相似度量


编辑距离

所谓编辑距离
求解方法
从编辑距离到相似度量


一点看法




本文是《文本...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org1b0e74a&quot;&gt;最长公共子序列&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org9e2d67b&quot;&gt;问题定义&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org18f7859&quot;&gt;求解方法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8809000&quot;&gt;数学表示与相似度量&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge053564&quot;&gt;编辑距离&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org2f0b3ce&quot;&gt;所谓编辑距离&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1c231e3&quot;&gt;求解方法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8b04415&quot;&gt;从编辑距离到相似度量&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org984262a&quot;&gt;一点看法&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
本文是&lt;a href=&quot;http://linusp.github.io/2015/11/15/text_similarity_survey.html&quot;&gt;《文本相似度量方法(1): 概览》&lt;/a&gt; 一文的后续，着重讲述最长公共子序列(Longest Common Subsequence, LCS)和编辑距离的原理和实现。
&lt;/p&gt;

&lt;div id=&quot;outline-container-org1b0e74a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1b0e74a&quot;&gt;最长公共子序列&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org1b0e74a&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org9e2d67b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org9e2d67b&quot;&gt;问题定义&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org9e2d67b&quot;&gt;
&lt;p&gt;
对给定序列 A 和 B, 满足以下条件的一个序列 C 被称为 A 和 B 的公共子序列:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;C 中每一个元素都对应 A 和 B 中一个元素&lt;/li&gt;
&lt;li&gt;从 C 中挑选两个元素 \(C_{i}\) 和 \(C_{j}\) ，其中 \(i\) 和 \(j\) 表示这两个元素在 C 中的序号(从左至右)，假设这两个元素分别对应 \(A_{m}\) 和 \(A_{n}\) ，那么有 \((j - i)\cdot(n - m)\gt 0\)，在 B 中对应的两个元素同理&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
比如说给定 \(A =\) &quot;打南边来了个喇嘛，手里提拉着五斤鳎目&quot;, \(B =\) &quot;打北边来了个哑巴，腰里别着个喇叭&quot; ，以下都是 A 和 B 的子序列:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&quot;打边&quot;&lt;/li&gt;
&lt;li&gt;&quot;打边来了个&quot;&lt;/li&gt;
&lt;li&gt;&quot;边个着&quot;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
在所有可能的 C 中，长度最大的即所谓 &quot;最长公共子序列&quot;。上述例子中 A 和 B 的最长公共子序列是: &quot;打边来了个，里着&quot;。如下图所示:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/lcs_example.png&quot; alt=&quot;lcs_example.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
直观感受上，我们可以认为，如果 A 和 B 的最长公共子序列越长，A 和 B 就越相似。这也是用最长公共子序列来度量文本相似程度的思想。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org18f7859&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org18f7859&quot;&gt;求解方法&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org18f7859&quot;&gt;
&lt;p&gt;
LCS 是一个比较经典的算法问题，了解动态规划的读者应该对它不会陌生。
&lt;/p&gt;

&lt;p&gt;
要求解 LCS，朴素的想法是将 A 的所有子序列都枚举一遍，看是否是 B 的子序列，然后从中挑选出最长的。对给定字符串 A ，假定其长度为 \(L\)，其所有可能的子序列数量为 \(\sum_{i=1}^{L}\binom{L}{i}\) 也就是 \(2^{L} - 1\) ，所以暴力求解方法的复杂度至少是指数级的，这显然是不可取的。
&lt;/p&gt;


&lt;p&gt;
通常我们用动态规划方法来求解 LCS 问题。
&lt;/p&gt;

&lt;p&gt;
不难发现 LCS 的求解可以按照以下方法来得到:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;对比 A 和 B 的第一个字符，如果相等，则转入步骤 2，否则转入步骤 3&lt;/li&gt;
&lt;li&gt;将 A 和 B 的第一个字符记录为 LCS 的第一个字符，求 A 和 B 剩下部分的 LCS (转回步骤 1，下同)&lt;/li&gt;
&lt;li&gt;将 A 去掉第一个字符，用剩下的部分和 B 一起计算 LCS，转入步骤 4&lt;/li&gt;
&lt;li&gt;将 B 去掉第一个字符，用剩下的部分和 A 一起计算 LCS，转入步骤 5&lt;/li&gt;
&lt;li&gt;比较第 3 步和第 4 步得到的 LCS，其中较长的就是 A 和 B 的 LCS.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
上述过程很明显是一个递归过程，所以可以简单地实现出来。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;coding: utf-8&lt;/span&gt;

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;lcs&lt;/span&gt;(a, b):
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;not&lt;/span&gt; a &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;or&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;not&lt;/span&gt; b:
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; []

    &lt;span style=&quot;color: #ffcc66;&quot;&gt;res&lt;/span&gt; = []
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; a[0] == b[0]:
        res.append(a[0])
        res.extend(lcs(a[1:], b[1:]))
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;else&lt;/span&gt;:
        &lt;span style=&quot;color: #ffcc66;&quot;&gt;lcs_one&lt;/span&gt; = lcs(a[1:], b)
        &lt;span style=&quot;color: #ffcc66;&quot;&gt;lcs_two&lt;/span&gt; = lcs(a, b[1:])
        &lt;span style=&quot;color: #ffcc66;&quot;&gt;res&lt;/span&gt; = lcs_one &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;len&lt;/span&gt;(lcs_one) &amp;gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;len&lt;/span&gt;(lcs_two) &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;else&lt;/span&gt; lcs_two

    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; res

&lt;span style=&quot;color: #ffcc66;&quot;&gt;res&lt;/span&gt; = lcs(&lt;span style=&quot;color: #66cccc;&quot;&gt;'hello world'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'hero word'&lt;/span&gt;)
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;''&lt;/span&gt;.join(res)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上述代码可以解决问题，看起来行数也不多，但其实还是有问题的，那就是递归树的存在导致了大量的重复计算、以及可能存在的栈溢出风险。举个栗子，计算 &quot;hello&quot; 和 &quot;hero&quot; 的过程如下图所示:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/lcs_recursive.png&quot; alt=&quot;lcs_recursive.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到 &quot;lcs('lo', 'o')&quot; 被计算了两次。
&lt;/p&gt;

&lt;p&gt;
解决上面提到的问题的方法是将递归方法改为循环方法。用 \(m\) 表示 A 的长度，用 \(n\) 表示 B 的长度，我们可以构建一个 \(m\times n\) 的矩阵 \(D\) ，用来保存上面递归过程中计算到的 A 和 B 的公共子序列。
&lt;/p&gt;

&lt;p&gt;
具体方法是， \(D_{i,j}\) 表示去除 A 的前 i 个元素后的子串 \(A^{\prime}\) 和 B 去掉前 j 个元素后的子串 \(B^{\prime}\) 的 LCS。这样我们首先计算 \(D_{m,n}\) ，然后计算 \(D_{m-1,n}\) 和 \(D_{m,n-1}\) ，再计算 \(D_{m-1,n-1}\)，依次类推。为什么可以这么做呢？仔细看看之前提到的递归过程中的 2、3、4 步，以及上面那张计算 &quot;hello&quot; 和 &quot;hero&quot; 的 LCS 的递归树图，可以发现计算最后都可以归结为计算 A 和 B 尾部片段的 LCS 。
&lt;/p&gt;

&lt;p&gt;
我们发现上面的形式话表述不太直观，如果能先计算 \(D_{0,0}\) 是不是更好一些呢？是的，只要把之前提到的递归规则中的 &quot;比较 A 和 B 的第一个字符&quot; 改为 &quot;比较 A 和 B 的最后一个字符&quot; 并对步骤 2、3、4 做出相应的改变即可。
&lt;/p&gt;

&lt;p&gt;
这样，LCS 的算法可以改写为:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;coding: utf-8&lt;/span&gt;

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;as&lt;/span&gt; np


&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;lcs&lt;/span&gt;(a, b):
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;m&lt;/span&gt;, &lt;span style=&quot;color: #ffcc66;&quot;&gt;n&lt;/span&gt; = &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;len&lt;/span&gt;(a), &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;len&lt;/span&gt;(b)

    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#20026;&amp;#20415;&amp;#20110;&amp;#35745;&amp;#31639;&amp;#65292;&amp;#20026; D &amp;#22810;&amp;#22686;&amp;#21152;&amp;#19968;&amp;#34892;&amp;#19968;&amp;#21015;&lt;/span&gt;
    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#20854;&amp;#20013;&amp;#31532;&amp;#19968;&amp;#34892;&amp;#21644;&amp;#31532;&amp;#19968;&amp;#21015;&amp;#20013;&amp;#30340;&amp;#20803;&amp;#32032;&amp;#20445;&amp;#25345;&amp;#20026;&amp;#31354;&amp;#23383;&amp;#31526;&amp;#20018;&lt;/span&gt;
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;D&lt;/span&gt; = np.zeros((m+1, n+1), dtype=&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;object&lt;/span&gt;)
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;D&lt;/span&gt;[:] = &lt;span style=&quot;color: #66cccc;&quot;&gt;''&lt;/span&gt;                   &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#21021;&amp;#22987;&amp;#21270;&amp;#20026;&amp;#31354;&amp;#23383;&amp;#31526;&amp;#20018;&lt;/span&gt;

    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; idx_a, ch_a &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;enumerate&lt;/span&gt;(a, 1):
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; idx_b, ch_b &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;enumerate&lt;/span&gt;(b, 1):
            &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#33509; D &amp;#19981;&amp;#22686;&amp;#21152;&amp;#19968;&amp;#34892;&amp;#19968;&amp;#21015;&amp;#65292;&amp;#19979;&amp;#26631; idx_a-1/idx_b-1 &amp;#35201;&amp;#21028;&amp;#26029;&amp;#26159;&amp;#21542;&amp;#38750;&amp;#36127;&lt;/span&gt;
            &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; ch_a == ch_b:
                &lt;span style=&quot;color: #ffcc66;&quot;&gt;D&lt;/span&gt;[idx_a, idx_b] = D[idx_a-1, idx_b-1] + ch_a
            &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;else&lt;/span&gt;:
                &lt;span style=&quot;color: #ffcc66;&quot;&gt;lcs_one&lt;/span&gt; = D[idx_a, idx_b-1]
                &lt;span style=&quot;color: #ffcc66;&quot;&gt;lcs_two&lt;/span&gt; = D[idx_a-1, idx_b]
                &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;len&lt;/span&gt;(lcs_one) &amp;gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;len&lt;/span&gt;(lcs_two):
                    &lt;span style=&quot;color: #ffcc66;&quot;&gt;D&lt;/span&gt;[idx_a, idx_b] = lcs_one
                &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;else&lt;/span&gt;:
                    &lt;span style=&quot;color: #ffcc66;&quot;&gt;D&lt;/span&gt;[idx_a, idx_b] = lcs_two

    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; D[m, n]


&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; lcs(&lt;span style=&quot;color: #66cccc;&quot;&gt;'hello'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'hero'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
当然实际上我们不会去用一个二维数组来保存计算过程中用到的(非最长)公共子序列，这样虽然很直观，但是在内存使用上有点丑陋。标准的做法是只记录这些公共子序列的长度，计算完整个长度矩阵后，再从最后的位置回溯取得 LCS 。
&lt;/p&gt;

&lt;p&gt;
先观察一下计算 &quot;lcs('hello', 'hero')&quot; 时得到的公共子序列矩阵:
&lt;/p&gt;
&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;h&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;e&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;r&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;o&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;-&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;h&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;h&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;h&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;h&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;h&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;e&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;h&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;he&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;he&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;he&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;l&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;h&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;he&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;he&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;he&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;l&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;h&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;he&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;he&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;he&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;o&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;h&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;he&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;he&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;heo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
矩阵中出现过的公共子序列有: 'h', 'he' 和 'heo'。从中我们 &lt;b&gt;似乎可以发现这么一个规律&lt;/b&gt;: 从上往下逐行查看，这三个公共子序列 &lt;b&gt;第一次&lt;/b&gt; 出现的时候，恰好就是 'hello' 和 'hero' 中有字符相等的时候，换成记录长度后，也就对应某个特定的长度值第一次出现的时候。
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;h&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;e&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;r&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;o&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;-&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;h&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;e&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;l&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;l&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;o&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;-&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
就这个例子而言，我们 &lt;b&gt;似乎&lt;/b&gt; 可以这样来根据长度矩阵得到 LCS (行/列序号从 0 开始，后同):
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;在第 1 行第 1 列找到 1 ，对应的字符是 'h'&lt;/li&gt;
&lt;li&gt;在第 2 行第 2 列找到 2 ，对应的字符是 'e'&lt;/li&gt;
&lt;li&gt;在第 5 行第 4 列找到 3 ，对应的字符是 'o'&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
这种方法 &lt;b&gt;直观上感觉是对的，但实际上是有问题的&lt;/b&gt; ，下面是计算 'GCGGACTG' 和 'GCCCTAGCG' 时得到的长度矩阵。
&lt;/p&gt;
&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;&amp;#xa0;&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;G&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;C&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;C&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;C&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;T&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;A&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;G&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;C&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;G&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;G&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;C&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;G&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;G&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;A&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;C&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;T&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;G&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;5&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;5&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
如果按照刚才的做法来反推 LCS ，会得到下面的结果:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;在第 1 行第 1 列找到 1 ，对应的字符是 'G'&lt;/li&gt;
&lt;li&gt;在第 2 行第 2 列找到 2 ，对应的字符是 'C'&lt;/li&gt;
&lt;li&gt;在第 3 行第 7 列找到 3 ，对应的字符是 'G'&lt;/li&gt;
&lt;li&gt;在第 4 行第 9 列找到 4 ，对应的字符是 'G'&lt;/li&gt;
&lt;li&gt;第 4 步找到的 'G' 是 'GCCCTAGCG' 的最后一个字符(表中最后一列)，因此停止&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
实际上真正求得的 LCS 长度应该是 5 ，为 'GCGCG'、'GCACG' 或 'GCCTG'，而不是 'GCGG'。问题出在哪呢？ LCS 可以看成是一个最优解，但到达最优解的路径可能有不止一条，而且局部的最优解并不一定是最优解的组成部分，所以前面提到的贪心方法在有些情况下可以得到正确的结果，但有的情况下就会出错。
&lt;/p&gt;

&lt;p&gt;
正确的做法是从长度矩阵右下角，根据长度矩阵的计算规则往前反推，这样就能保证得到的结果是最长的公共子序列。
&lt;/p&gt;

&lt;p&gt;
先把子序列长度矩阵的计算方法实现:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;as&lt;/span&gt; np


&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;lcs_matrix&lt;/span&gt;(a, b):
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;m&lt;/span&gt;, &lt;span style=&quot;color: #ffcc66;&quot;&gt;n&lt;/span&gt; = &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;len&lt;/span&gt;(a), &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;len&lt;/span&gt;(b)
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;matrix&lt;/span&gt; = np.zeros((m+1, n+1), dtype=&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;int&lt;/span&gt;)

    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; idx_a, ch_a &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;enumerate&lt;/span&gt;(a, 1):
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; idx_b, ch_b &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;enumerate&lt;/span&gt;(b, 1):
            &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; ch_a == ch_b:
                &lt;span style=&quot;color: #ffcc66;&quot;&gt;matrix&lt;/span&gt;[idx_a, idx_b] = matrix[idx_a-1, idx_b-1] + 1
            &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;else&lt;/span&gt;:
                &lt;span style=&quot;color: #ffcc66;&quot;&gt;matrix&lt;/span&gt;[idx_a, idx_b] = &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;max&lt;/span&gt;(
                    matrix[idx_a, idx_b-1],
                    matrix[idx_a-1, idx_b]
                )

    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; matrix


&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; lcs_matrix(&lt;span style=&quot;color: #66cccc;&quot;&gt;'GCGGACTG'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'GCCCTAGCG'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
根据长度矩阵的计算规则，可以按照以下步骤来反推出 LCS:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;首先定位到长度矩阵右下角位置&lt;/li&gt;
&lt;li&gt;如果当前位置的值为 0 ，则停止；否则转到步骤 3&lt;/li&gt;
&lt;li&gt;如果当前位置对应的 A 和 B 的元素相等，则向当前位置的左上角后退一步(行号和列号各减 1)，并回到步骤 2，否则转到步骤 4&lt;/li&gt;
&lt;li&gt;检查矩阵当前位置左边的值和上边的值，跳转到其中值更大的那个位置(如果相等，则在往上和往左中选择一个方向)，回到步骤 2&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
用代码实现出来大概是这样:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;as&lt;/span&gt; np


&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;lcs_backtrace&lt;/span&gt;(a, b, matrix):
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;idx_a&lt;/span&gt;, &lt;span style=&quot;color: #ffcc66;&quot;&gt;idx_b&lt;/span&gt; = &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;len&lt;/span&gt;(a) - 1, &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;len&lt;/span&gt;(b) - 1

    &lt;span style=&quot;color: #ffcc66;&quot;&gt;lcs_list&lt;/span&gt; = []
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;while&lt;/span&gt; matrix[idx_a+1, idx_b+1] &amp;gt; 0:
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; a[idx_a] == b[idx_b]:
            lcs_list.append(a[idx_a])
            &lt;span style=&quot;color: #ffcc66;&quot;&gt;idx_a&lt;/span&gt; -= 1
            &lt;span style=&quot;color: #ffcc66;&quot;&gt;idx_b&lt;/span&gt; -= 1
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;else&lt;/span&gt;:
            &lt;span style=&quot;color: #ffcc66;&quot;&gt;upper_value&lt;/span&gt; = matrix[idx_a, idx_b+1]
            &lt;span style=&quot;color: #ffcc66;&quot;&gt;left_value&lt;/span&gt; = matrix[idx_a+1, idx_b]
            &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; upper_value &amp;gt; left_value:
                &lt;span style=&quot;color: #ffcc66;&quot;&gt;idx_a&lt;/span&gt; -= 1
            &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;else&lt;/span&gt;:
                &lt;span style=&quot;color: #ffcc66;&quot;&gt;idx_b&lt;/span&gt; -= 1

    lcs_list.reverse()
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; lcs_list


&lt;span style=&quot;color: #ffcc66;&quot;&gt;a&lt;/span&gt; = &lt;span style=&quot;color: #66cccc;&quot;&gt;'GCGGACTG'&lt;/span&gt;
&lt;span style=&quot;color: #ffcc66;&quot;&gt;b&lt;/span&gt; = &lt;span style=&quot;color: #66cccc;&quot;&gt;'GCCCTAGCG'&lt;/span&gt;
&lt;span style=&quot;color: #ffcc66;&quot;&gt;matrix&lt;/span&gt; = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                   [0, 1, 2, 2, 2, 2, 2, 2, 2, 2],
                   [0, 1, 2, 2, 2, 2, 2, 3, 3, 3],
                   [0, 1, 2, 2, 2, 2, 2, 3, 3, 4],
                   [0, 1, 2, 2, 2, 2, 3, 3, 3, 4],
                   [0, 1, 2, 3, 3, 3, 3, 3, 4, 4],
                   [0, 1, 2, 3, 3, 4, 4, 4, 4, 4],
                   [0, 1, 2, 3, 3, 4, 4, 5, 5, 5]], dtype=&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;int&lt;/span&gt;)
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; lcs_backtrace(a, b, matrix)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
需要注意的是，LCS 结果可能并不唯一。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org8809000&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8809000&quot;&gt;数学表示与相似度量&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8809000&quot;&gt;
&lt;p&gt;
上述求解方法可以用数学语言表示如下:
&lt;/p&gt;

&lt;p&gt;
\[\begin{eqnarray}LCS(A_{i}, B_{j}) = \begin{cases}
   0 &amp; if\quad i=0\quad or\quad j=0\\
   LCS(A_{i-1}, B_{j-1})+a_{i} &amp; if\quad a_{i}=b_{j}\\
   longest(LCS(A_{i}, B_{j-1}), LCS(A_{i-1}, B_{j})) &amp; if\quad a_{i}\neq b_{j}
   \end{cases}\end{eqnarray}\]
&lt;/p&gt;

&lt;p&gt;
其中 \(A_{i}\) 表示 A 的前 \(i\) 个字符组成的字符串，\(B_{j}\) 同理。
&lt;/p&gt;

&lt;p&gt;
直观上，我们可以认为 A 和 B 的 LCS 越长，那么 A 和 B 就越相似。为了使所有用于比较的 (A, B) 对得到的相似度量能进行横向比较，定义 LCS 相似度为:
&lt;/p&gt;

&lt;p&gt;
\[S(A, B) = \frac{2\cdot |LCS(A, B)|}{|A| + |B|}\]
&lt;/p&gt;

&lt;p&gt;
这样得到的相似度的值就被变换到 [0, 1] 区间中了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-orge053564&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge053564&quot;&gt;编辑距离&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge053564&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org2f0b3ce&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2f0b3ce&quot;&gt;所谓编辑距离&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2f0b3ce&quot;&gt;
&lt;p&gt;
编辑距离最早由俄罗斯科学家 &lt;a href=&quot;https://en.wikipedia.org/wiki/Vladimir_Levenshtein&quot;&gt;Levenshtein&lt;/a&gt; 提出，故又称 &quot;Levenshtein 距离&quot;。其定义为: 给定两个字符串 A 和 B，将 A 通过删除、插入、替换操作转换为 B 所需要的最少操作次数。
&lt;/p&gt;

&lt;p&gt;
比如将 &quot;kitten&quot; 转换为 &quot;sitting&quot; 需要进行如下操作:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;替换操作: kitten -&amp;gt; sitten (k -&amp;gt; s)&lt;/li&gt;
&lt;li&gt;替换操作: sitten -&amp;gt; sittin (e -&amp;gt; i)&lt;/li&gt;
&lt;li&gt;插入操作: sittin -&amp;gt; sitting (SPC -&amp;gt; g)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
我们就说 &quot;kitten&quot; 相对 &quot;sitting&quot; 的编辑距离是 3。
&lt;/p&gt;

&lt;p&gt;
编辑距离衡量的是两个字符串之间的差异程度，所以差异程度越小，相似程度就越大了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1c231e3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org1c231e3&quot;&gt;求解方法&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org1c231e3&quot;&gt;
&lt;p&gt;
编辑距离的核心过程 LCS 在我看来是一样的，可以看一下它的数学描述:
&lt;/p&gt;

&lt;p&gt;
\[\begin{eqnarray}LEV(A_{i}, B_{j}) = \begin{cases}
   max(i, j) &amp; if\quad min(i, j)=0\\
   min(LEV(A_{i-1}, B_{j})+1, LEV(A_{i}, B_{j-1})+1, LEV(A_{i-1}, B_{j-1})) &amp; if\quad a_{i}=b_{j}\\
   min(LEV(A_{i-1}, B_{j})+1, LEV(A_{i}, B_{j-1})+1, LEV(A_{i-1}, B_{j-1})+1) &amp; if\quad a_{i}\neq b_{j}\\
   \end{cases}\end{eqnarray}\]
&lt;/p&gt;

&lt;p&gt;
按照其数学描述，可以实现如下:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;coding: utf-8&lt;/span&gt;
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;as&lt;/span&gt; np


&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;edit_distance&lt;/span&gt;(a, b):
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;m&lt;/span&gt;, &lt;span style=&quot;color: #ffcc66;&quot;&gt;n&lt;/span&gt; = &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;len&lt;/span&gt;(a), &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;len&lt;/span&gt;(b)
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;dis_matrix&lt;/span&gt; = np.zeros((m+1, n+1), dtype=&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;int&lt;/span&gt;)

    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#21021;&amp;#22987;&amp;#21270;&amp;#36317;&amp;#31163;&amp;#30697;&amp;#38453;&amp;#30340;&amp;#31532; 0 &amp;#34892;&amp;#21644;&amp;#31532; 0 &amp;#21015;&lt;/span&gt;
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;dis_matrix&lt;/span&gt;[0, :] = np.arange(n+1)
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;dis_matrix&lt;/span&gt;[:, 0] = np.arange(m+1)

    &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#24320;&amp;#22987;&amp;#35745;&amp;#31639;&lt;/span&gt;
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; idx_a, ch_a &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;enumerate&lt;/span&gt;(a, 1):
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; idx_b, ch_b &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;enumerate&lt;/span&gt;(b, 1):
            &lt;span style=&quot;color: #ffcc66;&quot;&gt;cur_dis&lt;/span&gt; = &lt;span style=&quot;color: #6699cc;&quot;&gt;None&lt;/span&gt;

            &lt;span style=&quot;color: #ffcc66;&quot;&gt;dis_left&lt;/span&gt; = dis_matrix[idx_a, idx_b-1]
            &lt;span style=&quot;color: #ffcc66;&quot;&gt;dis_upper&lt;/span&gt; = dis_matrix[idx_a-1, idx_b]
            &lt;span style=&quot;color: #ffcc66;&quot;&gt;dis_upper_left&lt;/span&gt; = dis_matrix[idx_a-1, idx_b-1]
            &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; ch_a == ch_b:
                &lt;span style=&quot;color: #ffcc66;&quot;&gt;cur_dis&lt;/span&gt; = &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;min&lt;/span&gt;(dis_left+1, dis_upper+1, dis_upper_left)
            &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;else&lt;/span&gt;:
                &lt;span style=&quot;color: #ffcc66;&quot;&gt;cur_dis&lt;/span&gt; = &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;min&lt;/span&gt;(dis_left+1, dis_upper+1, dis_upper_left + 1)

            &lt;span style=&quot;color: #ffcc66;&quot;&gt;dis_matrix&lt;/span&gt;[idx_a, idx_b] = cur_dis

    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; dis_matrix[m, n]


&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; edit_distance(&lt;span style=&quot;color: #66cccc;&quot;&gt;'kitten'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'sitting'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8b04415&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8b04415&quot;&gt;从编辑距离到相似度量&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8b04415&quot;&gt;
&lt;p&gt;
与 LCS 不同的是，编辑距离衡量的是差异性，所以用编辑距离来表示相似程度，按照如下式子进行转换:
&lt;/p&gt;

&lt;p&gt;
\[S(A, B)=1-\frac{LEV(A, B)}{max(|A|, |B|)}\]
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org984262a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org984262a&quot;&gt;一点看法&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org984262a&quot;&gt;
&lt;p&gt;
LCS 和编辑距离都是基于相似的动态规划方法来进行求解，它们之间是有很强的共性的。不过 LCS 强调的是 &quot;公共子序列&quot; 这个概念，而编辑距离强调删除、插入、替换这三种编辑操作。实际上还有扩充的编辑距离，比较经典的是 Damerau-Levenshtein 距离，它在 Levenshtein 距离定义的三种编辑操作之外还加入了 &quot;交换相邻字符&quot; 这个操作，因为在输入时将邻近字符的顺序搞错的事情实在是蛮常见的(代码里的 typo 多是这种类型 XD)。
&lt;/p&gt;

&lt;p&gt;
编辑距离和 LCS 不同的另一点，那就是在 LCS 中，用于比较的两个串的 &lt;b&gt;地位&lt;/b&gt; 是等价的，而在编辑距离及其衍生方法中，一般会有一者被认为是 &lt;b&gt;标准的&lt;/b&gt; 。
&lt;/p&gt;

&lt;p&gt;
另外，在生物信息学中，序列比对是非常常见的计算，比如 DNA序列和氨基酸序列的比对。在这个领域中，经常使用 Needleman-Wunsch 算法和 Smith-Waterman 算法来进行相关的处理。大致上，这两种算法和编辑距离也很相似，都是基于动态规划的算法，但在生物信息学中， &lt;b&gt;序列的缺失&lt;/b&gt; 往往是更不能容忍的现象，因此对应于编辑距离中的删除错误，在这两种算法中，会给予比插入错误和替换错误更高的惩罚值。这些都是后话了，计划在下一篇博客中再详细讨论。
&lt;/p&gt;

&lt;p&gt;
在应用上，LCS 主要被应用于版本控制和 diff 工具中，下面是摘自 Git 源代码中的一个片段
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; (i = 1, baseend = base; i &amp;lt; origbaselen + 1; i++) {
  &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; (j = 1, newend = new; j &amp;lt; lennew + 1; j++) {
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; (match_string_spaces(baseend-&amp;gt;line, baseend-&amp;gt;len,
                            newend-&amp;gt;line, newend-&amp;gt;len, flags)) {
      lcs[i][j] = lcs[i - 1][j - 1] + 1;
      directions[i][j] = MATCH;
    } &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;else&lt;/span&gt; &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; (lcs[i][j - 1] &amp;gt;= lcs[i - 1][j]) {
      lcs[i][j] = lcs[i][j - 1];
      directions[i][j] = NEW;
    } &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;else&lt;/span&gt; {
      lcs[i][j] = lcs[i - 1][j];
      directions[i][j] = BASE;
    }
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; (newend-&amp;gt;next)
      newend = newend-&amp;gt;next;
  }
  &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; (baseend-&amp;gt;next)
    baseend = baseend-&amp;gt;next;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
而编辑距离则常见于模糊匹配、拼写检查等场景中，比如 GNU Aspell 使用的就是 Levenshtein 距离，而 GNU Ispell 则使用 Damerau-Levenshtein 距离。从我曾经的工作经历来看，在语音识别中和 OCR (光学字符识别)中，编辑距离也用于衡量识别结果的质量。此外在图像处理领域，也有使用编辑距离的场景。
&lt;/p&gt;

&lt;p&gt;
虽然说基于 LCS 或者编辑距离的文本相似方法都是朴素的、从表面上进行的判断，没有办法深入到语义层面，但用来做一些简单场景的分析已经是足够了，有必要的话还可以对其进行扩充，比如以词为单位来进行处理，比如扩充 item 和 item 的比较方法而不是简单地对比文本组成是否一致。
&lt;/p&gt;

&lt;p&gt;
(待续)
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>Numpy 笔记(二): 多维数组的切片(slicing)和索引(indexing)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/03/09/numpy-slicing-and-indexing.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2016/03/09/numpy-slicing-and-indexing</id>
    <published>2016-03-09T00:00:00+00:00</published>
    <updated>2016-03-09T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


切片(slicing)操作
索引(indexing) 操作

最简单的情况
获取多个元素


切片和索引的同异




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;切片(slicing)操作&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;索引(indexing) 操作&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;最简单的情况&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;获取多个元素&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;切片和索引的同异&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;切片(slicing)操作&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
Numpy 中多维数组的切片操作与 Python 中 list 的切片操作一样，同样由 start, stop, step 三个部分组成
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #eeeeec;&quot;&gt;arr&lt;/span&gt; = np.arange(12)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'array is:'&lt;/span&gt;, arr

&lt;span style=&quot;color: #eeeeec;&quot;&gt;slice_one&lt;/span&gt; = arr[:4]
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'slice begins at 0 and ends at 4 is:'&lt;/span&gt;, slice_one

&lt;span style=&quot;color: #eeeeec;&quot;&gt;slice_two&lt;/span&gt; = arr[7:10]
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'slice begins at 7 and ends at 10 is:'&lt;/span&gt;, slice_two

&lt;span style=&quot;color: #eeeeec;&quot;&gt;slice_three&lt;/span&gt; = arr[0:12:4]
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'slice begins at 0 and ends at 12 with step 4 is:'&lt;/span&gt;, slice_three
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
array is: [ 0  1  2  3  4  5  6  7  8  9 10 11]
slice begins at 0 and ends at 4 is: [0 1 2 3]
slice begins at 7 and ends at 10 is: [7 8 9]
slice begins at 0 and ends at 12 with step 4 is: [0 4 8]
&lt;/pre&gt;

&lt;p&gt;
上述例子是一维数组的例子，如果是多维数组，将不同维度上的切片操作用 &lt;b&gt;逗号&lt;/b&gt; 分开就好了
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;coding: utf-8&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #eeeeec;&quot;&gt;arr&lt;/span&gt; = np.arange(12).reshape((3, 4))
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'array is:'&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; arr

&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#21462;&amp;#31532;&amp;#19968;&amp;#32500;&amp;#30340;&amp;#32034;&amp;#24341; 1 &amp;#21040;&amp;#32034;&amp;#24341; 2 &amp;#20043;&amp;#38388;&amp;#30340;&amp;#20803;&amp;#32032;&amp;#65292;&amp;#20063;&amp;#23601;&amp;#26159;&amp;#31532;&amp;#20108;&amp;#34892;&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#21462;&amp;#31532;&amp;#20108;&amp;#32500;&amp;#30340;&amp;#32034;&amp;#24341; 1 &amp;#21040;&amp;#32034;&amp;#24341; 3 &amp;#20043;&amp;#38388;&amp;#30340;&amp;#20803;&amp;#32032;&amp;#65292;&amp;#20063;&amp;#23601;&amp;#26159;&amp;#31532;&amp;#20108;&amp;#21015;&amp;#21644;&amp;#31532;&amp;#19977;&amp;#21015;&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;slice_one&lt;/span&gt; = arr[1:2, 1:3]
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'first slice is:'&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; slice_one

&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#21462;&amp;#31532;&amp;#19968;&amp;#32500;&amp;#30340;&amp;#20840;&amp;#37096;&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#25353;&amp;#27493;&amp;#38271;&amp;#20026; 2 &amp;#21462;&amp;#31532;&amp;#20108;&amp;#32500;&amp;#30340;&amp;#32034;&amp;#24341; 0 &amp;#21040;&amp;#26411;&amp;#23614; &amp;#20043;&amp;#38388;&amp;#30340;&amp;#20803;&amp;#32032;&amp;#65292;&amp;#20063;&amp;#23601;&amp;#26159;&amp;#31532;&amp;#19968;&amp;#21015;&amp;#21644;&amp;#31532;&amp;#19977;&amp;#21015;&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;slice_two&lt;/span&gt; = arr[:, ::2]
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'second slice is:'&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; slice_two
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
array is:
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
first slice is:
[[5 6]]
second slice is:
[[ 0  2]
 [ 4  6]
 [ 8 10]]
&lt;/pre&gt;

&lt;p&gt;
对于 slice_two，如果 arr 是用 Python 的 list 表示的，那么要得到相同的结果得像下面这样，相对来说就麻烦多了:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #eeeeec;&quot;&gt;arr&lt;/span&gt; = np.arange(12).reshape((3, 4)).tolist()

&lt;span style=&quot;color: #eeeeec;&quot;&gt;slice_two&lt;/span&gt; = [
    row[::2] &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; row &lt;span style=&quot;color: #729fcf;&quot;&gt;in&lt;/span&gt; arr
]
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; slice_two
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[[0, 2], [4, 6], [8, 10]]
&lt;/pre&gt;

&lt;p&gt;
对于维数超过 3 的多维数组，还可以通过 '&amp;#x2026;' 来简化操作
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;coding: utf-8&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #eeeeec;&quot;&gt;arr&lt;/span&gt; = np.arange(24).reshape((2, 3, 4))

&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; arr[1, ...]               &lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#31561;&amp;#20215;&amp;#20110; arr[1, :, :]&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; arr[..., 1]               &lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#31561;&amp;#20215;&amp;#20110; arr[:, :, 1]&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[[12 13 14 15]
 [16 17 18 19]
 [20 21 22 23]]
[[ 1  5  9]
 [13 17 21]]
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;索引(indexing) 操作&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline3&quot;&gt;最简单的情况&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
对于一个多维数组来说，最简单的情况就是访问其中一个特定位置的元素了，如下所示:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;coding: utf-8&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #eeeeec;&quot;&gt;arr&lt;/span&gt; = np.array([
    [1, 2, 3, 4],
    [2, 4, 6, 8],
    [3, 6, 9, 12],
    [4, 8, 12, 16]
])
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'&amp;#31532;&amp;#20108;&amp;#34892;&amp;#31532;&amp;#20108;&amp;#21015;&amp;#30340;&amp;#20540;:'&lt;/span&gt;, arr[1, 1]
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
第二行第二列的值: 4
&lt;/pre&gt;

&lt;p&gt;
相比之下，如果用 Python 的 list 来表示上述二维数组，获取同一个位置的元素的方法为:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;coding: utf-8&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;arr&lt;/span&gt; = [
    [1, 2, 3, 4],
    [2, 4, 6, 8],
    [3, 6, 9, 12],
    [4, 8, 12, 16]
]
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'&amp;#31532;&amp;#20108;&amp;#34892;&amp;#31532;&amp;#20108;&amp;#21015;&amp;#30340;&amp;#20540;:'&lt;/span&gt;, arr[1][1]
&lt;span style=&quot;color: #729fcf;&quot;&gt;try&lt;/span&gt;:
    &lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'&amp;#31532;&amp;#20108;&amp;#34892;&amp;#31532;&amp;#20108;&amp;#21015;&amp;#30340;&amp;#20540;(&amp;#23581;&amp;#35797;&amp;#29992; Numpy &amp;#30340;&amp;#26041;&amp;#24335;&amp;#33719;&amp;#21462;):'&lt;/span&gt;, arr[1, 1]
&lt;span style=&quot;color: #729fcf;&quot;&gt;except&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;Exception&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; e:
    &lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;str&lt;/span&gt;(e)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
第二行第二列的值: 4
第二行第二列的值(尝试用 Numpy 的方式获取): list indices must be integers, not tuple
&lt;/pre&gt;

&lt;p&gt;
如果只是二维数组，这种差别可能看起来并不大，但想象一下假如有一个 10 维的数组，用 Python 的标准做法需要写 10 对中括号，而用 Numpy 依然只需要一对。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline4&quot;&gt;获取多个元素&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
事实上，在 Numpy 的索引操作方式 `x = arr[obj]` 中， obj 不仅仅可以是一个用逗号分隔开的数字序列，还可以是更复杂的内容。
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
用逗号分隔的数组序列
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;序列的长度和多维数组的维数要一致&lt;/li&gt;
&lt;li&gt;序列中每个数组的长度要一致&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #eeeeec;&quot;&gt;arr&lt;/span&gt; = np.array([
    [1, 2, 3, 4],
    [2, 4, 6, 8],
    [3, 6, 9, 12],
    [4, 8, 12, 16]
])

&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; arr[[0, 2], [3, 1]]
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[4 6]
&lt;/pre&gt;

&lt;p&gt;
以上面这个例子来说，其含义是: 选择第一行和第三行，然后对第一行选择第四列，对第三行选择第二列。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
boolean/mask index
&lt;/p&gt;

&lt;p&gt;
这个不太好翻译，所以就用原来的英语表达。
&lt;/p&gt;

&lt;p&gt;
所谓 boolean index，就是用一个由 boolean 类型值组成的数组来选择元素的方法。比如说对下面这样多维数组
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
array([[1, 2, 3, 4],
       [2, 4, 6, 8],
       [3, 6, 9, 12],
       [4, 8, 12, 16]])
&lt;/pre&gt;

&lt;p&gt;
如果要取其中 &lt;b&gt;值大于 5&lt;/b&gt; 的元素，就可以用上 boolean index 了，如下所示:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #eeeeec;&quot;&gt;arr&lt;/span&gt; = np.array([[1, 2, 3, 4],
                [2, 4, 6, 8],
                [3, 6, 9, 12],
                [4, 8, 12, 16]])
&lt;span style=&quot;color: #eeeeec;&quot;&gt;mask&lt;/span&gt; = arr &amp;gt; 5

&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'boolean mask is:'&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; mask

&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; arr[mask]
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
boolean mask is:
[[False False False False]
 [False False  True  True]
 [False  True  True  True]
 [False  True  True  True]]
[ 6  8  6  9 12  8 12 16]
&lt;/pre&gt;

&lt;p&gt;
除了比较运算能产生 boolean mask 数组以外， Numpy 本身也提供了一些工具方法:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;numpy.iscomplex&lt;/li&gt;
&lt;li&gt;numpy.isreal&lt;/li&gt;
&lt;li&gt;numpy.isfinite&lt;/li&gt;
&lt;li&gt;numpy.isinf&lt;/li&gt;
&lt;li&gt;numpy.isnan&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline5&quot;&gt;切片和索引的同异&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;p&gt;
切片和索引都是访问多维数组中元素的方法，这是两者的共同点，不同之处有:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;切片得到的是原多维数组的一个 &lt;b&gt;视图(view)&lt;/b&gt; ，修改切片中的内容会导致原多维数组的内容也发生变化&lt;/li&gt;
&lt;li&gt;切片得到在多维数组中连续(或按特定步长连续)排列的值，而索引可以得到任意位置的值，自由度更大一些&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
不考虑第一点的话，切片的操作是可以用索引操作来实现的，不过这没有必要就是了。
&lt;/p&gt;

&lt;p&gt;
对于第一点，见下面的实验:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #eeeeec;&quot;&gt;arr&lt;/span&gt; = np.arange(12).reshape(2, 6)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'array is:'&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; arr

&lt;span style=&quot;color: #eeeeec;&quot;&gt;slc&lt;/span&gt; = arr[:, 2:5]
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'slice is:'&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; slc

&lt;span style=&quot;color: #eeeeec;&quot;&gt;slc&lt;/span&gt;[1, 2] = 10000
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'modified slice is:'&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; slc
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'array is now:'&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; arr
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
array is:
[[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]]
slice is:
[[ 2  3  4]
 [ 8  9 10]]
modified slice is:
[[    2     3     4]
 [    8     9 10000]]
array is now:
[[    0     1     2     3     4     5]
 [    6     7     8     9 10000    11]]
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>Numpy 笔记(一): 多维数组的创建</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/02/25/creation-and-io-of-ndarray.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2016/02/25/creation-and-io-of-ndarray</id>
    <published>2016-02-25T00:00:00+00:00</published>
    <updated>2016-02-25T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


Numpy 及 ndarray 简介
ndarray 的创建

从已有数据中创建
创建特定形状的多维数组并进行填充
从 numerical range 创...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;Numpy 及 ndarray 简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;ndarray 的创建&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;从已有数据中创建&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;创建特定形状的多维数组并进行填充&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;从 numerical range 创建多维数组&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline6&quot;&gt;创建矩阵(二维数组)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;Numpy 及 ndarray 简介&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;

&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/numpy_logo.png&quot; alt=&quot;numpy_logo.png&quot; align=&quot;right&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.numpy.org/&quot;&gt;Numpy&lt;/a&gt; 是一个 Python 的科学计算包，提供了以下功能:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;强大、灵活的多维数组对象及丰富的操作&lt;/li&gt;
&lt;li&gt;C 实现，执行效率高&lt;/li&gt;
&lt;li&gt;线性代数、丰富的随机数功能&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
ndarray 就是 Numpy 中表示多维数组的类。本篇笔记将对 ndarray 的创建方法进行整理、总结。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;ndarray 的创建&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline3&quot;&gt;从已有数据中创建&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
从 list, tuple 对象中创建:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #eeeeec;&quot;&gt;a&lt;/span&gt; = np.array([1, 2, 3, 4])
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'a is:'&lt;/span&gt;, a

&lt;span style=&quot;color: #eeeeec;&quot;&gt;b&lt;/span&gt; = np.array((1, 2, 3, 4))
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'b is:'&lt;/span&gt;, b
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
a is: [1 2 3 4]
b is: [1 2 3 4]
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
从文件中读取
&lt;/p&gt;

&lt;p&gt;
从文件中读取的方法有: &lt;b&gt;fromfile&lt;/b&gt;, &lt;b&gt;load&lt;/b&gt;, *loadtxt*。其中 fromfile 方法不建议使用，因为 fromfile 读取的文件要求是用 tofile 保存的，而 tofile 方法保存数据到文件时的具体行为是和具体平台有关的。
&lt;/p&gt;

&lt;p&gt;
load 方法读取 save 方法保存下来的二进制文件:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np
&lt;span style=&quot;color: #729fcf;&quot;&gt;from&lt;/span&gt; tempfile &lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; TemporaryFile

&lt;span style=&quot;color: #eeeeec;&quot;&gt;origin_array&lt;/span&gt; = np.array([1, 2, 3, 4])
np.save(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'/tmp/array'&lt;/span&gt;, origin_array)

&lt;span style=&quot;color: #eeeeec;&quot;&gt;array_from_file&lt;/span&gt; = np.load(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'/tmp/array.npy'&lt;/span&gt;)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; array_from_file
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[1 2 3 4]
&lt;/pre&gt;

&lt;p&gt;
可以看一下 /tmp/array.npy 这个文件:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;file /tmp/array.npy
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
/tmp/array.npy: data
&lt;/pre&gt;

&lt;p&gt;
如果希望保存的文件是可读的，那么可以用 savetxt 这个方法，用这个方法保存的数据则用 loadtxt 来读取:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #eeeeec;&quot;&gt;origin_array&lt;/span&gt; = np.array([1, 2, 3, 4])
np.savetxt(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'/tmp/array.txt'&lt;/span&gt;, origin_array)

&lt;span style=&quot;color: #eeeeec;&quot;&gt;array_from_file&lt;/span&gt; = np.loadtxt(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'/tmp/array.txt'&lt;/span&gt;)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; array_from_file
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[ 1.  2.  3.  4.]
&lt;/pre&gt;

&lt;p&gt;
再来看一下 /tmp/array.txt 里面的内容:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;cat /tmp/array.txt
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
1.000000000000000000e+00
2.000000000000000000e+00
3.000000000000000000e+00
4.000000000000000000e+00
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
从字符串中读取
&lt;/p&gt;

&lt;p&gt;
用 &lt;b&gt;fromstring&lt;/b&gt; 方法可以从字符串中读取数据并转换为 &lt;b&gt;一维数组&lt;/b&gt;:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #eeeeec;&quot;&gt;array&lt;/span&gt; = np.fromstring(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'1 2 3 4'&lt;/span&gt;, dtype=&lt;span style=&quot;color: #729fcf;&quot;&gt;float&lt;/span&gt;, sep=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;' '&lt;/span&gt;)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; array
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[ 1.  2.  3.  4.]
&lt;/pre&gt;

&lt;p&gt;
如果是用 &lt;b&gt;tostring&lt;/b&gt; 将一个多维向量转换为字符串，然后再用 fromstring 读取，也只能得到一个一维数组。另外如果是读用 tostring 转换成的字符串， &lt;b&gt;建议使用 fromstring 的时候显式指定数组中元素的数据类型&lt;/b&gt; ，不然就 &lt;b&gt;有可能&lt;/b&gt; 发生下面这样的悲剧:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #eeeeec;&quot;&gt;array&lt;/span&gt; = np.array([1, 2, 3, 4], dtype=&lt;span style=&quot;color: #729fcf;&quot;&gt;int&lt;/span&gt;)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.fromstring(array.tostring())
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[  4.94065646e-324   9.88131292e-324   1.48219694e-323   1.97626258e-323]
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
&lt;b&gt;fromiter&lt;/b&gt;: 从可迭代对象中生成一维数组
&lt;/p&gt;

&lt;p&gt;
和第一种方法的不同之处在于:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;只能返回一维数组&lt;/li&gt;
&lt;li&gt;必须显式指定数组中元素的数据类型&lt;/li&gt;
&lt;li&gt;输入可以是 &lt;b&gt;所有可迭代对象&lt;/b&gt; ，包括 list、tuple、string、unicode, generator，但需要注意的是，这里的 list 和 tuple 不能有嵌套。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;coding: utf-8&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np


&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;count_generator&lt;/span&gt;():
    &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; i &lt;span style=&quot;color: #729fcf;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;range&lt;/span&gt;(4):
        &lt;span style=&quot;color: #729fcf;&quot;&gt;yield&lt;/span&gt; i


&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'from list:'&lt;/span&gt;, np.fromiter([1, 2, 3, 4], &lt;span style=&quot;color: #729fcf;&quot;&gt;int&lt;/span&gt;)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'from tuple:'&lt;/span&gt;, np.fromiter([1, 2, 3, 4], &lt;span style=&quot;color: #729fcf;&quot;&gt;int&lt;/span&gt;)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'from string:'&lt;/span&gt;, np.fromiter(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'1234'&lt;/span&gt;, &lt;span style=&quot;color: #729fcf;&quot;&gt;int&lt;/span&gt;)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'from unicode:'&lt;/span&gt;, np.fromiter(u&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'&amp;#30333;&amp;#26085;&amp;#20381;&amp;#23665;&amp;#23613;'&lt;/span&gt;, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'U1'&lt;/span&gt;)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'from generator:'&lt;/span&gt;, np.fromiter(count_generator(), &lt;span style=&quot;color: #729fcf;&quot;&gt;int&lt;/span&gt;)


&lt;span style=&quot;color: #729fcf;&quot;&gt;try&lt;/span&gt;:
    &lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'from nested list:'&lt;/span&gt;, np.fromiter([[1, 2], [3, 4]], &lt;span style=&quot;color: #729fcf;&quot;&gt;int&lt;/span&gt;)
&lt;span style=&quot;color: #729fcf;&quot;&gt;except&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;ValueError&lt;/span&gt;:
    &lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'bad list'&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
from list: [1 2 3 4]
from tuple: [1 2 3 4]
from string: [1 2 3 4]
from unicode: [u'\u767d' u'\u65e5' u'\u4f9d' u'\u5c71' u'\u5c3d']
from generator: [0 1 2 3]
from nested list: bad list
&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline4&quot;&gt;创建特定形状的多维数组并进行填充&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
ones
&lt;/p&gt;

&lt;p&gt;
创建给定形状的多维数组并将数组中所有元素填充为 1:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.ones((3, 4))
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[[ 1.  1.  1.  1.]
 [ 1.  1.  1.  1.]
 [ 1.  1.  1.  1.]]
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
zeros
&lt;/p&gt;

&lt;p&gt;
类似 ones ，但用 0 进行填充:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.zeros((3, 4))
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[[ 0.  0.  0.  0.]
 [ 0.  0.  0.  0.]
 [ 0.  0.  0.  0.]]
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
empty
&lt;/p&gt;

&lt;p&gt;
类似 ones, 但不进行初始化，得到的多维数组中的元素值是不确定的。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.empty((3, 4))
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[[  6.93164023e-310   1.66900197e-316   4.64956088e-317   4.00193173e-322]
 [  1.77481898e-316   6.93164023e-310   9.30845863e-039   2.42092166e-322]
 [  6.93164023e-310   6.93164023e-310   4.68423639e-320   0.00000000e+000]]
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
full
&lt;/p&gt;

&lt;p&gt;
类似 ones, 但需要自己手动指定需为多维数组填充的值。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.full((3, 4), 17)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[[ 17.  17.  17.  17.]
 [ 17.  17.  17.  17.]
 [ 17.  17.  17.  17.]]
&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline5&quot;&gt;从 numerical range 创建多维数组&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
arange
&lt;/p&gt;

&lt;p&gt;
创建一个一维的数组，用法同 Python 内建方法 &lt;b&gt;range&lt;/b&gt;:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.arange(10)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.arange(0, 10)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.arange(9, -1, -1)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[0 1 2 3 4 5 6 7 8 9]
[0 1 2 3 4 5 6 7 8 9]
[9 8 7 6 5 4 3 2 1 0]
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
linspace
&lt;/p&gt;

&lt;p&gt;
给定一个区间，取其 N 等分点组成一个一维数组:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.linspace(1, 10, num=10)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[  1.   2.   3.   4.   5.   6.   7.   8.   9.  10.]
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
logspace
&lt;/p&gt;

&lt;p&gt;
给定一个 &lt;b&gt;对数尺度(log scale)区间&lt;/b&gt; ，取其 N 等分点对应的 &lt;b&gt;线性尺度(linear scale)上的数值&lt;/b&gt;:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.logspace(1, 3, num=3)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.log10(np.logspace(1, 3, num=3))
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[   10.   100.  1000.]
[ 1.  2.  3.]
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
meshgrid
&lt;/p&gt;

&lt;p&gt;
根据给定的坐标向量创建坐标矩阵。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np


&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.meshgrid(np.arange(0, 6))
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt;

&lt;span style=&quot;color: #eeeeec;&quot;&gt;x&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;y&lt;/span&gt; = np.meshgrid(np.arange(-1, 2), np.arange(0, 2))
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'x is:'&lt;/span&gt;, x
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'y is:'&lt;/span&gt;, y
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt;

&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'points built by (x, y):'&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.rec.fromarrays([x, y])
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[array([0, 1, 2, 3, 4, 5])]

x is: [[-1  0  1]
 [-1  0  1]]
y is: [[0 0 0]
 [1 1 1]]

points built by (x, y):
[[(-1, 0) (0, 0) (1, 0)]
 [(-1, 1) (0, 1) (1, 1)]]
&lt;/pre&gt;

&lt;p&gt;
在上面的例子中，所得到的是 X 轴上 [-1, 0, 1] 和 X 轴上 [0, 1] 构成的一个 3x2 的网格，共有 6 个点。返回的两个值中的 x 是这 6 个点 在 X 轴上的投影， y 则是这 6 个点在 y 轴上的投影。
&lt;/p&gt;

&lt;p&gt;
meshgrid 方法的参数数量不受限，可以得到任意 N 维空间中的坐标矩阵。
&lt;/p&gt;

&lt;p&gt;
了解 meshgrid 方法的功能后，可以来做一些有趣的事情，比如:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np
&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; matplotlib.pyplot &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; plt

&lt;span style=&quot;color: #eeeeec;&quot;&gt;x&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;y&lt;/span&gt; = np.meshgrid(np.arange(-1, 1, 0.01), np.arange(-1, 1, 0.01))

&lt;span style=&quot;color: #eeeeec;&quot;&gt;contor&lt;/span&gt; = np.sqrt(x ** 2 + y ** 2)
plt.imshow(contor)
plt.colorbar()

plt.savefig(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'contor.png'&lt;/span&gt;)
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'/assets/img/contor.png'&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/contor.png&quot; alt=&quot;contor.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
mgrid
&lt;/p&gt;

&lt;p&gt;
mgrid 的功能与 meshgrid 类似，但有几点不同:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;mgrid 不是函数，而是一个类的对象&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
mgrid 和 meshgrid 的使用方式不一样，meshgrid 需要传入一维数组作为对象，而 mgrid 则直接使用 '[]' 运算符
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

np.meshgrid(np.arange(-1, 2), np.arange(-1, 2))
np.mgrid[-1:2, -1:2]
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
返回值的前两个顺序相反
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #eeeeec;&quot;&gt;x&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;y&lt;/span&gt; = np.meshgrid(np.arange(-1, 1), np.arange(-1, 1))
&lt;span style=&quot;color: #eeeeec;&quot;&gt;xx&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;yy&lt;/span&gt; = np.mgrid[-1:1, -1:1]
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; (x - yy).&lt;span style=&quot;color: #729fcf;&quot;&gt;sum&lt;/span&gt;(), (y - xx).&lt;span style=&quot;color: #729fcf;&quot;&gt;sum&lt;/span&gt;()

&lt;span style=&quot;color: #eeeeec;&quot;&gt;x&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;y&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;z&lt;/span&gt; = np.meshgrid(np.arange(-1, 1), np.arange(-1, 1), np.arange(-1, 1))
&lt;span style=&quot;color: #eeeeec;&quot;&gt;xx&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;yy&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;zz&lt;/span&gt; = np.mgrid[-1:1, -1:1, -1:1]
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; (x - yy).&lt;span style=&quot;color: #729fcf;&quot;&gt;sum&lt;/span&gt;(), (y - xx).&lt;span style=&quot;color: #729fcf;&quot;&gt;sum&lt;/span&gt;(), (z - zz).&lt;span style=&quot;color: #729fcf;&quot;&gt;sum&lt;/span&gt;()

&lt;span style=&quot;color: #eeeeec;&quot;&gt;x&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;y&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;z&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;w&lt;/span&gt; = np.meshgrid(np.arange(-1, 1), np.arange(-1, 1), np.arange(-1, 1), np.arange(-1, 1))
&lt;span style=&quot;color: #eeeeec;&quot;&gt;xx&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;yy&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;zz&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;ww&lt;/span&gt; = np.mgrid[-1:1, -1:1, -1:1, -1:1]
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; (x - yy).&lt;span style=&quot;color: #729fcf;&quot;&gt;sum&lt;/span&gt;(), (y - xx).&lt;span style=&quot;color: #729fcf;&quot;&gt;sum&lt;/span&gt;(), (z - zz).&lt;span style=&quot;color: #729fcf;&quot;&gt;sum&lt;/span&gt;(), (w - ww).&lt;span style=&quot;color: #729fcf;&quot;&gt;sum&lt;/span&gt;()
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
0 0
0 0 0
0 0 0 0
&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
ogrid
&lt;/p&gt;

&lt;p&gt;
ogrid 与 mgrid 类似，也是类的对象而非函数，但和 mgrid 的不同之处在于，它返回的结果是 &lt;b&gt;稀疏&lt;/b&gt; 的。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #eeeeec;&quot;&gt;x&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;y&lt;/span&gt; = np.mgrid[-1:2, 3:6]
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'x from mgrid:'&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; x
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'y from mgrid:'&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; y

&lt;span style=&quot;color: #eeeeec;&quot;&gt;x&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;y&lt;/span&gt; = np.ogrid[-1:2, 3:6]
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'x from ogrid:'&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; x
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'y from ogrid:'&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; y
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
x from mgrid:
[[-1 -1 -1]
 [ 0  0  0]
 [ 1  1  1]]
y from mgrid:
[[3 4 5]
 [3 4 5]
 [3 4 5]]
x from ogrid:
[[-1]
 [ 0]
 [ 1]]
y from ogrid:
[[3 4 5]]
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
fromfunction
&lt;/p&gt;

&lt;p&gt;
fromfunction 的行为稍微有点不一样，它有三个参数:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;function&lt;/li&gt;
&lt;li&gt;shape&lt;/li&gt;
&lt;li&gt;dtype(optional)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
其中 function 的参数个数要和 shape 的长度一致，fromfunction 会对 shape 对应的多维数组中每个元素的坐标传给 function ，然后将返回值组合起来。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;f&lt;/span&gt;(x, y):
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; (x, y)


&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;g&lt;/span&gt;(x, y):
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; x + y


&lt;span style=&quot;color: #eeeeec;&quot;&gt;x&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;y&lt;/span&gt; = np.fromfunction(f, (3, 3))
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'x generated by f is:\n'&lt;/span&gt;, x
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'y generated by f is:\n'&lt;/span&gt;, y
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'array generated by g is:\n'&lt;/span&gt;, np.fromfunction(g, (3, 3))
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
x generated by f is:
[[ 0.  0.  0.]
 [ 1.  1.  1.]
 [ 2.  2.  2.]]
y generated by f is:
[[ 0.  1.  2.]
 [ 0.  1.  2.]
 [ 0.  1.  2.]]
array generated by g is:
[[ 0.  1.  2.]
 [ 1.  2.  3.]
 [ 2.  3.  4.]]
&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline6&quot;&gt;创建矩阵(二维数组)&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline6&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
eye:
&lt;/p&gt;

&lt;p&gt;
创建一个对角矩阵或者 super/sub diagional square matrix，且所指定的对角线上的元素值为 1.
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.eye(2)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.eye(2, 3, k=1)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.eye(2, 3, k=-1)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[[ 1.  0.]
 [ 0.  1.]]
[[ 0.  1.  0.]
 [ 0.  0.  1.]]
[[ 0.  0.  0.]
 [ 1.  0.  0.]]
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
identity
&lt;/p&gt;

&lt;p&gt;
创建单位矩阵
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.identity(2)
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.identity(3)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[[ 1.  0.]
 [ 0.  1.]]
[[ 1.  0.  0.]
 [ 0.  1.  0.]
 [ 0.  0.  1.]]
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
diag
&lt;/p&gt;

&lt;p&gt;
创建对角矩阵或 super/sub diagional matrix。与 eye 的不同之处在于:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;对角线上的元素值不是都为 1 ，而是手动指定&lt;/li&gt;
&lt;li&gt;不需要制定矩阵的形状，而是靠指定对角线上元素值来确定矩阵的形状&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.diag([1, 1, 1])
&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.diag([3, 4], 1)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[[1 0 0]
 [0 1 0]
 [0 0 1]]
[[0 3 0]
 [0 0 4]
 [0 0 0]]
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
diaglat
&lt;/p&gt;

&lt;p&gt;
对输入进行 flatten 然后用之创建对角矩阵
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; numpy &lt;span style=&quot;color: #729fcf;&quot;&gt;as&lt;/span&gt; np

&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; np.diagflat([[1, 1], [1, 1]])
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&quot;example&quot;&gt;
[[1 0 0 0]
 [0 1 0 0]
 [0 0 1 0]
 [0 0 0 1]]
&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>词形还原工具对比</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2016/01/21/lemmatization-survey.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2016/01/21/lemmatization-survey</id>
    <published>2016-01-21T00:00:00+00:00</published>
    <updated>2016-01-21T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


词形还原(Lemmatization)
词形还原的工具

Python: NLTK
Python: Pattern
Python: TextBlob
Tr...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org27348ec&quot;&gt;词形还原(Lemmatization)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb18d34f&quot;&gt;词形还原的工具&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgde20842&quot;&gt;Python: NLTK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8fabfe7&quot;&gt;Python: Pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5e9b797&quot;&gt;Python: TextBlob&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org91b7093&quot;&gt;Tree Tagger&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;b&gt;注: 本文仅讨论英文&lt;/b&gt;
&lt;/p&gt;

&lt;div id=&quot;outline-container-org27348ec&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org27348ec&quot;&gt;词形还原(Lemmatization)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org27348ec&quot;&gt;
&lt;p&gt;
在英文当中，一些词会在不同的情况中有不同的形态：名词有单复数，动词有时态和语态，形容词有比较级。而在自然语言处理的一些场景中，这种形态的差异是没有意义的甚至有干扰作用，需要将不同形态的词转换为其 &lt;b&gt;原型&lt;/b&gt; ，这种处理就称为 &quot;词形还原(Lemmatization/Lemmatisation)&quot; ，得到的原型被称为 &quot;词元(Lemma)&quot; 。
&lt;/p&gt;

&lt;p&gt;
举栗子:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;dogs -&amp;gt; dog, cats -&amp;gt; cat&lt;/li&gt;
&lt;li&gt;doing -&amp;gt; do, done -&amp;gt; do&lt;/li&gt;
&lt;li&gt;better -&amp;gt; good&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
为什么说词的不同形态有干扰作用呢？这么说其实不太严谨，要结合实际应用来说才是有意义的，不妨以文档相似计算这个应用来看一看。
&lt;/p&gt;

&lt;p&gt;
假设我们有三个文档，内容分别为:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
D1: I work at home
D2: I was working at home
D3: I was sleeping at home
&lt;/pre&gt;

&lt;p&gt;
从表达的内容上来看，我们会认为 D1 和 D2 是更接近的，而 D2 和 D3 表达的是两件事情。接下来计算一下 Document-Term 矩阵
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;D1&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;D2&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;D3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;I&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;was&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;work&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;working&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;sleeping&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;at&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;home&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
然后计算三个文档之间两两的相似性，为计算简单，这里定义文档相似性为: 两个文档在表中对应的列中 &lt;b&gt;相同位的个数&lt;/b&gt; ，那么
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;D1&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;D2&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;D3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;D1&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;7&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;D2&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;7&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;5&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;D3&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;5&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
结果是: D2 和 D3 最相似 —— 这和预期的结果是不一致的。
&lt;/p&gt;

&lt;p&gt;
如果对文档中每个词都进行词形还原，那么结果会不一样。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;注意，词形还原(lemmatization)与词干提取(stemming)在一些词的表现上很相似，但它们是两个东西。&lt;/b&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb18d34f&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgb18d34f&quot;&gt;词形还原的工具&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgb18d34f&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgde20842&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgde20842&quot;&gt;Python: &lt;a href=&quot;http://www.nltk.org/&quot;&gt;NLTK&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgde20842&quot;&gt;
&lt;p&gt;
NLTK 是著名的 Python 自然语言处理包，其中包含了非常多的自然语言处理相关方法和工具，其中也包含了词形还原的功能。
&lt;/p&gt;

&lt;p&gt;
NLTK 中的词形还原功能依赖 WordNet 语料和一个名为 averaged_perceptron_tagger 的词性标注集，所以在使用其词形还原方法前需要先下载相关的数据:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; nltk

nltk.download(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;wordnet&quot;&lt;/span&gt;)
nltk.download(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;averaged_perceptron_tagger&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
使用方法:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; nltk.stem &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; WordNetLemmatizer

&lt;span style=&quot;color: #ffcc66;&quot;&gt;lemmatizer&lt;/span&gt; = WordNetLemmatizer()
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; lemmatizer.lemmatize(&lt;span style=&quot;color: #66cccc;&quot;&gt;'dogs'&lt;/span&gt;)
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; lemmatizer.lemmatize(&lt;span style=&quot;color: #66cccc;&quot;&gt;'working'&lt;/span&gt;, pos=&lt;span style=&quot;color: #66cccc;&quot;&gt;'v'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
NLTK 里这个词形还原工具的一个问题是需要手动指定词性，比如上面例子中的 &quot;working&quot; 这个词，如果不加后面那个 pos 参数，输出的结果将会是 &quot;working&quot; 本身。
&lt;/p&gt;

&lt;p&gt;
如果希望在实际应用中使用 NLTK 进行词形还原，一个完整的解决方案是:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;输入一个完整的句子&lt;/li&gt;
&lt;li&gt;用 NLTK 提供的工具对句子进行分词和词性标注&lt;/li&gt;
&lt;li&gt;将得到的词性标注结果转换为 WordNet 的格式&lt;/li&gt;
&lt;li&gt;使用 WordNetLemmatizer 对词进行词形还原&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
其中分词和词性标注又有数据依赖:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;nltk.download(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;punkt&quot;&lt;/span&gt;)
nltk.download(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;maxent_treebank_pos_tagger&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
给一个小 demo
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; nltk.corpus &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; wordnet
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; nltk &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; word_tokenize, pos_tag
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; nltk.stem &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; WordNetLemmatizer


&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;get_wordnet_pos&lt;/span&gt;(treebank_tag):
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; treebank_tag.startswith(&lt;span style=&quot;color: #66cccc;&quot;&gt;'J'&lt;/span&gt;):
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; wordnet.ADJ
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;elif&lt;/span&gt; treebank_tag.startswith(&lt;span style=&quot;color: #66cccc;&quot;&gt;'V'&lt;/span&gt;):
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; wordnet.VERB
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;elif&lt;/span&gt; treebank_tag.startswith(&lt;span style=&quot;color: #66cccc;&quot;&gt;'N'&lt;/span&gt;):
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; wordnet.NOUN
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;elif&lt;/span&gt; treebank_tag.startswith(&lt;span style=&quot;color: #66cccc;&quot;&gt;'R'&lt;/span&gt;):
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; wordnet.ADV
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;else&lt;/span&gt;:
        &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #6699cc;&quot;&gt;None&lt;/span&gt;


&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;lemmatize_sentence&lt;/span&gt;(sentence):
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;res&lt;/span&gt; = []
    &lt;span style=&quot;color: #ffcc66;&quot;&gt;lemmatizer&lt;/span&gt; = WordNetLemmatizer()
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; word, pos &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; pos_tag(word_tokenize(sentence)):
        &lt;span style=&quot;color: #ffcc66;&quot;&gt;wordnet_pos&lt;/span&gt; = get_wordnet_pos(pos) &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;or&lt;/span&gt; wordnet.NOUN
        res.append(lemmatizer.lemmatize(word, pos=wordnet_pos))

    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;return&lt;/span&gt; res
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8fabfe7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8fabfe7&quot;&gt;Python: &lt;a href=&quot;https://github.com/clips/pattern&quot;&gt;Pattern&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8fabfe7&quot;&gt;
&lt;p&gt;
Pattern 是一个 Python 的数据挖掘库，还实现了自然语言处理、机器学习以及数据可视化等一整套的功能，是一个非常强大的库， Github 上 4000 多个 star 呢。
&lt;/p&gt;

&lt;p&gt;
Pattern 中的 en 模块是专门用于英文的自然语言处理的，实现了很多非常棒的方法，比如:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; pattern.en &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; quantify

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; quantify([&lt;span style=&quot;color: #66cccc;&quot;&gt;'goose'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'goose'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'duck'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'chicken'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'chicken'&lt;/span&gt;, &lt;span style=&quot;color: #66cccc;&quot;&gt;'chicken'&lt;/span&gt;])
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; quantify({&lt;span style=&quot;color: #66cccc;&quot;&gt;'carrot'&lt;/span&gt;: 100, &lt;span style=&quot;color: #66cccc;&quot;&gt;'parrot'&lt;/span&gt;: 20})
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; quantify(&lt;span style=&quot;color: #66cccc;&quot;&gt;'carrot'&lt;/span&gt;, amount=1000)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
再比如:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; pattern.en &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; comparative, superlative

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; comparative(&lt;span style=&quot;color: #66cccc;&quot;&gt;'bad'&lt;/span&gt;)
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; superlative(&lt;span style=&quot;color: #66cccc;&quot;&gt;'bad'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
嗯，跑题了……使用 Pattern 进行词形还原在形式上非常简单，如下所示:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; pattern.en &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; lemma

&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; lemma(&lt;span style=&quot;color: #66cccc;&quot;&gt;'working'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
So easy!完全不用管什么词性标注之类的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5e9b797&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org5e9b797&quot;&gt;Python: &lt;a href=&quot;https://github.com/sloria/textblob&quot;&gt;TextBlob&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org5e9b797&quot;&gt;
&lt;p&gt;
TextBlob 是一个专注自然语言处理的 Python 库，集成了 NLTK 和 Pattern 的一些功能。其中的词形还原功能使用如下:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;from&lt;/span&gt; textblob &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;import&lt;/span&gt; TextBlob

&lt;span style=&quot;color: #ffcc66;&quot;&gt;blob&lt;/span&gt; = TextBlob(&lt;span style=&quot;color: #66cccc;&quot;&gt;'I was working at home'&lt;/span&gt;)
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; blob.words
&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;for&lt;/span&gt; word &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;in&lt;/span&gt; blob.words:
    &lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;print&lt;/span&gt; word.lemmatize()
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果并不是很理想，同 NLTK 一样，可以传入词性来使词形提高还原结果。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org91b7093&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org91b7093&quot;&gt;&lt;a href=&quot;http://www.cis.uni-muenchen.de/~schmid/tools/TreeTagger/&quot;&gt;Tree Tagger&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org91b7093&quot;&gt;
&lt;p&gt;
Tree Tagger 是一个命令行词性标注工具，词形还原是它附带的功能。
&lt;/p&gt;

&lt;p&gt;
安装:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;下载词性标注器: &lt;a href=&quot;http://www.cis.uni-muenchen.de/~schmid/tools/TreeTagger/data/tree-tagger-linux-3.2.tar.gz&quot;&gt;Linux&lt;/a&gt; / &lt;a href=&quot;http://www.cis.uni-muenchen.de/~schmid/tools/TreeTagger/data/tree-tagger-MacOSX-3.2-intel.tar.gz&quot;&gt;Mac OS-X&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;下载词性标注 &lt;a href=&quot;http://www.cis.uni-muenchen.de/~schmid/tools/TreeTagger/data/tagger-scripts.tar.gz&quot;&gt;脚本&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;下载安装工具: &lt;a href=&quot;http://www.cis.uni-muenchen.de/~schmid/tools/TreeTagger/data/install-tagger.sh&quot;&gt;install-tagger.sh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;下载需要处理的语言的参数文件: &lt;a href=&quot;http://www.cis.uni-muenchen.de/~schmid/tools/TreeTagger/data/english-par-linux-3.2-utf8.bin.gz&quot;&gt;英语&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
将上述下载好的资源放到同一个目录中，其中的压缩包不需要解压，直接执行 install-tagger.sh
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-sh&quot;&gt;chmod +x install-tagger.sh &amp;amp;&amp;amp; ./install-tagger.sh
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
完成上述操作后将会在当前目录中生成 bin 和 cmd 两个目录，其中是一些可执行程序或脚本，不多介绍。想要进行词形还原，以英语为例，可以这么做:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;'I was working at home'&lt;/span&gt; | tree-tagger-english
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>2015年总结与2016年展望</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/12/27/annual-summary-of-2015.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2015/12/27/annual-summary-of-2015</id>
    <published>2015-12-27T00:00:00+00:00</published>
    <updated>2015-12-27T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


2015 年计划完成情况
2015 年总结
2016 年展望与计划




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;2015 年计划完成情况&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;2015 年总结&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;2016 年展望与计划&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
跨年夜是工作日，大概不会有时间来写这个，所以决定现在来把它完成。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;2015 年计划完成情况&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
以下是 2015 年计划的完成情况
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
换一份工作，去一个让自己觉得自己很傻逼又很牛逼的环境，而且草稿纸要无限量供应(虽然我也做不到无限量消耗啦)
&lt;/p&gt;

&lt;p&gt;
3月份的时候来到了现在的这家公司，总体来说我对现在的工作环境是比较满意的，特别是技术团队的氛围和默契。当然草稿纸无限量供应这件事情并没有得到满足 —— 遇到难题的时候我需要靠纸和笔来梳理思路才能更快地解决问题，所以我对这个还是蛮依赖的，勉强靠自己解决了。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;完成&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
系统掌握概率论、数理统计、微积分、线性代数这几个数学学科的基础知识
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;未完成&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
阅读五本以上的历史书籍，做到基本了解欧洲史和中国商周时期历史
&lt;/p&gt;

&lt;p&gt;
读了两本欧洲史，分别是:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://book.douban.com/subject/5366248/&quot;&gt;极简欧洲史&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://book.douban.com/subject/2326273/&quot;&gt;欧洲中世纪史&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
以及把吕思勉的 &lt;a href=&quot;http://book.douban.com/subject/3707886/&quot;&gt;中国通史&lt;/a&gt; 读了两遍。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;未完成&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
阅读两本以上的哲学史书籍，做到对西哲和中国哲学有一个总体认识
&lt;/p&gt;

&lt;p&gt;
冯友兰的 &lt;a href=&quot;http://book.douban.com/subject/6780545/&quot;&gt;中国哲学史&lt;/a&gt; 在读。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;未完成&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
阅读一到两本 Python 书籍，系统地掌握 Python 的语法和工程知识
&lt;/p&gt;

&lt;p&gt;
书没有读，不过 Python 的语法和工程知识已经算比较熟悉了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
学习并实践设计模式
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;未完成&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
读完《Effective C++》和《The Design and Evolution of C++》，了解并掌握C++的一些语言特性
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;未完成&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
读完《统计学习方法》、《The Elements of Statistical Learning》，掌握 Machine Learning 领域的基本概念和方法
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;未完成&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
读完《Neural Networks and Learning Machine》，实现几种常用的神经网络结构
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;未完成&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
了解NLP的常用工具、主要问题和流行方法
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;未完成&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
每月至少写三篇博客(不包括当月小结)
&lt;/p&gt;

&lt;p&gt;
上半年基本能保持每个月两篇的博客产出，下半年写得比较少。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;未完成&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
完成构想的小说系列第一部的草稿
&lt;/p&gt;

&lt;p&gt;
故事在生长，但是 &lt;b&gt;未完成&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
养成良好的睡眠习惯
&lt;/p&gt;

&lt;p&gt;
有一段时间坚持早睡早起，但是并没有养成长期的习惯。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;未完成&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
独自游历五个以上的城市(在经济条件允许的情况下)——我是土包子我要出去多见见世面
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;未完成&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
以上计划为什么大部分都没有完成呢？
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;懒，事实上上半年我基本没去执行过这些计划(换工作、写博客之类的除外)&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
好的计划应该是具体的、量化的，且应该具有阶段性，比如说这几个计划
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;阅读五本以上的历史书籍，做到基本了解欧洲史和中国商周时期历史&lt;/li&gt;
&lt;li&gt;阅读两本以上的哲学史书籍，做到对西哲和中国哲学有一个总体认识&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
这两个虽然也没有完全完成，但都得到了一定程度的推进。
&lt;/p&gt;

&lt;p&gt;
而这几个计划则是失败的计划:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;系统掌握概率论、数理统计、微积分、线性代数这几个数学学科的基础知识&lt;/li&gt;
&lt;li&gt;学习并实践设计模式&lt;/li&gt;
&lt;li&gt;了解NLP的常用工具、主要问题和流行方法&lt;/li&gt;
&lt;li&gt;养成良好的睡眠习惯&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
都因为太过模糊而没有被执行。如果重新使用这这几个 &lt;b&gt;失败&lt;/b&gt; 的计划，我会多问自己几个问题:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
对 &quot;系统掌握概率论、数理统计、微积分、线性代数这几个数学学科的基础知识&quot;
&lt;/p&gt;

&lt;p&gt;
我要问: 系统掌握这些学科的知识的目的何在？学习到什么程度算是 &quot;掌握&quot;？这四门学科是一起学习还是分阶段先后学习？
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
对 &quot;学习并实践设计模式&quot;
&lt;/p&gt;

&lt;p&gt;
我要问: 为何要学习设计模式？如何学习设计模式？
&lt;/p&gt;

&lt;p&gt;
事实上我并不觉得自己现在需要花大块的时间来去学习设计模式。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
对 &quot;了解NLP的常用工具、主要问题和流行方法&quot;
&lt;/p&gt;

&lt;p&gt;
我要问: NLP 是什么？什么叫做 &quot;常用工具&quot;、&quot;主要问题&quot; 和 &quot;流行方法&quot;？
&lt;/p&gt;

&lt;p&gt;
这个计划本身就是个问题……
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
养成良好的睡眠习惯
&lt;/p&gt;

&lt;p&gt;
我要问: 什么样才算是良好的睡眠习惯？我为什么要养成良好的睡眠习惯？
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;2015 年总结&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
翻阅了一下自己这一年来写的日记，在日记里频繁出现或者带有强烈情绪的几个主题有:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
交谈，与他人的交往
&lt;/p&gt;

&lt;p&gt;
我很渴望与他人交谈，但更希望和他人交谈有意义的事情。在我的日记里有这么一段话:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
交谈真是个奇妙的事情，能让你觉得自己和这个世界又有了联系，在求同存异想法的指引下，不同的观点、相同的观点都被再次确认，感觉很好。

还想继续聊聊，但认真的话往往难说往往难被听，世界这张网还是靠大量貌似毫无意义的语言交流所构筑起来。

于是只好沉默。
&lt;/pre&gt;

&lt;p&gt;
当然，&quot;沉默&quot; 的一部分责任也在我，有的人是能从 &quot;毫无意义的语言交流&quot; 开始，逐渐将话题引导向有意义的方向的。
&lt;/p&gt;

&lt;p&gt;
我佩服这种人，我渴望成为这种人，我知道很难。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
做菜
&lt;/p&gt;

&lt;p&gt;
今年比较大的一个变化是和两个同班同学以及其中一个同学的女朋友住到了一起 —— 我们戏称 &quot;一对狗男女和两个单身狗&quot; 。有客厅、有厨房，有大电视和游戏机，有木地板和真皮沙发，总之现在的住处有 &quot;家&quot; 的感觉，而去年在沙河生活时，我的日记里从来都是写 &quot;回到住处&quot; 。
&lt;/p&gt;

&lt;p&gt;
然后学会了做菜，虽然到现在也还只能做一些简单的菜式，但是觉得因此对生活的掌控感得到了提升。
&lt;/p&gt;

&lt;p&gt;
我吃什么可以由我自己选择，大概是这种感觉。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
身体的不适
&lt;/p&gt;

&lt;p&gt;
频繁出现的不适现象有: 头疼，脖子疼，眼睛疼，鼻炎。
&lt;/p&gt;

&lt;p&gt;
导致这些的主要原因有:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;北京糟糕的空气&lt;/li&gt;
&lt;li&gt;并不良好的睡眠习惯&lt;/li&gt;
&lt;li&gt;上班一坐不起&lt;/li&gt;
&lt;li&gt;缺乏锻炼&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
家庭
&lt;/p&gt;

&lt;p&gt;
父母的关系，弟弟的成长 —— 苦恼大于幸福。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
公司
&lt;/p&gt;

&lt;p&gt;
慢慢地在这个团队里得到认可，和大家在工作上产生默契，并对公司产品从毫不在意转变为主动了解其优缺点 —— 这种感觉还是很好的。
&lt;/p&gt;

&lt;p&gt;
同事们都很可爱、很优秀，我也想变得更优秀 —— 跟优秀的人共事真的是一件很重要的事情。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Machine Learning 领域的学习
&lt;/p&gt;

&lt;p&gt;
Machine Learning 是我为自己选择的主要职业方向，所以一直没有中断这方面的学习。但我想我的学习方法有点问题，具体来说，是理论学习没有配合工程实践。因为一直是在看相关的英文原版书籍，导致:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;进度慢&lt;/li&gt;
&lt;li&gt;毫无成就感&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
2016 年，这方面的学习将继续，但是学习方法需要调整。
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
还有一些零碎的事情，比如:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;换了 iPhone 6s，幸福感大大提高 —— 倒不是不喜欢 Android，主要是 Android 需要刷机、进行权限管理、防范病毒入侵，而这些事情无疑是会消耗大量精力的&lt;/li&gt;
&lt;li&gt;买了 HHKB，Emacer 表示很幸福&lt;/li&gt;
&lt;li&gt;去年买的 Kindle 丢了，然后买了个 Paperwhite，更轻巧分辨率更高，也是一件开心的事情(咦丢了东西为什么开心)&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
以上是生活上的一些情况，而在专业能力上，则有以下变化:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;掌握了 Python 语法和工程知识&lt;/li&gt;
&lt;li&gt;了解或掌握了以下工具:

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Flask&lt;/li&gt;
&lt;li&gt;Requests&lt;/li&gt;
&lt;li&gt;Redis&lt;/li&gt;
&lt;li&gt;Tesseract&lt;/li&gt;
&lt;li&gt;SQLAlchemy&lt;/li&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;Django&lt;/li&gt;
&lt;li&gt;Imagemagick&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;掌握了搜索引擎的基本原理&lt;/li&gt;
&lt;li&gt;掌握了 OCR 的基本原理&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
我对自己这一年来的专业技能上的进步是不太满意的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;2016 年展望与计划&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
先说大的目标，再定细的计划。
&lt;/p&gt;

&lt;p&gt;
大的目标:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;生活方面，希望能:

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;提高身体素质&lt;/li&gt;
&lt;li&gt;多跟别人交流，提高自己的社交能力，改善自己的精神、心理状况&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
专业能力方面
&lt;/p&gt;

&lt;p&gt;
2014 年，我在工作中学会了分析问题、解决问题；2015 年，我在两个领域(搜索、OCR)有了初步的、系统的理解，并且对一个完整产品的开发过程有了比较清晰的认识；2016 年，我希望自己能够拥有快速解决问题、快速实现自己想法的能力。
&lt;/p&gt;

&lt;p&gt;
为了达到上述目标，我需要:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;掌握后端开发的基础&lt;/li&gt;
&lt;li&gt;掌握移动端开发的基础&lt;/li&gt;
&lt;li&gt;了解运营和产品的基本概念&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
除此以外，在自己的长期职业方向上也要继续前进:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;继续学习 Machine Learning&lt;/li&gt;
&lt;li&gt;继续学习相关的数学知识&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;个人修养方面

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;提高阅读量&lt;/li&gt;
&lt;li&gt;练习并坚持写作&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;orgheadline4&quot;&gt;生活方面的计划&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
我并不喜欢健身房，2016 年依然不打算去健身房系统健身(至少目前是这样的)。
&lt;/p&gt;

&lt;p&gt;
公司离家大约是 6 公里，考虑早上起早一些走路上班，顺便为北京治霾做贡献。第一次考虑走路上班是在跟同事抱怨早上公交难挤的时候，开玩笑说 &quot;干脆走路上班好了&quot; ，后来看了下距离其实是能接受的。6 公里，百度地图显示耗时约 80 分钟，不考虑吃早饭的事情，8 点出门就能保证 9 点半到达公司了。
&lt;/p&gt;

&lt;p&gt;
再就是 2016 年想买一辆自行车，这样周末能比较方便地到处去逛逛，或者骑车上下班。
&lt;/p&gt;

&lt;p&gt;
提升社交能力的事情，我的打算是在 2016 年多去参加一些线下活动。我并不指望这一年就能有多么大的改观，但至少要保证自己习惯和别人交流这么一件事情。
&lt;/p&gt;

&lt;p&gt;
所以具体的计划如下:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
&lt;b&gt;每周至少两次&lt;/b&gt; 走路上班或下班
&lt;/p&gt;

&lt;p&gt;
我将在 2015 年 12 月 28 日早上进行第一次尝试，之后根据具体感受可能会对该计划有所调整
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;b&gt;每两周&lt;/b&gt; 参加一次线下活动，并进行记录&lt;/li&gt;
&lt;li&gt;&lt;b&gt;每周末&lt;/b&gt; 花费一个 &lt;b&gt;上午&lt;/b&gt; 进行无目的的漫游，比如随便坐上一辆公交车坐到终点站什么的，细节待定

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;时间定为 &lt;b&gt;上午&lt;/b&gt; ，确保至少有周末两天至少有一天早起&lt;/li&gt;
&lt;li&gt;我不喜欢大多数所谓的 &lt;b&gt;景点&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;保证自己能持续地接受外部环境刺激&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;orgheadline5&quot;&gt;专业能力方面的计划&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;p&gt;
首先是 &quot;产品-后端-移动端-运营&quot; 这个链条，我打算这么去做:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;持续地开发出一个个 App 或网站，通过开发过程来掌握产品设计、后端开发和移动端开发的基础知识和工具链&lt;/li&gt;
&lt;li&gt;运营一个微信公众号，将开发记录通过它进行发布，对于完成度较高且更具实用性的产品，也通过它来进行推广&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
不过我对这整个过程现在都没有很清晰的认识，所以不太好确定时间安排。暂且先做如下计划:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;2016 年第一季度先进行工具链的了解、资源(服务器、公众号)的准备以及初步的 idea 收集&lt;/li&gt;
&lt;li&gt;后三个季度，每两个月完成一个产品，其中 8 月份中断一个月进行总结和计划的修正(如果有必要)&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
在 Machine Learning 方面，希望在 2016 年达到以下目标:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;通读《统计学习方法》、《The Elements of Statistical Learning》、《Neural Networks and Learning Machine》三本书&lt;/li&gt;
&lt;li&gt;掌握几种较常用的神经网络结构的原理与应用&lt;/li&gt;
&lt;li&gt;掌握文本分类、聚类的常用方法和工具&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
从目前来看，我对自己在 Machine Learning 方向上的学习目标不是很明确，所以后续可能还需要多思考一些。
&lt;/p&gt;

&lt;p&gt;
相关的计划如下:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;2016 年 1 月，掌握 Numpy, Pandas, Theano 这三个 Python 的库&lt;/li&gt;
&lt;li&gt;2016 年 2 月 - 2015 年 3 月，学习完 《Deep Learning Tutorials》&lt;/li&gt;
&lt;li&gt;每天早上用一小时的时间阅读《统计学习方法》、《The Elements of Statistical Learning》、《Neural Networks and Learning Machine》这三本书&lt;/li&gt;
&lt;li&gt;2015 年 4 月对 Machine Learning 的学习进行总结，然后进行后续的计划制订&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
文本分类、聚类的方法和工具会在我的工作中涉及到，因此此处不做具体规划。
&lt;/p&gt;

&lt;p&gt;
至于数学方面的学习，暂定如下:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;2016 年第一季度完成线性代数的学习&lt;/li&gt;
&lt;li&gt;2016 年第二季度完成概率论与统计学的学习&lt;/li&gt;
&lt;li&gt;2016 年第三季度完成微积分的学习&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline6&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;orgheadline6&quot;&gt;个人修养方面的计划&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-orgheadline6&quot;&gt;
&lt;p&gt;
阅读方面，目前我并没有形成自己的个人风格和习惯，所以对于阅读的主题目前不能做出很好的规划，因此只是做如下计划:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
每天保证两小时的阅读量
&lt;/p&gt;

&lt;p&gt;
每天下班回到家到入睡之间至少是有三个小时的，减少游戏时间是能保证的。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;在偿还完自己的阅读债务(借鉴 &quot;技术债务&quot;)前，不再购买新书&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
具体细节将会在季度计划、月度计划中进行展开，当然这部分就不会再发布到博客上来了 :)
&lt;/p&gt;

&lt;p&gt;
在写作方面，希望能在 2016 年养成坚持写作的习惯，相关的计划如下:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;坚持每天记录日记&lt;/li&gt;
&lt;li&gt;2016 年第一季度，保证每周至少 1000 字的非日记写作，目前考虑在简书上进行这件事情&lt;/li&gt;
&lt;li&gt;2016 年 4 月份进行总结和调整&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>Redis 性能分析与优化</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/12/16/redis-performance-analysis.html"/>
    <category term="Redis" scheme="http://www.zmonster.me/categories.html#Redis"/>
    <id>http://www.zmonster.me/2015/12/16/redis-performance-analysis</id>
    <published>2015-12-16T00:00:00+00:00</published>
    <updated>2015-12-16T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


Redis 简介
从遇到的问题说起
用于分析 Redis 性能的一些命令(参数)

redis-cli 参数
redis-cli 子命令


Redis ...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;Redis 简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;从遇到的问题说起&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;用于分析 Redis 性能的一些命令(参数)&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;redis-cli 参数&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;redis-cli 子命令&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline6&quot;&gt;Redis 使用的一点点经验&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;Redis 简介&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
Redis 是一个 key-value 内存存储系统，并且支持丰富的数据结构，包括:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;string&lt;/li&gt;
&lt;li&gt;list&lt;/li&gt;
&lt;li&gt;hash table&lt;/li&gt;
&lt;li&gt;set(集合)&lt;/li&gt;
&lt;li&gt;zset(有序集合)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
其体量很小，但却支持丰富的数据结构和相应的操作方式，是一个非常好的工具。
&lt;/p&gt;

&lt;p&gt;
然而像很多工具一样，Redis 也有一些坑，我也是被坑过一段时间的……
&lt;/p&gt;

&lt;p&gt;
当然，这里就不对 Redis 的数据结构及操作做过多说明了，可能的话单独再写一篇文章，不过考虑网上类似的文章实在不少，估计是不会去写了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;从遇到的问题说起&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
目前我负责的一个项目使用着 Redis ，在 10 月中下旬的时候发现往 Redis 写数据的定时任务频繁 timeout ，同时从同一个 Redis 读数据的线上项目的 log 也显示经常一些读操作耗时增长了十倍甚至更多。
&lt;/p&gt;

&lt;p&gt;
发现问题的时候，首先怀疑是不是自己代码里的逻辑写得有问题，花了两天时间把相关的代码翻来覆去看了好几遍，虽然是有一些地方有待优化，但这些地方的问题是不足以引发前面说的问题的。而在我为代码中每个 Redis 操作都加上了超时检测后，发现甚至连 &lt;b&gt;get&lt;/b&gt; 这样的操作都会发生超时(所取的 key 的 value 并不大)后，就已经大致明白应该和我的代码没有关系。
&lt;/p&gt;

&lt;p&gt;
找 SA 要来 Redis server 所在服务器上的帐号后开始跑脚本往 Redis 写数据，同时监控 Redis server 的 log ，最后发现了这么一条 log:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
[25206] 04 Nov 17:34:41.090 * Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting     for fsync to complete, this may slow down Redis.
&lt;/pre&gt;

&lt;p&gt;
&lt;b&gt;this may slow down Redis&lt;/b&gt; !
&lt;/p&gt;

&lt;p&gt;
原来，这个 Redis server 的持久化方式是 RDB+AOF，而上述警告信息是因为 AOF 操作造成的。有了这个明确的警告信息后，再去网上搜索就找到了不少类似的案例:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://engineering.sharethrough.com/blog/2013/06/06/how-redis-took-us-offline-and-what-we-did-about-it/&quot;&gt;how redis took us offline and what we did about it&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/twitter/twemproxy/issues/248&quot;&gt;logs of timeout in someone second #248&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
各种迹象都说明我遇到的问题是和这条警告信息密切相关的，于是回过头重新启动脚本，并且监控 Redis server 日志中包含 &quot;Asynchronous AOF fsync is taking too long&quot; 的内容。经过一个下午的观察，确定超时错误与这条日志是同时出现的。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/redisdebugger.png&quot; alt=&quot;redisdebugger.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
最后的解决办法是在 Redis master 上关闭了 AOF。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;用于分析 Redis 性能的一些命令(参数)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
都是在解决上面提到的问题的过程中，所了解到的 tricks。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline4&quot;&gt;redis-cli 参数&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
&amp;#x2013;bigkeys
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;redis-cli -h &amp;lt;host&amp;gt; -p &amp;lt;port&amp;gt; -n &amp;lt;db&amp;gt; --bigkeys
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这条命令会从指定的 Redis DB 中持续采样，实时输出当时得到的 &lt;b&gt;value&lt;/b&gt; 占用空间最大的 &lt;b&gt;key&lt;/b&gt; 值，并在最后给出各种数据结构的 &lt;b&gt;biggest key&lt;/b&gt; 的总结报告:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
user $ redis-cli -h myhost -p 12345 --bigkeys

# Scanning the entire keyspace to find biggest keys as well as
# average sizes per key type.  You can use -i 0.1 to sleep 0.1 sec
# per 100 SCAN commands (not usually needed).

[00.00%] Biggest hash   found so far 'idx:同类项' with 1 fields
[00.00%] Biggest hash   found so far 'idx:格点' with 3 fields
[00.00%] Biggest hash   found so far 'idx:任意' with 14 fields
[02.29%] Biggest hash   found so far 'idx:设' with 16 fields
[02.29%] Biggest hash   found so far 'idx:4' with 69 fields
[04.45%] Biggest set    found so far 'indexed_word_set' with 1482 members
[05.93%] Biggest hash   found so far 'idx:c' with 159 fields
[11.79%] Biggest hash   found so far 'idx:的' with 196 fields

-------- summary -------

Sampled 1484 keys in the keyspace!
Total key length in bytes is 13488 (avg len 9.09)

Biggest    set found 'indexed_word_set' has 1482 members
Biggest   hash found 'idx:的' has 196 fields

0 strings with 0 bytes (00.00% of keys, avg size 0.00)
0 lists with 0 items (00.00% of keys, avg size 0.00)
2 sets with 1710 members (00.13% of keys, avg size 855.00)
1482 hashs with 6731 fields (99.87% of keys, avg size 4.54)
0 zsets with 0 members (00.00% of keys, avg size 0.00)
&lt;/pre&gt;

&lt;p&gt;
这条命令给出的 &quot;big key&quot; ，是值得去分析一下的。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
&amp;#x2013;latency, &amp;#x2013;latency-history
&lt;/p&gt;

&lt;p&gt;
这两条命令用来测试 Redis 服务端的响应延迟，&amp;#x2013;latency 的输出是这样的
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
min: 7, max: 1230, avg: 66.22 (89 samples)
&lt;/pre&gt;

&lt;p&gt;
&amp;#x2013;latency-history 的输出是这样的:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
min: 7, max: 3332, avg: 157.41 (91 samples) -- 15.23 seconds range
min: 6, max: 774, avg: 75.69 (176 samples) -- 15.10 seconds range
min: 7, max: 1631, avg: 93.49 (147 samples) -- 15.23 seconds range
min: 7, max: 714, avg: 67.90 (194 samples) -- 15.14 seconds range
min: 7, max: 809, avg: 95.09 (143 samples) -- 15.04 seconds range
&lt;/pre&gt;

&lt;p&gt;
两者的区别在于前者显示的是持续的采样结果，而后者则只输出一段时间内的采样结果。
&lt;/p&gt;

&lt;p&gt;
用这两个参数可以判断客户端与服务端之间的网络通信造成的延迟对整体延迟的影响，方法是在 Redis Server 所在的服务器上使用 &amp;#x2013;latency/&amp;#x2013;latency-history 得到大致的延迟结果，然后在客户端所在机器上同样得到延迟情况进行对比。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline5&quot;&gt;redis-cli 子命令&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
slowlog 命令
&lt;/p&gt;

&lt;p&gt;
默认的 Redis server 配置中有这么两条:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-conf&quot;&gt;slowlog-log-slower-than 10000
slowlog-max-len 128
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这两条配置会产生这样的效果: 如果一条命令的响应时间超过了 10000us (即 10ms) ，那么将会作为 &quot;slow command&quot; 被记录，并且将只保留最新的 &lt;b&gt;128 条&lt;/b&gt; 记录。
&lt;/p&gt;

&lt;p&gt;
需要说明的是，这里所说的 &lt;b&gt;响应时间&lt;/b&gt; 不包括客户端与服务端之间的通信开销，仅仅指命令在 Redis server 中的执行时间消耗。
&lt;/p&gt;

&lt;p&gt;
使用 slowlog 这个子命令可以获取当前的这些记录:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
127.0.0.1:6379&amp;gt; slowlog get 3
1) 1) (integer) 26
   2) (integer) 1450253133
   3) (integer) 43097
   4) 1) &quot;flushdb&quot;
2) 1) (integer) 25
   2) (integer) 1450252804
   3) (integer) 33115
   4) 1) &quot;flushdb&quot;
3) 1) (integer) 24
   2) (integer) 1450248951
   3) (integer) 3328650
   4) 1) &quot;flushdb&quot;
&lt;/pre&gt;

&lt;p&gt;
在不指定记录数量的情况下(slowlog get)，默认返回 10 条记录，每条记录包含四个字段，以下面这个为例来说明
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
1) (integer) 26
2) (integer) 1450253133
3) (integer) 43097
4) 1) &quot;flushdb&quot;
&lt;/pre&gt;

&lt;p&gt;
第一个字段表示该条记录在所有慢日志中的序号，最新的记录被展示在最前面；
&lt;/p&gt;

&lt;p&gt;
第二个字段是这条记录被记录时的系统时间，可以用 &lt;b&gt;date&lt;/b&gt; 命令来将其转换为友好的格式:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;linusp $ date -d @1450253133
2015&amp;#24180; 12&amp;#26376; 16&amp;#26085; &amp;#26143;&amp;#26399;&amp;#19977; 16:05:33 CST
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
第三个字段表示这条命令的响应时间，单位为 us (微秒)；
&lt;/p&gt;

&lt;p&gt;
第四个字段为对应的 Redis 操作。
&lt;/p&gt;

&lt;p&gt;
因此上面这个例子的含义就是: 在 2015 年 12 月 16 日 16 时 5 分 33 秒执行的 flushdb 操作耗时 43ms ，因为超过了设定的值被记录到慢日志中。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
info
&lt;/p&gt;

&lt;p&gt;
顾名思义，这个子命令用来获取 Redis server 的一些信息，这些信息按照内容被分成了很多部分，可以用额外的参数来单独获取，如下:
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;参数名&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;server&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;获取 server 信息，包括 version, OS, port 等信息&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;clients&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;获取 clients 信息，如客户端连接数等&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;memory&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;获取 server 的内存信息，包括当前内存消耗、内存使用峰值&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;persistence&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;获取 server 的持久化配置信息&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;stats&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;获取 server 的一些基本统计信息，如处理过的连接数量等&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;replication&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;获取 server 的主从配置信息&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;cpu&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;获取 server 的 CPU 使用信息&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;keyspace&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;获取 server 中各个 DB 的 key 的数量&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;cluster&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;获取集群节点信息，仅在开启集群后可见&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;commandstas&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;获取每种命令的统计信息，非常有用&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
挑几个个人觉得有用的部分再详细说明一下.
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
info memory
&lt;/p&gt;

&lt;p&gt;
输出如下:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
# Memory
used_memory:17348250392
used_memory_human:16.16G
used_memory_rss:14339567616
used_memory_peak:17348362312
used_memory_peak_human:16.16G
used_memory_lua:33792
mem_fragmentation_ratio:0.83
mem_allocator:jemalloc-3.0.0
&lt;/pre&gt;

&lt;p&gt;
了解 Redis server 的内存占用是很有必要的
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
info keyspace
&lt;/p&gt;

&lt;p&gt;
输出如下:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
db0:keys=52021100,expires=0,avg_ttl=0
db1:keys=520062,expires=0,avg_ttl=0
db2:keys=559810,expires=0,avg_ttl=0
db4:keys=513887,expires=0,avg_ttl=0
&lt;/pre&gt;

&lt;p&gt;
由于 Redis 要为每个 key 维护一些入口信息，因此 key 会比 value 中的对象额外消耗一些内存，当 key 的数量太多的时候会多消耗不少内存。一些优化 Redis 内存占用的方法基本都是基于减少 key 的数量以及减少 key 的平均长度这两个思路。
&lt;/p&gt;

&lt;p&gt;
key 的数量太多时可以使用 hash 结构将 key 进行分隔成两部分来减少数量，当然这个要看是否能满足具体的业务、功能需求了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
info commandstats
&lt;/p&gt;

&lt;p&gt;
其输出如下:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
cmdstat_get:calls=774811168,usec=2567380170,usec_per_call=3.31
cmdstat_set:calls=4616783,usec=17308580,usec_per_call=3.75
cmdstat_append:calls=290375669,usec=2051415709,usec_per_call=7.06
cmdstat_exists:calls=41374218,usec=72561479,usec_per_call=1.75
cmdstat_sadd:calls=60640,usec=540252,usec_per_call=8.91
cmdstat_sismember:calls=3,usec=16,usec_per_call=5.33
cmdstat_smembers:calls=1863495,usec=253706917,usec_per_call=136.15
cmdstat_incrby:calls=114499073,usec=157843782,usec_per_call=1.38
cmdstat_keys:calls=1,usec=79743,usec_per_call=79743.00
cmdstat_multi:calls=4618103,usec=6087466,usec_per_call=1.32
cmdstat_exec:calls=4618103,usec=2597435761,usec_per_call=562.45
cmdstat_replconf:calls=335,usec=512,usec_per_call=1.53
cmdstat_flushdb:calls=5,usec=842393,usec_per_call=168478.59
cmdstat_info:calls=825297,usec=39131868,usec_per_call=47.42
cmdstat_slowlog:calls=23,usec=22646,usec_per_call=984.61
......
&lt;/pre&gt;

&lt;p&gt;
输出中包含处理过的每一种命令的调用次数、消耗的总 CPU 时间(单位 ms)以及平均 CPU 耗时，这对了解自己的程序所使用的 Redis 操作情况非常有用。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline6&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline6&quot;&gt;Redis 使用的一点点经验&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline6&quot;&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;管理好自己的 key，比如用一个 set 来存放所有同类型的 key，这样可以避免使用 keys 来获取该类型所有 key，由于 Redis 是单线程的，在数据量大的情况下将会阻塞 Redis 中其他的操作&lt;/li&gt;
&lt;li&gt;如果不能避免使用 keys 操作，那么使用 scan 来替代，将遍历 Redis DB 中所有 key 的操作放到客户端来做，这样就不会导致其他操作被阻塞了&lt;/li&gt;
&lt;li&gt;在数据量大的情况下，key 或 value 的微小的压缩也能带来不小的内存使用提高&lt;/li&gt;
&lt;li&gt;hash 结构是个好东西，但是它只支持一级 hash，所以如果需要使用多级 hash，那就进行序列化吧&lt;/li&gt;
&lt;li&gt;注意客户端和服务端之间的网络通信情况(&amp;#x2013;latency/&amp;#x2013;latency-history)&lt;/li&gt;
&lt;li&gt;Redis 的 python 接口返回的 key 的类型和 value 中的最小结构的类型都是 string，记得转换成自己需要的类型&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>文本相似度量方法(1): 概览</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/11/15/text_similarity_survey.html"/>
    <category term="NLP" scheme="http://www.zmonster.me/categories.html#NLP"/>
    <id>http://www.zmonster.me/2015/11/15/text_similarity_survey</id>
    <published>2015-11-15T00:00:00+00:00</published>
    <updated>2015-11-15T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


距离度量与相似度量
文本相似度量方法一览
String Based Methods

Character Based Methods
Term Based...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org681fedd&quot;&gt;距离度量与相似度量&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf530886&quot;&gt;文本相似度量方法一览&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd5ee168&quot;&gt;String Based Methods&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga6ab31d&quot;&gt;Character Based Methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgda83040&quot;&gt;Term Based Methods&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org7b7a384&quot;&gt;Corpus Based Methods&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgf98ef20&quot;&gt;Language Model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge4d8871&quot;&gt;Topic Model&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org681fedd&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org681fedd&quot;&gt;距离度量与相似度量&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org681fedd&quot;&gt;
&lt;p&gt;
距离度量或相似度量是被广泛应用的概念，简单来说，可以这么认为:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;距离度量是度量两个“物体”之间的差异程度的&lt;/li&gt;
&lt;li&gt;相似度量是度量两个“物体”之间的近似程度的&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
在数学上，这两者都有严格的定义，比如说一个严格意义上的距离度量，是应该满足以下几个条件的:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;对称性，即 \(d(A, B) = d(B, A)\)&lt;/li&gt;
&lt;li&gt;非负性，即 \(\forall A\forall B, d(A, B) \ge 0\)&lt;/li&gt;
&lt;li&gt;一致性，即 \(A = B\Leftrightarrow d(A, B) = 0\)&lt;/li&gt;
&lt;li&gt;次可加性(subadditivity)/三角不等式，即 \(d(A, B) \le d(A, C) + d(C, D)\)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
严格意义上的相似度量也有类似的限制，比较基本的两条有:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;如果 \(A\) 和 \(B\) 完全不同，那么 \(s(A, B) = 0\)&lt;/li&gt;
&lt;li&gt;如果 \(A\) 和 \(B\) 完全相同，那么 \(s(A, B) = 1\)&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
距离度量和相似度量是互有关联的，在一些具体的方法中，甚至是可以互相转换的，后续谈到的一些具体的度量方法，其原始目的就是度量距离的。但这两者仍然是有区别的，为了防止混淆，我会尽量统一表示成相似度量。
&lt;/p&gt;

&lt;p&gt;
另外一点需要注意的是，由于具体应用场景的限制或者特殊的需求，往往不一定会应用严格意义的相似度量方法 —— 对这些方法，称之为“度量”其实是不严谨的，但为了表述上的一致，我将保持这种用法。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf530886&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf530886&quot;&gt;文本相似度量方法一览&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf530886&quot;&gt;
&lt;p&gt;
此处的“文本”一词涵盖以下两个对象:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;字符串/序列&lt;/li&gt;
&lt;li&gt;包含较多文本内容的文档&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
相关的度量方法可以分为两大类，各类下面再有一些具体的分类，比较常用的方法如见下图
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/similarity_survey.png&quot; alt=&quot;similarity_survey.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
总的来说，文本相似度量方法可以分为两大类:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;String Based，即基于待比较的文本本身中的信息，该类方法评估的是”词法“上的相似性，或说朴素的相似性&lt;/li&gt;
&lt;li&gt;Corpus Based，即基于一个较大的文本集合中的信息，该类方法评估的是“语义”上的相似性&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
这些方法被普遍应用于以下领域:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;信息检索&lt;/li&gt;
&lt;li&gt;文档分类&lt;/li&gt;
&lt;li&gt;文档聚类&lt;/li&gt;
&lt;li&gt;主题检测&lt;/li&gt;
&lt;li&gt;自动问答&lt;/li&gt;
&lt;li&gt;自动摘要&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd5ee168&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgd5ee168&quot;&gt;String Based Methods&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgd5ee168&quot;&gt;
&lt;p&gt;
要比较两个文本的相似性，比较直观的方法是逐个字符比对，看看有多少个字符是一致的 —— String Based 的方法就是从这种思路中发展出来的。其中以字符为单位去比较的方法被统称为 Character Based，而以词为单位的则被称为 Term Based。
&lt;/p&gt;

&lt;p&gt;
Character Based 的方法普遍用来进行较短文本、小规模的比较，会注意文本中各字符的顺序和位置；Term Based 的方法则更适合用来进行较长文本或大规模的比较，而且通常会抛弃文本中各个单元(通常是词)之间的顺序、位置信息 —— 一般的做法是用文本中的词组成的向量来表示文本，也就是所谓的“向量空间模型(Vecter Space Model, &lt;b&gt;VSM&lt;/b&gt;)”。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga6ab31d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga6ab31d&quot;&gt;Character Based Methods&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga6ab31d&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
最长公共子序列(Longest Common Subsequence, LCS)
&lt;/p&gt;

&lt;p&gt;
LCS 方法通过计算出两个字符串/序列之间的最长公共子序列，并使用这个子序列的长度来反映两个字符串/序列之间的相似程度。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
编辑距离(Leveinshtein Distance)
&lt;/p&gt;

&lt;p&gt;
在两个字符串的比较中应用编辑距离时，通常会有一者作为”标准字符串“，另一者则作为”可能错误“的字符串，通过将后者变换成前者所进行的字符的 &lt;b&gt;插入&lt;/b&gt; 、 &lt;b&gt;删除&lt;/b&gt; 或 &lt;b&gt;替换&lt;/b&gt; 操作次数作为衡量两者差异程度的指标。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
扩展的编辑距离(Damerau-Levenshtein Distance)
&lt;/p&gt;

&lt;p&gt;
扩展的编辑距离在思想上与编辑距离一样，只是除插入、删除和替换操作外，还支持 &lt;b&gt;相邻字符的交换&lt;/b&gt; 这样一个操作，增加这个操作的考虑是人们在计算机上输入文档时的错误情况中，因为快速敲击而前后两个字符的顺序被输错的情况很常见。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Needleman-Wunsch Similarity
&lt;/p&gt;

&lt;p&gt;
该方法被广泛运用于生物信息学中的序列比对，如氨基酸序列比对、核苷酸序列比对等。其基本思路与编辑距离相近，但在编辑距离中，三种不同的错误情况是平等的，而在生物信息学中，序列中的单元缺失情况比错误(位置匹配但内容不同)情况更不能容忍，因此在 Needleman-Wunsch 方法中，插入错误和删除错误会被赋予较高的惩罚分数。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Smith-Waterman Similarity
&lt;/p&gt;

&lt;p&gt;
Smith-Waterman 方法用于生物信息学中的序列比对，但与 Needleman-Wunsch 方法不一样，它是一个 &lt;b&gt;局部最优比对&lt;/b&gt; 方法，简单来说，它的目的是找出两个序列之间 &lt;b&gt;连续且相同&lt;/b&gt; 的子序列。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Jaro Similarity 和 Jaro-Winkler Similarity
&lt;/p&gt;

&lt;p&gt;
Jaro 方法和 Jaro-Winkler 方法考虑两个字符串之间相同字符的顺序位置和个数，只适用于像人名这样的较短字符串之间的比较。其中 Jaro-Winkler 方法是对 Jaro 方法的改进，而 Jaro 方法现在已经不常用。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Hamming Distance
&lt;/p&gt;

&lt;p&gt;
Hamming 距离用于 &lt;b&gt;长度相同&lt;/b&gt; 的序列之间的比较，思想非常简单，就是逐位比较得到的不同次数。Hamming 距离被广泛应用于信息学。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgda83040&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgda83040&quot;&gt;Term Based Methods&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgda83040&quot;&gt;
&lt;p&gt;
Term Based 方法中的 term 不一定是词，也可以是关键词、短语，当选定”词“作为 term 时，可以用 Bag-of-Words Model(BOW) 来更精确地描述此时的模型。为了表述上的方便，本系列文章将此处的 term 视为词。
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
Cosine Similarity
&lt;/p&gt;

&lt;p&gt;
余弦相似度建立在用向量表示文档的前提上。两个文档的向量，同一个维度应该是表示的同一个词，而每一个维度的值，一般是用”词频-逆文档频率(Term Frequency-Inverse Document Frequency, &lt;b&gt;TF-IDF&lt;/b&gt;)“ 来表示。
&lt;/p&gt;

&lt;p&gt;
建立向量表示后，通过计算两个向量之间的夹角大小来衡量两个文档之间的近似程度，由于夹角的余弦值的计算方便，而且天然地处在 0 和 1 之间，故一般是用夹角的余弦值而不是夹角的大小来作为度量。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Dice's Coefficient 和 Jaccard Similarity
&lt;/p&gt;

&lt;p&gt;
Dice 系数和 Jaccard 相似性起初被用于生态学上，作为一种判断物种间相似性的方法。在生态学上，要比较两个物种间相似程度时，通常会对该物种的特性进行采样，最后得到各自的特性集合，而 Dice 系数和 Jaccard 相似性都是通过比较两者之间的 &lt;b&gt;共有特性&lt;/b&gt; 占比来度量相似性的，因此这两种方法都不是很关心每个 &quot;Term&quot; 的具体量，只是关心有没有某个 &quot;Term&quot;。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org7b7a384&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org7b7a384&quot;&gt;Corpus Based Methods&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org7b7a384&quot;&gt;
&lt;p&gt;
Corpus Based 方法通过对大量文档的统计分析得到语义上的相似，这里 “大量文档” 就是 Corpus 即语料了。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf98ef20&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf98ef20&quot;&gt;Language Model&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgf98ef20&quot;&gt;
&lt;p&gt;
常见的语言模型(Language Model, LM)都基于马尔可夫假设(Markov Assumption)，即认为语言中每个词只与其前面长度为 N-1 个词有关 —— 这 N-1 个词其实就构成了该词的上文，同时由于每个词都会成为其他词的上文，下文信息也会得到表现。也就是说，语言模型统计的其实是语言中每个词的一定程度的上下文情况。基于语言模型的这个特点，以及下面这样一个假设:
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
   具有相同(或相近)上下文的词，其语义是相近的。
&lt;/pre&gt;

&lt;p&gt;
就可以用语言模型来进行文本的相似度量了。具体一点，有两种方式:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;通过语言模型来发现同义词、近义词，来弥补 Term Based Methods 的缺陷；&lt;/li&gt;
&lt;li&gt;扩大 &quot;term&quot; 的表示范围，比如说按照词组来进行统计，甚至按照句子来进行统计，那么就可以反映词组之间的相似性、句子之间的相似性了。&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge4d8871&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge4d8871&quot;&gt;Topic Model&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orge4d8871&quot;&gt;
&lt;p&gt;
主题模型与向量空间模型有共同的一点是也是基于 BOW 模型的，也就是说，并不像语言模型一样考虑词与词之间的顺序、位置，而只是通过词与词的共现(Co-occurrence)来反映词与词之间的相似性。
&lt;/p&gt;

&lt;p&gt;
主题模型是一种无监督的方法，与聚类方法在外在表现上会有一定的相似性，但它们各自的内在原理是相差较大的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>对算法工程师一职的思考</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/10/11/algorithm-engineer.html"/>
    <category term="算法" scheme="http://www.zmonster.me/categories.html#算法"/>
    <id>http://www.zmonster.me/2015/10/11/algorithm-engineer</id>
    <published>2015-10-11T00:00:00+00:00</published>
    <updated>2015-10-11T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


从做过的工作说起
再谈这个职位
参考




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;从做过的工作说起&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;再谈这个职位&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;参考&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
如果要我想别人做自我介绍，那么大概我会这样来描述自己:
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
我是一个热爱幻想小说的理智而沉默的人，目前在一家在线教育公司中从事算法工程师一职。
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
然而有时候我发现自己并不能向别人很好地解释清楚”算法工程师“的具体含义，进而只好列举自己当前的工作内容。按理说作为算法工程师，我自己应该是对这个职位有足够的理解，但当我自问算法工程师究竟为何时，得到的也是含糊不清的回答。
&lt;/p&gt;

&lt;p&gt;
我尝试去梳理自己对这个职位的理解，并记录下来，如果以后能一直从事相关工作，再回过头来看这篇文章，大概也会别有一番趣味。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;从做过的工作说起&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
作为一个算法工程师的我，做过什么工作呢？从项目的角度上来说，主要有这么几个:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;说话人分割(Speaker Diarization): 对一段音频，确定 &lt;b&gt;何人在何时说话&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;情感识别: 对一段音频，判断说话者在其中表达的是 &lt;b&gt;正面的情感&lt;/b&gt; 还是 &lt;b&gt;负面的情感&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;题库搜索&lt;/li&gt;
&lt;li&gt;OCR&lt;/li&gt;
&lt;li&gt;学生能力评估&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
以上工作，都需要设计一个完整的算法或“系统”来去解决，然而这里作为一个具体解决方案的“算法”和“系统”，与普通的项目解决方案有什么本质上的区别呢？
&lt;/p&gt;

&lt;p&gt;
第一点不同是，以上问题的“输入”都存在很大的不确定因素，而且对这些不确定因素不易检测和处理。对于普通的软件、APP以及网站来说，所谓的输入(主要为用户操作)，是会限定在一个有限集合中的，因而可以按照设计好的逻辑进行处理；但在上述具体项目中，无法保证输入是符合要求的，对输入数据的处理(过滤、规整、变换)——即所谓的“预处理”是系统中的必需部分。
&lt;/p&gt;

&lt;p&gt;
数据的预处理，在算法岗涉及的工作中，是非常重要的。核心的算法，在学术界的推动下，都有很多成熟、可靠的选择，但这些算法，往往都对输入的数据有严苛的要求，数据的预处理如果做得不好，再好的核心算法往往也无能为力。 但由于输入数据天然的不稳定性和复杂性，数据预处理往往也是烦琐而复杂的，需要根据实际的业务情况和数据情况设置各种各样的规则来处理。对于一些成熟的领域如语音、图像，异常数据的种类是有限的，因此也有通用的处理方法，所谓的“去噪”就是图像和语音识别中比较重要的预处理方法；但业务情况却随产品的定位和功能而千变万化，这就需要算法工程师对具体产品的业务有深入的理解。
&lt;/p&gt;

&lt;p&gt;
以我做过的“说话人分割项目“来说，在预处理阶段，需要做这些事情:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
音频格式转换
&lt;/p&gt;

&lt;p&gt;
收到的客户的音频数据往往格式杂乱，而且这些音频为了便于保存和传输，大都是经过压缩的格式，在进行转换后可能会有一定程度的失真。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
去除明显的非人声和静音，所谓非人声包括: 通信噪音、场景噪音、音乐
&lt;/p&gt;

&lt;p&gt;
对于与人声不重叠的非人声，可以通过语音活性检测(Voice Activity Detection, VAD)来进行区分，难点在于如何处理与人声混杂在一起的噪声。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
定位不同说话人连续语音的起始和结束点
&lt;/p&gt;

&lt;p&gt;
如果有两个人(甚至三个人以上)同时在说话，那么这个起始和结束点会不准确。
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
此外还有一些干扰情况，如音频是无效的、损坏的数据 —— 这种情况往往不多，但由于混杂在大量正常数据中，往往直到造成了问题才会被发现。
&lt;/p&gt;

&lt;p&gt;
其他几个项目同样面临这个问题，甚至在一些项目上，数据如何才算有效、健康都尚待定义，这种情况数据预处理更为艰难。
&lt;/p&gt;

&lt;p&gt;
但数据还不是影响算法工程师工作的首要环节，需求才是。
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
需求 &amp;gt; 数据 &amp;gt; 系统 &amp;gt; 算法
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
算法工程师，首先是作为工程师存在的，其工作成果当然也要为实际需求服务；其次，算法工程师的项目不会是孤立的，必然会和其他项目有关联。对项目提出的直接需求，以及对相关联项目的需求，都会对项目有很大影响:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;需求会决定数据的来源和质量&lt;/li&gt;
&lt;li&gt;需求会决定算法实现的复杂性&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
当然了，这一点不是算法工程师与其他开发人员的工作内容上的差异，因为其他开发人员同样要受到业务需求的影响。
&lt;/p&gt;

&lt;p&gt;
也许有人会觉得算法工程师处理的问题都需要高深的理论基础，但其实不是的，或者说不单纯是。从项目实现角度上来说，现在已经有了非常多的、高效的系统和框架，各种具体的算法也有成熟的实现，单纯想要建立一个解决问题的系统，非算法工程师只要了解一下相关的专有名词，根据业务需求调研使用何种框架或库，熟读相关的文档和 tutorial，也是可以做到的。但得到一个基本可用的系统后，由于之前提到的数据问题，以及系统本身的问题，是无法得到完美的结果的，需要通过大量数据进行持续的调优，而这个过程，是需要对业务情况和相关理论有较深的理解的。
&lt;/p&gt;

&lt;p&gt;
这是第二点不同，即项目需要使用大量的数据进行长期的观察、优化，从一个基本可用的项目到一个令人满意的项目，中间往往需要比较长的时间。
&lt;/p&gt;

&lt;p&gt;
以上是个人根据自身经历得到的一些体会。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;再谈这个职位&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
由于无法进行快速迭代，算法工程师的工作强度不算太大(相对而言)，而且一般待遇不错，这算是这个职位的优点了。而相对的，算法工程师的工作会比较枯燥，远没有外行人所想象的那么“酷”，而且大部分时间是在做工程化和调优，其实并没有太多时间去做探索性的工作。
&lt;/p&gt;

&lt;p&gt;
在我看来，要做好算法工程师的工作，首先确实需要有一定的理论基础，其次应该要一定的数据处理能力和意识，然后要有足够的耐心。另外一些人对算法工程师工作的看法的一个误区是，太过重视某种流行的模型、方法的作用，接触到问题后就想直接套用某个模型 —— 选择使用什么模型、方法应当慎之又慎，至少应当在对业务和数据有足够多的认识后再做决定，并且要有全局性的思维，从数据处理，特征工程，到模型，到结果解释，要对各个环节都有考虑。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;参考&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://www.cnblogs.com/aquastone/p/algorithm-technology-and-others.html&quot;&gt;算法、技术即其他&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.wentrue.net/blog/?p=1552&quot;&gt;算法工程师的三重境界&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://segmentfault.com/a/1190000000308327&quot;&gt;算法工程师的爱与哀愁&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>Tesseract: 训练(续)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/08/15/tesseract-training-again.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2015/08/15/tesseract-training-again</id>
    <published>2015-08-15T00:00:00+00:00</published>
    <updated>2015-08-15T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


更易配置和使用的训练工具

获取工具
配置
训练


字符识别歧义校正

旧版本格式
新版本格式


词典: DAWG 文件




续上篇: 《Tess...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;更易配置和使用的训练工具&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;获取工具&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;配置&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;训练&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;字符识别歧义校正&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline6&quot;&gt;旧版本格式&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline7&quot;&gt;新版本格式&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline8&quot;&gt;词典: DAWG 文件&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
续上篇: &lt;a href=&quot;http://linusp.github.io/2015/05/05/tesseract-training.html&quot;&gt;《Tesseract:训练》&lt;/a&gt;。本篇主要解释一下 DAWG 文件的生成方法，并提供一个更易用的训练工具。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;更易配置和使用的训练工具&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
Tesseract 自身提供的训练工具分为了多个不同的程序，用起来比较灵活，但说实话，要记住每个程序的使用方法还真是一件费力的事情。此外，为了得到较好的训练结果，往往会需要用多种字体进行训练，而不同的字体除了一两个参数(一般为字体名称、位置)不一样外，其他的过程、参数都是相似的，这里有大量的重复性操作。
&lt;/p&gt;

&lt;p&gt;
为此我写了一个更好的训练工具，只要开始时在配置文件中设置好字体、文本等信息，然后就可以敲击几个简单的命令进行训练。当然了，与此同时，训练过程中的灵活性会受到一定的影响。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline2&quot;&gt;获取工具&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
工具放在我的 Github 项目中，项目地址为:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
https://github.com/Linusp/zutil
&lt;/pre&gt;

&lt;p&gt;
项目 python 目录下的 tess_train.py 就是了
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline3&quot;&gt;配置&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
见项目 python/configs/ 目录下的 tess.json，其内容为:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;{
    &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;chi_eng&quot;&lt;/span&gt;,
    &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;font&quot;&lt;/span&gt;: {
        &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;wqy&quot;&lt;/span&gt;: {
            &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;font-dir&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;/usr/share/fonts/truetype&quot;&lt;/span&gt;,
            &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;sub-font&quot;&lt;/span&gt;: {
                &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;fixed&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;WenQuanYi Micro Hei&quot;&lt;/span&gt;
            }
        },
        &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;sun&quot;&lt;/span&gt;: {
            &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;font-dir&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;/home/linusp/datas/fonts/&quot;&lt;/span&gt;,
            &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;sub-font&quot;&lt;/span&gt;: {
                &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;serif&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;SimSun&quot;&lt;/span&gt;
            }
        },
        &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;nsun&quot;&lt;/span&gt;: {
            &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;font-dir&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;/home/linusp/datas/fonts/&quot;&lt;/span&gt;,
            &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;sub-font&quot;&lt;/span&gt;: {
                &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;serif&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;NSimSun&quot;&lt;/span&gt;
            }
        },
        &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;times&quot;&lt;/span&gt;: {
            &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;font-dir&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;/home/linusp/data/fonts/TimesNewRoman&quot;&lt;/span&gt;,
            &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;sub-font&quot;&lt;/span&gt;: {
                &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;italic&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Times New Roman, Italic&quot;&lt;/span&gt;,
                &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;bold&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Times New Roman, Bold&quot;&lt;/span&gt;,
                &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;serif&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Times New Roman,&quot;&lt;/span&gt;
            }
        }
    },
    &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;data&quot;&lt;/span&gt;: {
        &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;chi&quot;&lt;/span&gt;: {
            &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;file-name&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;chi.txt&quot;&lt;/span&gt;,
            &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;font-list&quot;&lt;/span&gt;: [&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;wqy&quot;&lt;/span&gt;, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;sun&quot;&lt;/span&gt;, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;nsun&quot;&lt;/span&gt;]
        },
        &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;eng&quot;&lt;/span&gt;: {
            &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;file-name&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;eng.txt&quot;&lt;/span&gt;,
            &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;font-list&quot;&lt;/span&gt;: [&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;wqy&quot;&lt;/span&gt;, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;times&quot;&lt;/span&gt;]
        }
    }
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到，配置文件内容分为三大块:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;name: 即最后生成的 traineddata 文件名称&lt;/li&gt;
&lt;li&gt;font: 要使用到的字体&lt;/li&gt;
&lt;li&gt;data: 要用于训练的文本，以及它们各自要使用的字体&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
name 和 data 这两块都比较易懂，这里只对 font 这一块多做一点说明。
&lt;/p&gt;

&lt;p&gt;
以其中的 times 为例:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;times&quot;&lt;/span&gt;: {
    &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;font-dir&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;/home/linusp/data/fonts/TimesNewRoman&quot;&lt;/span&gt;,
    &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;sub-font&quot;&lt;/span&gt;: {
        &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;italic&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Times New Roman, Italic&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;bold&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Times New Roman, Bold&quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;serif&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Times New Roman,&quot;&lt;/span&gt;
    }
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&quot;times&quot; 是这个字体的名称，用于区别其他字体，在训练过程中生成中间结果时也会用到。需要注意的是，一个名称不一定是只对应 &lt;b&gt;一个字体文件&lt;/b&gt; ，因为种字体除了它的普通形式外，还有斜体、粗体等不同样式，这些不同的样式可能是通过不同的字体文件来表现的。
&lt;/p&gt;

&lt;p&gt;
&quot;font-dir&quot; 就是字体文件所在的目录了，如上，如果要使用同一种字体的多种样式且它们在不同的字体文件中，请将它们放置到相同的目录下。
&lt;/p&gt;

&lt;p&gt;
&quot;sub-font&quot; 指定需要使用的字体样式，可用的有五种，分别是:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;italic: 斜体&lt;/li&gt;
&lt;li&gt;bold: 粗体&lt;/li&gt;
&lt;li&gt;serif: 衬线体&lt;/li&gt;
&lt;li&gt;fixed: 无衬线体&lt;/li&gt;
&lt;li&gt;fraktur: 哥特体&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
serif 和 fixed 都是字体的普通样式，但是这两者是只能有其一的，这是字体自身设计决定的。
&lt;/p&gt;

&lt;p&gt;
每种字体样式对应的 &lt;b&gt;真实字体名称&lt;/b&gt; ，可以用 text2image 来的到:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;text2image --fonts_dir=/home/linusp/data/fonts/TimesNewRoman --list_available_fonts
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline4&quot;&gt;训练&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
在设置好配置文件后，就可以方便地使用 tess_train.py 进行训练了， tess_train.py 的使用方法是:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;./tess_train.py -c &amp;lt;conf file&amp;gt; [-a &amp;lt;action&amp;gt;]
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
不使用 -a 选项时，会认为是一个全新的训练过程，并将处理整个训练过程，通过 -a 选项可以指定进行训练过程中的某个子步骤，以便更灵活地控制训练过程。可以使用的 &amp;lt;action&amp;gt; 有:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;tifbox: 用配置文件中 &quot;data&quot; 部分指定的文本生成图像和 BOX 文件&lt;/li&gt;
&lt;li&gt;charset: 提取字符集信息并生成字符集文件&lt;/li&gt;
&lt;li&gt;fontprop: 生成字体信息文件&lt;/li&gt;
&lt;li&gt;feature: 用之前生成的图像和 BOX 文件提取每个字符的特征&lt;/li&gt;
&lt;li&gt;cluster: 从特征文件产生每个字符的 &lt;b&gt;原型&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;combine: 将中间文件打包成 traineddata&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline5&quot;&gt;字符识别歧义校正&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;p&gt;
针对单个字符的识别，所谓歧义，包含以下三种情况(以下A, B皆为代指):
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;将字符 A 识别作字符 B&lt;/li&gt;
&lt;li&gt;将一个字符 A 识别多个字符&lt;/li&gt;
&lt;li&gt;将多个字符识别作一个字符 A&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
第一种情况就是典型的误分类情况，其后两种情况则和字符分割不正确有关系。
&lt;/p&gt;

&lt;p&gt;
对于这三种情况，Tesseract 提供了途径，以便在后处理时对识别结果进行校正。方法是在 traineddata 中添加 unicharambigs 这个 &lt;b&gt;歧义校正文件&lt;/b&gt; 。
&lt;/p&gt;

&lt;p&gt;
该文件有两种格式，旧版本格式在文件首行用 &lt;b&gt;v1&lt;/b&gt; 标识，对应的新版本的则用 &lt;b&gt;v2&lt;/b&gt; 标识。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;注意: 歧义校正文件应编码为 UTF-8&lt;/b&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline6&quot;&gt;旧版本格式&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline6&quot;&gt;
&lt;p&gt;
不管是哪个版本，unicharambigs 文件都是以文本文件的形式存在，并且每行一条校正规则。
&lt;/p&gt;

&lt;p&gt;
在旧版本格式中，每条校正规则是这样的:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
&amp;lt;字符数量&amp;gt; &amp;lt;字符串&amp;gt; &amp;lt;校正后的字符数量&amp;gt; &amp;lt;校正后的字符串&amp;gt; &amp;lt;是否强制替换&amp;gt;
&lt;/pre&gt;

&lt;p&gt;
最后一个字段如果为 0,则表示匹配到该规则时，不会进行强制替换，只是提供 &quot;建议&quot; ；为 0 时则进行强制替换。
&lt;/p&gt;

&lt;p&gt;
比如说如果 unicharambigs 文件中内容为:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
v1
2 ' ' 1 &quot; 1
1 m 2 r n 0
3 i i i 1 m 0
&lt;/pre&gt;
&lt;p&gt;
从前到后三条规则的含义分别为:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;识别结果中两个连续的单引号(')应当被强制替换为双引号(&quot;)&lt;/li&gt;
&lt;li&gt;识别结果中的字符 m 有可能是 rn&lt;/li&gt;
&lt;li&gt;识别结果中的连续字符串 iii 可能是字符 m&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline7&quot;&gt;新版本格式&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline7&quot;&gt;
&lt;p&gt;
新版本格式更为友好一点，每条校正规则为:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
&amp;lt;字符串&amp;gt; &amp;lt;字符串&amp;gt; &amp;lt;是否强制替换&amp;gt;
&lt;/pre&gt;

&lt;p&gt;
上面那个例子可以写作:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
v2
'' &quot; 1
m rn 0
iii m 0
&lt;/pre&gt;

&lt;p&gt;
需要注意的是，新版本格式里的两个字符串 &lt;b&gt;内部不能有空格&lt;/b&gt; 。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline8&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline8&quot;&gt;词典: DAWG 文件&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline8&quot;&gt;
&lt;p&gt;
上篇中提到有 DAWG 文件可以增强、调整识别结果，这些 DAWG 文件被称为词典(dictionary)，使用来对识别结果进行后处理的。
&lt;/p&gt;

&lt;p&gt;
所谓后处理是这样的: 对没一个字符，都会有多个候选结果，如果每次都挑选候选结果中最好的结果，不一定是正确的，这是因为实际的数据中会有各种各样的干扰信息，所谓的 &quot;最好结果&quot; 并不一定是正确的结果。在 &lt;b&gt;假设&lt;/b&gt; 待识别的文本都是由正常的、 &lt;b&gt;拼写正确的&lt;/b&gt; 词组成的时，通过预定义的词典，就可以 &lt;b&gt;以词为单位&lt;/b&gt; 对识别结果进行校正。
&lt;/p&gt;

&lt;p&gt;
在 Tesseract 中，DAWG 文件就是作为词典用在后处理中的，自然也应该是从训练用的文本中进行统计得到的。
&lt;/p&gt;

&lt;p&gt;
Tesseract 中支持的 DAWG 文件有五种类型，分别是:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
word-dawg
&lt;/p&gt;

&lt;p&gt;
这个词典文件记录可用的词，每个词占一行。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
freq-dawg
&lt;/p&gt;

&lt;p&gt;
这个词典文件记录最常用的一些词，建议数量在 &lt;b&gt;百&lt;/b&gt; 这个量级。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
bigram-dawg
&lt;/p&gt;

&lt;p&gt;
这个词典记录二元词，同样每个二元词一行。
&lt;/p&gt;

&lt;p&gt;
所谓的二元词是由前后连续的两个词组成的一个单元，比如说
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
生存 还是 死亡 这 是 一个 问题
&lt;/pre&gt;
&lt;p&gt;
这句话里的二元词就有:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
生存 还是
还是 死亡
死亡 这
这 是
是 一个
一个 问题
&lt;/pre&gt;

&lt;p&gt;
其实这已经近似一个二元语言模型(2-Gram Language Model)了，只不过这里不记录词频等信息。
&lt;/p&gt;

&lt;p&gt;
另外一点要注意的是，在 bigram-dawg 中，二元词之中的数字统一用英文的问号(?)替代
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
number-dawg
&lt;/p&gt;

&lt;p&gt;
这个词典用来记录包含数字的词，同样每个词一行，但和 word-dawg 不一样的是，这里记录的词里面的数字，都要用空格替代。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
punc-dawg
&lt;/p&gt;

&lt;p&gt;
这个文件用来记录标点的 &lt;b&gt;模式&lt;/b&gt; ，所谓模式就是说标点在训练用的文本(或语言)中是如何使用的。描述不太直观，下面是从 Tesseract 的英文 traineddata 中 punc-dawg 提取出来的的一段，可以参考一下:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
[
[ ]
[ ],
[ ];
[ ]:
[ ]!
[ ]!!!
[ ]?
[ ]?!
[ ]???
[ ].
[ ]...
{
{ }
{ },
{ };
{ }:
{ }!
{ }!!!
{ }?
{ }?!
{ }???
{ }.
{ }...
&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
这五个文件的名称必须是 word-dawg, freq-dawg, bigram-dawg, number-dawg 和 punc-dawg，然后和其他所有用于打包 traineddata 的中间结果一样，应当加上前缀，如要生成名为 eng.traineddata 的最终结果，这五个文件必须是 eng.word-dawg, eng.freq-dawg, eng.bigram-dawg, eng.number-dawg 和 eng.punc-dawg
&lt;/p&gt;

&lt;p&gt;
另外，这五个文件必须是 DAWG 格式，而不是文本文件。一般是先从训练文本中生成对应的文本文件，然后用 Tesseract 提供的 wordlist2dawg 来进行转换，如将 word-list-last 转换为 eng.word-dawg
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;wordlist2dawg word-list-last eng.word-dawg eng.unicharset
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;b&gt;注意: 以上文件都应编码为 UTF-8 再转换为 DAWG 文件&lt;/b&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>深度学习框架 Caffe 的安装与基本使用</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/07/21/caffe-base-usage.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2015/07/21/caffe-base-usage</id>
    <published>2015-07-21T00:00:00+00:00</published>
    <updated>2015-07-21T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


Caffe 简介
Caffe 的安装
相关概念

Blob
Layer
Net


使用 Caffe 进行训练

训练参数设置
网络结构定义
数据准备
训...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;Caffe 简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;Caffe 的安装&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;相关概念&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;Blob&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;Layer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline6&quot;&gt;Net&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline7&quot;&gt;使用 Caffe 进行训练&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline8&quot;&gt;训练参数设置&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline9&quot;&gt;网络结构定义&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline10&quot;&gt;数据准备&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline11&quot;&gt;训练与测试&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;Caffe 简介&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
Caffe 是一个 C++ 编写的深度学习框架，原来是 UC Berkeley 博士毕业的贾扬清的个人项目，后来被他开源。由于其清晰与高效而被广泛使用，用户逐渐地也形成了一个开放的社区，各方的一些重要的研究成果(主要是各种模型)都被分享到社区中，这是非常棒的一点。
&lt;/p&gt;

&lt;p&gt;
Caffe 的清晰表现在网络结构与参数都独立于代码，用户只要以普通文本(但需遵循一定的简单格式)就可以定义好自己的神经网络，并按自己的需要进行调整。而其高效体现在对 CUDA 的支持，GPU 运算能极大地提高运算速度，同时提供了在 CPU 模式和 GPU 模式之间切换的简便方法。
&lt;/p&gt;

&lt;p&gt;
另外，代码也写得很漂亮!
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;Caffe 的安装&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
Caffe 依赖以下外部的库或者工具:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
&lt;a href=&quot;http://www.nvidia.cn/object/cuda-cn.html&quot;&gt;CUDA&lt;/a&gt;: NVIDIA 公司发布的并行计算框架，通过利用 GPU 的处理能力来大幅提升计算性能。由于需要数据的量很大以及 DNN 本身的结构复杂性，DNN 的训练过程通常会非常非常慢，如果能够利用 CUDA 能极大地提高效率。
&lt;/p&gt;

&lt;p&gt;
来块 TITAN 吧少年!
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gtx690-1.jpg&quot; alt=&quot;gtx690-1.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gtx690-2.jpg&quot; alt=&quot;gtx690-2.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gtx690-3.jpg&quot; alt=&quot;gtx690-3.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href=&quot;http://www.netlib.org/blas/&quot;&gt;BLAS&lt;/a&gt;: 被广泛使用的线性代数库&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.boost.org/&quot;&gt;Boost&lt;/a&gt;(&amp;gt;=1.55): 著名的 C++ 第三方库&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://opencv.org/&quot;&gt;OpenCV&lt;/a&gt;(&amp;gt;=2.4): 著名的计算机视觉库&lt;/li&gt;
&lt;li&gt;Google 开源的一套东西:

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;protobuf: 数据序列化框架&lt;/li&gt;
&lt;li&gt;gflags: 命令行参数解析库&lt;/li&gt;
&lt;li&gt;glog: 日志记录框架&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;IO 相关的库

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;hdf5&lt;/li&gt;
&lt;li&gt;leveldb&lt;/li&gt;
&lt;li&gt;snappy&lt;/li&gt;
&lt;li&gt;lmdb&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
以上依赖中可以从系统软件源安装的有 2, 5 中除 glog 外的其他两个, 6。在 Debian 上使用以下命令进行安装:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;sudo apt-get install libatlas-dev libblas-dev libatlas-base-dev libatlas3-base  &lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;BLAS&lt;/span&gt;
sudo apt-get install libprotobuf-dev protobuf-compiler libgflags-dev
sudo apt-get install libhdf5-dev libleveldb-dev libsnappy-dev liblmdb-dev
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Boost 虽然也能从软件源安装，但需要注意版本，如果版本过低还是需要进行编译安装。
&lt;/p&gt;

&lt;p&gt;
glog 会在 Caffe 安装的时候自动安装，所以需要手动安装的就剩下:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;CUDA&lt;/li&gt;
&lt;li&gt;Boost&lt;/li&gt;
&lt;li&gt;OpenCV&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
CUDA 的安装笔者没有经验，就不作展开了，另外两个通过源代码编译安装即可。OpenCV 建议选择稳定版本 2.4.10。
&lt;/p&gt;

&lt;p&gt;
解决上述依赖问题后进行编译安装即可。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;cd&lt;/span&gt; caffe &amp;amp;&amp;amp; mkdir build
&lt;span style=&quot;color: #729fcf;&quot;&gt;cd&lt;/span&gt; build
cmake ..
make &amp;amp;&amp;amp; make install
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上述命令将会把 Caffe 安装到 caffe/build/install 目录下，如果需要安装在其他位置，可以在执行 cmake 时附加参数 &quot;CMAKE_INSTALL_PREFIX&quot;:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;cmake -DCMAKE_INSTALL_PREFIX=/opt/caffe ../
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
注意 cmake 输出中的 &quot;Install path&quot; 以确认是否生效。
&lt;/p&gt;

&lt;p&gt;
如果权限允许，比较方便的方法是安装到 /usr/local 下面，这样相应的头文件、库文件都是在系统的查找路径中，在使用 Caffe 的 API 时就无需再另外指定头文件位置和链接参数。
&lt;/p&gt;

&lt;p&gt;
此外 Caffe 还提供了 Python 的接口，在安装目录中有一个 python 目录，将其加入到环境变量中即可在 Python 项目中使用:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;PYTHONPATH&lt;/span&gt;=/opt/caffe/python:$&lt;span style=&quot;color: #eeeeec;&quot;&gt;PYTHONPATH&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
当然了，这个 python 接口也有一些依赖需要安装，这些依赖在 python 目录下的 requirements.txt 中设置，使用 pip 即可进行安装:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;sudo pip install -r requirements.txt
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
其中一个依赖 scipy 需要 fortran 编译器:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;sudo apt-get install gfortran
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
至此安装结束，此时可用的资源有:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;C++ 库,包括头文件、动态链接库(或静态链接库)&lt;/li&gt;
&lt;li&gt;Python 接口&lt;/li&gt;
&lt;li&gt;命令行工具，位于安装目录的 bin/ 目录下面&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;相关概念&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline4&quot;&gt;Blob&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
Blob 是用于存储数据的对象，在 Caffe 中各种数据(图像输入、模型参数)都是以 Blob 的形式在网络中传输的。同时 Blob 还能在 CPU 和 GPU 之间进行同步以支持 CPU/GPU 的混合运算。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline5&quot;&gt;Layer&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;p&gt;
Layer 是网络的次级单元，也是 Caffe 中能在外部进行调整的最小网络结构单元 —— 一般来说，都让同一层的神经元具备相同的性质，因此也就没有必要提供对单个神经元的操作。
&lt;/p&gt;

&lt;p&gt;
每个 Layer 都会有输入的 Blob 和输出的 Blob。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline6&quot;&gt;Net&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline6&quot;&gt;
&lt;p&gt;
即一个完整的包含输入层、隐藏层、输出层的深度网络，在 Caffe 中一般是一个卷积神经网络(Convolution Neural Networ, CNN)。
&lt;/p&gt;

&lt;p&gt;
通过定义不同类型的 Layer，并用 Blob 将不同的 Layer 连接起来，就能产生一个 Net 。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline7&quot;&gt;使用 Caffe 进行训练&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline7&quot;&gt;
&lt;p&gt;
这里以 MNIST 的例子来进行说明。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline8&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline8&quot;&gt;训练参数设置&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline8&quot;&gt;
&lt;p&gt;
训练参数通常记录到一个统一的文件中，关键参数有:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
训练(及测试)使用的网络
&lt;/p&gt;

&lt;p&gt;
网络结构要在另外一个文件中定义，在配置文件中用 &quot;net&quot; 指定其位置，如:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
net: &quot;examples/mnist/lenet_train_test.prototxt&quot;
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
学习率等网络迭代参数
&lt;/p&gt;

&lt;p&gt;
Caffe 中的权值更新通过学习率和动量项来进行计算
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
base_lr: 0.01        # 初始学习率
momentum: 0.9        # 动量项
&lt;/pre&gt;

&lt;p&gt;
同时还有 &quot;lr_policy&quot; 等参数用于学习率的自适应优化:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
lr_policy: &quot;inv&quot;
gamma: 0.0001
power: 0.75
&lt;/pre&gt;

&lt;p&gt;
此外还可以通过 &quot;weight_decay&quot; 来设置权重衰减
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
weight_decay: 0.0005
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
训练迭代次数
&lt;/p&gt;

&lt;p&gt;
设置最大迭代次数:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
max_iter: 10000
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
训练模式(CPU/GPU)
&lt;/p&gt;

&lt;p&gt;
如果系统安装了 CUDA 支持 GPU 运算，那么 GPU 模式是更好的选择，否则应当选择 CPU 模式:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
solver_mode: CPU
&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
除以上参数外，还有用于测试的一些参数:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;test_iter: 测试次数&lt;/li&gt;
&lt;li&gt;test_interval: 两次测试之间的间隔&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
在 MNIST 例子中，配置文件为 examples/mnist/lenet_solver.prototxt，其内容为:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
# The train/test net protocol buffer definition
net: &quot;examples/mnist/lenet_train_test.prototxt&quot;

# test_iter specifies how many forward passes the test should carry out.
# In the case of MNIST, we have test batch size 100 and 100 test iterations,
# covering the full 10,000 testing images.
test_iter: 100

# Carry out testing every 500 training iterations.
test_interval: 500

# The base learning rate, momentum and the weight decay of the network.
base_lr: 0.01
momentum: 0.9
weight_decay: 0.0005

# The learning rate policy
lr_policy: &quot;inv&quot;
gamma: 0.0001
power: 0.75

# Display every 100 iterations
display: 100

# The maximum number of iterations
max_iter: 10000

# snapshot intermediate results
snapshot: 5000

snapshot_prefix: &quot;examples/mnist/lenet&quot;

# solver mode: CPU or GPU
solver_mode: GPU
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline9&quot;&gt;网络结构定义&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline9&quot;&gt;
&lt;p&gt;
如前所述，Net 由 Layer 组成，每个 Layer 的定义都是以下形式:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
layer {
  name: &quot;&amp;lt;name&amp;gt;&quot;
  type: &quot;&amp;lt;type&amp;gt;&quot;
  bottom: &quot;&amp;lt;input blob&amp;gt;&quot;
  top: &quot;&amp;lt;output blob&amp;gt;&quot;
  transform_param {
    ...
  }
  &amp;lt;prefix&amp;gt;_param {
    ...
  }
}
&lt;/pre&gt;

&lt;p&gt;
可用的 Layer 类型及其参数见 &lt;a href=&quot;http://caffe.berkeleyvision.org/tutorial/layers.html&quot;&gt;Caffe|Layer catalogue&lt;/a&gt; 。
&lt;/p&gt;

&lt;p&gt;
层与层通过输入和输出联系在一起，比如说定义一个两层的前馈网络，可以这样:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
layer {
  name: &quot;input&quot;
  type: &quot;Data&quot;
  top: &quot;data&quot;
}
layer {
  name: &quot;output&quot;
  type: &quot;SoftmaxWithLoss&quot;
  bottom: &quot;data&quot;
  top: &quot;loss&quot;
}
&lt;/pre&gt;
&lt;p&gt;
&quot;input&quot; 层的输出 Blob 是 &quot;data&quot; ，同时 &quot;data&quot; 这个 Blob 又是 &quot;output&quot; 层的输出，这两个层就这样被连接起来了。
&lt;/p&gt;

&lt;p&gt;
在 MNIST 例子中，网络结构定于于 examples/mnist/lenet_train_test.prototxt 中，由于其内容较长，这里就不详细写出来了，仅以图示之。
&lt;/p&gt;

&lt;p&gt;
TODO: 图
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline10&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline10&quot;&gt;数据准备&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline10&quot;&gt;
&lt;p&gt;
在 MNIST 的例子中，需要将 MNIST 数据集转换为 lmdb 格式。先来看看 MNIST 数据集的处理再谈一下普通的数据如何转换成可用于训练的数据。
&lt;/p&gt;

&lt;p&gt;
首先要获取数据，这都已经在 Caffe 的源代码包中提供了相应的工具:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;data/mnist/get_mnist.sh&lt;/li&gt;
&lt;li&gt;examples/mnist/create_mnist.sh&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
第一个脚本用于下载 MNIST 数据集，阅读一下脚本内容，发现不过就是几条 wget 命令而已:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;wget http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
wget --no-check-certificate http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz
wget --no-check-certificate http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz
wget --no-check-certificate http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
第二个脚本用于将下载的 MNIST 数据集转换为 lmdb 文件，脚本内容如下，也是比较简单。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #eeeeec;&quot;&gt;EXAMPLE&lt;/span&gt;=examples/mnist
&lt;span style=&quot;color: #eeeeec;&quot;&gt;DATA&lt;/span&gt;=data/mnist
&lt;span style=&quot;color: #eeeeec;&quot;&gt;BUILD&lt;/span&gt;=build/examples/mnist

&lt;span style=&quot;color: #eeeeec;&quot;&gt;BACKEND&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;lmdb&quot;&lt;/span&gt;

&lt;span style=&quot;color: #729fcf;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Creating ${BACKEND}...&quot;&lt;/span&gt;

rm -rf $&lt;span style=&quot;color: #eeeeec;&quot;&gt;EXAMPLE&lt;/span&gt;/mnist_train_${&lt;span style=&quot;color: #eeeeec;&quot;&gt;BACKEND&lt;/span&gt;}
rm -rf $&lt;span style=&quot;color: #eeeeec;&quot;&gt;EXAMPLE&lt;/span&gt;/mnist_test_${&lt;span style=&quot;color: #eeeeec;&quot;&gt;BACKEND&lt;/span&gt;}

$&lt;span style=&quot;color: #eeeeec;&quot;&gt;BUILD&lt;/span&gt;/convert_mnist_data.bin $&lt;span style=&quot;color: #eeeeec;&quot;&gt;DATA&lt;/span&gt;/train-images-idx3-ubyte &lt;span style=&quot;color: #ad7fa8;&quot;&gt;\&lt;/span&gt;
                              $&lt;span style=&quot;color: #eeeeec;&quot;&gt;DATA&lt;/span&gt;/train-labels-idx1-ubyte $&lt;span style=&quot;color: #eeeeec;&quot;&gt;EXAMPLE&lt;/span&gt;/mnist_train_${&lt;span style=&quot;color: #eeeeec;&quot;&gt;BACKEND&lt;/span&gt;} --backend=${&lt;span style=&quot;color: #eeeeec;&quot;&gt;BACKEND&lt;/span&gt;}
$&lt;span style=&quot;color: #eeeeec;&quot;&gt;BUILD&lt;/span&gt;/convert_mnist_data.bin $&lt;span style=&quot;color: #eeeeec;&quot;&gt;DATA&lt;/span&gt;/t10k-images-idx3-ubyte &lt;span style=&quot;color: #ad7fa8;&quot;&gt;\&lt;/span&gt;
                              $&lt;span style=&quot;color: #eeeeec;&quot;&gt;DATA&lt;/span&gt;/t10k-labels-idx1-ubyte $&lt;span style=&quot;color: #eeeeec;&quot;&gt;EXAMPLE&lt;/span&gt;/mnist_test_${&lt;span style=&quot;color: #eeeeec;&quot;&gt;BACKEND&lt;/span&gt;} --backend=${&lt;span style=&quot;color: #eeeeec;&quot;&gt;BACKEND&lt;/span&gt;}

&lt;span style=&quot;color: #729fcf;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Done.&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
对于我们自己的数据，一般来说是一堆图片，Caffe 也提供了 &lt;b&gt;convert_imageset&lt;/b&gt; 这个工具，这是安装 Caffe 后提供的命令行工具之一。该命令的使用方式为:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
convert_imageset [FLAGS] ROOTFOLDER/ LISTFILE DB_NAME
&lt;/pre&gt;
&lt;p&gt;
其中 LISTFILE 每行记录一张图片的(相对)路径及类别，如:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
pics/0_1.png 0
&lt;/pre&gt;
&lt;p&gt;
需要注意的是，这里的 &quot;类别&quot; &lt;b&gt;必须是一个整数&lt;/b&gt; 。ROOTFOLDER 和 LISTFILE 中图片的路径构成图片的真实路径，DB_NAME 是要创建的 lmdb 文件的名称。
&lt;/p&gt;

&lt;p&gt;
如果图片集中存在图片大小不一致的情况，可以用 -resize_height 和 -resize_width 来将所有图片规整成统一的尺寸。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;convert_imageset -resize_height 64 -resize_width 64 ./ pic_label.list mydb
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline11&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline11&quot;&gt;训练与测试&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline11&quot;&gt;
&lt;p&gt;
在以上步骤都完成后即可开始进行训练与测试，使用命令行工具中的 caffe 命令即可:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;caffe train --solver=lenet_train_test.prototxt
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
在训练过程中会观察到类似下面这样的输出:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
I1203 solver.cpp:204] Iteration 100, lr = 0.00992565
I1203 solver.cpp:66] Iteration 100, loss = 0.26044
...
I1203 solver.cpp:84] Testing net
I1203 solver.cpp:111] Test score #0: 0.9785
I1203 solver.cpp:111] Test score #1: 0.0606671
&lt;/pre&gt;

&lt;p&gt;
这些输出表明了学习率、loss 和测试数据在当前网络上的表现，这些输出都是需要注意的。举个栗子
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/chesnut.jpg&quot; alt=&quot;chesnut.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
如果在开始时学习率设置过大，导致训练过程不收敛了，是能够通过观察 loss 和 测试数据在当前网络上的表现判断出来的。
&lt;/p&gt;

&lt;p&gt;
在 MNIST 的例子中，最后训练生成的模型是: examples/mnist/lenet_iter_10000.caffemodel。这个模型可以在之后的分类中使用。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>强大的 Org mode(2): 任务管理</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/07/15/org-mode-planning.html"/>
    <category term="Emacs" scheme="http://www.zmonster.me/categories.html#Emacs"/>
    <id>http://www.zmonster.me/2015/07/15/org-mode-planning</id>
    <published>2015-07-15T00:00:00+00:00</published>
    <updated>2015-07-15T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


基本的任务管理
自定义状态序列

添加新的状态
为状态设置不同外观
多个终结状态及快速选择
进入与离开时的额外操作


基于列表的任务
子任务、任务进度与...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org3b3f517&quot;&gt;基本的任务管理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb56e62e&quot;&gt;自定义状态序列&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org3793ce6&quot;&gt;添加新的状态&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb51e4aa&quot;&gt;为状态设置不同外观&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org8cc7568&quot;&gt;多个终结状态及快速选择&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgd74fcca&quot;&gt;进入与离开时的额外操作&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org9676ddb&quot;&gt;基于列表的任务&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org99414a4&quot;&gt;子任务、任务进度与任务依赖&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
本文是《强大的 Org mode》系列的第二篇文章，系列文章如下：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2015/07/12/org-mode-introduction.html&quot;&gt;强大的 Org mode(1): 简单介绍与基本使用 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2015/07/15/org-mode-planning.html&quot;&gt;强大的 Org mode(2): 任务管理 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2016/06/03/org-mode-table.html&quot;&gt;强大的 Org mode(3): 表格的基本操作及公式、绘图 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2018/02/28/org-mode-capture.html&quot;&gt;强大的 Org mode(4): 使用 capture 功能快速记录 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div id=&quot;outline-container-org3b3f517&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3b3f517&quot;&gt;基本的任务管理&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3b3f517&quot;&gt;
&lt;p&gt;
在 Org mode 中，可以在 headline 的星号与内容之间插入特定的表示进度的关键词，来将一个 headline 标记为一个任务(Plan)，默认情况下，支持两个关键词，分别是 &quot;TODO&quot; 和 &quot;DONE&quot;。当一个 headline 作为一个任务时，一方面标示其状态的关键词会被高亮(如下图所示)，另一方面 Org mode 提供了一组完善的功能来对这些任务进行处理。
&lt;/p&gt;


&lt;div id=&quot;org0f0d255&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-task-status.png&quot; alt=&quot;org-task-status.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
对任务管理而言，最基本的功能，就是快速地更改任务的状态，在这里，用户当然不用手动去修改表示任务状态的关键词，Org mode 已经提供了这样的一组快捷键给用户:
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;快捷键&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;功能&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;C-c C-t&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;按照 无状态-&amp;gt;TODO-&amp;gt;DONE-&amp;gt;无状态 的顺序更改任务状态&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;org-todo&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Shift-&amp;lt;right&amp;gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;同上&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Shift-&amp;lt;left&amp;gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;按照与 Shift-&amp;lt;right&amp;gt; 相反的顺序更改任务状态&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
下图是一个示例:
&lt;/p&gt;


&lt;div id=&quot;orgf0f532e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-task-status-change.gif&quot; alt=&quot;org-task-status-change.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
除此以外，Org mode 也提供了快速创建任务的操作
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;快捷键&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;功能&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;C-S-return&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;在当前任务的内容后面建立一个同级任务，标记为TODO&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无任务时创建一级任务，标记为TODO&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-S-return&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;在当前任务后建立一个同级任务，标记为TODO&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;同上&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
上表中的“任务”指的就是带有相关关键词的 headline，由于 headline 是可以分级嵌套的，所以这里的任务也可以分级嵌套，这也是 Org mode 中任务结构的基础。有关子任务的话题将在后面补充。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb56e62e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgb56e62e&quot;&gt;自定义状态序列&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgb56e62e&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org3793ce6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3793ce6&quot;&gt;添加新的状态&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org3793ce6&quot;&gt;
&lt;p&gt;
上一节提到，默认情况下，Org mode 接受的任务状态关键词只有 &quot;TODO&quot; 和 &quot;DONE&quot; 两个，分别表示 &quot;待办&quot; 与 &quot;完成&quot;。这样的分类对于一些不可再分的小任务，当然是足够用的，但有时候需要设置更为丰富的任务状态，如添加一个表示 &quot;正在进行&quot; 状态的关键词 &quot;DOING&quot;，在不进行设置的情况下，这个关键词是无法高亮的:
&lt;/p&gt;


&lt;div id=&quot;orge25606d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-task-add-doing.png&quot; alt=&quot;org-task-add-doing.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这个词将会被视作任务名称的一部分，而不是表示任务状态的标识。用本文之前提到的快捷键更改任务的状态，会看到下面这样的变化。
&lt;/p&gt;


&lt;div id=&quot;org62561a5&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-task-status-doing-ignored.gif&quot; alt=&quot;org-task-status-doing-ignored.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
要达到预期的目的，有两种方法，一种方法是全局的，另一种则只在当前文件生效。
&lt;/p&gt;

&lt;p&gt;
Org mode 中有一个变量 &lt;b&gt;org-todo-keywords&lt;/b&gt; 存储着作用于全局的状态序列，它的默认值是:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;'((sequence &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #cc9393;&quot;&gt;TODO&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #afd8af;&quot;&gt;DONE&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt;))
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
这就是默认状态只有两个的原因，修改这个变量的值也就能达到全局修改状态序列的目的了。
&lt;/p&gt;

&lt;p&gt;
需要注意的是，状态序列在定义时的顺序是从左至右有序的，最后一个关键词会被认为是 &lt;b&gt;表示任务终结&lt;/b&gt; 的关键词。所以如果要添加 &quot;DOING&quot; 这个状态，应该像下面这样进行设置:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; org-todo-keywords '((sequence &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #cc9393;&quot;&gt;TODO&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;DOING&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #afd8af;&quot;&gt;DONE&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt;)))
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
默认情况下表示非终结状态的关键词与表示终结的关键词的高亮颜色是不一样的，而且在更改为终结状态时，会在任务下添加一条下面这样的标记。
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org1f12d6e&quot;&gt;
CLOSED: [2015-07-15 三 23:20]
&lt;/pre&gt;
&lt;p&gt;
如果将 &quot;DOING&quot; 放置到序列的末端，那么状态变化时的现象就会和预期的不一致:
&lt;/p&gt;


&lt;div id=&quot;org8362bf8&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-task-wrong-status.png&quot; alt=&quot;org-task-wrong-status.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
如果只想在某个文件中为其设置独有的关键词序列，那么可以在org文件的头部用&quot;#+SEQ_TODO&quot;来进行设置:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+SEQ_TODO: TODO DOING DONE&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb51e4aa&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb51e4aa&quot;&gt;为状态设置不同外观&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb51e4aa&quot;&gt;
&lt;p&gt;
之前提到，Org mode 在高亮时只区分非终结状态与终结状态，但如果各个状态都能以不同的颜色显示，那肯定能让任务的状态更加一目了然。通过修改 &lt;b&gt;org-todo-keyword-faces&lt;/b&gt; 这个变量可以达到这个目的。例如我们希望 &quot;TODO&quot; 以红色显示，&quot;DOING&quot; 以黄色显示，&quot;DONE&quot; 用绿色显示，就可以这样设置:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; org-todo-keyword-faces '((&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #cc9393;&quot;&gt;TODO&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt; . &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;red&quot;&lt;/span&gt;)
                               (&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;DOING&quot;&lt;/span&gt; . &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;yellow&quot;&lt;/span&gt;)
                               (&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #afd8af;&quot;&gt;DONE&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt; . &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;green&quot;&lt;/span&gt;)))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
以下是这样设置后的效果图:
&lt;/p&gt;


&lt;div id=&quot;org82f33ab&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-todo-keywords-face.png&quot; alt=&quot;org-todo-keywords-face.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org8cc7568&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org8cc7568&quot;&gt;多个终结状态及快速选择&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org8cc7568&quot;&gt;
&lt;p&gt;
前面所以说 &quot;终结状态&quot; 而不说 &quot;完成状态&quot;，是因为 &quot;终结状态&quot; 可能有不止一种，比如在表示正常完成的状态外，还可以有表示异常中止的状态。当有多个表示终结的状态时，相应的关键词要处于关键词序列的尾部，并且用&quot;|&quot;和非终结状态分隔开来，也就是这样:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; org-todo-keywords '((sequence &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #cc9393;&quot;&gt;TODO&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;DOING&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;|&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #afd8af;&quot;&gt;DONE&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;ABORT&quot;&lt;/span&gt;)))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
若在文件中进行设置，则是:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+SEQ_TODO: TODO DOING | DONE ABORT&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这样的话有一个问题，那就是，一般来说，对于一个任务来说，一般只会用到多个终结状态中的一个，但假如我要将一个原先为&quot;TODO&quot;状态的任务标记为&quot;ABORT&quot;，我就要使用快捷键&quot;C-c C-t&quot;或&quot;S-left&quot;/&quot;S-right&quot;，依次经过&quot;DOING&quot;、&quot;DONE&quot;，最后才标记为&quot;ABORT&quot;。这样的行为和理想的体验是不符合的。
&lt;/p&gt;

&lt;p&gt;
好在 Org mode 也提供了解决这一场景的方法，那就是，可以为每一个状态设立一个快速选择键，在使用快捷键&quot;C-c C-t&quot;时，会等待输入这个快速选择键来迅速指定为特定状态。使用这个功能所需要的设置也很简单。
&lt;/p&gt;

&lt;p&gt;
第一个是将变量&quot;org-use-fast-todo-selection&quot;的值设置为真(t)——一般来说，这个变量的值默认就是真(t):
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; org-use-fast-todo-selection t)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后在定义关键词序列时，在每个关键词后跟随括号并在其中指定快速选择键，如:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; org-todo-keywords '((sequence &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #cc9393;&quot;&gt;TODO&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;(t)&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;DOING(i)&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;|&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #afd8af;&quot;&gt;DONE&lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;(d)&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;ABORT(a)&quot;&lt;/span&gt;)))
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
或在文件头部设置:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+SEQ_TODO: TODO(t) DOING(i) | DONE(d) ABORT(a)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这样使用快捷键&quot;C-c C-t&quot;时，就能够方便地切换任务的状态了，如下图所示:
&lt;/p&gt;


&lt;div id=&quot;orgc929863&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-task-fast-select.gif&quot; alt=&quot;org-task-fast-select.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd74fcca&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgd74fcca&quot;&gt;进入与离开时的额外操作&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgd74fcca&quot;&gt;
&lt;p&gt;
除了上述内容以外，Org mode 还允许定义进入状态和离开状态时的额外动作，可用的动作包含两个:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;添加笔记和状态变更信息(包括时间信息)，用&quot;@&quot;表示&lt;/li&gt;
&lt;li&gt;只添加状态变更信息，用&quot;!&quot;表示&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
这个通过定义带快速选择键的关键词时，在快速选择键后用&quot;X/Y&quot;来表示，X表示进入该状态时的动作，Y表示离开该状态时的动作。对于一个状态(以&quot;DONE&quot;为例)，以下形式都是合法的:
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org968a9cb&quot;&gt;
DONE(d@)       ; 进入时添加笔记
DONE(d/!)      ; 离开时添加变更信息
DONE(d@/!)     ; 进入时添加笔记，离开时添加变更信息
&lt;/pre&gt;

&lt;p&gt;
而这个是不合法的:
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org7c864a0&quot;&gt;
DONE(d@/)
&lt;/pre&gt;

&lt;p&gt;
需要注意的是，当由状态 A 到达状态 B 时，为状态 A 设置的离开动作 Y&lt;sub&gt;A&lt;/sub&gt; 只在状态 B 未设置进入动作 X&lt;sub&gt;B&lt;/sub&gt; 时生效；如果目标状态设置了进入动作，那么出发状态的离开动作不被执行，而是执行目标状态的进入动作。下图为演示。
&lt;/p&gt;


&lt;div id=&quot;orgec1f163&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-task-changing-action.gif&quot; alt=&quot;org-task-changing-action.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org9676ddb&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org9676ddb&quot;&gt;基于列表的任务&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org9676ddb&quot;&gt;
&lt;p&gt;
除了基于 headline 的任务管理外，Org mode 还提供基于列表的任务管理，即将每个列表项作为任务，方法是在列表标记与列表项内容之间添加一个 &quot;[ ]&quot; 标记(注意中间包含一个字符的预留位置)，这个标记在 Org mode 中被称为 &lt;b&gt;checkbox&lt;/b&gt; 。这种任务只有三种状态(待办、进行中和完成)，分别用 &quot;[ ]&quot;, &quot;[-]&quot; 和 &quot;[X]&quot; 表示，如下图所示:
&lt;/p&gt;


&lt;div id=&quot;org4966140&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-checkbox-task.png&quot; alt=&quot;org-checkbox-task.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
若要将用 checkbox 标记的任务标记为完成，将光标移动到对应的行，然后使用快捷键 &quot;C-c C-c&quot; 即可。对于包含子任务的任务，如果其子任务未全部完成，用此快捷键更改其子任务状态时，该任务的状态会自动设置为 &quot;进行中([-])&quot;，表示子任务未全部完成；当用快捷键将所有子任务标记为完成时，它会自动更新为完成状态。
&lt;/p&gt;

&lt;p&gt;
用&quot;TODO&quot;等关键词标记为headline为任务时，使用的快捷键同样适用于checkbox，不过略有不同:
&lt;/p&gt;
&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;快捷键&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;功能&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;C-S-return&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;在当前列表项的内容后面建立一个同级列表项，标记为 &quot;[ ]&quot;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无列表项时不创建&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-S-return&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;在当前列表项后建立一个同级列表项，标记为T&quot;[ ]&quot;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
checkbox 任务相对来说更轻量、简洁一些，自然也会有人群更倾向于使用这种方式进行任务管理。不过就我个人而言，基于 headline 的任务管理可以设置 deadline，可以设置为周期循环任务，还可以计时统计，这些功能是更有吸引力而且有必要的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org99414a4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org99414a4&quot;&gt;子任务、任务进度与任务依赖&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org99414a4&quot;&gt;
&lt;p&gt;
在之前本文提到过 &quot;子任务&quot; 这个概念，这个在 Org mode 里的表现形式是很简单的:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;一个基于 headline 的任务，如果其下的更低等级的 headline 也被作为一个任务，那么这个更低等级的任务就是子任务&lt;/li&gt;
&lt;li&gt;一个用列表项表示的任务同理&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
对包含子任务的任务，可以在该任务中加入 &quot;[\/]&quot; 或者 &quot;[\%]&quot; 来实时展现该任务的完成进度跟踪，在用快捷键来改变子任务的状态时，父任务的完成进度会被自动更新，当然，也可以执行函数 &lt;b&gt;org-update-statistics-cookies&lt;/b&gt; 来手动更新，默认情况下，这个函数被绑定到快捷键 &quot;C-c #&quot; 上。
&lt;/p&gt;

&lt;p&gt;
下图是对 checkbox 任务进行更新时进度的自动更新情况，基于 headline 的任务进度更新类似。
&lt;/p&gt;


&lt;div id=&quot;orgbe921eb&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-task-update-cookie.gif&quot; alt=&quot;org-task-update-cookie.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
对于包含子任务的复杂任务，除了进度跟踪外，Org mode本身还提供两种简单的任务依赖处理:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;当任务还有子任务未完成时，阻止任务从未完成状态到完成状态的改变&lt;/li&gt;
&lt;li&gt;对基于 headline 的任务而言，若其上一级任务设置了 &quot;:ORDERED:&quot; 属性，则在其前面的同级任务完成前，无法被设置为完成状态&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
不过以上两种行为默认是被关闭的，如果要开启这些功能，要对变量 &lt;b&gt;org-enforce-todo-dependencies&lt;/b&gt; 进行设置:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; org-enforce-todo-dependencies t)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
效果如图:
&lt;/p&gt;


&lt;div id=&quot;orgd965c90&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-task-dependencies.gif&quot; alt=&quot;org-task-dependencies.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
当然，还可以通过org-depend.el实现更复杂的依赖处理，这里就不做深入展开了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>强大的 Org mode(1): 简单介绍与基本使用</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/07/12/org-mode-introduction.html"/>
    <category term="Emacs" scheme="http://www.zmonster.me/categories.html#Emacs"/>
    <id>http://www.zmonster.me/2015/07/12/org-mode-introduction</id>
    <published>2015-07-12T00:00:00+00:00</published>
    <updated>2015-07-12T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


简介
安装与基础设置
基本使用

所谓大纲(outline)
基本语法






</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgf01a498&quot;&gt;简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orge7864c5&quot;&gt;安装与基础设置&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org11a4506&quot;&gt;基本使用&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org7d39a64&quot;&gt;所谓大纲(outline)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4d5dfd2&quot;&gt;基本语法&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
本文是《强大的 Org mode》系列的第一篇文章，系列文章如下：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2015/07/12/org-mode-introduction.html&quot;&gt;强大的 Org mode(1): 简单介绍与基本使用 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2015/07/15/org-mode-planning.html&quot;&gt;强大的 Org mode(2): 任务管理 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2016/06/03/org-mode-table.html&quot;&gt;强大的 Org mode(3): 表格的基本操作及公式、绘图 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zmonster.me/2018/02/28/org-mode-capture.html&quot;&gt;强大的 Org mode(4): 使用 capture 功能快速记录 · ZMonster's Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div id=&quot;outline-container-orgf01a498&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf01a498&quot;&gt;简介&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf01a498&quot;&gt;
&lt;p&gt;
&lt;b&gt;Org mode&lt;/b&gt; 是 Emacs 的一个插件，能为 Emacs 用户提供一个强大的纯文本编辑环境，下面是 Org mode 官网上对自己的介绍:
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
Org mode is for keeping notes, maintaining TODO lists, planning projects, and authoring documents with a fast and effective plain-text system.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
Org mode 实际上是一种轻量级标记语言，与 &lt;a href=&quot;https://zh.wikipedia.org/wiki/ReStructuredText&quot;&gt;RST&lt;/a&gt;、 &lt;a href=&quot;https://zh.wikipedia.org/wiki/Markdown&quot;&gt;Markdown&lt;/a&gt; 类似，不过要比这两者拥有更为强大的功能和特性，是众多 Emacs 用户重度依赖的一个插件，对我个人来说也是构成日常工作、生活必不可少的重要工具。正如它的自我介绍所言， Org mode 与 RST 、 Markdown 相比，除了作为编辑环境以外，还可以进行任务管理、项目规划、笔记收集整理等各种操作 —— 事实上由于 Org mode 作为 Emacs 的插件，构建在 emacs lisp 语言之上，也使得它具备了无与伦比的可扩展性，但同时由于有统一的开发团队进行维护，而使得其语法规则没有因为强大的可扩展性而导致不同方言的泛滥，而 Markdown 就没有避免这个问题。
&lt;/p&gt;

&lt;p&gt;
需要说明的是，作为一个标记语言， Org mode 的基本语法规则其实是很简单的，但它同时还提供了大量的“功能”使得其变得异常强大，但这些功能都是构建在基本的语法规则之上的。对于初学者来说，Org mode 能够很快地上手，而在上手后又还有非常丰富的内容可待探索。
&lt;/p&gt;

&lt;p&gt;
以下是Org mode的几大特性:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;基于大纲的编辑(outline-based editing)&lt;/li&gt;
&lt;li&gt;灵活强大的任务管理(planning)&lt;/li&gt;
&lt;li&gt;任务计时及统计(clocking)&lt;/li&gt;
&lt;li&gt;日程管理(agendas)&lt;/li&gt;
&lt;li&gt;快速捕获(capture)&lt;/li&gt;
&lt;li&gt;功能丰富的表格操作(tables)&lt;/li&gt;
&lt;li&gt;导出到多种外部格式(exporting)&lt;/li&gt;
&lt;li&gt;文学编程(working with source code)&lt;/li&gt;
&lt;li&gt;移动端支持(with your mobile phone)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
下图是Org mode官网上的一张示例图，对上述一些特性(outline-based editing, planning, agendas)进行了展示。
&lt;/p&gt;


&lt;div id=&quot;org919a4c7&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-main.jpg&quot; alt=&quot;org-main.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orge7864c5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge7864c5&quot;&gt;安装与基础设置&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orge7864c5&quot;&gt;
&lt;p&gt;
自 Emacs 22 后，Emacs 都自带了可用的 Org mode，在 Emacs 中，Org mode 作为一个 major mode，在用 Emacs 打开(或新建)后缀为 &quot;org&quot; 的文件时即会启用，如果您的 Emacs 在打开 org 文件时没有启用 org-mode 这个 major mode，可以在配置文件中加入:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'auto-mode-alist  '(&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;\\.org\\'&quot;&lt;/span&gt; . org-mode))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
另外 Org mode 在默认情况下不开启自动折行，这将导致一行文字的长度超出屏幕范围时，行会继续往右延伸而导致部分内容不可见(因在屏幕范围外而无法看见)，要开启自动折行，应在配置中进行设置:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; truncate-lines nil)
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
除此以外，基本上就不用进行其他设置了(至少基本功能的使用是不需要的)。
&lt;/p&gt;

&lt;p&gt;
需要注意的是，Emacs 自带的 Org mode 一般版本都偏旧，存在一些已知的 bug，建议替换为新版本，要达到该目的有两种办法:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;若 Emacs 版本为 24 或更新，可以通过内置的包管理器 &lt;b&gt;elpa&lt;/b&gt; 来安装新版的 Org mode，使用 &lt;b&gt;package-install&lt;/b&gt; 命令并在要求输入包名时输入 &lt;span class=&quot;underline&quot;&gt;org&lt;/span&gt; 。这种方法安装的 Org mode 不需要进行额外配置即可在 Emacs 启动时被加载。&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
从 &lt;a href=&quot;http://orgmode.org/&quot;&gt;Org mode的官网&lt;/a&gt; 上下载最新的包，解压后在 Emacs 的配置文件中添加配置进行加载，比如将其解压在 ~/.emacs.d/site-lisp/org/ 目录下，那么配置语句可以是这样的:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(add-to-list 'load-path &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/.emacs.d/site-lis/org/lisp&quot;&lt;/span&gt;)
(add-to-list 'load-path &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/.emacs.d/site-lis/org/contrib/lisp&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
相比用 elpa 安装的方法，这种方法的一个优点是能使用一些其他开发者贡献的、暂未成为核心功能的增强功能，就是上面的第二条配置语句的目的。
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org11a4506&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org11a4506&quot;&gt;基本使用&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org11a4506&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org7d39a64&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org7d39a64&quot;&gt;所谓大纲(outline)&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org7d39a64&quot;&gt;
&lt;p&gt;
在 Org mode 中，文档内容是通过 headline 来组织成一个树状结构的 —— 由于在 Org mode 中还存在 &quot;title&quot; 这种文章级的标题，为避免混淆，就不对 &quot;headline&quot; 进行翻译了，我们只要知道这几点就行:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;headline 是一节内容的标题(概要)&lt;/li&gt;
&lt;li&gt;headline 可以分级&lt;/li&gt;
&lt;li&gt;headline 可以有子 headline&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
我想凡是有 Markdown 、RST 乃至 Microsoft Office 使用经验的人，都能理解什么是 &quot;headline&quot;。
&lt;/p&gt;

&lt;p&gt;
headline 在 Org mode 中会被高亮显示，且不同级别的 headline 会以不同的颜色显示。要创建 headline 也很简单，只要一行文字以若干个连续星号(*)顶格，并在星号结束后跟随至少一个空格，则该行会被视为一个 headline ，连续星号的数量被视为 headline 的层级，如图所示。
&lt;/p&gt;

&lt;p&gt;
实际上 Org mode 提供了丰富的快捷键来操作 headline，不需要手动输入星号(*)来创建 headline。以下是这些快捷键的一个总结:
&lt;/p&gt;
&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;快捷键&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;功能&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;C-&amp;lt;return&amp;gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;在当前 headline 所属的内容后建立一个同级 headline&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无 headline 时创建一个一级 headline&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-&amp;lt;return&amp;gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;在当前 headline 后建立一个同级 headline&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;同上&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-&amp;lt;right&amp;gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;降低当前 headline 的层级&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-&amp;lt;left&amp;gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;提高当前 headline 的层级&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-&amp;lt;up&amp;gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;将当前 headline 及其内容作为整体向上移动&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-&amp;lt;down&amp;gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;将当前 headline 及其内容作为整体向下移动&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
通过 headline 来组织文档内容便于组织思想，这在很多其他编辑环境或者软件上都有体现，但与它们不同的是，Org能够方便地隐藏各级 headline 下的内容只显示 headline 的树状结构或者只显示第一级headline——这就是所谓 &lt;b&gt;outline&lt;/b&gt; 了，如下图所示。只要通过 headline 组织好 Org 文档，概览文档、快速定位和编辑都能很方便地做到。
&lt;/p&gt;


&lt;div id=&quot;org066cda2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-outline.png&quot; alt=&quot;org-outline.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
通过快捷键 TAB 可以对某个 headline 及其内容的显示在三种状态(Folded, Children, Subtree)中切换；快捷键 S-TAB 则对整个 org 文件的内容显示在三种状态(Overview, Contents, Show all)中切换。Org 的文档称这种行为为&quot;cycling&quot;，前者称为&quot;subtree cycling&quot;，后者则是&quot;global cycling&quot;。
&lt;/p&gt;

&lt;p&gt;
subtree cycling的状态
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Folded: 对当前 headline，只显示 headline，其下的子节点及内容隐藏&lt;/li&gt;
&lt;li&gt;Children: 对当前 headline，显示当前 headline 及其下更低一级的 headline&lt;/li&gt;
&lt;li&gt;Subtree: 对当前 headline，只显示当前 headline 及其下更低级的 headline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
下面的动态图像展示了subtree cycling 的状态变化(Folded -&amp;gt; Children -&amp;gt; Subtre)。
&lt;/p&gt;


&lt;div id=&quot;org3b0ec94&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/subtree-cycling.gif&quot; alt=&quot;subtree-cycling.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
global cycling 的状态变化与 subtree cycling 类似，不过针对的是整个文档，下面图像展示了 global cycling 的状态变化(Overview -&amp;gt; Contents -&amp;gt; Show all)
&lt;/p&gt;


&lt;div id=&quot;org567c98b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/global-cycling.gif&quot; alt=&quot;global-cycling.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
Org mode 的几大特性中，任务管理、任务计时、项目管理都是建立在 outline 结构上的，捕获虽然可以不基于这个结构，但一般来说都会使用。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4d5dfd2&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4d5dfd2&quot;&gt;基本语法&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org4d5dfd2&quot;&gt;
&lt;p&gt;
除了 headline 外，Org mode 还支持列表、文字修饰(粗体、斜体、下划线等)、代码块、引用等常见的功能。
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
列表
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;+ &amp;#26080;&amp;#24207;&amp;#21015;&amp;#34920;
  * &amp;#29992;&quot;+&quot;,&quot;-&quot;, &quot;*&quot;&amp;#24320;&amp;#22836;&amp;#65292;&amp;#21518;&amp;#36319;&amp;#38543;&amp;#29992;&amp;#31354;&amp;#26684;&amp;#20998;&amp;#38548;&amp;#24320;&amp;#30340;&amp;#21015;&amp;#34920;&amp;#39033;&amp;#21517;&amp;#31216;&amp;#12289;&amp;#20869;&amp;#23481;
  * &quot;*&quot;&amp;#22312;&amp;#34892;&amp;#39318;&amp;#39030;&amp;#26684;&amp;#30340;&amp;#35805;&amp;#21017;&amp;#26159;headline&amp;#65292;&amp;#36825;&amp;#20010;&amp;#35201;&amp;#27880;&amp;#24847;
  * &amp;#22914;&amp;#26524;&amp;#24819;&amp;#32467;&amp;#26463;&amp;#19968;&amp;#20010;&amp;#21015;&amp;#34920;&amp;#65292;&amp;#37027;&amp;#20040;&amp;#22312;&amp;#20854;&amp;#21518;&amp;#36319;&amp;#38543;&amp;#20004;&amp;#20010;&amp;#31354;&amp;#34892;

+ &amp;#26377;&amp;#24207;&amp;#21015;&amp;#34920;
  1. &amp;#29992;&quot;1.&quot;,&quot;1)&quot;&amp;#24320;&amp;#22836;&amp;#65292;&amp;#21518;&amp;#36319;&amp;#38543;&amp;#29992;&amp;#31354;&amp;#26684;&amp;#20998;&amp;#38548;&amp;#24320;&amp;#30340;&amp;#21015;&amp;#34920;&amp;#39033;&amp;#21517;&amp;#31216;&amp;#12289;&amp;#20869;&amp;#23481;
  2. &amp;#20854;&amp;#20313;&amp;#21516;&amp;#26080;&amp;#24207;&amp;#21015;&amp;#34920;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
列表和 headline 一样，也是可以分级、嵌套的，列表相关的快捷键也与 headline 相关的快捷键部分重叠(Org mode 会根据实际情况来进行合理的操作，所以不用担心混淆问题):
&lt;/p&gt;
&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;快捷键&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;功能&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;C-&amp;lt;return&amp;gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;在当前列表项的内容后建立一个同级列表项&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;光标在列表项同一行时有效&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-&amp;lt;return&amp;gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;在当前列表项后建立一个同级列表项&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;同上&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-&amp;lt;right&amp;gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;降低当前列表项的层级&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;同上&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-&amp;lt;left&amp;gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;提高当前列表项的层级&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;同上&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-&amp;lt;up&amp;gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;将当前列表项及其内容作为整体向上移动&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;同上&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;M-&amp;lt;down&amp;gt;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;将当前列表项及其内容作为整体向下移动&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;同上&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
粗体
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;#31895;&amp;#20307;&lt;/span&gt; &amp;#29992;&amp;#20004;&amp;#20010;&amp;#26143;&amp;#21495;&amp;#21253;&amp;#35065;&amp;#65292;&amp;#26143;&amp;#21495;&amp;#19982;&amp;#31895;&amp;#20307;&amp;#21069;&amp;#21518;&amp;#30340;&amp;#20854;&amp;#20182;&amp;#23383;&amp;#24212;&amp;#35813;&amp;#21508;&amp;#26377;&amp;#33267;&amp;#23569;&amp;#19968;&amp;#20010;&amp;#31354;&amp;#26684;&amp;#25110;&amp;#33521;&amp;#25991;&amp;#26631;&amp;#28857;&amp;#20998;&amp;#38548;&amp;#24320;&amp;#26469;
&lt;span style=&quot;font-weight: bold;&quot;&gt;bold&lt;/span&gt;,word,&amp;#29992;&amp;#33521;&amp;#25991;&amp;#36887;&amp;#21495;&amp;#20998;&amp;#38548;&amp;#24320;&amp;#65292;bold&amp;#26174;&amp;#31034;&amp;#20986;&amp;#31895;&amp;#20307;&amp;#25928;&amp;#26524;
*bold*word&amp;#21017;&amp;#19981;&amp;#26174;&amp;#31034;&amp;#31895;&amp;#20307;&amp;#25928;&amp;#26524;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
斜体
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;font-style: italic;&quot;&gt;hello&lt;/span&gt; &amp;#29992;&quot;&lt;span style=&quot;font-style: italic;&quot;&gt;&quot;&amp;#21253;&amp;#35065;&amp;#65292;&amp;#35268;&amp;#21017;&amp;#21516;&amp;#31895;&amp;#20307;&lt;/span&gt;
&lt;span style=&quot;font-style: italic;&quot;&gt;&amp;#26012;&amp;#20307;&lt;/span&gt; &amp;#22909;&amp;#20687;&amp;#23545;&amp;#20013;&amp;#25991;&amp;#19981;&amp;#31649;&amp;#29992;?&amp;#23548;&amp;#20986;&amp;#25104;HTML&amp;#26102;&amp;#30475;&amp;#21040;&amp;#36824;&amp;#26159;&amp;#29983;&amp;#25928;&amp;#20102;&amp;#65292;&amp;#21487;&amp;#33021;&amp;#26159;&amp;#23383;&amp;#20307;&amp;#20851;&amp;#31995;&amp;#21543;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
下划线
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&amp;#19979;&amp;#21010;&amp;#32447;&lt;/span&gt; &amp;#29992;&quot;_&quot;&amp;#22312;&amp;#21069;&amp;#21518;&amp;#21253;&amp;#35065;&amp;#65292;&amp;#35268;&amp;#21017;&amp;#21516;&amp;#31895;&amp;#20307;
_&amp;#19979;&amp;#21010;&amp;#32447;_&amp;#32039;&amp;#36319;&amp;#20854;&amp;#20182;&amp;#23383;&amp;#65292;&amp;#21017;&amp;#19981;&amp;#29983;&amp;#25928;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
删除线
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;text-decoration: line-through;&quot;&gt;&amp;#21024;&amp;#38500;&amp;#32447;&lt;/span&gt; &amp;#29992;&quot;+&quot;&amp;#22312;&amp;#21069;&amp;#21518;&amp;#21253;&amp;#35065;&amp;#65292;&amp;#35268;&amp;#21017;&amp;#21516;&amp;#31895;&amp;#20307;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
引用块
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+BEGIN_QUOTE&lt;/span&gt;
&amp;#24341;&amp;#29992;&amp;#20869;&amp;#23481;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+END_QUOTE&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
在org文件中输入&quot;&amp;lt;q&quot;然后按 TAB 键会自动插入一个引用块，插入后在其中进行编辑即可。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
示例块
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+Begin_EXAMPLE&lt;/span&gt;
&amp;#31034;&amp;#20363;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+END_EXAMPLE&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
在org文件中输入 &quot;&amp;lt;e&quot; 然后按 TAB 键来插入一个示例块，可以移动到其中并使用快捷键&quot;C-'(单引号)&quot;来在新窗格中编辑它，编辑好后用同样的快捷键来保存。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
代码块
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+BEGIN_SRC C++&lt;/span&gt;
&lt;span style=&quot;color: #cc99cc; background-color: #f2f2f2;&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #6699cc; font-style: italic;&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt;;&lt;/span&gt;

&lt;span style=&quot;color: #6699cc;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;argc&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #6699cc;&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color: #ffcc66;&quot;&gt;argv&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color: #f99157;&quot;&gt;{&lt;/span&gt;
&lt;span style=&quot;color: #f99157;&quot;&gt;    cout &amp;lt;&amp;lt; &lt;/span&gt;&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;&amp;#20195;&amp;#30721;&amp;#22359;&quot;&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; &amp;lt;&amp;lt; endl;&lt;/span&gt;

&lt;span style=&quot;color: #f99157;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #f99157;&quot;&gt; 0;&lt;/span&gt;
&lt;span style=&quot;color: #f99157;&quot;&gt;}&lt;/span&gt;
&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#+END_SRC&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
代码块稍微复杂一点，插入的话是通过输入&quot;&amp;lt;s&quot;然后按 TAB 键来达到，但插入后还要在&quot;#+BEGIN_SRC&quot;后指定代码的语言类型(如上例所示)。
&lt;/p&gt;

&lt;p&gt;
Org mode可以根据代码所属的语言来对其进行高亮，不过自Emacs 24.1后，默认设置下不对代码块进行高亮，需要进行设置
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold; font-style: italic;&quot;&gt;setq&lt;/span&gt; org-src-fontify-natively t)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
在编辑代码块的时候也会开启对应语言的 major mode，若对应的语言配置得当，在编辑 Org mode 中的代码块时，自动缩进、自动补全等功能都可以享用。编辑与保存的快捷键同示例块(exmple block)。
&lt;/p&gt;


&lt;div id=&quot;org5230d7a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/source-edit.gif&quot; alt=&quot;source-edit.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
此外在 Org mode 中还可以对代码进行求值，产生了很多丰富的应用方式，这个留待后续。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
图片
&lt;/p&gt;

&lt;p&gt;
在 Org mode 中，可以插入本地图片，并在 Org mode 中进行显示。要做到这个，直接在 org 文件中写入本地文件的路径，然后开启 iimage-mode 即可(M-x iimage-mode)。
&lt;/p&gt;

&lt;p&gt;
为进行区分，通常会在图片地址前加上&quot;file&quot;前缀，如
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org60a5c6b&quot;&gt;
file:/assets/img/source-edit.gif
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
链接
&lt;/p&gt;

&lt;p&gt;
链接的语法规则是这样的:
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;org0de2d8a&quot;&gt;
[[&amp;lt;link url&amp;gt;][&amp;lt;text&amp;gt;]]
&lt;/pre&gt;

&lt;p&gt;
比如
&lt;/p&gt;
&lt;pre class=&quot;example&quot; id=&quot;orge7b09cd&quot;&gt;
[[http://linusp.github.io/][Linusp's Blog]]
&lt;/pre&gt;

&lt;p&gt;
会显示为 &lt;a href=&quot;http://linusp.github.io/&quot;&gt;Linusp's Blog&lt;/a&gt;。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>Shell 中的随机数生成方法</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/07/10/random-in-bash.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2015/07/10/random-in-bash</id>
    <published>2015-07-10T00:00:00+00:00</published>
    <updated>2015-07-10T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


$RANDOM
/dev/random
seq + sort
shuf




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;$RANDOM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;/dev/random&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;seq + sort&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;shuf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;
昨天写了个脚本，用 &lt;a href=&quot;http://www.imagemagick.org/script/index.php&quot;&gt;ImageMagick&lt;/a&gt; 生成单个字符的图片，并随机为其附加模糊、噪声、旋转、扭曲等效果，这个脚本生成的图片是准备用来测试 DNN 的。目前来看的话，用 ImageMagick 生成的图片并不完全理想 —— 不过还能凑合着用。总之，为了生成尽量多尽量丰富的样本，我希望各种效果的作用程度是随机的，而且应用哪些效果也是随机的。毫无疑问这里是需要使用随机数的了。
&lt;/p&gt;

&lt;p&gt;
当然了，本文提到的“随机数”实质上都是伪随机数，毕竟计算机只能模拟这一过程。
&lt;/p&gt;

&lt;p&gt;
最后我选择的是使用 &lt;a href=&quot;http://www.gnu.org/software/coreutils/manual/html_node/shuf-invocation.html#shuf-invocation&quot;&gt;shuf&lt;/a&gt; 这个工具，不过在解决这个问题的过程中也总结了不止一种办法，在这里分享一下。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;$RANDOM&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
照 &lt;a href=&quot;http://www.tldp.org/LDP/abs/html/randomvar.html&quot;&gt;这里&lt;/a&gt; 讲， RANDOM 是 Bash 的一个内建函数(而不是常量)，会返回一个在区间 [0, 32767] 内的整数。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;echo&lt;/span&gt; $&lt;span style=&quot;color: #eeeeec;&quot;&gt;RANDOM&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;4230&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
使用这个方法时，可以通过设置相同的 seed 来得到相同的随机数，当然也可以反过来用不同的 seed 来产生不同的随机数。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #eeeeec;&quot;&gt;RANDOM&lt;/span&gt;=10
&lt;span style=&quot;color: #729fcf;&quot;&gt;echo&lt;/span&gt; $&lt;span style=&quot;color: #eeeeec;&quot;&gt;RANDOM&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;4230&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
设置相同的 seed 后，可以观察到连续使用 $RANDOM 生成的随机数序列都是一样的。实际情况中我们可能希望生成的“随机数”尽量的不同，我们可以将时间转换为数字来设置 seed:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;random_with_time&lt;/span&gt;{} {
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;RANDOM&lt;/span&gt;=$(&lt;span style=&quot;color: #fa8072;&quot;&gt;date&lt;/span&gt; +%s)
    &lt;span style=&quot;color: #729fcf;&quot;&gt;echo&lt;/span&gt; $&lt;span style=&quot;color: #eeeeec;&quot;&gt;RANDOM&lt;/span&gt;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
不过需要注意的是，由于这里 date 命令的输出是精确到秒，seed 的值在 1 秒内是不变的，产生的随机数值也会相同。而在不设置 seed 的情况下，RANDOM 的输出在 1 秒内是会变化的，这里只是为了说明而举个例子而已。
&lt;/p&gt;

&lt;p&gt;
如果需要产生特定范围内的随机数，可以这么写:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;@args &amp;lt;beg&amp;gt; &amp;lt;end&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;return random integer in [&amp;lt;beg&amp;gt;, &amp;lt;end&amp;gt;)&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;random_range&lt;/span&gt;() {
    &lt;span style=&quot;color: #729fcf;&quot;&gt;local&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;beg&lt;/span&gt;=$&lt;span style=&quot;color: #eeeeec;&quot;&gt;1&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;local&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;end&lt;/span&gt;=$&lt;span style=&quot;color: #eeeeec;&quot;&gt;2&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;echo&lt;/span&gt; $((RANDOM % ($&lt;span style=&quot;color: #eeeeec;&quot;&gt;end&lt;/span&gt; - $&lt;span style=&quot;color: #eeeeec;&quot;&gt;beg&lt;/span&gt;) + $&lt;span style=&quot;color: #eeeeec;&quot;&gt;beg&lt;/span&gt;))
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;/dev/random&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
/dev/random 是 Linux 上的一个字符设备，里面会源源不断地产生随机数，只要进行读取就行了。一般来说，用 od 命令即可:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;od -An -N2 -i /dev/random
&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;13176&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
这里的 -N2 指定要读取的字节数， -i 则是指定输入。
&lt;/p&gt;

&lt;p&gt;
若要产生特定范围内的随机数，则和使用 $RANDOM 的方法类似:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;@args &amp;lt;beg&amp;gt; &amp;lt;end&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;return random integer in [&amp;lt;beg&amp;gt;, &amp;lt;end&amp;gt;)&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;random_range&lt;/span&gt;() {
    &lt;span style=&quot;color: #729fcf;&quot;&gt;local&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;beg&lt;/span&gt;=$&lt;span style=&quot;color: #eeeeec;&quot;&gt;1&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;local&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;end&lt;/span&gt;=$&lt;span style=&quot;color: #eeeeec;&quot;&gt;2&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;echo&lt;/span&gt; $(($(&lt;span style=&quot;color: #fa8072;&quot;&gt;od&lt;/span&gt; -An -N2 -i /dev/random) % ($&lt;span style=&quot;color: #eeeeec;&quot;&gt;end&lt;/span&gt; - $&lt;span style=&quot;color: #eeeeec;&quot;&gt;beg&lt;/span&gt;) + $&lt;span style=&quot;color: #eeeeec;&quot;&gt;beg&lt;/span&gt;))
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;seq + sort&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
sort 命令有一个 -R 选项，可以根据随机 hash 排序，那么我们就可以用 seq 命令先生成一个整数序列，然后用 sort 的 -R 选项处理取其中一行即可。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;@args &amp;lt;beg&amp;gt; &amp;lt;end&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;return random integer in [&amp;lt;beg&amp;gt;, &amp;lt;end&amp;gt;]&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;random_range&lt;/span&gt; {
    &lt;span style=&quot;color: #729fcf;&quot;&gt;local&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;beg&lt;/span&gt;=$&lt;span style=&quot;color: #eeeeec;&quot;&gt;1&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;local&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;end&lt;/span&gt;=$&lt;span style=&quot;color: #eeeeec;&quot;&gt;2&lt;/span&gt;
    seq $&lt;span style=&quot;color: #eeeeec;&quot;&gt;beg&lt;/span&gt; $&lt;span style=&quot;color: #eeeeec;&quot;&gt;end&lt;/span&gt; | sort -R | head -n1
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
值得注意的是，使用这种方法时，要求的值域可以包含负数区域，而之前的两种方法则要进行不同的处理。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline4&quot;&gt;shuf&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
shuf 和 'sort -R' 的作用类似，用来根据输入生成随机序列:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;@args &amp;lt;beg&amp;gt; &amp;lt;end&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;return random integer in [&amp;lt;beg&amp;gt;, &amp;lt;end&amp;gt;]&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;random_range&lt;/span&gt; {
    shuf -i $&lt;span style=&quot;color: #eeeeec;&quot;&gt;1&lt;/span&gt;-$&lt;span style=&quot;color: #eeeeec;&quot;&gt;2&lt;/span&gt; -n1
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
在各种方法中，使用 shuf 命令是最简洁的，因此就选择了这种方法。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>GDB调试技巧(续)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/06/12/gdb-tricks-again.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2015/06/12/gdb-tricks-again</id>
    <published>2015-06-12T00:00:00+00:00</published>
    <updated>2015-06-12T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


设置环境变量
修改、设置程序中的变量
查看变量的类型
调用函数




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;设置环境变量&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;修改、设置程序中的变量&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;查看变量的类型&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;调用函数&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
以下是这段时间阅读 Tesseract 源代码时所学习并实践过的一些 GDB 调试技巧，和 &lt;a href=&quot;http://linusp.github.io/2014/07/27/gdb-tricks.html&quot;&gt;前一篇&lt;/a&gt; 一样，我也认为这些是比较实用的(虽然对别人来说未必)。
&lt;/p&gt;

&lt;p&gt;
另外，我觉得阅读源代码的话，最好的办法莫过于进行调试，深入其内部的处理流程 —— 当然如果作者有提供完善的文档的话可以省下很多的精力。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;设置环境变量&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
这个其实倒和 GDB 本身没多大关系，一般来说在 shell 里启动 GDB 的话，是能够正常使用用户的环境变量的，不过作为一个 Emacser ，我更喜欢在 Emacs 里用 gud-gdb 来进行调试，Emacs 会为 GDB 提供一个更易用的用户界面，但问题是这种情况下自己设置的一些环境变量都没有被读取。
&lt;/p&gt;

&lt;p&gt;
在调试 Tesseract 的时候，程序要使用一个外部的环境变量 TESSDATA_PREFIX ，于是就出现问题了。
&lt;/p&gt;

&lt;p&gt;
解决这个问题的方法是用 &lt;b&gt;set&lt;/b&gt; 命令在 GDB 里设置环境变量:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;set&lt;/span&gt; environment &lt;span style=&quot;color: #eeeeec;&quot;&gt;TESSDATA_PREFIX&lt;/span&gt;=/home/linusp/data/tessdata
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
当然了 set 命令还可以用来设置、修改变量的值，是非常有用的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;修改、设置程序中的变量&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
有两种办法，一种是使用 &lt;b&gt;set&lt;/b&gt; 命令，另外一种是使用 &lt;b&gt;print&lt;/b&gt; 命令。
&lt;/p&gt;

&lt;p&gt;
set 命令:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;set&lt;/span&gt; variable &lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt;=0
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
或者先得到待设置的变量的地址(用 print 命令)，然后根据地址来修改值:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;set&lt;/span&gt; *((int *) 0xbfbb0000) = 20
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
print 命令:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;print &lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt;=0
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;查看变量的类型&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
使用 &lt;b&gt;whatis&lt;/b&gt; 命令可以得到变量的类型，如果变量的类型是一个复合类型而非 C/C++ 的基础类型，则可以通过 &lt;b&gt;ptype&lt;/b&gt; 命令来查看该类型的定义。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gdb_show_type.png&quot; alt=&quot;gdb_show_type.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline4&quot;&gt;调用函数&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
在调试的时候可以通过 &lt;b&gt;call&lt;/b&gt; 命令来调用一些函数。在调试 Tesseract 时，它使用的图像库 Leptonica 提供了一个显示图像的函数 pixDisplay ，让我能够用 call 命令来调用它查看每一步处理结束后图像变成了什么样子，实在是帮了大忙了。
&lt;/p&gt;

&lt;p&gt;
除了辅助调试外，不妨将思维发散一下，用 call 命令可以调用函数，而 print 命令则能执行一些非函数调用的普通语句(不过控制语句无法被执行)，结合这两者我们就有了一个几乎是交互式的 C/C++ 运行环境了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>百度 OCR API 的使用以及与 Tesseract 的简单对比</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/06/10/baidu_ocr_api_usage.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2015/06/10/baidu_ocr_api_usage</id>
    <published>2015-06-10T00:00:00+00:00</published>
    <updated>2015-06-10T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


百度 OCR API 初探
用 Python 调用百度 OCR API
与 Tesseract 的简单对比




百度 OCR API 初探


近日得...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;百度 OCR API 初探&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;用 Python 调用百度 OCR API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;与 Tesseract 的简单对比&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;百度 OCR API 初探&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
近日得知百度在其 &lt;a href=&quot;http://apistore.baidu.com/&quot;&gt;APIStore&lt;/a&gt; 上开放了 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E5%85%89%E5%AD%A6%E5%AD%97%E7%AC%A6%E8%AF%86%E5%88%AB&quot;&gt;OCR&lt;/a&gt; 的 API，目前以 &lt;a href=&quot;http://apistore.baidu.com/apiworks/readyapiprefecture.html&quot;&gt;即用API&lt;/a&gt; 的形式试运行，所谓 &quot;即用&quot; 指可立即调用、无需注册付费，但也加上了有使用次数这么一个限制。
&lt;/p&gt;

&lt;p&gt;
目前该 API 的文档很少，不过接口和参数都在其 &lt;a href=&quot;http://apistore.baidu.com/apiworks/servicedetail/146.html&quot;&gt;API页面&lt;/a&gt; 进行了说明，要用起来还是没有问题的。下面是接口的信息
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;接口地址: &lt;a href=&quot;http://apis.baidu.com/apistore/idlocr/ocr&quot;&gt;http://apis.baidu.com/apistore/idlocr/ocr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;请求方法: POST&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
相关的参数则有
&lt;/p&gt;
&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;参数名&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;类型&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;必填&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;参数位置&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;描述&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;可用值&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;fromdevice&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;string&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;yes&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;bodyParam&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;来源设备&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;android, iPhone, pc&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;clientip&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;string&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;yes&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;bodyParam&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;客户端出口ip&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;detecttype&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;string&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;yes&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;bodyParam&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;OCR服务类型&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;LocateRecognize, Recognize, Locate, SingleCharRecognize&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;languagetype&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;string&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;yes&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;bodyParam&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;待检测的文字类型&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;CHN_ENG, ENG, JAP, KOR&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;imagetype&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;string&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;yes&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;bodyParam&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;图片资源类型&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;1: 经过BASE64处理的字符串; 2: 图片源文件&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;image&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;string&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;yes&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;bodyParam&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;图片资源,300K以下&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;apikey&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;string&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;yes&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;header&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;API 密钥&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;
返回的结果会是一个 JSON 字符串，如下所示:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
{
    &quot;errNum&quot;: 0,
    &quot;errMsg&quot;: &quot;success&quot;,
    &quot;querySign&quot;: &quot;3845925467,2370020290&quot;,
    &quot;retData&quot;: [
        {
            &quot;rect&quot;: {
                &quot;left&quot;: &quot;0&quot;,
                &quot;top&quot;: &quot;0&quot;,
                &quot;width&quot;: &quot;33&quot;,
                &quot;height&quot;: &quot;31&quot;
            },
            &quot;word&quot;: &quot;  8&quot;
        }
    ]
}
&lt;/pre&gt;

&lt;p&gt;
各字段的意义如下:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
errNum
&lt;/p&gt;

&lt;p&gt;
标识处理是否成功, 0: 表示成功, 其它值, 表示失败。在 &lt;a href=&quot;http://apistore.baidu.com/apiworks/servicedetail/146.html&quot;&gt;API页面&lt;/a&gt; 上可以查看更详细的错误码列表。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
errMsg
&lt;/p&gt;

&lt;p&gt;
错误类型说明，当服务调用成功时为字符串 'success'
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
querySign
&lt;/p&gt;

&lt;p&gt;
本次请求用户传递原图或rl的唯一标示, 方便定位问题
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
retData
&lt;/p&gt;

&lt;p&gt;
返回内容集合
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
rect
&lt;/p&gt;

&lt;p&gt;
该行文字所在的矩形区域的信息
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
word
&lt;/p&gt;

&lt;p&gt;
该行所识别出的文字
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;用 Python 调用百度 OCR API&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
在 API 页面上倒是提供了 Python 的调用示例，不过个人感觉比较丑，居然还在使用 urllib !我们完全可以用 requests 来做这些事情，下面是我写的一个方法:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;-*- coding: utf-8 -*-&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; requests

&lt;span style=&quot;color: #eeeeec;&quot;&gt;URL&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'http://apis.baidu.com/apistore/idlocr/ocr'&lt;/span&gt;
&lt;span style=&quot;color: #eeeeec;&quot;&gt;LANG_LIST&lt;/span&gt; = [&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'CHN_ENG'&lt;/span&gt;, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'ENG'&lt;/span&gt;, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'JAP'&lt;/span&gt;, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'KOR'&lt;/span&gt;]


&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;ocr&lt;/span&gt;(picture, lang=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'CHN_ENG'&lt;/span&gt;):
    &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&quot;&quot;Recognize a picture and return the text on it.&lt;/span&gt;

&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    picture could be a local picture or url of picture on web.&lt;/span&gt;

&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    lang should be one of CHN_ENG, ENG, JAP, KOR&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;data&lt;/span&gt; = {}
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;data&lt;/span&gt;[&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'fromdevice'&lt;/span&gt;] = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;pc&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;data&lt;/span&gt;[&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'clientip'&lt;/span&gt;] = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'10.10.10.0'&lt;/span&gt;
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;data&lt;/span&gt;[&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'detecttype'&lt;/span&gt;] = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'Recognize'&lt;/span&gt;
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;data&lt;/span&gt;[&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'imagetype'&lt;/span&gt;] = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;2&quot;&lt;/span&gt;

    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; lang &lt;span style=&quot;color: #729fcf;&quot;&gt;not&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;in&lt;/span&gt; LANG_LIST:
        &lt;span style=&quot;color: #729fcf;&quot;&gt;raise&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;Exception&lt;/span&gt;(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'invalid language: %s'&lt;/span&gt; % lang)
    &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt;:
        &lt;span style=&quot;color: #eeeeec;&quot;&gt;data&lt;/span&gt;[&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'languagetype'&lt;/span&gt;] = lang

    &lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#27492;&amp;#22788;&amp;#24212;&amp;#20351;&amp;#29992;&amp;#33258;&amp;#24049;&amp;#30340; API key&lt;/span&gt;
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;header&lt;/span&gt; = {&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;apikey&quot;&lt;/span&gt;: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;your api key&quot;&lt;/span&gt;}

    &lt;span style=&quot;color: #eeeeec;&quot;&gt;image_file&lt;/span&gt; = &lt;span style=&quot;color: #e6a00f;&quot;&gt;None&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;try&lt;/span&gt;:
        &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; picture.startswith(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'http://'&lt;/span&gt;) &lt;span style=&quot;color: #729fcf;&quot;&gt;or&lt;/span&gt; picture.startswith(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'https://'&lt;/span&gt;):
            &lt;span style=&quot;color: #eeeeec;&quot;&gt;image_file&lt;/span&gt; = requests.get(picture).content
        &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt;:
            &lt;span style=&quot;color: #eeeeec;&quot;&gt;image_file&lt;/span&gt; = &lt;span style=&quot;color: #729fcf;&quot;&gt;open&lt;/span&gt;(picture, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'rb'&lt;/span&gt;).read()
    &lt;span style=&quot;color: #729fcf;&quot;&gt;except&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;Exception&lt;/span&gt;:
        &lt;span style=&quot;color: #729fcf;&quot;&gt;raise&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;Exception&lt;/span&gt;(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'invalid picture: %s'&lt;/span&gt; % picture)

    &lt;span style=&quot;color: #eeeeec;&quot;&gt;resp&lt;/span&gt; = requests.post(URL, headers=header, data=data, files={&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;image&quot;&lt;/span&gt;: (&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;baidu.jpg&quot;&lt;/span&gt;, image_file)})

    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; resp &lt;span style=&quot;color: #729fcf;&quot;&gt;is&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;not&lt;/span&gt; &lt;span style=&quot;color: #e6a00f;&quot;&gt;None&lt;/span&gt;:
        &lt;span style=&quot;color: #eeeeec;&quot;&gt;resp&lt;/span&gt; = resp.json()
        &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt;  &lt;span style=&quot;color: #729fcf;&quot;&gt;int&lt;/span&gt;(resp.get(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'errNum'&lt;/span&gt;)) != 0:
            &lt;span style=&quot;color: #729fcf;&quot;&gt;raise&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;Exception&lt;/span&gt;(reps.get(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'errMsg'&lt;/span&gt;))
        &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt;:
            &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; resp.get(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'retData'&lt;/span&gt;)[0].get(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'word'&lt;/span&gt;)
    &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt;:
        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #e6a00f;&quot;&gt;None&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
需要注意的是，虽然 API 页面上说图片目前仅支持 jpg 格式，但实际上对图片格式的检查很有可能是通过检查文件名的后缀来进行的，所以通过将 &quot;imagetype&quot; 设置为 2 并将图片以 jpg 作为后缀名进行上传来绕过这个限制。
&lt;/p&gt;

&lt;p&gt;
然后拿一张图片来看看!好，就是下面这张了:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/ocr_test_002.jpg&quot; alt=&quot;ocr_test_002.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
识别结果如下:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/ocr_test_002_result.png&quot; alt=&quot;ocr_test_002_result.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;与 Tesseract 的简单对比&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
要比较全面、客观地对比出两个不同的产品的性能是需要大量的数据和详尽地设计的，这里只是根据我个人对 OCR 系统的认识，使用了少量的数据进行的对比，至于两者孰优孰劣请读者自行试验再下结论。
&lt;/p&gt;

&lt;p&gt;
图一:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/ocr_test_001.jpg&quot; alt=&quot;ocr_test_001.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
百度 OCR API 识别结果:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
讨论代数方程r+积—劲—1=0在(—”0)内实根的情况
&lt;/pre&gt;

&lt;p&gt;
Tesseract 识别结果:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
讨论代数方程娱+4筹－3χ－l=O在 (－∞,O〉 内实根的情况₋
&lt;/pre&gt;

&lt;p&gt;
图二:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/ocr_test_002.jpg&quot; alt=&quot;ocr_test_002.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
百度 OCR API 识别结果:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
L(理)已知:是虚数单位.则(―1―D《2―D=一一一一f》    A―3+iB―1―3  C―3+3D―1―1
&lt;/pre&gt;

&lt;p&gt;
Tesseract 识别结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
L₍₋₎已概ᵢ量ᵦ效单位。口(—₁针)(２₋E,＝ ⋯烟～₋ (
A₋₋₃+ᵢ BL－{•S宜

 C.－3+3i D·一l震拿

罐震 ,△、an．△ᵅ＝₂₋！₋₃—?又₋T＝xf —$⩽ᵣ⩽玉 ₋l S校 r＝ —
&lt;/pre&gt;

&lt;p&gt;
图三:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/ocr_test_003.jpg&quot; alt=&quot;ocr_test_003.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
百度 OCR API 识别结果:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
新课标全国)在一组样本数据(Xl,y)G,y)%不全相等的散点图中,若所有样本点ki,y4+|上,则这组样本数据的样本相关系数为0      Boc.号
&lt;/pre&gt;

&lt;p&gt;
Tesseract 识别结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
!新课标全国)在岗组样本数据Uh趴汕懒h…
蘑. 不全相等)的散点图中，若所有样本点牺酬

L篆+I 上,则这组样本数据的样本相关系数为 o

1
B.0 时
&lt;/pre&gt;


&lt;p&gt;
图四:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/ocr_test_004.jpg&quot; alt=&quot;ocr_test_004.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
百度 OCR API 识别结果:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
11分)如图271日.在△A风中,∠C=45·现妹10.高AD=8.矩形EFPQ的一边吐在风边上,1
&lt;/pre&gt;

&lt;p&gt;
Tesseract 识别结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
.’⁻．∴ 、,〉 、、．罐’∣【




r\∪【川 '′ ∣⋃.／L 、∥('中．
&quot;pQ的
&lt;/pre&gt;


&lt;p&gt;
图五:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/ocr_test_005.jpg&quot; alt=&quot;ocr_test_005.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
百度 OCR API 识别结果:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
B
&lt;/pre&gt;

&lt;p&gt;
Tesseract 识别结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
乐散说, 你是找的全部
你是耕掌希宁触-都余
但找的主命宁
猪漆能装有你

就傅
她环东能玻节玻引才
A美未能表有童气
大她东能装有四兔
&lt;/pre&gt;

&lt;p&gt;
从以上这些对比，我得到以下一些 &lt;b&gt;不一定客观&lt;/b&gt; 的结论:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;百度的 OCR 系统对噪声、模糊等有较强的抗干扰性，这一点上要优于 Tesseract&lt;/li&gt;
&lt;li&gt;百度的 OCR 系统没有进行布局分析，但 Tesseract 在布局分析上做得比较好&lt;/li&gt;
&lt;li&gt;百度的 OCR 系统 &lt;b&gt;可能&lt;/b&gt; 对 &lt;b&gt;黑底白字&lt;/b&gt; 的图像识别不好&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>Tesseract源代码阅读:字符串 STRING</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/05/11/string-in-tesseract.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2015/05/11/string-in-tesseract</id>
    <published>2015-05-11T00:00:00+00:00</published>
    <updated>2015-05-11T00:00:00+00:00</updated>
    <description>
    
      <p>
STRING 类是 Tesseract 中自定义的字符串类，封装了一些字符串操作，该类定义于 ccutil/strngs.h 中，同样的，不知道出于什么目的，其设计让人一开始摸不着头脑。


</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
STRING 类是 Tesseract 中自定义的字符串类，封装了一些字符串操作，该类定义于 ccutil/strngs.h 中，同样的，不知道出于什么目的，其设计让人一开始摸不着头脑。
&lt;/p&gt;

&lt;p&gt;
按理来说，如果要实现一个字符串类，那么其内部应该要有一个保存字符串内容的数据成员，这个 STRING 类确实有数据成员，不过其类型是内部定义的一个结构 STRING_HEADER:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;TESS_API&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;STRING&lt;/span&gt; {
&lt;span style=&quot;color: #729fcf;&quot;&gt;public&lt;/span&gt;:
    &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;....&lt;/span&gt;

&lt;span style=&quot;color: #729fcf;&quot;&gt;private&lt;/span&gt;:
    &lt;span style=&quot;color: #729fcf;&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;struct&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;STRING_HEADER&lt;/span&gt; {
        &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;capacity_&lt;/span&gt;;

        &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;used_ is how much of the capacity is currently being used,&lt;/span&gt;
        &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;including a '\0' terminator.&lt;/span&gt;
        &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;if used_ is 0 then string is NULL(not even the '\0')&lt;/span&gt;
        &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;else if used_ &amp;gt; 0 then it is strlen() + 1 (because it includes '\0')&lt;/span&gt;
        &lt;span style=&quot;color: #729fcf;&quot;&gt;mutable&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;used_&lt;/span&gt;;
    } &lt;span style=&quot;color: #8ae234;&quot;&gt;STRING_HEADER&lt;/span&gt;;

    &lt;span style=&quot;color: #8ae234;&quot;&gt;STRING_HEADER&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;data_&lt;/span&gt;;

    &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;....&lt;/span&gt;
};
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到这个数据成员中并没有保存字符串内容的部分。
&lt;/p&gt;

&lt;p&gt;
STRING 类中有两个方法，返回的是一个 &lt;b&gt;const char *&lt;/b&gt; 类型的值，这两个方法的名称为 &lt;b&gt;string()&lt;/b&gt; 和 &lt;b&gt;c_str()&lt;/b&gt; ，从这两点上来看，可以认为这两个方法是将 STRING 类内部存储的字符串内容转换为 &lt;b&gt;const char *&lt;/b&gt; 类型返回了出来，那么可以从这两个方法去入手来发掘这个类的秘密。
&lt;/p&gt;

&lt;p&gt;
这两个方法的实现都很简单:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
string() 方法
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt;* &lt;span style=&quot;color: #e6a00f;&quot;&gt;STRING&lt;/span&gt;::&lt;span style=&quot;color: #edd400;&quot;&gt;string&lt;/span&gt;() &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; {
    &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;STRING_HEADER&lt;/span&gt;* &lt;span style=&quot;color: #eeeeec;&quot;&gt;header&lt;/span&gt; = GetHeader();
    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (header-&amp;gt;used_ == 0)
        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;;

    &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;mark header length unreliable because tesseract might&lt;/span&gt;
    &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;cast away the const and mutate the string directly.&lt;/span&gt;
    header-&amp;gt;used_ = -1;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; GetCStr();
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
c_str()
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt;* &lt;span style=&quot;color: #e6a00f;&quot;&gt;STRING&lt;/span&gt;::&lt;span style=&quot;color: #edd400;&quot;&gt;c_str&lt;/span&gt;() &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; {
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; string();
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
c_str() 方法是 string() 方法的别名，而 string() 方法中返回的结果是 GetCStr() 这个方法的结果，顺藤摸瓜找到这个方法，发现它的实现如下:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;inline&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt;* &lt;span style=&quot;color: #edd400;&quot;&gt;GetCStr&lt;/span&gt;() &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; {
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; ((&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *)data_) + &lt;span style=&quot;color: #729fcf;&quot;&gt;sizeof&lt;/span&gt;(STRING_HEADER);
};
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
也就是说，STRING 类把字符串内容放在了 data_ 后面的那个地址空间上，不过这段空间是匿名的，只能通过上面这样的方式进行访问。
&lt;/p&gt;

&lt;p&gt;
到底是出于何种考虑进行这样的设计，我也无从得之，但我个人是对这个设计不太赞同的。要说有什么优点，就是在进行内存分配时少了一步操作 —— 在 STRING::AllocData 中是这样进行内存分配的:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #e6a00f;&quot;&gt;STRING&lt;/span&gt;::&lt;span style=&quot;color: #edd400;&quot;&gt;AllocData&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;used&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;capacity&lt;/span&gt;) {
    data_ = (&lt;span style=&quot;color: #8ae234;&quot;&gt;STRING_HEADER&lt;/span&gt; *)alloc_string(capacity + &lt;span style=&quot;color: #729fcf;&quot;&gt;sizeof&lt;/span&gt;(STRING_HEADER));

    &lt;span style=&quot;color: #8ae234;&quot;&gt;STRING_HEADER&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;header&lt;/span&gt; = GetHeader();
    header-&amp;gt;capacity_ = capacity;
    header-&amp;gt;used_ = used;

    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; GetCStr();
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
另外，上面这个方法里的 GetHeader() 方法返回的就是 data_ ，直接这样我想也是可以的:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;data_ = (&lt;span style=&quot;color: #8ae234;&quot;&gt;STRING_HEADER&lt;/span&gt; *)alloc_string(capacity + &lt;span style=&quot;color: #729fcf;&quot;&gt;sizeof&lt;/span&gt;(STRING_HEADER));

data_-&amp;gt;capacity_ = capacity;
data_-&amp;gt;used_ = used;

&lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; GetCStr();
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
在 STRING 类封装的方法里，大部分在 C/C++ 中已有对应的字符串操作。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>编译安装启动器 Synapse</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/05/09/install-synapse.html"/>
    <category term="Linux" scheme="http://www.zmonster.me/categories.html#Linux"/>
    <id>http://www.zmonster.me/2015/05/09/install-synapse</id>
    <published>2015-05-09T00:00:00+00:00</published>
    <updated>2015-05-09T00:00:00+00:00</updated>
    <description>
    
      <p>
Synapse 是一个类似 Gnome-Do 的语义型启动器(sementic launcher)，只要输入部分字符就可以匹配相应的文件或程序，能够有效地提高工作效率 —— 特别是对于 Ema...</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
Synapse 是一个类似 Gnome-Do 的语义型启动器(sementic launcher)，只要输入部分字符就可以匹配相应的文件或程序，能够有效地提高工作效率 —— 特别是对于 Emacs/Vim 用户来说
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/synapse.png&quot; alt=&quot;synapse.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
网上能找到关于该软件的更多介绍以及安装方法，不过大都是介绍如何通过 PPA 来安装，我不太喜欢这种方式，加上 Debian 因为 Synapse 的不稳定而把它移出了软件仓库，所以我只有选择编译安装了。所以本文只是一篇水文啦，在这里简单地把自己编译过程里遇到的坑分享出来，如果有人也编译安装的话，希望能有所帮助。
&lt;/p&gt;

&lt;p&gt;
源代码下载链接&lt;a href=&quot;https://launchpad.net/synapse-project/0.3/0.2.99.1/+download/synapse-0.2.99.1.tar.xz&quot;&gt;在此&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
Synapse 的依赖有:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;libnotify-dev&lt;/li&gt;
&lt;li&gt;libjson-glib-dev&lt;/li&gt;
&lt;li&gt;libkeybinder-3.0-dev&lt;/li&gt;
&lt;li&gt;libgee-0.8-dev&lt;/li&gt;
&lt;li&gt;libzeitgeist-2.0-dev&lt;/li&gt;
&lt;li&gt;valac&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
前面 lib 开头的是 Synapse 依赖的库，从软件仓库安装即可，另外 Synapse 还依赖 gtk 的几个库，但是没记录下来，所以不记得对应的库的名称了。不过这些依赖都在源代码包中的 configure 这个脚本里面写了。在 Synapse 0.2.99.1 (我用的版本) 中，configure 中的依赖列表是这样的:
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;glib-2.0&lt;/li&gt;
&lt;li&gt;gdk-x11-3.0&lt;/li&gt;
&lt;li&gt;gtk+-3.0&lt;/li&gt;
&lt;li&gt;gio-2.0&lt;/li&gt;
&lt;li&gt;gio-unix-2.0&lt;/li&gt;
&lt;li&gt;gobject-2.0&lt;/li&gt;
&lt;li&gt;gthread-2.0&lt;/li&gt;
&lt;li&gt;gee-0.8&lt;/li&gt;
&lt;li&gt;json-glib-1.0&lt;/li&gt;
&lt;li&gt;keybinder-3.0&lt;/li&gt;
&lt;li&gt;libnotify&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
除了这些库依赖外，由于 Synapse 是 Vala 语言编写的，还需要安装 Vala 编译器 valac。
&lt;/p&gt;

&lt;p&gt;
在完成以上依赖安装后，就可以进行 Synapse 的编译安装了:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;./configure --prefix=/opt/synapse
make
make install
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Done!
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>Tesseract源代码阅读:单链表 ELIST</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/05/06/linked-list-in-tesseract.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2015/05/06/linked-list-in-tesseract</id>
    <published>2015-05-06T00:00:00+00:00</published>
    <updated>2015-05-06T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


ELIST_LINK
ELIST
ELIST_ITERATOR
实际单链表的实现方法
Tesseract 中实际被使用的单链表类




因为工作以及个人...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;ELIST_LINK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;ELIST&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;ELIST_ITERATOR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;实际单链表的实现方法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;Tesseract 中实际被使用的单链表类&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
因为工作以及个人兴趣原因，已经阅读了一段时间 Tesseract 的源代码了(Tesseract 的介绍见&lt;a href=&quot;http://linusp.github.io/2015/04/17/tesseract-install-usage.html&quot;&gt;我的另一篇文章&lt;/a&gt;)。从这篇文章开始，会不定期地将阅读笔记整理好发布出来。
&lt;/p&gt;

&lt;p&gt;
ELIST 是 Tesseract 中的单链表基类， Tesseract 的核心处理流程中有不少不同类型的单链表类都继承自 ELIST ，因此了解 ELIST 的具体实现是很有必要的。
&lt;/p&gt;

&lt;p&gt;
虽然这里先提到 ELIST ，但实际上这个单链表由三个类组成，它们分别是:
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;ELIST_LINK: 链表节点&lt;/li&gt;
&lt;li&gt;ELIST: 链表，保存了链表头节点&lt;/li&gt;
&lt;li&gt;ELIST_ITERATOR: 封装了对链表的具体操作&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
这三个类都定义于 ccutil/elst.h 中
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;ELIST_LINK&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
该类的定义为:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;DLLSYM&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;ELIST_LINK&lt;/span&gt;
{
    &lt;span style=&quot;color: #729fcf;&quot;&gt;friend&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_ITERATOR&lt;/span&gt;;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;friend&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST&lt;/span&gt;;

    &lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_LINK&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;next&lt;/span&gt;;

&lt;span style=&quot;color: #729fcf;&quot;&gt;public&lt;/span&gt;:
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;ELIST_LINK&lt;/span&gt;() {
        next = &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;;
    }

    &lt;span style=&quot;color: #888a85;&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;constructor&lt;/span&gt;
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;ELIST_LINK&lt;/span&gt;(                 &lt;span style=&quot;color: #888a85;&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;copy constructor&lt;/span&gt;
        &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_LINK&lt;/span&gt; &amp;amp;) {   &lt;span style=&quot;color: #888a85;&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;dont copy link&lt;/span&gt;
        next = &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;;
    }

    &lt;span style=&quot;color: #8ae234;&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;operator&lt;/span&gt;&lt;span style=&quot;color: #eeeeec;&quot;&gt;=&lt;/span&gt; (            &lt;span style=&quot;color: #888a85;&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;dont copy links&lt;/span&gt;
        &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_LINK&lt;/span&gt; &amp;amp;) {
        next = &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;;
    }
};
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这个类实际被作为链表的 &quot;节点&quot;。
&lt;/p&gt;

&lt;p&gt;
可以看到，这个类的定义异常简单，数据成员只有一个同类型的指针，也没有定义除构造方法外的其他方法。而且在拷贝构造函数和赋值运算符重载中，直接忽略了传入的参数，从注释里也能明白，作者是将 &quot;拷贝&quot; 这个行为直接禁止了 —— 如果不显式定义拷贝构造函数的话，编译器会生成一个默认的拷贝构造函数，里面还是会进行拷贝操作的，赋值运算符重载同理。
&lt;/p&gt;

&lt;p&gt;
不过令人疑惑的是，为什么这个 &quot;节点&quot; 类型里没有保存节点数据的成员呢?这个待会再说，不妨先保留着疑问吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;ELIST&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
该类的定义如下(出于简洁考虑，这里没有列出它内部的一些方法):
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;DLLSYM&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;ELIST&lt;/span&gt;
{
    &lt;span style=&quot;color: #729fcf;&quot;&gt;friend&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_ITERATOR&lt;/span&gt;;

    &lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_LINK&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;last&lt;/span&gt;;           &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;End of list&lt;/span&gt;
    &lt;span style=&quot;color: #888a85;&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;(points to head)&lt;/span&gt;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_LINK&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;First&lt;/span&gt;() {       &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;return first&lt;/span&gt;
        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; last ? last-&amp;gt;next : &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;;
    }

&lt;span style=&quot;color: #729fcf;&quot;&gt;public&lt;/span&gt;:
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;ELIST&lt;/span&gt;() {
        last = &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;;
    }

    &lt;span style=&quot;color: #8ae234;&quot;&gt;bool&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;empty&lt;/span&gt;() &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; {
        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; !last;
    }

    &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;......&lt;/span&gt;
};
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
正如之前所说，ELIST 中记录了链表的头节点，同时还定义、实现了一些链表层面的操作方法。
&lt;/p&gt;

&lt;p&gt;
令人比较在意的是，ELIST 中表示头节点的成员的名称为 &quot;last&quot; ，而且名为 &quot;First&quot; 的私有方法也是返回这个头节点的 &lt;b&gt;下一个节点&lt;/b&gt; ，脱离上下文来看的话，可能会觉得别扭。不过其实 ELIST 实现的是一个单向循环链表，这里的 &quot;last&quot; 确实是指向了最后一个节点，而这最后一个节点又指向了第一个节点。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;ELIST_ITERATOR&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
顾名思义，该类是 ELIST 类的 &quot;迭代器&quot; ，可以用来对 ELIST 进行遍历操作。该类的定义为:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;DLLSYM&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;ELIST_ITERATOR&lt;/span&gt; {
    &lt;span style=&quot;color: #729fcf;&quot;&gt;friend&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color: #e6a00f;&quot;&gt;ELIST&lt;/span&gt;::&lt;span style=&quot;color: #eeeeec;&quot;&gt;assign_to_sublist&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_ITERATOR&lt;/span&gt; *, &lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_ITERATOR&lt;/span&gt; *);

    &lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;list&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_LINK&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;prev&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_LINK&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;current&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_LINK&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;next&lt;/span&gt;;

    &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#20854;&amp;#20182;&amp;#25104;&amp;#21592;&lt;/span&gt;

&lt;span style=&quot;color: #729fcf;&quot;&gt;public&lt;/span&gt;:
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;ELIST_ITERATOR&lt;/span&gt;() {
        list = &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;;
    }

    &lt;span style=&quot;color: #eeeeec;&quot;&gt;ELIST_ITERATOR&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;list_to_iterate&lt;/span&gt;);

    &lt;span style=&quot;color: #8ae234;&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;set_to_list&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;list_to_iterate&lt;/span&gt;);

    &lt;span style=&quot;color: #8ae234;&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;add_after_then_move&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_LINK&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;new_link&lt;/span&gt;);

    &lt;span style=&quot;color: #8ae234;&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;add_after_stay_put&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_LINK&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;new_link&lt;/span&gt;);

    &lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_LINK&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;forward&lt;/span&gt;();

    &lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_LINK&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;extract&lt;/span&gt;();

    &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#20854;&amp;#20182;&amp;#26041;&amp;#27861;&lt;/span&gt;
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline4&quot;&gt;实际单链表的实现方法&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
刚才提到，在表示节点的类型 ELIST_LINK 中其实是没有表示节点数据的成员的，如果直接使用，肯定是没有意义的 —— 实际上 Tesseract 中确实也没有哪儿直接就使用 ELIST 了。Tesseract 中通过多重继承来解决了这个问题。
&lt;/p&gt;

&lt;p&gt;
比如说我们希望我们的节点中保存一个点的坐标，那么我们可以先定义一个 Point 类:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;Point&lt;/span&gt;
{
&lt;span style=&quot;color: #729fcf;&quot;&gt;public&lt;/span&gt;:
    &lt;span style=&quot;color: #edd400;&quot;&gt;Point&lt;/span&gt;(): _x(0), &lt;span style=&quot;color: #edd400;&quot;&gt;_y&lt;/span&gt;(0) {}
    &lt;span style=&quot;color: #edd400;&quot;&gt;Point&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;x&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;y&lt;/span&gt;): _x(x), &lt;span style=&quot;color: #8ae234;&quot;&gt;_y&lt;/span&gt;(&lt;span style=&quot;color: #eeeeec;&quot;&gt;y&lt;/span&gt;) {}
    ~&lt;span style=&quot;color: #edd400;&quot;&gt;Point&lt;/span&gt;();

&lt;span style=&quot;color: #729fcf;&quot;&gt;private&lt;/span&gt;:
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;_x&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;_y&lt;/span&gt;;
};
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后定义节点类 POINT ，继承 Point 和 ELIST_LINK:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;POINT&lt;/span&gt;: &lt;span style=&quot;color: #729fcf;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;ELIST_LINK&lt;/span&gt;, &lt;span style=&quot;color: #729fcf;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;Point&lt;/span&gt;
{
&lt;span style=&quot;color: #729fcf;&quot;&gt;public&lt;/span&gt;:
    &lt;span style=&quot;color: #edd400;&quot;&gt;POINT&lt;/span&gt;();
    ~&lt;span style=&quot;color: #edd400;&quot;&gt;POINT&lt;/span&gt;();
};
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后依次定义 POINT_LIST(继承 ELIST) 和 POINT_IT(继承 ELIST_ITERATOR)。
&lt;/p&gt;

&lt;p&gt;
在 Tesseract 中提供了两个宏来直接产生 POINT_LIST 类和 POINT_IT 类的定义与实现，这两个宏分别是:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;ELISTIZEH&lt;/li&gt;
&lt;li&gt;ELISTIZE&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
第一个宏用来产生 POINT_LIST 和 POINT_IT 的定义，第二个宏用来产生实现，其用法是(仍以 POINT 为例):
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
在 point.h 中类 POINT 的定义之后，添加以下语句:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;ELISTIZEH(POINT)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
在 point.cpp 中，添加以下语句:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;ELISTIZE(POINT)
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
这两个宏也是在 ccutil/elst.h 中定义的。这种用宏来展开类定义和实现的做法，在代码编写上确实很方便，但是阅读起来真的是好头疼，刚开始了解这个单链表的时候，我为了找 BLOCK_LIST (继承自 ELIST 的单链表类)的定义头疼地要死，代码里找不着，Google 也搜索不到答案，着实费了一番功夫。
&lt;/p&gt;

&lt;p&gt;
由于 Tesseract 的这个设计把链表的操作与对节点数据的操作分离开来了，所以虽然没使用多态机制，这一套设计依然工作良好。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline5&quot;&gt;Tesseract 中实际被使用的单链表类&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;p&gt;
之前说过，Tesseract 中有不少不同类型的单链表都是从 ELIST 继承的，由于对 ELIST 的继承都是在宏展开后进行的，从代码里是找不到这些类的定义的，不过链表节点却是要手动去定义、实现的，所以查看那些继承了 ELIST_LINK 类的类就可以知道了。从 &lt;a href=&quot;http://tesseract-ocr.repairfaq.org/classELIST__LINK.html&quot;&gt;Tesseract 的 API Refrence&lt;/a&gt; 可以得知有 20 个类继承自 ELIST_LINK，它们是:
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;ASSOC&lt;/li&gt;
&lt;li&gt;BLOB_CHOICE&lt;/li&gt;
&lt;li&gt;BLOCK_RES&lt;/li&gt;
&lt;li&gt;C_BLOB&lt;/li&gt;
&lt;li&gt;C_OUTLINE_FRAG&lt;/li&gt;
&lt;li&gt;CHAR_SAMPLE&lt;/li&gt;
&lt;li&gt;CHAR_SAMPLES&lt;/li&gt;
&lt;li&gt;FPSEGPT&lt;/li&gt;
&lt;li&gt;FRAGMENT&lt;/li&gt;
&lt;li&gt;ICOORDELT&lt;/li&gt;
&lt;li&gt;MENU_L&lt;/li&gt;
&lt;li&gt;OUTLINE_FRAG&lt;/li&gt;
&lt;li&gt;PBLOB&lt;/li&gt;
&lt;li&gt;PIXROW&lt;/li&gt;
&lt;li&gt;REGION_OCC&lt;/li&gt;
&lt;li&gt;ROW&lt;/li&gt;
&lt;li&gt;ROW_RES&lt;/li&gt;
&lt;li&gt;SORTED_FLOAT&lt;/li&gt;
&lt;li&gt;WERD&lt;/li&gt;
&lt;li&gt;WERD_RES&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>Tesseract:训练</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/05/05/tesseract-training.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2015/05/05/tesseract-training</id>
    <published>2015-05-05T00:00:00+00:00</published>
    <updated>2015-05-05T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


资源文件
资源文件的训练

数据准备
图像与BOX文件生成
字符集文件与字体信息文件生成
特征文件生成
聚集
[可选]添加配置文件、歧义修正文件、DAWG...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;资源文件&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;资源文件的训练&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;数据准备&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;图像与BOX文件生成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;字符集文件与字体信息文件生成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline6&quot;&gt;特征文件生成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline7&quot;&gt;聚集&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline8&quot;&gt;[可选]添加配置文件、歧义修正文件、DAWG文件&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline9&quot;&gt;打包&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;资源文件&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
在&lt;a href=&quot;http://linusp.github.io/2015/04/17/tesseract-install-usage.html&quot;&gt;上一篇文章&lt;/a&gt;中已经讲述了 Tesseract 的基本使用，同时也提到， Tesseract 在识别是需要使用存储在磁盘上的 &quot;语言文件&quot; —— 为不产生歧义，这里简单以 &quot;资源文件&quot; 称呼它。在 Windows 系统上，这些资源文件可以在安装目录下的 tessdata 目录下找到；在 Linux 系统上，这些资源文件通常是在 /usr/share/tesseract-ocr/tessdata 目录下。按照 Tesseract 的约定，这些资源文件以 &quot;traineddata&quot; 作为后缀，除去后缀的部分则是该资源文件的 &quot;名称&quot; ，在使用 Tesseract 命令行工具或者 API 时，就通过这个名称来引用需要的资源文件。比如我们要用英语的资源文件来识别一张图像，通常会这么写:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;tesseract input.png output -l eng
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上述命令将会引用 eng.traineddata 这个资源文件。在 API 使用中同理。
&lt;/p&gt;

&lt;p&gt;
除了默认的路径， Tesseract 还会在环境变量 TESSDATA_PREFIX 指定的目录中的 tessdata 目录下寻找资源文件 —— 事实上在 Windows 系统中，安装系统就是把该环境变量的值设置成了 Tesseract 的安装目录。这方便我们管理我们自己生成的资源文件。
&lt;/p&gt;

&lt;p&gt;
如果系统中没有资源文件，或者没有需要的资源文件，该如何获取呢?一种办法是到 Tesseract 的&lt;a href=&quot;https://code.google.com/p/tesseract-ocr/downloads/list&quot;&gt;下载页面&lt;/a&gt;去下载，在 &quot;Summary+Labels&quot; 一栏标注中有 &quot;language data&quot; 的就是了。对于 Linux 系统，可以直接从软件仓库中安装，以 Debian 为例，假如我们需要安装繁体中文的资源文件，可以执行
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;sudo apt-get install tesseract-ocr-chi-tra
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
如果不知道需要的资源文件在安装时用什么名称，可以使用 aptitude 进行搜索，在描述字段会有说明。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;aptitude search tesseract-ocr-
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
存储位置与获取方式讲完了，如果是一个有足够好奇心的人，肯定会想了解一下这个资源文件里有什么内容 —— 哈，说得就是我自己啦!当然啦，我也是后面才知道怎么去查看的。
&lt;/p&gt;

&lt;p&gt;
Tesseract 提供了工具来将一个资源文件打开，这个工具叫做 combine_tessdata ，它的更常用的功能是将训练过程中产生的各种资源打包到一起产生一个 Tesseract 可用的资源文件。以 eng.traineddata 为例，我们可以这样来解开它
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;combine_tessdata -u /usr/share/tesseract-ocr/tessdata/eng.traineddata english/eng
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上述命令将会把 eng.traineddata 解开并将结果保存到 english 目录下，所有结果文件都会以 eng 作为前缀。需要注意的是，这里如果 english 这个目录不存在，是会出错的。下面是我在我的系统上的一次实际操作:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/tessdata-extract.png&quot; alt=&quot;tessdata-extract.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到，这个资源文件里包含了很多东西，这些文件各自的意义为:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;config: 配置文件&lt;/li&gt;
&lt;li&gt;unicharset: 字符集文件，所谓 &quot;字符集&quot; 即是所有可被识别的字符的集合&lt;/li&gt;
&lt;li&gt;unicharambigs: 识别歧义修正文件&lt;/li&gt;
&lt;li&gt;inttemp: 每个字符的 &quot;原型&quot; ，或者是 &quot;标准型&quot; ，当然啦，这里面其实是包含了字符的各种特征，并不是一个标准的 &quot;字符图像&quot;&lt;/li&gt;
&lt;li&gt;pffmtable: 指明了每个字符的特征数量&lt;/li&gt;
&lt;li&gt;normproto: 项目网站上的说法是 &quot;normalization sensitivity prototypes&quot; ，不知道怎么翻译合适&lt;/li&gt;
&lt;li&gt;以 dawg 结尾的文件: 有向非循环词图(Directed Acyclic Word Graph, DAWG)文件，用来增强、调整识别过程&lt;/li&gt;
&lt;li&gt;cube-unicharset, cube-word-dawg: 用于 Tesseract 内部名为 CUBE 的识别引擎，无资料，不详&lt;/li&gt;
&lt;li&gt;shapetable: 同样是个不知道如何翻译的家伙，反正项目网站上说这个文件已经不需要使用(但还是得有这个文件)，就不纠结了&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
对于这些文件，我们可以用 combine_tessdata 将其重新打包起来:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;cd&lt;/span&gt; english
combine_tessdata eng
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
上述命令会在该目录下寻找前缀为 eng 的必要文件，然后打包成 eng.traineddata。这些文件里面有一些是资源文件的必须成分，有一些则是锦上添花的成分。读者可以试试进入到这些文件所在的目录，尝试去掉其中一些然后进行打包操作。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;资源文件的训练&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
如果刚才按照建议进行过了尝试，应该能发现哪些是必要的文件，它们是:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;unicharset&lt;/li&gt;
&lt;li&gt;inttemp&lt;/li&gt;
&lt;li&gt;pffmtable&lt;/li&gt;
&lt;li&gt;normproto&lt;/li&gt;
&lt;li&gt;shapetable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
训练的过程就是为了从训练数据中产生这些东西。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline3&quot;&gt;数据准备&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
首先要准备好训练用的文本数据，根据不同的应用场景，对文本数据的要求会不一样。这些文本数据有两个用途:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;用以产生字符集&lt;/li&gt;
&lt;li&gt;用以产生语言模型&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
产生字符集好理解，数据文件应尽量涵盖可能出现的字 —— 不过字符集越大，在使用生成的资源文件进行识别时时间消耗也会越大，所以应该根据实际情况进行折衷处理，比如说汉语的识别，一般来说涵盖了国标一级常用汉字(3755个)就已经足够了。
&lt;/p&gt;

&lt;p&gt;
除了字符集尽量涵盖可能出现的字外，我们也希望训练用的数据中的文字组合能尽量贴合真实场景，我们可以用这些数据来产生语言模型信息添加到最后的资源文件中。之前例子中的 DAWG 文件中就承载了这些信息。不过比较遗憾的是，对于中文训练，我目前知道的只是添加高频词表(freq-dawg)与词表(word-dawg)，如何添加 ngram 信息目前毫无头绪。将简体中文资源文件 chi_sim.traieddata 解开后里面有一个名为 chi_sim.fixed-length-dawgs 的文件，从项目网站上来看，应该是与 ngram 信息对应的文件，但该文件无法解开，项目网站上对这个文件也是语焉不详。 &lt;b&gt;如果有对这个问题的解决办法，请不吝赐教。&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
所以这一步要做的事情有两个:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;数据清洗，这个和自然语言处理里的清洗是一样的&lt;/li&gt;
&lt;li&gt;字符集提取，简单来说，排序、去重即可&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
其中清洗后的数据用来提取语言模型信息，去重后的字符集数据用来进行训练。
&lt;/p&gt;

&lt;p&gt;
项目网站上说到，每个字在训练用的数据文件中一般应该有 10 个样本，低频字也至少要有 5 个，高频的应该在 20 个以上。不过就我目前进行的中文训练情况来看，每个字一个样本得到的结果也没有明显的差异，读者可以自行试验。
&lt;/p&gt;

&lt;p&gt;
需要注意的是，在生成图像时可能存在一部分字符要用某个字体来表示，而另一部分字符要用另外一个字体来表示 —— 比如汉字通常用宋体而英文可能用 Time News Roman ，这种情况下建议将数据分割成开来。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline4&quot;&gt;图像与BOX文件生成&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
有了数据文件后，我们需要用这些数据文件中的文字来生成图像，用这些图像去进行训练。在 3.03 后， Tesseract 已经提供了相应的工具 text2image，使用方法为:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;text2image  --text=chinese.txt --outputbase=chinese.sun.exp0 --font=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;SimSun&quot;&lt;/span&gt; --fonts_dir=./fonts/
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上述命令以 chinese.txt 作为输入，字体使用宋体，将图像输出为 chinese.sun.exp0.tif。同时还会输出一个名为 chinse.sun.exp0.box 的 BOX 文件，里面会对应每一个文字在图像中的位置信息。
&lt;/p&gt;

&lt;p&gt;
同一个数据文件，可以应用不同的字体产生不同的图像，字体越多，产生的资源文件所能支持的实际情况也就越多，但建议还是按照实际应用情况来添加字体支持。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline5&quot;&gt;字符集文件与字体信息文件生成&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;p&gt;
提取 Tesseract 能读取、处理的字符集文件，使用 unicharset_extractor 命令:
&lt;/p&gt;

&lt;p&gt;
unicharset_extractor  chinses.box  english.box
&lt;/p&gt;

&lt;p&gt;
该命令以上一步输出的 BOX 文件作为输入，实际使用时，应将本次训练时的所有 BOX 文件作为输入。该命令的输出是名为 &lt;b&gt;unicharset&lt;/b&gt; 的文件。
&lt;/p&gt;

&lt;p&gt;
此外，在后续步骤中需要字体属性文件，该文件的名称应为 &lt;b&gt;font_properties&lt;/b&gt; ，该文件中每一行表示一种字体的信息，其格式为:
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
&amp;lt;font name&amp;gt; &amp;lt;italic?&amp;gt; &amp;lt;bold?&amp;gt; &amp;lt;fixed?&amp;gt; &amp;lt;serif?&amp;gt; &amp;lt;fraktur?&amp;gt;
&lt;/pre&gt;

&lt;p&gt;
第一个字段为字体名称，名称中不能有空格，名称可以任意，但建议尽量贴近字体在操作系统上的名称，后面五个字段分别表示:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;该字体是否有斜体&lt;/li&gt;
&lt;li&gt;该字体是否有粗体&lt;/li&gt;
&lt;li&gt;该字体是否有无衬线体&lt;/li&gt;
&lt;li&gt;该字体是否有衬线体&lt;/li&gt;
&lt;li&gt;该字体是否有哥特体&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
比如宋体是有衬线体的，对应的，它在 font_properties 这个文件中的内容应为:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
SimSun 1 1 0 1 0
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline6&quot;&gt;特征文件生成&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline6&quot;&gt;
&lt;p&gt;
特征文件的生成使用 tesseract 命令:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;tesseract chinese.sun.exp0.tif chinese.sun.exp0 nobatch box.train
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上述命令将生成名为 chinese.sun.exp0.tr 的特征文件。对每一张生成的 TIFF 图像，都要进行该步骤以生成特征文件。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline7&quot;&gt;聚集&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline7&quot;&gt;
&lt;p&gt;
上一步的特征文件生成后，需要将同样文字的不同字体的特征聚集到一起来产生该文字的一个 &lt;b&gt;原型&lt;/b&gt; ，这一步需要执行三个命令:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;shape_clustering -F font_properties -U unicharset  *.tr
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这一步将会生成一个名为 &lt;b&gt;shapetable&lt;/b&gt; 的文件。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;mftraining -F font_properties -U unicharset -O banker.unicharset *.tr
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这一步将会生成一个名为 &lt;b&gt;inttemp&lt;/b&gt; 的文件和一个名为 &lt;b&gt;pffmtable&lt;/b&gt; 的文件。
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;cntraining *.tr
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这一步将会生成一个名为 &lt;b&gt;normproto&lt;/b&gt; 的文件。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline8&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline8&quot;&gt;[可选]添加配置文件、歧义修正文件、DAWG文件&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline8&quot;&gt;
&lt;p&gt;
略(后面补上)
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline9&quot;&gt;打包&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline9&quot;&gt;
&lt;p&gt;
在上述步骤都完成后，将要打包入资源文件的那些文件加上一个统一的前缀，该前缀即是待生成的资源文件的名称，这里假定我们要生成 chi.traineddata 这样一个资源文件，那么我们的可能操作就是:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;mv unicharset chi.unicharset
mv shapetable chi.shapetable
mv inttemp chi.inttemp
mv pffmtable chi.pffmtable
mv normproto chi.normproto

combine_tessdata chi
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
至此，训练过程结束。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>Emacs中的窗口操作</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/04/19/emacs-window.html"/>
    <category term="Emacs" scheme="http://www.zmonster.me/categories.html#Emacs"/>
    <id>http://www.zmonster.me/2015/04/19/emacs-window</id>
    <published>2015-04-19T00:00:00+00:00</published>
    <updated>2015-04-19T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


窗口
窗口的新增
窗口的删除
窗口的切换

默认的方法
windmove package


窗口布局的保存与恢复




窗口


这里的窗口并不是指桌...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;窗口&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;窗口的新增&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;窗口的删除&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;窗口的切换&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;默认的方法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline6&quot;&gt;windmove package&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline7&quot;&gt;窗口布局的保存与恢复&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;窗口&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
这里的窗口并不是指桌面环境中的窗口，而是指 Emacs 中的显示单元。在 Emacs 中，显示一个缓冲区内容的区域，就被称为 &quot;窗口&quot;。
&lt;/p&gt;

&lt;p&gt;
一个窗口中只能显示一个缓冲区，而一个缓冲区是可以显示在多个窗口中的。出于一些需要，我们可能在使用 Emacs 的时候将整个 Emacs 显示区域分割成多个窗口，本文就将对这种情形下对窗口的常用操作做简要介绍。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;窗口的新增&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
新增窗口是通过对当前窗口的分割来产生的，分割有两种方式:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
C-x 2: 将当前窗口分割为上下两个，如下图所示
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/emacs-window-split-hor.gif&quot; alt=&quot;emacs-window-split-hor.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
C-x 3: 将当前窗口分割为左右两个，如下图所示
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/emacs-window-split-ver.gif&quot; alt=&quot;emacs-window-split-ver.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
分割后的子窗口都想显示被分割的窗口当时显示的缓冲区，如果想要在分割后切换到另外一个缓冲区，以下我编写的方法可以作为参考:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;;; &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#23558;&amp;#24403;&amp;#21069;&amp;#31383;&amp;#21475;&amp;#20998;&amp;#21106;&amp;#20026;&amp;#19978;&amp;#19979;&amp;#20004;&amp;#20010;&amp;#65292;&amp;#24182;&amp;#20999;&amp;#25442;&amp;#21040;&amp;#21478;&amp;#22806;&amp;#19968;&amp;#20010; buffer&lt;/span&gt;
(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;split-window-new-buffer&lt;/span&gt; ()
  (interactive)
  (split-window-below)
  (call-interactively 'switch-to-buffer))
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;窗口的删除&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
窗口的删除有三个可用的快捷键，分别是:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;C-x 0: 删除当前窗口&lt;/li&gt;
&lt;li&gt;C-x 1: 删除当前窗口外的其他窗口&lt;/li&gt;
&lt;li&gt;C-x 4 0: 删除当前窗口，并关闭其中显示的缓冲区&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline4&quot;&gt;窗口的切换&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline5&quot;&gt;默认的方法&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;p&gt;
Emacs 中提供了 C-x o(字母) 这个快捷键来在窗口间循环移动，方向大致是顺时针方向。分割的窗口数稍微一多的话，这么一个快捷键肯定是不够的。
&lt;/p&gt;

&lt;p&gt;
事实上 C-x o 是调用了 other-window 这个内建方法，通过 C-h f 可以知道这个方法的原型是:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(other-window COUNT &lt;span style=&quot;color: #8ae234;&quot;&gt;&amp;amp;optional&lt;/span&gt; ALL-FRAMES)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
它的参数里我们要关心的是 COUNT 这个参数，这个参数可以取三种值:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;为正整数: 顺时针前进指定数目的窗口&lt;/li&gt;
&lt;li&gt;等于0: 原地不动&lt;/li&gt;
&lt;li&gt;为负整数: 逆时针前进指定数目(COUNT的绝对值)的窗口&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
所以我们可以很自然地写出一个 &quot;切换到上一个窗口&quot; 的方法来:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;prev-window&lt;/span&gt; ()
  (interactive)
  (other-window -1))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后可以按自己的需要绑定到指定的快捷键上，以 C-x p 为例:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(global-set-key (kbd &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;C-x p&quot;&lt;/span&gt;) 'prev-window)
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline6&quot;&gt;windmove package&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline6&quot;&gt;
&lt;p&gt;
Emacs 中其实还内置了更为简易的切换方法，可以向当前窗口指定方向的邻近窗口切换，不过并未给这些方法提供默认的快捷键绑定。
&lt;/p&gt;

&lt;p&gt;
共有四个方法，它们在 windmove 这个包中被定义和实现:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;windmove-up&lt;/li&gt;
&lt;li&gt;windmove-down&lt;/li&gt;
&lt;li&gt;windmove-right&lt;/li&gt;
&lt;li&gt;windmove-left&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
功能的话看它们的名称就看得出来，我想就不用多解释了。
&lt;/p&gt;

&lt;p&gt;
我们可以自己来进行绑定，或者也可以使用默认的设置:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(windmove-default-keybindings)
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
在配置文件中添加上面这句后，我们将可以使用 Shift+方向键 的方式来进行窗口切换。为求方便一般还会在其后跟上以下这句:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(setq windmove-wrap-around t)
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
这一条语句的作用是让 windmove 在边缘的窗口也能正常运作。举个例子，当前窗口已经是最左端的窗口了，如果使用 Shift+left ，将仍会停留在当前窗口——因为已经到边缘了，左边没有窗口可供选择。但在添加了上面这句后，Shift+left 将会跳到最右边的窗口中。垂直方向上的窗口切换同理。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-orgheadline7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline7&quot;&gt;窗口布局的保存与恢复&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline7&quot;&gt;
&lt;p&gt;
Emacs 中已经内置了窗口布局的保存与恢复功能，通过在配置文件中添加下列语句就可以启用布局保存功能:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(desktop-save-mode 1)
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
初次启用的时候会询问是否保存 &quot;desktop&quot; ，这个时候需要选择保存位置，布局一般会保存为名为 .emacs.desktop 的文件。
&lt;/p&gt;

&lt;p&gt;
desktop-save-mode 不仅会保存窗口布局，还会保存每个窗口中打开了什么缓冲区，每个缓冲区中的光标位于哪一行这些非常游泳的信息，所以还是非常方便的。
&lt;/p&gt;

&lt;p&gt;
不过虽然保存了 desktop 文件，Emacs 启动的时候却不会去主动加载它，一种办法是在配置文件里定义一个变量保存 desktop 文件所在的目录，然后在启动的时候就加载它:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(setq desktop-dir &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;~/Dropbox/doc/&quot;&lt;/span&gt;)
(desktop-read desktop-dir)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
不过上面这样的设置是不够完美的，假如我们不带任何参数启动 Emacs ，当然是没什么问题，但如果我们是用 Emacs 打开某个文件，这样做明显是不合理的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>Tesseract:安装与命令行使用</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/04/17/tesseract-install-usage.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2015/04/17/tesseract-install-usage</id>
    <published>2015-04-17T00:00:00+00:00</published>
    <updated>2015-04-17T00:00:00+00:00</updated>
    <description>
    
      <p>Tesseract是一款被广泛使用的开源 OCR 工具，本文将对其进行简单的介绍</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;获取,安装与配置&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;Windows&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;命令行使用&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;a href=&quot;https://code.google.com/p/tesseract-ocr/&quot;&gt;Tesseract&lt;/a&gt; 是一款被广泛使用的开源 OCR 工具，本文将对其进行简单的介绍.
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;简介&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;

&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/tesseract.gif&quot; alt=&quot;tesseract.gif&quot; align=&quot;right&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
Tesseract(/'tesərækt/) 这个词的意思是&quot;超立方体&quot;，指的是几何学里的四维标准方体，又称&quot;正八胞体&quot;。右图是一个正八胞体绕着两个四维空间中互相正交的平面进行双旋转时的透视投影。不过这里要讲的，是一款以其命名的开源 OCR(Optical Character Recognition, 光学字符识别) 软件。
&lt;/p&gt;

&lt;p&gt;
所谓 OCR 是图像识别领域中的一个子领域，该领域专注于对图片中的文字信息进行识别并转换成能被常规文本编辑器编辑的文本。
&lt;/p&gt;

&lt;p&gt;
Tesseract 已经有 30 年历史，开始它是惠普实验室的一款专利软件，然后在 2005 年开源，自 2006 年后由 Google 赞助进行后续的开发和维护。
&lt;/p&gt;

&lt;p&gt;
在 1995 年 Tesseract 曾是世界前三的 OCR 引擎，而且在现在的免费 OCR 引擎中，其识别精度也仍然是出类拔萃的。因为其免费与较好的效果，许多的个人开发者以及一些较小的团队在使用着 Tesseract ，诸如验证码识别、车牌号识别等应用中，不难见到 Tesseract 的身影。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;获取,安装与配置&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline3&quot;&gt;Linux&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
主流的 Linux 发行版都可以通过包管理器来安装 Tesseract，以 Debian 及其衍生版为例:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;sudo apt-get install tesseract-ocr
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
如果想用 Tesseract 对图像进行识别，还需要对应的语言文件。所谓的语言文件是 Tesseract 识别某种语言的文字图像时需要的一些资源，这些东西也可以通过包管理器获取。比如我们需要识别英语和简体中文，那么:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;sudo apt-get install tesseract-ocr-eng tesseract-ocr-chi-sim
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
当然了，这是通过包管理器的方式进行安装，如果需要，还可以通过编译安装的方式来构建最新版的 Tesseract.
&lt;/p&gt;

&lt;p&gt;
Tesseract 的项目托管在 Google Code 上，在&lt;a href=&quot;https://code.google.com/p/tesseract-ocr/downloads/list&quot;&gt;下载页面&lt;/a&gt;可以自己选择需要的版本，假如我们需要安装 tesseract-ocr-3.02.02.tar.gz 这个版本:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;wget https://tesseract-ocr.googlecode.com/files/tesseract-ocr-3.02.02.tar.gz
tar xzvf tesseract-ocr-3.02.02.tar.gz
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Tesseract 的编译需要 automake, autoconf, libtool 支持，所以这几个工具得装上:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;sudo apt-get install autoconf automake libtool
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
当然了, Tesseract 还依赖一些图像库:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;sudo apt-get install ligjpeg62-dev libtiff4-dev libpng12-dev libleptonica-dev
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;b&gt;注意: 以上安装的包的名称可能在不同发行版上略有不同&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
需要注意的是，&lt;a href=&quot;http://www.leptonica.org/&quot;&gt;Leptonica&lt;/a&gt; 是 Tesseract 的一个比较重要的依赖，而且不同版本的 Tesseract 对 Leptonica 的版本要求也不一样，需要留意包管理器所安装的 Leptonica 版本是否满足要求，如果不满足要求，最好还是下载 Leptonica 的源代码编译安装。
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Tesseract 3.01: Leptonica 版本不低于 1.67&lt;/li&gt;
&lt;li&gt;Tesseract 3.02: Leptonica 版本不低于 1.69&lt;/li&gt;
&lt;li&gt;Tesseract 3.03: Leptonica 版本不低于 1.70&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
解决依赖后按常规方法编译安装即可:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;./configure
make
sudo make install
sudo ldconfig
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
在 3.03 及以上版本中，用于训练产生语言文件的工具需要单独编译和安装:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;make training
sudo make training-install
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
建议在执行 ./configure 时加上参数 &amp;#x2013;prefix=xxx 来指定安装路径，这样以后要卸载会方便一些——当然如果这样做的话在安装完后需要做一些额外的工作，包括:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;添加 Tesseract 的可执行程序路径到环境变量 PATH 中&lt;/li&gt;
&lt;li&gt;在 /usr/include 目录或者 /usr/local/include 目录下建立 Tesseract 安装目录下 include/tesseract 的符号链接&lt;/li&gt;
&lt;li&gt;在 /usr/lib 目录或者 /usr/local/lib 目录下建立 Tesseract 安装目录下的 lib 目录下的静态链接库、动态链接库的符号链接&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
安装完成后，无论是通过包管理器安装的还是通过编译源代码安装的，建立都配置一下 TESSDATA_PREFIX 这个环境变量。在这个环境变量未设置的情况下，Tesseract 将会在安装目录中的 share/tessdata 这个目录下去寻找、加载语言文件，这本身当然没什么问题。
&lt;/p&gt;

&lt;p&gt;
问题在于当我们想添加新的语言文件时，会遇到一些麻烦——程序一般都是安装的系统目录中，也就是说，我们需要提升权限才能将语言文件放到正确的地方。假如是在公司的服务器上进行相关的操作，普通用户一般都是没有 sudo 权限的。将语言文件放置在用户目录中可以解决这个问题，方法是在 .bashrc (假设您使用 bash 作为日常的 shell)中设置
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;TESSDATA_PREFIX&lt;/span&gt;=$&lt;span style=&quot;color: #eeeeec;&quot;&gt;HOME&lt;/span&gt;/
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
如上设置时，将语言文件放在 ~/tessdata/ 下面即可。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline4&quot;&gt;Windows&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
Windows 上的安装也很简单，下载对应的安装程序，双击运行，按照提示进行即可。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/tesseract-install.png&quot; alt=&quot;tesseract-install.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
注意在 &quot;Language data&quot; 那个选项里，默认是只勾选了英文的，如果需要进行其他语言的识别，记得勾选对应的语言。
&lt;/p&gt;

&lt;p&gt;
再一个是，如果需要进行相应的开发工作，建立把 &quot;Tesseract development files&quot; 这个选项也勾选。
&lt;/p&gt;

&lt;p&gt;
安装完成后如无异常，会将安装目录添加到环境变量 PATH 中，这样就可以在 cmd 中直接运行程序了——Tesseract 并没有提供图形界面的工具，只能在命令行中使用，当然了，我们可以自己编写 GUI 应用程序来调用它，这个准备后面再讲。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline5&quot;&gt;命令行使用&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;p&gt;
这里只简单讲一下 Tesseract 识别图像的基本用法，关于训练和开发将另开新篇来专门讲述。
&lt;/p&gt;

&lt;p&gt;
由于 Tesseract 只提供命令行工具，这里讲到的用法对 Linux 和 Windows 平台都适用。
&lt;/p&gt;

&lt;p&gt;
首先可以通过 &quot;&amp;#x2013;list-langs&quot; 来查看有哪些可用的 &quot;语言&quot; ，如果之前的 TESSDATA_PREFIX 环境变量没有设置错，将会看到这样的输出:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
bash &amp;gt; tesseract --list-langs
List of available languages (17):
math
chi
chi_sim
eng
&lt;/pre&gt;

&lt;p&gt;
这里的 &quot;eng&quot; 和 &quot;chi_sim&quot; 是 Tesseract 提供的英文和简体中文的语言文件，而其他的几个则是我自己训练得到的。
&lt;/p&gt;

&lt;p&gt;
另外要说明的是，这里的 &quot;语言文件&quot; 的本质是包含了某种 &quot;自然语言&quot; 的文字的特征等辅助识别的一些资源，但像 chi_sim 这个中文简体里也包含了英文字母与阿拉伯数字的资源。而我们也可以为了特定的用途而去训练产生对应的资源，这里的 &quot;math&quot; 是用于识别简单数学表达式的一个资源，并不是说有一种叫做 &quot;math&quot; 的语言。
&lt;/p&gt;

&lt;p&gt;
如果发现以上命令的输出为空，那应该去检查一下 TESSDATA_PREFIX 这个环境变量。在这个环境变量无误且 &quot;语言文件&quot; 存在的情况下，假设我们有一张名为 paper.png 的图片，则通过以下命令对图片进行识别，
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;tesseract paper.png paper -l chi_sim
&lt;/pre&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;第一个参数是待识别的图像的文件名&lt;/li&gt;
&lt;li&gt;第二个参数用于指定输出，如果希望直接输出而不是保存到文件，那么就使用 stdout，否则这个参数将会作为保存结果的文件的前缀&lt;/li&gt;
&lt;li&gt;-l chi_sim 这个应该很好理解，就是用来指定使用哪个 &quot;语言文件&quot;，如果是使用 英文(eng) ，这个参数可以不加，因为默认就是使用英文的 &quot;语言文件&quot; 来进行识别&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
以上命令如不出错，结果将会保存到 paper.txt 这个文本文件中。
&lt;/p&gt;

&lt;p&gt;
此外 Tesseract 还提供非常丰富的可选参数来对识别过程进行调整，可用的参数及其默认值可以通过以下命令进行查看:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;tesseract --print-parameters
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
参数的使用有两种:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
使用 -c 选项来设定单项参数的值，比如:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;tesseract paper.png paper -l chi_sim -c &lt;span style=&quot;color: #eeeeec;&quot;&gt;language_model_ngram_on&lt;/span&gt;=1
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
允许使用多个 -c 选项来设置多个参数的值。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
将多项参数设置写入文件，然后在识别时使用该文件，比如:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;tesseract paper.png paper -l chi_sim tess.conf
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
需要注意的是，如果使用配置文件，用作参数的配置文件名要放在最后面——这里也支持多个配置文件，但它们必须要在最后面。假如我有两个配置文件 tess_1.conf 和 tess_2.conf，那么这样是正确的:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;tesseract paper.png paper -l chi_sim tess_1.conf tess_2.conf
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
而这样则是错误的:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;tesseract paper.png paper tess_1.conf -l chi_sim tess_2.conf
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
至于 Tesseract 那些参数各有什么含义，官方没有提供任何文档来进行解释，这里有一个&lt;a href=&quot;http://www.sk-spell.sk.cx/tesseract-ocr-parameters-in-302-version&quot;&gt;链接&lt;/a&gt;提供了部分参数的用处说明，应该是阅读了 Tesseract 源代码后得到的结论。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>近况</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/03/22/recent.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2015/03/22/recent</id>
    <published>2015-03-22T00:00:00+00:00</published>
    <updated>2015-03-22T00:00:00+00:00</updated>
    <description>
    
      <p>
2015年3月22日，9点37分。


</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
2015年3月22日，9点37分。
&lt;/p&gt;

&lt;p&gt;
雕刻时光靠窗的位置上，可以看到街道边无叶的树木在风中柔和地摇摆，13号线列车装满了乘客，从五道口站缓缓开出，顺着轨道渐渐消失在视野中。周日的上午，风大，微凉，往日人群熙攘的五道口稍显冷清。
&lt;/p&gt;

&lt;p&gt;
我有一种冲动，想要顺着这貌似熟悉的道路往前走，去按下那个门铃，去和彩云天气的众人畅谈对这个世界的看法，以及对这个世界的未来的看法。
&lt;/p&gt;

&lt;p&gt;
在新公司工作已经两周了——我把彩云天气拒绝了，去了优答。至于这个选择对不对，我不清楚，但毫无疑问我是更喜欢袁行远他们的。不过我在年前对袁行远说我会去他们那，回来后却又改变了主意，这种行为对袁行远他们造成的伤害和损失，我想我再多说几声抱歉，也是无济于事。而且我自己也无法原谅自己的这种行为。
&lt;/p&gt;

&lt;p&gt;
承诺不应该是能被随意涂改的，如果希望留有余地，那么就不要轻易做决定。
&lt;/p&gt;

&lt;p&gt;
工作上的事情大致就是这样吧，不管这样的改变对我来说有多重要，也不过是这个世界无关紧要的小涟漪。
&lt;/p&gt;

&lt;p&gt;
搬家也已经两周了，和熟悉的朋友一起很自在，更何况他们都是很热爱生活的人，我想我是会被他们所感染，也变得更好的。
&lt;/p&gt;

&lt;p&gt;
一切安好。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>Python触发按键事件</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/03/02/keyboard-control-with-python.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2015/03/02/keyboard-control-with-python</id>
    <published>2015-03-02T00:00:00+00:00</published>
    <updated>2015-03-02T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


缘起
适用于Linux的方法
适用于Windows的方法
跨平台的方法




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;缘起&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;适用于Linux的方法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;适用于Windows的方法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;跨平台的方法&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;缘起&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
最近想尝试做一个简单的命令控制系统，关于命令控制方面的技术暂且不说，这个我也还在调研、学习，估计进度会很慢——我将问题分解后，发现有一些无关语音技术的小问题是可以优先去解决的，比如音频的录制，还有就是本篇所说的按键触发。
&lt;/p&gt;

&lt;p&gt;
按键的捕获这个是很容易做的事情，很容易想到 Python 众多的 GUI 库必然都会包含这一功能，但按键触发的 Python 库找了一圈也没找到几个。最后还是在 StackOverflow 上找到了可靠的答案。也就是说，本文也不过是一些已有信息的组织和加工而已——事实上我写的大部分博客都属于此列吧。
&lt;/p&gt;

&lt;p&gt;
按键触发最终必然涉及到底层系统调用，对于这些底层的东西，我不太关心，我只是想达到效果而已。所以我也是对我觉得好用的库进行实践说明了。鉴于我的开发环境是 Linux，我只会对适用于 Linux 的或者跨平台的库进行说明。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;适用于Linux的方法&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
在 Linux 的 X 环境(即桌面环境)上，可以通过 &lt;b&gt;xautomation&lt;/b&gt; 软件包中的 &lt;b&gt;xte&lt;/b&gt; 工具来触发按键、鼠标点击等事件，在 Linux 系统上通过软件包管理系统直接安装即可。其效果如下图所示:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/xte.gif&quot; alt=&quot;xte.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在 Linux 上的办法就是在 Python 中通过子进程来调用 xte ，以达到效果。下面是一个简短的示例代码:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;!/usr/bin/env python&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;-*- coding: utf-8 -*-&lt;/span&gt;

&lt;span style=&quot;color: #729fcf;&quot;&gt;from&lt;/span&gt; subprocess &lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; Popen, PIPE

&lt;span style=&quot;color: #eeeeec;&quot;&gt;emacs_save_sequence&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'''keydown Control_L&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;key x&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;key s&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;keyup Control_L&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'''&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;keypress&lt;/span&gt;(sequence):
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;p&lt;/span&gt; = Popen([&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'xte'&lt;/span&gt;], stdin=PIPE)
    p.communicate(&lt;span style=&quot;color: #729fcf;&quot;&gt;input&lt;/span&gt;=sequence)

keypress(emacs_save_sequence)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
上述代码触发的是 Emacs 的保存快捷键&quot;C-x C-s&quot;。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;适用于Windows的方法&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
在Windows系统上可以通过&lt;a href=&quot;https://pypi.python.org/pypi/pyHook&quot;&gt; pyHook &lt;/a&gt;来进行按键触发，限于环境，就不作展开了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline4&quot;&gt;跨平台的方法&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
&lt;a href=&quot;https://github.com/SavinaRoja/PyUserInput&quot;&gt;PyUserInput &lt;/a&gt;这个 Python 库能够在 Linux 、Mac 和 Windows 三个系统上使用，考虑跨平台的工具的话可以使用它。
&lt;/p&gt;

&lt;p&gt;
它的使用也很简单，对于按键事件来说，是通过一个 PyKeyboard 对象来进行的，通过三种不同的方法来触发不同的事件
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;press_key: 按下&lt;/li&gt;
&lt;li&gt;release_key: 松开&lt;/li&gt;
&lt;li&gt;tap_key: 敲击&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
当然，它还提供了如 type_string 这样的方法来进行字符串的输入。
&lt;/p&gt;

&lt;p&gt;
下面是用 PyUserInput 写的触发 Emacs 的保存快捷键 &quot;C-x C-s&quot;的示例代码:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;!/usr/bin/env python&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;-*- coding: utf-8 -*-&lt;/span&gt;

&lt;span style=&quot;color: #729fcf;&quot;&gt;from&lt;/span&gt; pykeyboard &lt;span style=&quot;color: #729fcf;&quot;&gt;import&lt;/span&gt; PyKeyboard

&lt;span style=&quot;color: #eeeeec;&quot;&gt;k&lt;/span&gt; = PyKeyboard()

k.press_key(k.control_l_key)
k.tap_key(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'x'&lt;/span&gt;)
k.tap_key(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'s'&lt;/span&gt;)
k.release_key(k.control_l_key)
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>Linux Shell技巧: 进程替代(Process Substitution)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/01/03/process-substitution.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2015/01/03/process-substitution</id>
    <published>2015-01-03T00:00:00+00:00</published>
    <updated>2015-01-03T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


What is process substitution?
Process substitution on Linux
Some more




Wha...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;What is process substitution?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;Process substitution on Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;Some more&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;What is process substitution?&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
&quot;Process Substitution&quot;，我将之翻译为&quot;进程替代&quot;，不知道有没有更相应的专业中文翻译，姑且先用着好了。它允许用将命令的输出结果当作&quot;文件&quot;来使用——这句话的意思是这样的，假设你有一个工具，它原本接受的参数应该是一个指代某个具体文档的&quot;文件名&quot;，使用&quot;进程替代&quot;后，我们可以用其他命令的输出来作为文件的内容，让这个工具去处理。
&lt;/p&gt;

&lt;p&gt;
说得比较绕，先看看 Wikipedia 上的解释:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
In computing, process substitution is a form of inter-process communication that allows the input or output of a command to appear as a file. The command is substituted in-line, where a file name would normally occur, by the command shell. This allows programs that normally only accept files to directly read from or write to another program.
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;Process substitution on Linux&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
在Linux上，通过下面的形式使用 process substituion:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&amp;lt;(&amp;lt;some command&amp;gt; &amp;lt;args&amp;gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
下面用一个实际的例子来说明它的使用。
&lt;/p&gt;

&lt;p&gt;
以我的工作为例，对于一个测试集，在进行完 Speaker Diarization 后，会根据标注文件(即用作参照的标准结果)计算它的错误率，而 Speaker Diarization 的错误率由三部分组成:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Missed speech&lt;/li&gt;
&lt;li&gt;False alarm speech&lt;/li&gt;
&lt;li&gt;Speaker error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
读者不必对这些词的具体含义去深究，只要知道是一个错误率的统计，同时总体错误由三个成分组成就行了。
&lt;/p&gt;

&lt;p&gt;
在计算了错误率之后，会将统计结果记录在一个文件中，在这个文件中，每一行都一个音频的测试结果，形式如下:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
1.wav Miss = 2.9 False = 3.4 Speaker = 1.0 Total = 7.3
&lt;/pre&gt;

&lt;p&gt;
现在我们有两个这样的文件，是对同一批测试集进行了两次测试后得到的结果，第一个文件 2015-05-31-der.log 的内容如下:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
1.wav Miss = 2.9 False = 3.4 Speaker = 1.0 Total = 7.3
2.wav Miss = 1.0 False = 2.5 Speaker = 0.0 Total = 3.5
3.wav Miss = 2.7 False = 1.1 Speaker = 0.1 Total = 3.9
&lt;/pre&gt;

&lt;p&gt;
第二个文件 2015-06-22-der.log 的内容如下:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
2.wav Miss = 0.5 False = 2.2 Speaker = 0.9 Total = 3.6
1.wav Miss = 2.8 False = 0.0 Speaker = 0.0 Total = 2.8
3.wav Miss = 2.4 False = 1.3 Speaker = 0.4 Total = 4.1
&lt;/pre&gt;

&lt;p&gt;
(注: 以上数据纯属杜撰，与我目前工作中的实际错误率情况没有任何关系)
&lt;/p&gt;

&lt;p&gt;
我需要根据这两个文件，得到每个音频在两次测试中各个成分的对比情况，希望输出的每一行是这样的:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
1.wav Miss = 2.9 False = 3.4 Speaker = 1.0 Total = 7.3 | Miss = 2.8 False = 0.0 Speaker = 0.0 Total = 2.8
&lt;/pre&gt;

&lt;p&gt;
比较容易想到需要根据文件名进行 sort ，然后使用 paste 把两个文件拼接起来，那么很自然地可以这样写:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;sort -k1,1 2015-05-31-der.log &amp;gt; 2015-05-31-der-sorted.log
sort -k1,1 2015-06-22-der.log | cut -d &lt;span style=&quot;color: #ad7fa8;&quot;&gt;' '&lt;/span&gt; -f 2- &amp;gt; 2015-06-22-der-sorted.log
paste -d &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'|'&lt;/span&gt; 2015-05-31-der-sorted.log 2015-06-22-der-sorted.log
rm *-sorted.log
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
使用进程替代的话，我可以用一行就搞定，而且不需要生成临时文件:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;paste -d &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'|'&lt;/span&gt; &amp;lt;(sort -k1,1 2015-05-31-der.log) &amp;lt;(sort -k1,1 2015-06-22-der.log | cut -d &lt;span style=&quot;color: #ad7fa8;&quot;&gt;' '&lt;/span&gt; -f 2-)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
另外一个例子，就是使用 diff 比较两个文件内容的时候，而且我们关心的是某个文件中某个记录在另外一个文件中有没有，不希望受次序影响时——diff是按行来进行文件内容对比的。还是来假设一个场景吧。
&lt;/p&gt;

&lt;p&gt;
假设我和我的一个朋友各自出去购物，完了回来想比较一下我们购买东西的区别:我买的东西里面哪些他没有买，他买的哪些我没有买。
&lt;/p&gt;

&lt;p&gt;
我的购物清单是 shopping-list-1.txt ，内容如下:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
苹果
上衣
毛巾
耳机
无线键盘
&lt;/pre&gt;

&lt;p&gt;
我朋友的购物清单是 shopping-list-2.txt ，内容如下:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
耳机
苹果
无线键盘
科幻小说
五号电池
体重秤
移动电源
&lt;/pre&gt;

&lt;p&gt;
那么相比不用进程替代的传统办法，使用进程替代的办法会简单很多，一行搞定:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;diff &amp;lt;(sort shopping-list-1.txt) &amp;lt;(sort shopping-list-2.txt)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果如下:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/diff-result.png&quot; alt=&quot;diff-result.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到，我买了而我朋友没买的东西是:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
毛巾
上衣
&lt;/pre&gt;

&lt;p&gt;
我朋友买了而我没买的东西是:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
科幻小说
体重秤
五号电池
移动电源
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;Some more&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
实际上，进程替代也不是什么很新奇的东西，Wikipedia 上说，它是进程间通信的一种方式，事实上也确实是这样。在 Linux 上使用进程替代的时候，系统会创建一个临时的文件描述符，然后将用以替代的进程的输出和这个文件描述符关联起来，这个可以通过以下命令来验证:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;echo&lt;/span&gt; &amp;lt;(sort shopping-list-1.txt)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
不出意外，应该会看到这样的输出:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
/dev/fd/63
&lt;/pre&gt;

&lt;p&gt;
&quot;fd&quot;就是文件描述父(File Description)的缩写，但你去/dev/fd/下面找这个文件描述符，却会发现找不到，那是因为这个文件描述符是临时的，在传给&quot;echo&quot;命令后就被释放了。
&lt;/p&gt;

&lt;p&gt;
此外，进程替代并不能和文件完全等价，这一点要切记。进程替代所建立的&quot;对象&quot;，是不能进行写入和随机读取操作的。不能写入的话应该很好理解，因为如果进行写操作，将会写到那个临时的文件描述符里面去，而这个临时文件描述符会被迅速地释放掉，而且由于创建的这个&quot;文件&quot;——姑且这么称呼，不是一个 regular file (与之相对的是 special file)，如果在写入时有严格的检查，甚至连写入都会被拒绝；有时候我们需要对文件进行随机读取，比如 C 语言里的 fseek() 函数的操作，这样的操作将不能在进程替代产生的临时对象上正常运作。
&lt;/p&gt;

&lt;p&gt;
总的来说，我个人是很喜欢这个功能的，减少了处理数据时不少的工作量。
&lt;/p&gt;

&lt;p&gt;
That's it!
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>2014年总结与2015年展望</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2015/01/02/annual-summary-of-2014-and-plan-of-2015.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2015/01/02/annual-summary-of-2014-and-plan-of-2015</id>
    <published>2015-01-02T00:00:00+00:00</published>
    <updated>2015-01-02T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


2014年计划完成情况
回顾与总结
2015年展望与计划




本来应该在跨年夜或者昨天来完成这篇博客的，不过12月31日身体不太舒服，昨天的话在解决 ...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;2014年计划完成情况&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;回顾与总结&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;2015年展望与计划&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
本来应该在跨年夜或者昨天来完成这篇博客的，不过12月31日身体不太舒服，昨天的话在解决 BP 神经网络实现的问题——上午的时候把问题解决了，下午分析了一下原因，这些过些时候再另外写一篇博客吧。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;2014年计划完成情况&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
先看一下去年制定的2014年计划吧。
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
找到一份工作，至少能养活自己
&lt;/p&gt;

&lt;p&gt;
这个是完成了，目前的工作虽然在有些方面不如人意，但养活自己这点是不成问题的。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
保持身体健康
&lt;/p&gt;

&lt;p&gt;
2014年12月中旬的体检结果表明，我的身体总体是健康的，不过由于缺乏锻炼以及不良的睡眠习惯，我的精力还是比较差。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
和至少十个朋友保持联络
&lt;/p&gt;

&lt;p&gt;
什么样的联络频率才能称之为&quot;保持联络&quot;呢?这个目标本身就不明确，姑且算是完成吧。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
阅读二十本书
&lt;/p&gt;

&lt;p&gt;
这个也是完成了，我的阅读记录在&lt;a href=&quot;http://linusp.gitcafe.com/record.html&quot;&gt;这个页面&lt;/a&gt;上可以看到，可以看到，我这一年的阅读大部分都是小说——这个目标的制定也是不合理和不明确的。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
每月至少写五篇博客
&lt;/p&gt;

&lt;p&gt;
上半年我还是比较勤快的，下半年就比较懒散了，所以这个目标是没有完成的……
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
学习数学，主要是线性代数、矩阵论以及概率论
&lt;/p&gt;

&lt;p&gt;
学习了一点概率论方面的基础知识，线性代数和矩阵论方面的知识并没有有目的地去学习，只是在平时学习 Machine Learning 的时候顺便了解了一些而已。
&lt;/p&gt;

&lt;p&gt;
也就是说，没有完成。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
掌握机器学习的基本理论及实现方法，掌握常用的人工神经网络，编写一个C语言的神经网络库
&lt;/p&gt;

&lt;p&gt;
到目前为止，我的主要工作都是 Speaker Diarization ，这是一个聚类领域的问题，由于工作和神经网络不相关，加上自己懒散的原因，在好长的时间里都没有去研究过神经网络了。只是通过一些 Paper 了解过诸如卷积神经网络(Convolution Neural Network, CNN)、循环神经网络(Recurrent Neural Network, RNN)这些神经网络的结构和概念，但连最基础的经典 BP 神经网络都没有去实现过——当然，2014年12月我用 Python 实现了这样一个 BP 神经网络，但由于实现过程中存在的问题，导致连异或问题都解决不了，直到今天才解决。
&lt;/p&gt;

&lt;p&gt;
所以这个目标也是没有完成啦。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
买一个树莓派，做点事情(做什么现在还没想好)
&lt;/p&gt;

&lt;p&gt;
都没想好的东西就敢列出来作为目标，没有完成也是活该了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
研究 Minecraft 红石，至少能在 Minecraft 中构造出一个简单的时序逻辑电路
&lt;/p&gt;

&lt;p&gt;
我研究了与门、非门、或门和异或门——好吧，其实与、或、非三种逻辑门在 Minecraft 中是最简单的红石电路了……异或门我倒是没看官方 Wiki 做了出来，不过做得非常丑陋。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
学会做菜
&lt;/p&gt;

&lt;p&gt;
上次在朋友那蹭饭，让我帮忙打个鸡蛋都打不好……
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;回顾与总结&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
2014年上半年，我的心理相对还是比较消极，孤独感和不安是那段时间的主要心理成分。
&lt;/p&gt;

&lt;p&gt;
这方面也很感谢北京的小伙伴，住在柳芳的 &lt;b&gt;修泽&lt;/b&gt; 他们经常让我蹭吃蹭喝蹭床蹭电影，让我度过了很多个温馨又开心的周末；&lt;a href=&quot;http://wlwang41.github.io/&quot;&gt;Crow&lt;/a&gt;、老徐则经常和我在网上讨论一些行业里好玩、有趣的东西，或者畅想创业、理想之类的东西，也很感谢他们。
&lt;/p&gt;

&lt;p&gt;
公司里的一些同事——主要是本组的一些开发人员，也让我学习到很多东西，让我了解到自己身上的一些以前未能发现的不足之处，也要感谢他们。不过一个个的跳槽，现在都走得差不多了，我呢，大概也是快要离开了吧。
&lt;/p&gt;

&lt;p&gt;
上半年到下半年这个过程里心理又发生了一些大的变化，主要是因为经济独立对人生观和价值观产生了比较大的改变吧，然后对自我认知、定位这些方面也造成了比较大的影响。上半年我比较不安，所以这方面的思考也比较多一些，这些思考累积到了一定的量后就造成了这种改变吧。
&lt;/p&gt;

&lt;p&gt;
技能上呢，由于经常要处理一些数据，都是自己写脚本，所以 Shell 技能也是得到了很大的提升。编码能力上进步就不大了，毕竟我负责的项目算上注释和空行这些乱七八糟的也就六七千行，算上重构、优化的工作，估计也就一到两万行吧。加上平时大部分时间花在算法的优化上，一些纯编码方面的知识，比如设计模式啦、语言内部机制啦，都没怎么去了解过。
&lt;/p&gt;

&lt;p&gt;
Machine Learning 方面的学习，也是做得很不好，下半年系统的学习基本上就是停滞了。一方面也是我的懒散；另外一方面我也算是实践派，学到某个东西的时候总想去动手实现一下，但公式推导起来简单，实现起来却不是那么回事，每次碰到这样的情况我就在那钻牛角尖……其实跳过去，先系统、全局地掌握这个领域的情况，会更好一些。
&lt;/p&gt;

&lt;p&gt;
阅读方面的话，因为不是抱着学习的态度去阅读的，基本上就是看到感兴趣的书就去读，导致主要都是在看小说了，这样其实是不好的。为了阅读而阅读，可以这么来描述我2014年的阅读情况吧。
&lt;/p&gt;

&lt;p&gt;
差不多就是这样了吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;2015年展望与计划&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
2015年，要赚更多的钱，要更热爱生活!
&lt;/p&gt;

&lt;p&gt;
嘛，喊口号表决心这种事情，我小学的时候就会了。
&lt;/p&gt;

&lt;p&gt;
以下是2015年的一些目标吧，视具体情况，可能途中会对这些目标进行修改。
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;换一份工作，去一个让自己觉得自己很傻逼又很牛逼的环境，而且草稿纸要无限量供应(虽然我也做不到无限量消耗啦)&lt;/li&gt;
&lt;li&gt;系统掌握概率论、数理统计、微积分、线性代数这几个数学学科的基础知识&lt;/li&gt;
&lt;li&gt;阅读五本以上的历史书籍，做到基本了解欧洲史和中国商周时期历史&lt;/li&gt;
&lt;li&gt;阅读两本以上的哲学史书籍，做到对西哲和中国哲学有一个总体认识&lt;/li&gt;
&lt;li&gt;阅读一到两本 Python 书籍，系统地掌握 Python 的语法和工程知识&lt;/li&gt;
&lt;li&gt;学习并实践设计模式&lt;/li&gt;
&lt;li&gt;读完《Effective C++》和《The Design and Evolution of C++》，了解并掌握C++的一些语言特性&lt;/li&gt;
&lt;li&gt;读完《统计学习方法》、《The Elements of Statistical Learning》，掌握 Machine Learning 领域的基本概念和方法&lt;/li&gt;
&lt;li&gt;读完《Neural Networks and Learning Machine》，实现几种常用的神经网络结构&lt;/li&gt;
&lt;li&gt;了解NLP的常用工具、主要问题和流行方法&lt;/li&gt;
&lt;li&gt;每月至少写三篇博客(不包括当月小结)&lt;/li&gt;
&lt;li&gt;完成构想的小说系列第一部的草稿&lt;/li&gt;
&lt;li&gt;养成良好的睡眠习惯&lt;/li&gt;
&lt;li&gt;独自游历五个以上的城市(在经济条件允许的情况下)——我是土包子我要出去多见见世面&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>2014年9月&amp;10月小结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/11/05/september-and-october-of-2014.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2014/11/05/september-and-october-of-2014</id>
    <published>2014-11-05T00:00:00+00:00</published>
    <updated>2014-11-05T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


工作
生活
阅读




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;工作&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;生活&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;阅读&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;工作&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
写八月小结的时候说，接下来的工作是进行算法优化，这个目标达成了。在经过了对测试结果的细致观察和对算法实现的反复推敲后，终于在九月份的时候发现了算法实现中的问题，并找到了对异常结果的理论解释。在经过优化后，现有的算法的方差已经已经大大下降，在不同的数据集和模型下的表现也都不再出现之前那种巨大的差异。
&lt;/p&gt;

&lt;p&gt;
十月份的时候开始分析模型对结果的影响，不过暂时没有什么成果。
&lt;/p&gt;

&lt;p&gt;
十月底——精确地说，是10月23日，我开始了我工作以来的第一次出差经历。不过这次出差还是蛮坎坷的，早上出发时太过匆忙，以致将装有银行卡和身份证件的钱包都落在了所借宿的朋友家里，到了广州以后过了好几天尴尬的生活——到处办事都需要身份证。还好后来朋友及时地把我的钱包寄了过来。
&lt;/p&gt;

&lt;p&gt;
由于我出差是作为技术支持人员的，到广州以后倒还是蛮闲的，严格来说并没有做太多事情，但公司交代的事情，我是百分百地做好啦!
&lt;/p&gt;

&lt;p&gt;
除此以外，我还给公司的实施人员作了Git使用培训，虽然只是讲些粗浅的东西，但我也有认真去准备，花了一点时间去制作图文并茂的演示文档，完了以后也得到了同事的肯定。原定在十月底还要给市场部作Git使用培训的，不过因为出差，就推到十一月了。
&lt;/p&gt;

&lt;p&gt;
总之呢，我有努力工作！不过努力地还不够，工作的时候不太专注就是了，这些以后慢慢改进吧！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;生活&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
十一长假的时候，回了一趟武汉，待了两天，见了一下班长，和Crow好好谈了谈。
&lt;/p&gt;

&lt;p&gt;
学校里还是一如既往地安宁喜人，走在空阔的道路上，看着那些学生们嬉笑打闹，觉得很开心。虽然喜欢学校里这样的生活，但我并不后悔不读研的决定。毕业离校的那天晚上，我在火车站给一些朋友逐个打电话告别。就算是在当时那种处境下，我依然说:&quot;我害怕着这一天，但也期待着这一天&quot;。在那天以前，我并不是作为一个个体而生活着的，精神上和物质上，我都依赖着他人，我渴望着成为一个独立的人。
&lt;/p&gt;

&lt;p&gt;
现在我是这样生活着的，现在我过得很开心。
&lt;/p&gt;

&lt;p&gt;
广州出差的日子，对我的心境好像也有一点正面的影响。一方面外出走动本身对我这种不常出门的人就有好处，其次出差这段经历也提高了我的自信。到现在为止，我依然在一些方面很不自信，但相比以前，也已经好很多了，按照现在这样去生活，进入正面积极的循环里，总是会越来越好的吧!
&lt;/p&gt;

&lt;p&gt;
十月底的时候，Crow所租的房子快到期了，邀我一起租房，不过后来由于选的几个点的房子都太贵，还是作罢了。
&lt;/p&gt;

&lt;p&gt;
生活上也没什么不如意的，除了工资稍微有点低。这个看看年底或者明年给不给我涨工资吧，我想我的工作成果和工作态度，领导也是知道的，希望他们不会让我失望。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;阅读&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
这一点还是比较惭愧，这两个月，都没怎么读书。读完了的书有以下几本:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;《爬虫馆杀人事件》&lt;/li&gt;
&lt;li&gt;《科学革命的结构》&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
有一些书则还在读，比如《The Elements of Statistical Learning》和《Neural Network and Learning Machine》，李航的《统计学习方法》，陈希孺的《概率论与数理统计》，这些书都读得很慢，当然也有比较枯燥自己没太花时间去看的缘故吧。
&lt;/p&gt;

&lt;p&gt;
想买个Kindle看一些历史、文学方面的书，不过又不太舍得花近千块钱，所以一直在犹豫，以后找个时间问问买过Kindle的朋友吧，或者在V2ex上收个二手的也行。
&lt;/p&gt;

&lt;p&gt;
2014年还剩下两个月，计划在这段时间内把这些书都看完:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;陈希孺的《概率论与数理统计》&lt;/li&gt;
&lt;li&gt;《C陷阱与缺陷》&lt;/li&gt;
&lt;li&gt;李航的《统计学习方法》&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
另外两本还在啃的书我估计今年是看不完了，特别是ESL，中译本的书名“统计学习基础”根本是误导，翻译成“统计学习精要”还差不多，特别地深入，要啃下来还真费劲。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>2014年8月小结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/09/08/august-of-2014.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2014/09/08/august-of-2014</id>
    <published>2014-09-08T00:00:00+00:00</published>
    <updated>2014-09-08T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


工作
生活
阅读




工作


8月我所做的工作，主要有：


稳定了新版本说话人分割，同时解决了接入引擎时的种种bug；
在引擎中实现了新增的协议内...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;工作&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;生活&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;阅读&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;工作&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
8月我所做的工作，主要有：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;稳定了新版本说话人分割，同时解决了接入引擎时的种种bug；&lt;/li&gt;
&lt;li&gt;在引擎中实现了新增的协议内容；&lt;/li&gt;
&lt;li&gt;参与了新版本引擎的更新，主要是一些重要结构及相关流程的改动。&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
实现和接入的工作到8月底应该就算是完成了，接下来的一段日子应该会主要花在算法的调优上了——调优工作之前虽然也有做，但也只是简单地尝试过几次而已，并没有进行系统、全面的试验。想一想，这种工作，可能也会比较枯燥吧，但这种程度的枯燥，我想我还是可以忍受的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;生活&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
8月去电影院看了《驯龙高手2》和《猩球崛起2》，算是工作之余比较令人满意的活动，以后有好电影我也会去电影院看的。
&lt;/p&gt;

&lt;p&gt;
另外，近来多有反思，思考自己现在一些思想状态是否正确，隐约有种否定自己一些自以为坚定不移想法的态势，不过人嘛，总是在不断否定与改变自己中前进的嘛，能发现自己的错误之处，哪怕只是去思考自己可能错误，我觉得也是好的。只不过如何进行有条理的思考这一点，我还是没有多少概念，只是根据自己的经验与惯性而已，难免在一些地方有偏差。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;阅读&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
这个月还算读了一点书，以下是这个月完成的书籍：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;《江城》&lt;/li&gt;
&lt;li&gt;《边城》&lt;/li&gt;
&lt;li&gt;《长河》&lt;/li&gt;
&lt;li&gt;《百年孤独》&lt;/li&gt;
&lt;li&gt;《分歧者》&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
此外，还去了一趟国图，办了一张读者证，打算以后每周都抽空去一次吧，在那边阅读还是挺有感觉的。
&lt;/p&gt;

&lt;p&gt;
现在想想，计划中一年二十本书的阅读量其实也不算什么吧，另外阅读计划的重点也不应该是只关心阅读量，还应该关心阅读质量以及涉及范围——如果是看喜欢的小说的话，我大概都可以以一天两到三本的速度推进了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>中国象棋残局骗局见闻(1)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/08/31/chinese-chess-scheme-1.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2014/08/31/chinese-chess-scheme-1</id>
    <published>2014-08-31T00:00:00+00:00</published>
    <updated>2014-08-31T00:00:00+00:00</updated>
    <description>
    
      <p>
来北京工作后，我住在了北京昌平区沙河的于新庄，步行到地铁十分钟，对我上班来说还是比较方便的。这儿住着大量的外来人口，其中有不少一部分和我一样，是IT从业者，然而其他形形色色人等，估计也是不缺的...</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
来北京工作后，我住在了北京昌平区沙河的于新庄，步行到地铁十分钟，对我上班来说还是比较方便的。这儿住着大量的外来人口，其中有不少一部分和我一样，是IT从业者，然而其他形形色色人等，估计也是不缺的。由于大量外来人口，这儿不少本地人都经营房屋出租业务，除此以外，还有从外来人口中挖掘商机的各色商贩——这些商贩里固然有本地居民，但我想也有不少嗅着钞票味道从别处而来的人。人员多而混杂，三教九流无所不有，在让此地无时不刻热闹喧嚣的同时，自然也在此地俨然形成了一个小小江湖，除了商贩，还有不少骗子在此间出没。
&lt;/p&gt;

&lt;p&gt;
最常见到的骗子就是大摆象棋残局的中年男人，一般都在地铁站出站口到于新庄入口这几百米的道路上出没。平日上下班见这等骗局，都以为不过是低劣骗术，稍微看看那残局，想明白其中关键后，就笑笑走人。也大概明了围观群众中、自荐打擂者中，必有若干骗子同伙，与摆擂者同台唱戏，引诱自恃棋技且贪欲冲头的人上当。抱着明哲保身的心态，也从不敢去揭穿其骗局——当然一众旁观者大都是明白其中必无好意这个道理的。但今日下了地铁后，若平时那般想明白关键笑笑走人后，却不禁推敲起其行骗手段技法来，走到一半，很好奇对方是否如我所想象推敲般，于是又返身回去，继续从旁冷眼细看。
&lt;/p&gt;

&lt;p&gt;
开始的残局如下，是一个相对简单直白的残局。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/chess_1.png&quot; alt=&quot;chess_1.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
摆擂者明言红先三步必胜，并不断用言语表示自己的公正与坦荡。这个时候呢，有一个挎着小包的中年男子上前来，在和摆擂者交谈了一些规则后，极其爽快地从包里抽出三张红色的百元大钞，然后开始走起棋来。
&lt;/p&gt;

&lt;p&gt;
第一个挑战者大都表现得极其愚蠢，甚至连“看上去能赢”的走法都走不出来，比如说对于上面这个残局，甚至能走出 &lt;b&gt;車五退一&lt;/b&gt; 这样的棋来。
&lt;/p&gt;

&lt;p&gt;
摆擂者在挑战者走每一步棋后，都会大声地进行点评，诸如，“唉，你走这一步是好棋，是对的”，但又会一再反复强调，“走赢要三步哈，你这一步对了，下一步不一定对咯”。然而不管摆擂者如何提醒，挑战者似乎都完全不能领会，最后仍然是败下阵来。
&lt;/p&gt;

&lt;p&gt;
第二个挑战者看上去会比第一个挑战者聪明一点，能把“看上去能赢”的走法走出一部分来。比如说上面这个残局，很容易想到的是这么一个走法是先 &lt;b&gt;車三进四&lt;/b&gt; 然后双炮上去将。然而我观察到的第二个挑战者，在走完 &lt;b&gt;車三进四&lt;/b&gt; 后，却来了个 &lt;b&gt;車五退六&lt;/b&gt; 吃卒，后面纵然想到了双炮将，也由于没有車在九宫中央限制黑将而最终败下阵来。
&lt;/p&gt;

&lt;p&gt;
这个时候，往往会有一些旁观者在旁边大呼可惜，连声责备说不该如此这般。摆擂者也摇头叹气，说你差一点就走对了诸如此类。
&lt;/p&gt;

&lt;p&gt;
在第二个挑战者结束后，摆擂者高声声明如果无人再战，30秒后就要换成另外一局棋了，然后第三个挑战者就上前来了，最终双炮将从摆擂者那拿走了双倍的赌注。
&lt;/p&gt;

&lt;p&gt;
三个挑战者无一例外都是同伙，这点稍微用心观察就不难得出结论。然后这行骗手段当真低劣吗？我看未必，这里面对旁观者心理的揣测琢磨怕是非常到位的。先以第一个同伙展示其糟糕的棋技，让旁观者高估自己的棋技；第二个同伙用来引导旁观者往“看似正确的走法”上思考；在第二个同伙输钱后，已经能够勾起一部分人的贪欲和盲目的赢棋信心，如果有人上当，那自然是到手一笔钞票，如若不然，也还有第三个同伙来“赢棋”，让犹豫不决者后悔自己没有下手而寄希望于下一个残局。
&lt;/p&gt;

&lt;p&gt;
但是同所有象棋骗局一样，上面这个“看似能赢”的残局也是不可能赢的。下面是我在电脑上的一个模拟演示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/chess_1.gif&quot; alt=&quot;chess_1.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
事实上双炮将根本是不可行的，但在第三个挑战者走棋时，摆擂者故意在红方走 &lt;b&gt;炮二进四&lt;/b&gt; 时走了 &lt;b&gt;象7退5&lt;/b&gt; 。
&lt;/p&gt;

&lt;p&gt;
第二个残局如下图所示。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/chess_2.png&quot; alt=&quot;chess_2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这个时候，我观察到之前的三个挑战者陆续离开了此处，看似无意地走到了相隔百来米处的另外一个象棋残局处，同时出那个方向走来的一些人中，似乎很好奇地又围了过来观看残局。然后呢，又开始了上面那个过程。
&lt;/p&gt;

&lt;p&gt;
先说这个残局吧，比较容易想到的是双車平六送吃，让开一路后双炮沉底将军，也就是：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
后車平六
車4退1
車一平六
車4退1
炮二进六
马6进7
炮一进六
&lt;/pre&gt;

&lt;p&gt;
但事实上黑方在第二次红車平六将军的时候，可以选择 &lt;b&gt;马6进4&lt;/b&gt; ，让红方双炮将的意图彻底落空。和前一个残局一样，红方无赢棋可能&lt;sup&gt;&lt;a id=&quot;fnr.1&quot; class=&quot;footref&quot; href=&quot;#fn.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;。
&lt;/p&gt;

&lt;p&gt;
仔细观察，骗子的同伙其实不难辨认，多为中年男性，穿着庸俗，掏钱时爽快大方，输钱也毫无肉痛表情——当然，这些外在表现可以通过提高演技来掩饰，但观其走棋章法，便可明白。
&lt;/p&gt;
&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;&amp;#33050;&amp;#27880;: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.1&quot; class=&quot;footnum&quot; href=&quot;#fnr.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
该残局为古谱《蕉窗逸品》中《马跃檀溪》局，终局为和局
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>使用Inform7创作互动式小说:世界的雏形</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/08/17/inform7-world-design.html"/>
    <category term="IF" scheme="http://www.zmonster.me/categories.html#IF"/>
    <id>http://www.zmonster.me/2014/08/17/inform7-world-design</id>
    <published>2014-08-17T00:00:00+00:00</published>
    <updated>2014-08-17T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


概念说明
开始前的设定
创建场地
双向连接与单向连接
创建区域
名字缩写
一图胜千言




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;概念说明&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;开始前的设定&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;创建场地&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;双向连接与单向连接&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;创建区域&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline6&quot;&gt;名字缩写&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline7&quot;&gt;一图胜千言&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
如果对Inform7是什么还有疑问，请看我的前一篇文章: &lt;a href=&quot;http://linusp.github.io/2014/06/28/interactive-fiction-writing-with-inform7.html&quot;&gt;使用Inform创作交互式小说&lt;/a&gt;。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;概念说明&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
在Inform7中，关于&quot;世界&quot;，也就是故事所发生的&quot;地方&quot;，存在两个比较重要的相关的对象。一个是区域(reqion)，另一个是场地(room).
&lt;/p&gt;

&lt;p&gt;
对于&quot;场地&quot;，Inform7为何用'room'这样一个词表示，我是不知道啦，一开始还比较疑惑呢，以为它就是表示一个&quot;房间&quot;，后来随着逐渐的学习，才发现它要表示的应该是&quot;场地&quot;才对——之前考虑过使用&quot;场景&quot;这个词，后来发现在Inform7中，还有专门表示&quot;场景&quot;的对象，除了地点外，一个场景还包含了某个开始和结束时刻，所以这里用&quot;场景&quot;来表示'room'是不合适的。
&lt;/p&gt;

&lt;p&gt;
以下是相关的一些概念:
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
场地(room)
&lt;/p&gt;

&lt;p&gt;
表示 &lt;b&gt;具体&lt;/b&gt; 的某个可见的地点，是 &lt;b&gt;主角&lt;/b&gt; 移动时的最小单位。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
描述(description)
&lt;/p&gt;

&lt;p&gt;
对场地、区域以及物品的描述，用英文双引号(&quot;&quot;)括起来，作为对这些对象的描述，会在游戏进行时作为展示给玩家的信息。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
场地连接(connection)
&lt;/p&gt;

&lt;p&gt;
通过类似&quot;A的东方是B&quot;这样的语句可以创建A和B之间的连接，产生一条联通A和B的路径。通过这些连接，可以将众多的&quot;场地&quot;连接起来，构成一个完整的&quot;世界&quot;。孤立的、无法到达的场地是毫无意义的。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
区域(region)
&lt;/p&gt;

&lt;p&gt;
区域通常是 &lt;b&gt;若干个场地的集合&lt;/b&gt; ，通过将一些场地聚合在一起，可以在之上定义普适于这些场景的一些规则。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
下面就通过实际的例子来讲解这些概念的实际使用吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;开始前的设定&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
首先，就以我的学校&lt;a href=&quot;http://www.hust.edu.cn/&quot;&gt;华中科技大学&lt;/a&gt;作为参考来进行世界的设定吧。简单起见，就使用沁苑、西十二教学楼以及其中一个教室N206这三个地点作为具体的场地吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;创建场地&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
首先，创建&quot;沁苑&quot;这个场地吧:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
Qinyuan is a room. &quot;Qinyuan is a quiet place. Students of the Faculty of Computer Science and Technology live here. There is a east-west direction road called Bauhinia Road. Go along this road and you'll arrive at The West Twelfth Teaching Building.&quot;
&lt;/pre&gt;

&lt;p&gt;
后面用双引号括起的就是场地的描述。
&lt;/p&gt;

&lt;p&gt;
需要注意的是，在Inform7中，一个完整的语句最好都以表结束的标点结束，如句号(.)、问号(?)或感叹号(!)，像这样定义场地或其他事物时，是以句号结尾的。
&lt;/p&gt;

&lt;p&gt;
创建场地除了明确地用'is a room'声明，还可以通过下面这样的方式隐性地创建:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
The West Twelfth Teaching Building is west of Qinyuan. &quot;There is a statue of Lao tze in front of The West Twelfth Teaching Building. A arrow on the ground says 'Go N206'.&quot;
&lt;/pre&gt;

&lt;p&gt;
在创建场景时，可以用的表示方向的词有: north, south, west, east, northeast, northwest, southeast, southwest, above, below, inside, outside.
&lt;/p&gt;

&lt;p&gt;
比如说，教室N206是在西十二教学楼内部，就需要使用inside:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
Classroom N206 is a room. &quot;Classroom N206 is a normal classroom, it can hold 100 students.&quot;

Inside from The West Twelfth Teaching Building is Classroom N206.
&lt;/pre&gt;
&lt;p&gt;
在这里，'from'这个词很重要，它表示这个语句是将两个场地连接起来，而不是在一个场地内创建一个物品。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline4&quot;&gt;双向连接与单向连接&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
在刚才，我们创建了一个连接，在'Qinyuan'和'The West Twelfth Teaching Building'之间产生了一条路径。对于这条语句:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
The West Twelfth Teaching Building is west of Qinyuan.
&lt;/pre&gt;
&lt;p&gt;
Inform7会确切地知道在'Qinyuan'这个场地中，向西可以到达'The West Twelfth Teaching Building'，同时会推测，认为'The West Twelfth Teaching Building'向东可以到达'Qinyuan'。
&lt;/p&gt;

&lt;p&gt;
如果要创建一条单向连接，如让'The West Twelfth Teaching Building'不能到达'Qinyuan'，可以这样设置:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
East of The West Twelfth Teaching Building is nowhere.
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline5&quot;&gt;创建区域&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;p&gt;
区域的创建和场地的创建差不多:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
The Huazhong University of Science and Technology is a region. Qinyuan, the West Twelfth Teaching building, Classroom N206 are in a region called the Huazhong University of Science and Technology.
&lt;/pre&gt;

&lt;p&gt;
区域允许嵌套，但前提是被包含的区域必须被完全包含，即它不能有包含它的区域所没有的&quot;场地&quot;。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline6&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline6&quot;&gt;名字缩写&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline6&quot;&gt;
&lt;p&gt;
像这两个名字都太长了，不方便输入:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
The West Twelfth Teaching Building

The Huazhong University of Science and Technology
&lt;/pre&gt;
&lt;p&gt;
虽然在IF中可以简单地使用表示方向的词来进行移动，但使用'go'命令并跟随具体的场地名也是一种移动方式，应该考虑到这个，而在Inform7中，像'go'这样带参数的命令，只会解析其参数中的前9个字符，像上面这两个名字显然有点太长。
&lt;/p&gt;

&lt;p&gt;
通过'understand'命令可以指定缩写:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
Understand &quot;HUST&quot; as  The Huazhong University of Science and Technology. Understand &quot;C12&quot; as the West Twelfth Teaching Building.
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline7&quot;&gt;一图胜千言&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline7&quot;&gt;
&lt;p&gt;
上图:
&lt;/p&gt;

&lt;p&gt;
源文本:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/i7-eg-source.png&quot; alt=&quot;i7-eg-source.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
实际运行:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/i7-eg-run.gif&quot; alt=&quot;i7-eg-run.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
讲的比较简单，实际上各个环节都还有大量的细节，我也还在学习中。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>编写Shell脚本时的一些小技巧</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/08/10/tricks-in-shell-script.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2014/08/10/tricks-in-shell-script</id>
    <published>2014-08-10T00:00:00+00:00</published>
    <updated>2014-08-10T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


使用特殊变量
条件表达式
变量使用
处理文件
后记




自工作以来，写了不少脚本，有自己临时需要而写的，也有给测试妹子编写的工具。在这个过程中，碰到了...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;使用特殊变量&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;条件表达式&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;变量使用&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;处理文件&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;后记&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
自工作以来，写了不少脚本，有自己临时需要而写的，也有给测试妹子编写的工具。在这个过程中，碰到了许多问题，当然也就学习到了很多啦。有些零零碎碎的细节，花大篇幅讲有点没必要，就整合在这篇文章里吧。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;使用特殊变量&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
$#
&lt;/p&gt;

&lt;p&gt;
$#表示当前参数列表的长度，对需要参数的Shell函数，这个变量同样有效
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
$*与$@
&lt;/p&gt;

&lt;p&gt;
这两个都包含了当前所有参数，但当用 &lt;b&gt;双引号将这两个特殊变量括起来&lt;/b&gt; 后，它们之间会产生差异。
&lt;/p&gt;

&lt;p&gt;
编写一个简单的脚本spe_arg.sh，内容如下:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;!/bin/&lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;bash&lt;/span&gt;

&lt;span style=&quot;color: #729fcf;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;arg_num&lt;/span&gt;(){
    &lt;span style=&quot;color: #729fcf;&quot;&gt;echo&lt;/span&gt; $&lt;span style=&quot;color: #eeeeec;&quot;&gt;#&lt;/span&gt;, $&lt;span style=&quot;color: #eeeeec;&quot;&gt;1&lt;/span&gt;
}

arg_num &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;$*&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
执行它，随便给点参数:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;./spe_arg.sh a b c d
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
得到的结果是:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/spe_arg-1.png&quot; alt=&quot;spe_arg-1.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
而将脚本中的$*替换成$@后，得到的结果是:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/spe_arg-2.png&quot; alt=&quot;spe_arg-2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
$$
&lt;/p&gt;

&lt;p&gt;
这表示当前的进程号。我经常将其用于生成临时文件，由于每个脚本运行后，其进程号都是唯一的，可以保证不会和其他脚本产生的临时文件发生冲突。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
$?
&lt;/p&gt;

&lt;p&gt;
上一条命令的返回值，为0则表示上一条命令正常执行，否则就是出错了。通过这个值可以方便地进行错误处理。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
$0
&lt;/p&gt;

&lt;p&gt;
表示当前脚本的名字
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
$1, $2, &amp;#x2026; $9
&lt;/p&gt;

&lt;p&gt;
分别表示第1个、第2个&amp;#x2026;第9个参数
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;条件表达式&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
在Shell脚本中，有三种条件表达式的形式:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
一对中括号括起来的条件表达式，如
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
[ 0 -gt 1 ]
&lt;/pre&gt;

&lt;p&gt;
使用这种方式，在进行字符串比较时，用于比较的运算符&quot;&amp;lt;&quot;和&quot;&amp;gt;&quot;必须转义，即必须表示为&quot;\&amp;lt;&quot;和&quot;\&amp;gt;&quot;。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
用一对双中括号括起来的条件表达式，如
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
[[ 0 -gt 1 ]]
&lt;/pre&gt;
&lt;p&gt;
使用这种方式时，字符串比较的运算符不需要转义。因此，应该尽量使用这种方式而不是第一种。
&lt;/p&gt;

&lt;p&gt;
另外，无论是第一种方式还是第二种方式， &lt;b&gt;条件表达式前后一定都要有至少一个空格&lt;/b&gt; ，即下面这样的是非法的:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
[0 -gt 1]
[0 -gt 1 ]
[ 0 -gt 1]
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
用一对双括号括起来的条件表达式，如
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
(())
&lt;/pre&gt;
&lt;p&gt;
这种方式用于算术比较，写在其中的条件表达式应该按照类似C语言的风格来表示，即不需要遵循上面两种方法的限制，也不需要使用dollar符($)来表示变量的值。
&lt;/p&gt;

&lt;p&gt;
当然，双括号不只用于条件表达式，还可以在其中进行四则运算，for循环也可以使用它。
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;变量使用&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
局部变量
&lt;/p&gt;

&lt;p&gt;
在函数中，应该尽量将使用到的变量定义为局部变量，以下做法可以达到该目的:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;local&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;var&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
\(var与\){var}
&lt;/p&gt;

&lt;p&gt;
在可能产生歧义的地方，应该使用后一种方式。所谓的歧义，可能这个词我用得不太准确，还是举个例子来描述一下吧。
&lt;/p&gt;

&lt;p&gt;
以前阵子我写的一个脚本为例，当时我定义了一个循环计数变量，命名为&quot;i&quot;，然后在每一次循环时，根据其值创建一些文件，大致是下面这个样子
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;&lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt;=0
&lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; i&lt;span style=&quot;color: #729fcf;&quot;&gt; in&lt;/span&gt; $(&lt;span style=&quot;color: #fa8072;&quot;&gt;seq&lt;/span&gt; 1 3);&lt;span style=&quot;color: #729fcf;&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;now_file&lt;/span&gt;=$&lt;span style=&quot;color: #eeeeec;&quot;&gt;ROOT_PATH&lt;/span&gt;/$&lt;span style=&quot;color: #eeeeec;&quot;&gt;i_wavlist&lt;/span&gt;
    &amp;gt; $&lt;span style=&quot;color: #eeeeec;&quot;&gt;now_file&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
我的本意是产生诸如&quot;1_wavlist&quot;、&quot;2_wavlist&quot;这样的文件，但没注意下划线也是变量名合法字符这个事实。所以这样才是正确的:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;&lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt;=0
&lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; i&lt;span style=&quot;color: #729fcf;&quot;&gt; in&lt;/span&gt; $(&lt;span style=&quot;color: #fa8072;&quot;&gt;seq&lt;/span&gt; 1 3);&lt;span style=&quot;color: #729fcf;&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;now_file&lt;/span&gt;=$&lt;span style=&quot;color: #eeeeec;&quot;&gt;ROOT_PATH&lt;/span&gt;/${&lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt;}_wavlist
    &amp;gt; $&lt;span style=&quot;color: #eeeeec;&quot;&gt;now_file&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
在sed/grep/awk中使用Shell变量
&lt;/p&gt;

&lt;p&gt;
sed和grep可以一起说，因为是同样的问题。在sed/grep的表达式中使用Shell变量，如果想得到期望的结果，应该用双引号而不是单引号将表达式括起来。这是因为在Shell中，双引号是 &lt;b&gt;弱引用(Weak Quotes)&lt;/b&gt; ，而单引号是 &lt;b&gt;强引用(Strong Quotes)&lt;/b&gt; ，在一对单引号中的内容，会作为字符串内容原原本本地输出，也就是说，Shell的取值操作符dollar符($)在一对单引号中，也是被视为一个普通字符的。
&lt;/p&gt;

&lt;p&gt;
不仅仅是取值操作符，像转义符(\)、反引号符(`)等特殊字符，在一对单引号中，其特殊意义会统统失效。
&lt;/p&gt;

&lt;p&gt;
awk中的情况与前面两者类似，但又有所不同。由于awk的表达式中也用dollar符($)来取awk处理时每个域(field)的值，所以在awk中使用Shell变量，必须要区分开Shell变量与awk变量。
&lt;/p&gt;

&lt;p&gt;
第一种方法是通过&quot;-v&quot;选项定义一个awk变量并将Shell变量赋值给它，如下:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;awk -v &lt;span style=&quot;color: #eeeeec;&quot;&gt;var&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;$shell_var&quot;&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'{print var}'&lt;/span&gt; a.txt
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
第二种方法是用双引号来将awk的表达式括起来，但要注意的是，当用双引号括起awk表达式时，像&quot;$1&quot;这样的都会被认为是在获取Shell变量的值，即在awk处理这串表达式前，Shell会将所有以dollar符开头的东西按照Shell中取值规则取值，然后替换成这个值，于是本来想让awk打印第一个域(field)的意图就会落空。
&lt;/p&gt;

&lt;p&gt;
解决这个问题的方法是用转义符将不是使用Shell变量的地方转义，如下:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;awk &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;{print \$1, $shell_var}&quot;&lt;/span&gt; a.txt
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
第三种办法是通过额外的引用来达到目的，如下所示:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;awk &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'{print $1, &quot;'&lt;/span&gt;$&lt;span style=&quot;color: #eeeeec;&quot;&gt;shell_var&lt;/span&gt;&lt;span style=&quot;color: #ad7fa8;&quot;&gt;'&quot;}'&lt;/span&gt; a.txt
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline4&quot;&gt;处理文件&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
文本处理这里就不说了，只是说一下处理文件时的一些小细节。
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
文件属性判断
&lt;/p&gt;

&lt;p&gt;
条件表达式中，'-e'用于判断文件是否存在，'-d'用于判断是否是一个目录，'-s'用于判断文件是否存在但内容为空。这三个都是我比较常用的。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
获取文件绝对路径
&lt;/p&gt;

&lt;p&gt;
在一些情景下，我们需要获得文件的绝对路径，比较蠢的办法是:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;&lt;span style=&quot;color: #eeeeec;&quot;&gt;dir&lt;/span&gt;=$(&lt;span style=&quot;color: #fa8072;&quot;&gt;dirname&lt;/span&gt; $&lt;span style=&quot;color: #eeeeec;&quot;&gt;file&lt;/span&gt;)
&lt;span style=&quot;color: #eeeeec;&quot;&gt;full_dir&lt;/span&gt;=$(&lt;span style=&quot;color: #fa8072;&quot;&gt;cd&lt;/span&gt; $&lt;span style=&quot;color: #eeeeec;&quot;&gt;dir&lt;/span&gt; &amp;amp;&amp;amp; &lt;span style=&quot;color: #729fcf;&quot;&gt;pwd&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
但其实还有更好的办法，那就是使用'readlink'这个命令:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;&lt;span style=&quot;color: #eeeeec;&quot;&gt;dir&lt;/span&gt;=$(&lt;span style=&quot;color: #fa8072;&quot;&gt;dirname&lt;/span&gt; $(&lt;span style=&quot;color: #fa8072;&quot;&gt;readlink&lt;/span&gt; -f $&lt;span style=&quot;color: #eeeeec;&quot;&gt;file&lt;/span&gt;))
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline5&quot;&gt;后记&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;p&gt;
暂时先这样吧，以后还有东西，会继续更新本文。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>Shell脚本中参数处理方法</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/08/09/pare-arguments-in-shell-function.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2014/08/09/pare-arguments-in-shell-function</id>
    <published>2014-08-09T00:00:00+00:00</published>
    <updated>2014-08-09T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


手工解析
getopts
getopt
getopts处理长选项
在函数中解析参数




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org242584d&quot;&gt;手工解析&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org039a802&quot;&gt;getopts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org29fcbdf&quot;&gt;getopt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgefa2c7a&quot;&gt;getopts处理长选项&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org893ba73&quot;&gt;在函数中解析参数&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
在Shell脚本中处理命令行参数，可以使用getopts/getopt来进行——当然，手工解析也是可以的。
&lt;/p&gt;

&lt;p&gt;
下面通过一个特定的情景来讲一下这三种参数处理方法。
&lt;/p&gt;

&lt;p&gt;
这两天写了一个安全删除的脚本，原理就是将指定的文件移动到某个特定的目录下并保存其原始路径信息，这和在Windows下以及在Linux的桌面环境下&quot;将文件移动到回收站&quot;的意义是一样的。就拿这个来做例子吧。
&lt;/p&gt;

&lt;p&gt;
在这个脚本中，有五个选项，分别代表五种动作:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;-d : 将文件移动到回收站，该选项后需要指定一个文件或目录名&lt;/li&gt;
&lt;li&gt;-l : 列出被移动到回收站的文件及其id，该选项不需要值&lt;/li&gt;
&lt;li&gt;-b : 恢复被移动到回收站的文件，该选项需要指定一个文件对应的id&lt;/li&gt;
&lt;li&gt;-c : 清空回收站，该选项不需要值&lt;/li&gt;
&lt;li&gt;-h : 打印帮助信息&lt;/li&gt;
&lt;/ol&gt;

&lt;div id=&quot;outline-container-org242584d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org242584d&quot;&gt;手工解析&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org242584d&quot;&gt;
&lt;p&gt;
所谓的手工解析，就是取到参数后手工一个一个解析了，以下是手工解析上述情景参数的过程:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell-script&quot;&gt;&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;while&lt;/span&gt; [ $&lt;span style=&quot;color: #3498db;&quot;&gt;#&lt;/span&gt; -gt 0 ];&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;case&lt;/span&gt; $&lt;span style=&quot;color: #3498db;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt; in&lt;/span&gt;
        -d)
            &lt;span style=&quot;color: #2c3e50; background-color: #ecf0f1;&quot;&gt;shift&lt;/span&gt;
            &lt;span style=&quot;color: #3498db;&quot;&gt;file_to_trash&lt;/span&gt;=$&lt;span style=&quot;color: #3498db;&quot;&gt;1&lt;/span&gt;
            trash $&lt;span style=&quot;color: #3498db;&quot;&gt;file_to_trash&lt;/span&gt; &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;trash is a function&lt;/span&gt;
            ;;
        -l)
            print_trashed_file  &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;print_trashed_file is a function&lt;/span&gt;
            ;;
        -b)
            &lt;span style=&quot;color: #2c3e50; background-color: #ecf0f1;&quot;&gt;shift&lt;/span&gt;
            &lt;span style=&quot;color: #3498db;&quot;&gt;file_to_untrash&lt;/span&gt;=$&lt;span style=&quot;color: #3498db;&quot;&gt;1&lt;/span&gt;
            untrash $&lt;span style=&quot;color: #3498db;&quot;&gt;file_to_untrash&lt;/span&gt; &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;untrash is a function&lt;/span&gt;
            ;;
        -c)
            clean_all           &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;clean all is a function&lt;/span&gt;
            ;;
        -h)
            usage
            &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;exit&lt;/span&gt; 0
            ;;
        &lt;span style=&quot;color: #16a085;&quot;&gt;\?&lt;/span&gt;)
            usage
            &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;exit&lt;/span&gt; 1
            ;;
    &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;esac&lt;/span&gt;
&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这里用到了'shift'这个命令，这个命令的作用是将参数列表以空格为分隔符左移一个单位，或者可以理解为将第一个参数给去掉了，比如获取的命令行参数为:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
-d hello.txt
&lt;/pre&gt;
&lt;p&gt;
在执行了'shift'后，命令行参数就变成了
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
hello.txt
&lt;/pre&gt;

&lt;p&gt;
这样，在使用了shift后，我们每次都只要去看参数列表中的第一个就行了。当然，其实不用'shift'也是可以的，比如说这样:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell-script&quot;&gt;&lt;span style=&quot;color: #3498db;&quot;&gt;i&lt;/span&gt;=1
&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;while&lt;/span&gt; [ $&lt;span style=&quot;color: #3498db;&quot;&gt;i&lt;/span&gt; -le $&lt;span style=&quot;color: #3498db;&quot;&gt;#&lt;/span&gt; ];&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;case&lt;/span&gt; ${&lt;span style=&quot;color: #3498db;&quot;&gt;!&lt;/span&gt;i} &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;in&lt;/span&gt;
        -d)
            &lt;span style=&quot;color: #3498db;&quot;&gt;i&lt;/span&gt;=$(&lt;span style=&quot;color: #ff00ff;&quot;&gt;expr&lt;/span&gt; $&lt;span style=&quot;color: #3498db;&quot;&gt;i&lt;/span&gt; + 1)
            &lt;span style=&quot;color: #3498db;&quot;&gt;file_to_trash&lt;/span&gt;=${&lt;span style=&quot;color: #3498db;&quot;&gt;!&lt;/span&gt;i}
            trash $&lt;span style=&quot;color: #3498db;&quot;&gt;file_to_trash&lt;/span&gt; &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;trash is a function&lt;/span&gt;
            ;;
        -l)
            print_trashed_file  &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;print_trashed_file is a function&lt;/span&gt;
            ;;
        -b)
            &lt;span style=&quot;color: #3498db;&quot;&gt;i&lt;/span&gt;=$(&lt;span style=&quot;color: #ff00ff;&quot;&gt;expr&lt;/span&gt; $&lt;span style=&quot;color: #3498db;&quot;&gt;i&lt;/span&gt; + 1)
            &lt;span style=&quot;color: #3498db;&quot;&gt;file_to_untrash&lt;/span&gt;=${&lt;span style=&quot;color: #3498db;&quot;&gt;!&lt;/span&gt;i}
            untrash $&lt;span style=&quot;color: #3498db;&quot;&gt;file_to_untrash&lt;/span&gt; &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;untrash is a function&lt;/span&gt;
            ;;
        -c)
            clean_all           &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;clean all is a function&lt;/span&gt;
            ;;
        -h)
            usage
            &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;exit&lt;/span&gt; 0
            ;;
        &lt;span style=&quot;color: #16a085;&quot;&gt;\?&lt;/span&gt;)
            usage
            &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;exit&lt;/span&gt; 1
            ;;
    &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;esac&lt;/span&gt;
    &lt;span style=&quot;color: #3498db;&quot;&gt;i&lt;/span&gt;=$(&lt;span style=&quot;color: #ff00ff;&quot;&gt;expr&lt;/span&gt; $&lt;span style=&quot;color: #3498db;&quot;&gt;i&lt;/span&gt; + 1)
&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
对比可以发现使用'shift'会稍微方便一点。
&lt;/p&gt;

&lt;p&gt;
当然，上面的处理没有进行参数检查，这些检查应该要防止这些错误情况:参数个数为0、完全冲突的&quot;动作&quot;一起出现、选项需要值但未给值。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org039a802&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org039a802&quot;&gt;getopts&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org039a802&quot;&gt;
&lt;p&gt;
'getopts'是POSIX Shell中内置的一个命令，其使用方法是:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell-script&quot;&gt;&lt;span style=&quot;color: #2c3e50; background-color: #ecf0f1;&quot;&gt;getopts&lt;/span&gt; &amp;lt;opt_string&amp;gt; &amp;lt;optvar&amp;gt; &amp;lt;arguments&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
下面是在Shell中使用该命令的一个示例:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/getopts.gif&quot; alt=&quot;getopts.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
本质上来说，'getopts'的处理和我们手工处理是差不多的，它不过是提供了更便利的方式而已。它的使用方式非常简单明了，其形式为:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell-script&quot;&gt;&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;while &lt;/span&gt;&lt;span style=&quot;color: #2c3e50; background-color: #ecf0f1;&quot;&gt;getopts&lt;/span&gt; &amp;lt;opt_string&amp;gt; &amp;lt;optvar&amp;gt;
    &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;case&lt;/span&gt; $&amp;lt;optvar&amp;gt;&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt; in&lt;/span&gt;
        &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;...&lt;/span&gt;
    &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;esac&lt;/span&gt;
&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
其中&amp;lt;opt_string&amp;gt;是要处理的选项的一个集合，每个选项在其中用不包含连字符'-'的字母来表示，每个代表选项的字母前后可以有一个冒号，前面有冒号表示当处理该选项出错时不输出'getopts'自身产生的错误信息，这方便我们自己编写对应的错误处理方法;后面的冒号表示这个选项需要一个值。对于我们这个&quot;安全删除&quot;的例子，这个&amp;lt;opt_string&amp;gt;应该是:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell-script&quot;&gt;d:lb:ch
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
冒号的归属的话，先到先得吧，大概是这样。
&lt;/p&gt;

&lt;p&gt;
在使用'getopts'时，有两个特殊的变量，它们是 &lt;b&gt;OPTIND&lt;/b&gt; 和 &lt;b&gt;OPTARG&lt;/b&gt; ，前者表示当前参数在参数列表中的位置——相当于手工解析第二种方法中那个自定义的变量 &lt;b&gt;i&lt;/b&gt; ，其值初始时为1， 会在每次取了选项以及其值(如果有的话)后更新; &lt;b&gt;OPTARG&lt;/b&gt; 则是在选项需要值时，存储这个选项对应的值。这样，我们这个例子用'getopts'就可以写成:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell-script&quot;&gt;&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;while &lt;/span&gt;&lt;span style=&quot;color: #2c3e50; background-color: #ecf0f1;&quot;&gt;getopts&lt;/span&gt; d:lb:ch OPT;&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;case&lt;/span&gt; $&lt;span style=&quot;color: #3498db;&quot;&gt;OPT&lt;/span&gt;&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt; in&lt;/span&gt;
        d)
            &lt;span style=&quot;color: #3498db;&quot;&gt;file_to_trash&lt;/span&gt;=$&lt;span style=&quot;color: #3498db;&quot;&gt;OPTARG&lt;/span&gt;
            trash $&lt;span style=&quot;color: #3498db;&quot;&gt;file_to_trash&lt;/span&gt; &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;trash is a function&lt;/span&gt;
            ;;
        l)
            print_trashed_file  &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;print_trashed_file is a function&lt;/span&gt;
            ;;
        b)
            &lt;span style=&quot;color: #3498db;&quot;&gt;file_to_untrash&lt;/span&gt;=$&lt;span style=&quot;color: #3498db;&quot;&gt;OPTARG&lt;/span&gt;
            untrash $&lt;span style=&quot;color: #3498db;&quot;&gt;file_to_untrash&lt;/span&gt; &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;untrash is a function&lt;/span&gt;
            ;;
        c)
            clean_all           &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;clean all is a function&lt;/span&gt;
            ;;
        h)
            usage
            &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;exit&lt;/span&gt; 0
            ;;
        &lt;span style=&quot;color: #16a085;&quot;&gt;\?&lt;/span&gt;)
            usage
            &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;exit&lt;/span&gt; 1
            ;;
    &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;esac&lt;/span&gt;
&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
对比可以看到，相比手工解析的第一种办法，又更为简洁一点了。不过需要注意的是，'getopts'会从第一个参数开始，只按照&amp;lt;opt_string&amp;gt;指定的形式来寻找并解析参数，如果给出的实际命令行参数与其所描述的参数形式不符，则会出错中止。
&lt;/p&gt;

&lt;p&gt;
比如说，对于上面的例子，假设这个脚本已经完全写好了，脚本名为 &lt;b&gt;trash.sh&lt;/b&gt; ，其参数处理就是上面这样，那么如果我在终端里执行:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell-script&quot;&gt;./trash.sh a -b hello.txt
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
开始那个多余的参数'a'将会导致'getopts'在解析到选项'-b'前就出错终止。所以呢，像使用'getopts'这样的方法，其自由度不如手工解析，如果要保证脚本在任何情况下都能正确解析参数，它需要多做一点——当然啦，上面这个愚蠢的错误使用情况还是比较少出现的啦，反正我现在写的脚本里压根没考虑这样的情况。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org29fcbdf&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org29fcbdf&quot;&gt;getopt&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org29fcbdf&quot;&gt;
&lt;p&gt;
'getopt'与'getopts'类似，不过'getopts'只能处理短选项，'getopt'则能处理短选项和长选项。所谓的短选项就是类似下面这样的选项:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
-a
&lt;/pre&gt;

&lt;p&gt;
而下面这样的则是长选项
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
--action=delete
&lt;/pre&gt;

&lt;p&gt;
当然，事无绝对，通过一些技巧，用'getopts'处理长选项也是可能的。这里先说一下如何用'getopt'来处理参数吧。
&lt;/p&gt;

&lt;p&gt;
需要事先说明的一点是，'getopt'不是Shell内建的命令，而是'util-linux'这个软件包提供的功能，它不是POSIX标准的一部分，所以也有人&lt;a href=&quot;http://mywiki.wooledge.org/BashFAQ/035#getopts&quot;&gt;建议不使用'getopt'&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
首先将之前说到的五种动作对应的短选项扩展一下，以便讲解'getopt'的使用:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;-d/&amp;#x2013;delete : 将文件移动到回收站，该选项后需要指定一个文件或目录名&lt;/li&gt;
&lt;li&gt;-l/&amp;#x2013;list : 列出被移动到回收站的文件及其id，该选项不需要值&lt;/li&gt;
&lt;li&gt;-b/&amp;#x2013;back : 恢复被移动到回收站的文件，该选项需要指定一个文件对应的id&lt;/li&gt;
&lt;li&gt;-c/&amp;#x2013;clear : 清空回收站，该选项不需要值&lt;/li&gt;
&lt;li&gt;-h/&amp;#x2013;help : 打印帮助信息&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
'getopt'既能处理短选项也能处理长选项，短选项通过参数 &lt;b&gt;-o&lt;/b&gt; 指定，长选项通过参数 &lt;b&gt;-l&lt;/b&gt; 指定。同'getopts'一样，它一次也只解析一个选项，所以也需要循环处理，不过与'getopts'不同的是，'getopt'没有使用 &lt;b&gt;OPTIND&lt;/b&gt; 和 &lt;b&gt;OPTARG&lt;/b&gt; 这两个变量，所以我们还得手动对参数进行'shift'，对需要值的选项，也得手动去取出值。
&lt;/p&gt;

&lt;p&gt;
下面是在Shell中使用'getopt'的一个示例:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/getopt.gif&quot; alt=&quot;getopt.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到，'getopt'将参数中以下形式的内容:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
--longopt=argument
&lt;/pre&gt;
&lt;p&gt;
在返回结果中替换成下面这样的形式:
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
--longopt argument
&lt;/pre&gt;
&lt;p&gt;
这样就可以通过循环和'shift'来进行处理了，不过在脚本中，'shift'命令是对命令行参数起作用的，即特殊变量&quot;$@&quot;，而我们在脚本中只能将'getopt'的返回结果作为字符串存储到一个变量中。为了让'shift'起作用，通常还要使用'set'命令来将变量的值赋给&quot;$@&quot;这个特殊变量。
&lt;/p&gt;

&lt;p&gt;
真是有够麻烦的……算了，下面再集中吐槽吧……
&lt;/p&gt;

&lt;p&gt;
然后，在设置好短选项和长选项后，在将实际的参数传给'getopt'时，要在实际参数前加上一个两个连字符 &lt;b&gt;--&lt;/b&gt; ，而'getopt'会将这两个连字符放到返回结果的最后面，在处理时可以将这两个连字符视为结束标志。
&lt;/p&gt;

&lt;p&gt;
以下是针对本文假设的情景，使用'getopt'解析参数的流程:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell-script&quot;&gt;&lt;span style=&quot;color: #3498db;&quot;&gt;arg&lt;/span&gt;=$(&lt;span style=&quot;color: #ff00ff;&quot;&gt;getopt&lt;/span&gt; -o d:lb:ch -l delete:,list,back:,clear,help -- $&lt;span style=&quot;color: #3498db;&quot;&gt;@&lt;/span&gt;)

&lt;span style=&quot;color: #2c3e50; background-color: #ecf0f1;&quot;&gt;set&lt;/span&gt; -- &lt;span style=&quot;color: #16a085;&quot;&gt;&quot;$arg&quot;&lt;/span&gt;

&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;while&lt;/span&gt; true
&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;case&lt;/span&gt; $&lt;span style=&quot;color: #3498db;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt; in&lt;/span&gt;
        -d|--delete)
            &lt;span style=&quot;color: #3498db;&quot;&gt;file_to_trash&lt;/span&gt;=$&lt;span style=&quot;color: #3498db;&quot;&gt;2&lt;/span&gt;
            trash $&lt;span style=&quot;color: #3498db;&quot;&gt;file_to_trash&lt;/span&gt; &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;trash is a function&lt;/span&gt;
            &lt;span style=&quot;color: #2c3e50; background-color: #ecf0f1;&quot;&gt;shift&lt;/span&gt; 2
            ;;
        -l|--list)
            print_trashed_file  &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;print_trashed_file is a function&lt;/span&gt;
            &lt;span style=&quot;color: #2c3e50; background-color: #ecf0f1;&quot;&gt;shift&lt;/span&gt;
            ;;
        -b|--back)
            &lt;span style=&quot;color: #3498db;&quot;&gt;file_to_untrash&lt;/span&gt;=$&lt;span style=&quot;color: #3498db;&quot;&gt;2&lt;/span&gt;
            untrash $&lt;span style=&quot;color: #3498db;&quot;&gt;file_to_untrash&lt;/span&gt; &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;untrash is a function&lt;/span&gt;
            &lt;span style=&quot;color: #2c3e50; background-color: #ecf0f1;&quot;&gt;shift&lt;/span&gt;
            ;;
        -c|--clear)
            clean_all           &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;clean all is a function&lt;/span&gt;
            &lt;span style=&quot;color: #2c3e50; background-color: #ecf0f1;&quot;&gt;shift&lt;/span&gt;
            ;;
        -h|--help)
            usage
            &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;exit&lt;/span&gt; 0
            ;;
        --)
            &lt;span style=&quot;color: #2c3e50; background-color: #ecf0f1;&quot;&gt;shift&lt;/span&gt;
            &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;break&lt;/span&gt;
            ;;
    &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;esac&lt;/span&gt;
&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然而，知道了'getopt'的使用及其原理后，自然而然地可以发现，我可以不用去管这个结束标志，用&quot;$#&quot;这个表示参数个数的特殊变量，同样可以控制参数解析的流程，这完全和手工解析是同一个道理。我甚至可以将'getopt'的返回结果存储到一个数组里，直接循环处理这个数组，而不用使用'set'命令了。
&lt;/p&gt;

&lt;p&gt;
好了，吐槽时间。
&lt;/p&gt;

&lt;p&gt;
我之前写脚本都是用的'getopts'，一来我用不上长选项，二来'getopts'的使用足够简单。在写本文之前，我倒是知道'getopt'可以处理长选项，但没仔细了解过。这两天了解了一下，觉得还是别用'getopt'的好，理由如下:
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;'getopt'不是Shell内建命令，跨平台使用时可能会出现问题；&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
只是将'&amp;#x2013;longopt=val'这样的参数形式替换成了'&amp;#x2013;longopt val'，但因此增加了许多复杂性，比如使用了'set'命令，在使用'set'命令时还要考虑'getopt'的返回结果中有无Shell命令，有的话应该使用'eval'命令来消除可能导致的错误
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
eval set -- &quot;$arg&quot;
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;调用完还要进行与手工解析类似的工作，相比手工解析，并没有多大优势；&lt;/li&gt;
&lt;li&gt;真的需要长选项吗？我觉得短选项就足够了&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgefa2c7a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgefa2c7a&quot;&gt;getopts处理长选项&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgefa2c7a&quot;&gt;
&lt;p&gt;
既然不建议使用'getopt'，那么怎么处理长选项呢？自然是有办法的。
&lt;/p&gt;

&lt;p&gt;
为了方便讲解，这里假设一个简单的情景吧，在这个情景里，我们只需要处理两个可能的选项
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;-f/&amp;#x2013;file: 设置文件名，该选项需要值&lt;/li&gt;
&lt;li&gt;-h/&amp;#x2013;help: 打印帮助信息，该选项不需要值&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
用'getopts'处理这种情况，可以这么做:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell-script&quot;&gt;&lt;span style=&quot;color: #3498db;&quot;&gt;filename&lt;/span&gt;=&lt;span style=&quot;color: #16a085;&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;while &lt;/span&gt;&lt;span style=&quot;color: #2c3e50; background-color: #ecf0f1;&quot;&gt;getopts&lt;/span&gt; f:h-: opt;&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;case&lt;/span&gt; $&lt;span style=&quot;color: #3498db;&quot;&gt;opt&lt;/span&gt;&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt; in&lt;/span&gt;
        -)
            &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;case&lt;/span&gt; $&lt;span style=&quot;color: #3498db;&quot;&gt;OPTARG&lt;/span&gt;&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt; in&lt;/span&gt;
                &lt;span style=&quot;color: #2c3e50; background-color: #ecf0f1;&quot;&gt;help&lt;/span&gt;)
                    usage
                    &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;exit&lt;/span&gt; 0
                    ;;
                &lt;span style=&quot;color: #3498db;&quot;&gt;file&lt;/span&gt;=*)
                    &lt;span style=&quot;color: #3498db;&quot;&gt;filename&lt;/span&gt;=${&lt;span style=&quot;color: #3498db;&quot;&gt;OPTARG&lt;/span&gt;#*=}
                    ;;
            &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;esac&lt;/span&gt;
            ;;
        f)
            &lt;span style=&quot;color: #3498db;&quot;&gt;filename&lt;/span&gt;=$&lt;span style=&quot;color: #3498db;&quot;&gt;OPTARG&lt;/span&gt;
            ;;
        h)
            usage
            &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;exit&lt;/span&gt; 0
            ;;
        &lt;span style=&quot;color: #16a085;&quot;&gt;\?&lt;/span&gt;)
            usage
            &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;exit&lt;/span&gt; 1
            ;;
    &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;esac&lt;/span&gt;
&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
当然，也许并不比手工解析简洁多少，但用起来肯定是比'getopt'要舒服的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org893ba73&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org893ba73&quot;&gt;在函数中解析参数&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org893ba73&quot;&gt;
&lt;p&gt;
有时候，我们也许想把参数解析的工作放到函数中去做，比如说定义了一个'main'函数然后在'main'函数中封装整个流程处理逻辑。又或者像我一样，写了几个小小的工具函数，放到了Bash的配置文件 &lt;b&gt;.bashrc&lt;/b&gt; 中，参数解析的工作必须得在函数中做。
&lt;/p&gt;

&lt;p&gt;
手工解析是能想到的最直接的办法，简单可行。
&lt;/p&gt;

&lt;p&gt;
不过假如我们想用'getopts'来处理呢？动手尝试后，你会发现直接在函数中使用'getopts'是会出错的。要在函数中使用'getopts'，必须在这个函数中使用'getopts'前，将 &lt;b&gt;OPTIND&lt;/b&gt; 这个被'getopts'使用的特殊变量设置为函数局部变量，像这样:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell-script&quot;&gt;&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #9b59b6; background-color: #ecf0f1; font-weight: bold;&quot;&gt;main&lt;/span&gt;() {

    &lt;span style=&quot;color: #2c3e50; background-color: #ecf0f1;&quot;&gt;local&lt;/span&gt; OPTIND

    &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;while &lt;/span&gt;&lt;span style=&quot;color: #2c3e50; background-color: #ecf0f1;&quot;&gt;getopts&lt;/span&gt; d:lb:ch OPT;&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;do&lt;/span&gt;
       &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;case&lt;/span&gt; $&lt;span style=&quot;color: #3498db;&quot;&gt;OPT&lt;/span&gt;&lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt; in&lt;/span&gt;
           d)
               &lt;span style=&quot;color: #3498db;&quot;&gt;file_to_trash&lt;/span&gt;=$&lt;span style=&quot;color: #3498db;&quot;&gt;OPTARG&lt;/span&gt;
               trash $&lt;span style=&quot;color: #3498db;&quot;&gt;file_to_trash&lt;/span&gt; &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;trash is a function&lt;/span&gt;
               ;;
           l)
               print_trashed_file  &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;print_trashed_file is a function&lt;/span&gt;
               ;;
           b)
               &lt;span style=&quot;color: #3498db;&quot;&gt;file_to_untrash&lt;/span&gt;=$&lt;span style=&quot;color: #3498db;&quot;&gt;OPTARG&lt;/span&gt;
               untrash $&lt;span style=&quot;color: #3498db;&quot;&gt;file_to_untrash&lt;/span&gt; &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;untrash is a function&lt;/span&gt;
               ;;
           c)
               clean_all           &lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #95a5a6; font-style: italic;&quot;&gt;clean all is a function&lt;/span&gt;
               ;;
           h)
               usage
               &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;exit&lt;/span&gt; 0
               ;;
           &lt;span style=&quot;color: #16a085;&quot;&gt;\?&lt;/span&gt;)
               usage
               &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;exit&lt;/span&gt; 1
               ;;
       &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;esac&lt;/span&gt;
    &lt;span style=&quot;color: #2c3e50; font-weight: bold; font-style: italic;&quot;&gt;done&lt;/span&gt;
}

main $&lt;span style=&quot;color: #3498db;&quot;&gt;@&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
就是这样啦!
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>自定义Git</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/08/02/configure-git.html"/>
    <category term="Linux" scheme="http://www.zmonster.me/categories.html#Linux"/>
    <id>http://www.zmonster.me/2014/08/02/configure-git</id>
    <published>2014-08-02T00:00:00+00:00</published>
    <updated>2014-08-02T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


配置及配置文件
配置: Section user
配置: Section core
配置: Section color




配置及配置文件


Git...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;配置及配置文件&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;配置: Section user&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;配置: Section core&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;配置: Section color&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;配置及配置文件&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
Git可以使用命令
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;git config
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
来进行自定义设置，而这些设置，最终都会被写入对应的配置文件中，然后在适当的时候加载这些配置文件，来确定Git被使用时的一些表现。
&lt;/p&gt;

&lt;p&gt;
Git会在三个可能的地方寻找配置文件
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;系统级全局配置文件:/etc/gitconfig，对操作系统上所有用户都起作用&lt;/li&gt;
&lt;li&gt;用户级全局配置文件:~/.gitconfig，对用户的所有代码仓库起作用&lt;/li&gt;
&lt;li&gt;代码仓库级配置文件:&amp;lt;repo&amp;gt;/.git/confg，只对当前对应的代码仓库起作用&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
Git按照上面的顺序依次寻找配置文件并用其设置Git。
&lt;/p&gt;

&lt;p&gt;
第一个配置文件可能存在也可能不存在，在我的Debian上它是不存在的，可以通过命令:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;git config --system
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
来进行读写。
&lt;/p&gt;

&lt;p&gt;
第二个配置文件可以通过命令:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;git config --global
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
来进行读写。
&lt;/p&gt;

&lt;p&gt;
第三个配置文件可以在相应的代码仓库目录下，通过命令:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;git config
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
来进行读写(注意，不带 &amp;#x2013;global 选项)。
&lt;/p&gt;

&lt;p&gt;
以上命令都是用于在命令行中对Git的某个设置项进行设置，如果需要打开文件直接编辑，除了在编辑器中来直接打开文件，还可以通过命令:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;git config -e
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
来进行。在其后加上 &lt;b&gt;&amp;#x2013;system&lt;/b&gt; 则会打开/etc/目录下的gitconfig；加上 &lt;b&gt;&amp;#x2013;global&lt;/b&gt; 则会打开用户HOME目录下的配置文件.gitconfig；而在某个代码仓库目录下执行且不加 &lt;b&gt;&amp;#x2013;system&lt;/b&gt; 也不加 &lt;b&gt;&amp;#x2013;global&lt;/b&gt; 选项时，则会打开该代码仓库下的配置文件进行编辑。
&lt;/p&gt;

&lt;p&gt;
在配置文件中，以 '#' 或 ';' 开始的的行会被忽视，即这两个符号被用作注释符。
&lt;/p&gt;

&lt;p&gt;
配置文件的内容形式如下:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;[user]
    name = linusp
    email = linusp1024@gmail.com
[credential]
    helper = cache --timeout=3600
[color]
    ui = true
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
被中括号括起的内容被称为Section，其下有许多
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
xxx = xxx
&lt;/pre&gt;
&lt;p&gt;
的内容，其中等号前面的部分就是实际的配置项，后面的则是该配置项的值。要设置某个Section下面的项的值，以Section user下的name为例，可以通过如下命令:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;git config --global user.name linusp
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Git 提供了很多的可配置项，具体可以执行
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;git config --help
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
然后到 &quot;Variables&quot; 一节查看。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;配置: Section user&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
user下的配置项主要是用于在线认证的，比如说Github。
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
user.name
&lt;/p&gt;

&lt;p&gt;
设置用户名，比如我在Github上的用户名是'Linusp'，那么就设置:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;git config --global user.name Linusp
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
如果公司使用Git进行代码管理，这一步也是需要的.
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
user.email
&lt;/p&gt;

&lt;p&gt;
设置邮箱，同上，用于认证。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;配置: Section core&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
core.filemode
&lt;/p&gt;

&lt;p&gt;
设置是否检查文件权限，其值默认为'true'，对同样内容、名字的文件，如果其文件权限发生了改变，则会认为发生了'修改'。如果要忽略文件权限的检查，可以将该项的值设置为'false':
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;git config core.filemode false
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
core.ignorecase
&lt;/p&gt;

&lt;p&gt;
设置是否忽略文件名大小写的区别，默认为'false'，即默认情况下是大小写敏感的。在Windows的文件系统上，将这个项的值设置为'true'可能会比较常见
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
core.autocrlf
&lt;/p&gt;

&lt;p&gt;
设置Git对行尾的换行符的处理方式。这个设置项主要是为了解决跨平台开发时Windows操作系统与*nix系统上换行符不一致的矛盾。其值有三个可能:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
true
&lt;/p&gt;

&lt;p&gt;
设置为该值时，代码仓库里的代码会保证以*nix的换行符结尾，在用户提交时会把Windows的换行符替换为*nix的换行符，但在用户checkout后将会替换成Windows的换行符。在Windows环境下开发但其合作者中在*nix系统下开发的用户可以将'core.autocrlf'项的值设置为'true':
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;git config core.autocrlf true
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
input
&lt;/p&gt;

&lt;p&gt;
设置为该值时，代码仓库里的代码和checkout的结果都会保证以*nix的换行符结尾，如果提交时的文件中存在Windows的换行符，Git会将其替换为*nix的换行符。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
false
&lt;/p&gt;

&lt;p&gt;
设置为该值时，Git不对文件行结尾的换行符进行检测和处理。
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
core.excludesfile
&lt;/p&gt;

&lt;p&gt;
设置一个文件，文件中包含一些文件名或者正则表达式，代码仓库中被匹配到的文件将会被视为不是代码仓库中的文件，既不会检查其改动，在执行'git add'的时候也会自动忽略它们。
&lt;/p&gt;

&lt;p&gt;
在代码仓库中建立名为.gitignore的文件能起到相同的作用。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
core.editor
&lt;/p&gt;

&lt;p&gt;
设置'git commit'时编辑提交信息的编辑器，如要设置为vim，则:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;git config --global core.editor vim
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
core.pager
&lt;/p&gt;

&lt;p&gt;
设置在执行'git log'等包含大量输出的命令时的分页器，默认为'less'，通过这个项可以将其设置为'more'，或者设置为空以关闭分页输出:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;git config core.pager &lt;span style=&quot;color: #ad7fa8;&quot;&gt;''&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline4&quot;&gt;配置: Section color&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
该组配置可以让Git在输出时进行着色——默认情况下都是不着色的，而着色有助于阅读，比如在执行'git diff'和'git log'的时候。
&lt;/p&gt;

&lt;p&gt;
以下命令将会使'git diff'、'git log'、'git status'等带输出的命令对输出进行着色。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;git config --global color.ui true
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
当然也可以打单独对某个命令的输出进行着色设置:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;git config --global color.diff true
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>Bash 3.x 与 Bash 4.x中declare命令的区别</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/07/28/difference-in-bash-3-4-about-declare.html"/>
    <category term="Linux" scheme="http://www.zmonster.me/categories.html#Linux"/>
    <id>http://www.zmonster.me/2014/07/28/difference-in-bash-3-4-about-declare</id>
    <published>2014-07-28T00:00:00+00:00</published>
    <updated>2014-07-28T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


问题
Bash 版本
后记




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;问题&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;Bash 版本&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;后记&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;问题&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
今天下午的时候，测试的妹子说我写的脚本出了问题，跑过去一看，出错提示是：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
declare: -A: invalid option
&lt;/pre&gt;
&lt;p&gt;
我写的脚本里有两处使用
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-shell-script&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;declare&lt;/span&gt; -A
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
分别定义了一个&lt;a href=&quot;http://www.gnu.org/software/bash/manual/html_node/Arrays.html&quot;&gt;关联数组&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
一开始很诧异，这你的'declare'和我的'declare'还能不一样了？尝试了一下，还确实是不一样，妹子机器上的'declare'命令压根就没有'-A'这个选项。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;Bash 版本&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
'declare' 是 Bash内建的命令，既然两台机器上的'declare'不一样，那应该Bash也会不一样吧？抱着这样的心理，分别看了下两台机器的Bash版本。
&lt;/p&gt;

&lt;p&gt;
果然，出问题的机器上，Bash版本是3.x，而我的机器上的Bash版本是4.x。在网上搜了一下相关信息，才知道关联数组是在Bash 4.x中才支持的。这就是问题的原因了。
&lt;/p&gt;

&lt;p&gt;
也懒得继续用关联数组了，毕竟要适配不同的Bash版本，工作量还是略大。反正两个关联数组是用来存中间结果的，于是索性写到两个临时文件里去了，稍微多做了一点处理就OK了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;后记&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
这么短的博客难道不是在凑数吗？
&lt;/p&gt;

&lt;p&gt;
真没有啊！_(:3」∠)_
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>(2014年6月&amp;7月)小结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/07/27/june-july-of-2014.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2014/07/27/june-july-of-2014</id>
    <published>2014-07-27T00:00:00+00:00</published>
    <updated>2014-07-27T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


工作日志分析
编程以外的工作总结
工作以外的生活
阅读与写作




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;工作日志分析&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;编程以外的工作总结&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;工作以外的生活&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;阅读与写作&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
六月的总结没有写，这次作一个工作以来的大的总结吧。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;工作日志分析&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
工作以来，我每天都会将工作中遇到的问题、所做的事情记录在本子上，现在第四个本子已经用完一半了。现在日记虽然不能坚持写了，但工作日志也反映了工作日时我一天的经历。说到这里，我觉得我急切需要搞一张大桌子放到房间里，有时候其实很想写写东西的，但是桌子上堆满了东西，根本伸展不开，特别别扭。
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
第一本工作日志(2014/04-14 - 2014/05/16)
&lt;/p&gt;

&lt;p&gt;
这一个月主要是在阅读原有项目代码、学习理解相关原理，以及进行初步的API设计工作。
&lt;/p&gt;

&lt;p&gt;
相关原理方面，主要是MFCC、GMM、BIC、HMM这几个知识点。但其实没太在这方面花多少功夫，因为大部分的时间都花费在阅读理解原项目代码和API涉及工作上了。
&lt;/p&gt;

&lt;p&gt;
原先的代码写得很糟糕，于是在阅读代码和设计API上进展缓慢，这个过程也感觉很痛苦——现在项目已经由我重构了，虽然我不认为自己写的代码有多漂亮，但比原先的代码好我是有自信的。
&lt;/p&gt;

&lt;p&gt;
在这段时间的最后一周，确定了API的设计，由于涉及多线程，将API分为了三部分：
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
资源初始化与销毁
&lt;/p&gt;

&lt;p&gt;
初始化一些全局资源，比如模型和一些全局参数。这些全局资源在后面只会被线程读取而不会进行改变。同时在此处根据传入的参数预先创建若干个线程，每个线程将会在后面进行实际的处理操作。其实在API要接入的引擎中已经实现了线程池，此处之所以还要创建线程，是因为后续处理需要调用一个外部java包工具，因为是使用 &lt;b&gt;system&lt;/b&gt; 函数来调用的，而 &lt;b&gt;system&lt;/b&gt; 实际上会产生一个子进程，由于引擎为了保证内存使用稳定在一开始的时候会预分配比较大的内存，不通过线程，而是直接调用的话，会产生很大的内存开销。
&lt;/p&gt;

&lt;p&gt;
当然，这个主意并不是我想出来的，而是我的项目组组长的主意。现在已经弃用了那个java包，完全使用C++实现了，所以这个设计后来也废除了。
&lt;/p&gt;

&lt;p&gt;
对应的，在程序结束时会有资源的销毁处理。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;线程自有资源的初始化与销毁&lt;/li&gt;

&lt;li&gt;实际处理API&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
第二本工作日志(2014/05/19 - 2014/06/18)
&lt;/p&gt;

&lt;p&gt;
五月底原先负责项目的人离开了公司，所以我开始放心大胆地进行修改，后来实际上已经废弃了原有项目代码(但仍然是调用java包的模式)，只保留了我实现的部分。这一段时间主要是将API接入引擎，整理错误率计算工具并进行批量测试，并在测试结果上进行参数调整。
&lt;/p&gt;

&lt;p&gt;
以下是这段时间在编程上所犯的错误及次数统计
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;错误&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;次数&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;循环(线程/loop)处理中，一次处理完后未重置相关变量&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;使用未初始化的变量&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;使用错误的变量&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;拼写错误&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;读文件错误&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;在外部使用局部变量(通过指针)&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;命名空间、函数签错误名导致&quot;函数未定义&quot;&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;访问数组未检测下标是否合法&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;读文件是未检测文件是否打开成功&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;未关闭文件&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;未判断函数返回值，前一步处理失败仍继续进行&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;总错误次数&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;19&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
平均下来，大概每天犯一个错误。
&lt;/p&gt;

&lt;p&gt;
整理错误率计算工具也是花费了我不少功夫，在这个过程中对Shell脚本的编写更加地熟悉了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
第三、四本工作日志(2014/06/19 - 2014/07/25)
&lt;/p&gt;

&lt;p&gt;
这段时间开始，就彻底废弃了调用java包的模式，使用&lt;a href=&quot;http://kaldi.sourceforge.net/&quot;&gt;kaldi&lt;/a&gt; 来重构了整个项目，并且重新设计了API——API改动倒是不大，只是改动了一下参数类型、数目而已。然后在此基础上进行批量测试和结果分析，奈何错误率太高，在分析其原因上花费了接近两周时间——最后发现除了算法实现上有问题，还有我在编程上犯了一个细节错误，当时真想打死自己……
&lt;/p&gt;

&lt;p&gt;
这段时间依然在编程上犯了不少错误，统计如下：
&lt;/p&gt;

&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;错误&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-right&quot;&gt;次数&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;使用错误的变量&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;4&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;使用未初始化的变量&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;访问NULL指针&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;访问数组时未检测下标是否合法&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;3&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;循环处理中，一次处理完后未重置相关变量&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;读文件是未检测文件是否打开成功&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;2&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;前置声明类型但定义了该类型的非引用、指针成员&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;单链表插入实现错误&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;在不应该读取文件时读取了文件&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;类型转换错误(35.67 * 100 -&amp;gt; 3566)&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;'delete' memory allocated by 'calloc'&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;总错误次数&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;22&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;编程以外的工作总结&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
首先，这个月已经转正啦，工资稍微多一点了，不过还是不多。
&lt;/p&gt;

&lt;p&gt;
和组内的同事已经算是很熟悉了，面对新入职的同事说&quot;我也是新来的&quot;时会被其他同事吐槽说你已经旧了。前段时间还把公司配的电脑重装了系统，出于兼容性考虑还是装了Ubuntu，换上&lt;a href=&quot;http://cinnamon.linuxmint.com/&quot;&gt;Cinnamon&lt;/a&gt; 桌面环境，得了空闲的时候全屏跑着&lt;a href=&quot;http://www.asty.org/cmatrix/&quot;&gt;cmatrix&lt;/a&gt; (如下图所示)装逼，午餐的时候和同事谈论各种时事话题，每天的日子，按部就班，平平淡淡，就是这样。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cmatrix.gif&quot; alt=&quot;cmatrix.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
不过在相关技能上的学习还是太懈怠了，所以要加油！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;工作以外的生活&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
6月和7月在学习上比较懈怠，下了班都不想看专业性书籍，要么看看小说，要么就是搓几把炉石。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/heart-stone.jpg&quot; alt=&quot;heart-stone.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
Magi还是在构想当中，毕竟要达到设想中的水平，还有一些我没有掌握的技术需要学习。不过倒是学习了Inform 7这个制作Interactive Fiction的工具，算是预热吧。
&lt;/p&gt;

&lt;p&gt;
此外还参与到了朋友的两个小项目中，提了几次pull request。
&lt;/p&gt;

&lt;p&gt;
其他就没什么啦，周末宅着也就是打游戏或者看书，或者出去玩。出去玩的话一般都是找北京的朋友，不过有一周回到武汉参加了一次同学聚会。
&lt;/p&gt;

&lt;p&gt;
大致就是这样了
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline4&quot;&gt;阅读与写作&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
读完了以下几本书：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://book.douban.com/subject/6860890/&quot;&gt;《黑客:计算机革命的英雄》&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://book.douban.com/subject/24882304/&quot;&gt;《地海巫师》&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://book.douban.com/subject/3033223/&quot;&gt;《地海故事集》&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://book.douban.com/subject/25742768/&quot;&gt;《地海孤儿》&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
至于写作嘛……好像没写什么……
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>GDB调试技巧</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/07/27/gdb-tricks.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2014/07/27/gdb-tricks</id>
    <published>2014-07-27T00:00:00+00:00</published>
    <updated>2014-07-27T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


bt/backtrace
打印数组内容
设置源代码目录




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;bt/backtrace&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;打印数组内容&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;设置源代码目录&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
以下是这几个月工作以来所学习到的GDB调试技巧，虽然并不全面，但我认为还是比较实用的一些东西。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;bt/backtrace&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
这条命令可以在程序出错时打印出函数调用栈，方便追踪问题发生的所在。对于代码结构比较复杂的项目，这条命令是非常有用的，所以这条命令也是必须掌握的了。
&lt;/p&gt;

&lt;p&gt;
比如对于下面这个程序:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;read_int&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;FILE&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;fp&lt;/span&gt;)
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;a&lt;/span&gt; = 0;
    fscanf(fp, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%d&quot;&lt;/span&gt;, &amp;amp;a);
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; a;
}

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;FILE&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;file&lt;/span&gt; = fopen(argv[1], &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;r&quot;&lt;/span&gt;);
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;a&lt;/span&gt; = read_int(file);
    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;read %d\n&quot;&lt;/span&gt;, a);
    fclose(file);
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
该程序没有检查文件是否打开成功，便进行读文件操作，在文件打开失败的时候，将会发生段错误。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/sf-test.png&quot; alt=&quot;sf-test.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这个时候就可以用backtrace/bt 命令来发现是哪里出了问题：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gdb-backtrace.png&quot; alt=&quot;gdb-backtrace.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;打印数组内容&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
在GDB中，如果在数组的定义所在的函数内查看数组内容，直接调用print命令即可，如，对下面的代码：
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;add_one&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;arr&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;len&lt;/span&gt;)
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt; = 0;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (i = 0; i &amp;lt; len; ++i) {
        arr[i] = arr[i] + 1;
    }
}

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;a&lt;/span&gt;[] = {1, 2, 3, 4, 5, 6, 7};

    add_one(a, 7);

    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
在函数调用
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;add_one(a, 7);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
前执行&quot;p a&quot;，得到的结果如下：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gdb-print-array.png&quot; alt=&quot;gdb-print-array.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
但如果step进入函数 &lt;b&gt;add_one&lt;/b&gt; ，执行&quot;print arr&quot;，得到的却是这个结果了：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gdb-print-array2.png&quot; alt=&quot;gdb-print-array2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这是因为在函数 &lt;b&gt;add_one&lt;/b&gt; 中，数组的指针 &lt;b&gt;a&lt;/b&gt; 作为参数传入后退化为了普通指针了，这个时候如果要我们手动一个一个打印来查看，那无疑是很痛苦的。但在GDB中有查看这样的连续内存数据的方法，而且有多种，如下：
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
print *arr@7 / p *arr@7
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gdb-print-array3.png&quot; alt=&quot;gdb-print-array3.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
不管指针指向的内存中存储的是基本类型的数据还是自定义的类型，这个方法都适用。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
print (int [​7])*arr / p (int [​7])*arr
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gdb-print-array4.png&quot; alt=&quot;gdb-print-array4.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
同上，但在操作上要麻烦一点。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
x/7dw arr
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gdb-print-array5.png&quot; alt=&quot;gdb-print-array5.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;b&gt;x&lt;/b&gt; 是GDB中用来检查内存的命令，其使用方法是：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
x/nfu addr
&lt;/pre&gt;
&lt;p&gt;
其中 &lt;b&gt;n&lt;/b&gt; 表示要重复打印的次数，默认值为1;*f* 表示输出的格式，支持 x(十六进制)、d(十进制)、 u(无符号整型)、 o(八进制)、t(二进制)、a(地址值)、c(字符型)、f(浮点型)、s(字符串)这几种格式，默认使用 &lt;b&gt;x&lt;/b&gt; ;u表示每个输出的宽度，可以选择b(1字节)、h(2字节)、w(4字节)和g(8字节)，默认为4字节(w)。
&lt;/p&gt;

&lt;p&gt;
不过对于自定义的复杂类型，这个方法并不好用。
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;设置源代码目录&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
有时候存在这样的情况，程序运行的机器和源代码所在的机器不是同一台机器，假如程序崩溃了，因为没有源代码，也只能大致知道是在什么地方出错了，但却没有办法详查。当然，这种情况下，一个很笨的办法是，把整个项目代码拿过来，配置好编译环境，然后用编译好的程序替换原来的程序，再进行调试。
&lt;/p&gt;

&lt;p&gt;
但是这样实在是很麻烦。
&lt;/p&gt;

&lt;p&gt;
我们是可以这样的，首先定位问题发生的代码范围(涉及到哪些源文件)，并把这些涉及的源文件拷贝过来，然后在GDB调试时指定源代码目录就OK了。
&lt;/p&gt;

&lt;p&gt;
指定源代码目录有两种方式：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;在启动时使用 &lt;b&gt;-d&lt;/b&gt; 选项设置&lt;/li&gt;
&lt;li&gt;在启动后使用 &lt;b&gt;directory&lt;/b&gt; 命令设置&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
当然了，最后说一下，像这种跨机器的调试，最好是在运行机器上设置好能生成core文件，否则要重现问题可能要花费一番功夫。打开core dump的方法是执行：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
ulimit -c unlimited
&lt;/pre&gt;
&lt;p&gt;
当然，在shell中执行这个只是会暂时生效，如果需要在登录的时候生效，应该把这条语句写到 .bashrc 这个文件中去。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>在Gnome-Shell中关闭Hot-Corner</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/07/26/turn-off-hot-corner-in-gnome-shell.html"/>
    <category term="Linux" scheme="http://www.zmonster.me/categories.html#Linux"/>
    <id>http://www.zmonster.me/2014/07/26/turn-off-hot-corner-in-gnome-shell</id>
    <published>2014-07-26T00:00:00+00:00</published>
    <updated>2014-07-26T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


烦人的Hot Corner
系统设置：失败
Gnome Shell 扩展：失败
改代码吧混蛋




烦人的Hot Corner


在Gnome She...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;烦人的Hot Corner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;系统设置：失败&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;Gnome Shell 扩展：失败&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;改代码吧混蛋&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;烦人的Hot Corner&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
在Gnome Shell这个桌面环境中，存在一个叫做&quot;Hot Corner&quot;的特性。默认的位置是屏幕左上角，当鼠标移到那里的时候就会弹出一个界面，如下所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/hot-corner.png&quot; alt=&quot;hot-corner.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
而如图所示，我的面板是放在顶端的，左上角的位置正好是菜单的位置，所以经常发生这种事情：我将鼠标移动到左上角想打开菜单，结果却弹出来这么一个界面。
&lt;/p&gt;

&lt;p&gt;
因为位置非常接近，每次想打开菜单，我都得小心翼翼，但经常还是会点到Hot Corner上。非常烦躁。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/computer-crack.jpg&quot; alt=&quot;computer-crack.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
所以下定决心要干掉它。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;系统设置：失败&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
系统设置里压根就没设置这个东西的选项！Linux Mint的桌面环境 &lt;a href=&quot;http://cinnamon.linuxmint.com/&quot;&gt;Cinnamon&lt;/a&gt; 就是从Gnome Shell中衍生出来的，然后在其设置中就提供了对Hot Corner的设置。在Google上搜索&quot;hot corner gnome shell&quot;，出来的结果全都是抱怨这个功能不方便和寻找关闭Hot Corner的帖子。真不知道Gnome Shell的开发团队在想什么……
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;Gnome Shell 扩展：失败&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
到&lt;a href=&quot;https://extensions.gnome.org/&quot;&gt;Gnome Shell扩展网站&lt;/a&gt; 上下载了&lt;a href=&quot;https://extensions.gnome.org/extension/118/no-topleft-hot-corner/&quot;&gt;No Topleft Hot Corner&lt;/a&gt; 这个扩展，然后在gnome-tweak-tool中启用了它。
&lt;/p&gt;

&lt;p&gt;
然后还是没效果。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/holy-shit.jpg&quot; alt=&quot;holy-shit.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline4&quot;&gt;改代码吧混蛋&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
Hot Corner的实现是在 /usr/share/gnome-shell/js/ui/layout.js 中实现的，要关闭Hot Corner，只需要对下面的部分代码做出修改：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-javascript&quot;&gt;&lt;span style=&quot;color: #e6a00f;&quot;&gt;this&lt;/span&gt;._corner = &lt;span style=&quot;color: #729fcf;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;Clutter.Rectangle&lt;/span&gt;({ name: &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'hot-corner'&lt;/span&gt;,
                                       width: 1,
                                       height: 1,
                                       opacity: 0,
                                       reactive: &lt;span style=&quot;color: #e6a00f;&quot;&gt;true&lt;/span&gt; });
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
将最后的 &quot;reactive&quot; 的值修改为 &quot;false&quot; ，就OK了。
&lt;/p&gt;

&lt;p&gt;
搞定！没了烦人的东西真是开心啊……
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>生命游戏(Game of Life)及其Python实现</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/07/04/game-of-life-and-implementation-with-python.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2014/07/04/game-of-life-and-implementation-with-python</id>
    <published>2014-07-04T00:00:00+00:00</published>
    <updated>2014-07-04T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


生命游戏(The Game of Life)
Python实现
后记




生命游戏(The Game of Life)


生命游戏 是数学家John...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;生命游戏(The Game of Life)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;Python实现&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;后记&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;生命游戏(The Game of Life)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
&lt;a href=&quot;http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life&quot;&gt;生命游戏&lt;/a&gt; 是数学家&lt;a href=&quot;http://en.wikipedia.org/wiki/John_Horton_Conway&quot;&gt;John Horton Conway&lt;/a&gt; 发明的一个&quot;零玩家游戏&quot;，因此也被称为&quot;Conway's Game of Life&quot;。实际上它并非是一个游戏，其本质为一个元胞自动机(cellular automaton)。生命游戏由一个无限二维平面以及被定义在这个平面上的几条简单规则组成，一般来说，这个无限二维平面是由无限个相同大小的方形网格组成的，定义于其上的规则有：
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;每个网格称为cell&lt;/li&gt;
&lt;li&gt;每个cell有两种状态，alive和dead，分别用两种不同的颜色来表示&lt;/li&gt;
&lt;li&gt;每个cell的状态变化受其周围8个cell影响&lt;/li&gt;
&lt;li&gt;如果一个活的(alive)cell，其周围的活的cell数量少于2——即为0或1，则这个cell将死去(dead)&lt;/li&gt;
&lt;li&gt;如果一个活的cell，其周围的活的cell数量超过3——即为4至8，则这个cell将死去&lt;/li&gt;
&lt;li&gt;如果一个活的cell，其周围的活的cell数量为2或3，则它继续存活&lt;/li&gt;
&lt;li&gt;如果一个死的cell，其周围的活的cell数量为3，则它成为活的cell，否则仍然为死的cell&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
前面三条规则定义了&quot;世界&quot;的表示，后面四条规则定义了&quot;世界&quot;的变化规律。在这几条简单的规则下，生命游戏产生了难以想象的复杂、有规律的图像。
&lt;/p&gt;

&lt;p&gt;
首先来看看一些简单的、经典的模式(pattern):
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
滑翔机(Glider)
&lt;/p&gt;

&lt;img src=&quot;http://upload.wikimedia.org/wikipedia/commons/7/7e/GameOfLife_Glider_Animation.gif&quot; /&gt;

&lt;p&gt;
这个模式里的图案在不断变化时，形似一个在不断运行的滑翔机，因而得名。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
滑翔机枪(Gosper Glider Gun)
&lt;/p&gt;

&lt;img src=&quot;http://upload.wikimedia.org/wikipedia/commons/e/e5/Gospers_glider_gun.gif&quot; /&gt;

&lt;p&gt;
滑翔机枪可以源源不断地制造出滑翔机。最初John Horton Conway悬赏50美金希望有人创造出滑翔机枪，MIT的黑客&lt;a href=&quot;http://en.wikipedia.org/wiki/Bill_Gosper&quot;&gt;Bill Gosper&lt;/a&gt;尝试了上百种可能，最后率先发现了这个模式并得到了奖金，这个模式也因此冠以Gosper的名字。
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
然后来看一些复杂的模式：
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
旅行者(Weekender)
&lt;/p&gt;

&lt;img src=&quot;http://www.conwaylife.com/w/images/f/f5/Weekender_small.gif&quot; /&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
蜘蛛(Spider)
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/gol-spider.gif&quot; alt=&quot;gol-spider.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
生命游戏是Conway对&lt;a href=&quot;http://en.wikipedia.org/wiki/John_von_Neumann&quot;&gt;John von Neumann&lt;/a&gt;提出的&quot;可自我复制的机器&quot;产生兴趣后创作出来的，并于1970年10月在《科学美国人》(Scientific American)上发表。从理论上来说，生命游戏与通用图灵机(&lt;a href=&quot;http://en.wikipedia.org/wiki/Universal_Turing_machine&quot;&gt;Universal Turing Machine&lt;/a&gt;)是等价的。由于生命游戏的&quot;可进化性&quot;，在其发表后，就吸引了大批的人，时至今日，也仍然有不少人热衷于收集各种不同的模式，Unix/Linux系统上也还有生命游戏的实现，编辑器Emacs中也内置了一个生命游戏实现。
&lt;/p&gt;

&lt;p&gt;
此外，生命游戏中还展现出了&quot;涌现(&lt;a href=&quot;http://en.wikipedia.org/wiki/Emergence&quot;&gt;Emergence&lt;/a&gt;)&quot;和&quot;自组织(&lt;a href=&quot;http://en.wikipedia.org/wiki/Self-organization&quot;&gt;Self-organization&lt;/a&gt;)&quot;现象，甚至还催生出了人工生命(&lt;a href=&quot;http://en.wikipedia.org/wiki/Artificial_life&quot;&gt;Artificial Life&lt;/a&gt;)这一领域。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;Python实现&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
就生命游戏的规则而言，实现它是不需要多少工作量的，麻烦的是怎么通过图形来表现出来。最后我用Tkinter实现了一个简单的生命游戏，可以用鼠标点击的方式来设定初始模式，也可以通过下拉列表选择内置的模式，同时提供将自定义模式保存的功能。
&lt;/p&gt;

&lt;p&gt;
为了保持代码逻辑上的简洁，我将状态更新的逻辑封装到了一个类里：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;GOL&lt;/span&gt;():
    &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&quot;&quot;Status manager of GOL(Game of Life).&lt;/span&gt;

&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    Each world in game of life is a set of cells, and status of&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    every cell should be alive or dead. Status changes from gen&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    -eration to generation.&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;__init__&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;, row = 0, col = 0):
        &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&quot;&quot;Init size and status of world.&quot;&quot;&quot;&lt;/span&gt;
        &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.row = row
        &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.col = col
        &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.now = {}
        &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: #729fcf;&quot;&gt;next&lt;/span&gt; = {}
        &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.init_status([])

    &lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;init_status&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;, init_cells):
        &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&quot;&quot;Set status of world.&lt;/span&gt;

&lt;span style=&quot;color: #ad7fa8;&quot;&gt;        if the begining status given is not empty, then use them&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;        to initialize the world.&lt;/span&gt;

&lt;span style=&quot;color: #ad7fa8;&quot;&gt;        Args:&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;          init_cells: begining status given. It's a tow-dimensional&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;                      array. Becase its size maybe smaller than the&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;                      world, we should be map each coordinate to the&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;                      center area of world.&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;        &quot;&quot;&quot;&lt;/span&gt;
        &lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;code is hiden&lt;/span&gt;

    &lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;update&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;):
        &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&quot;&quot;Update status of world by status before.&lt;/span&gt;

&lt;span style=&quot;color: #ad7fa8;&quot;&gt;        For each cell in world, do these things:&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;        1. look and find how many alive neighbors around,each cell&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;        have eight neighbors&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;        2. update status of cell according the number of its alive&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;           neighbors. The following are the rules&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;           + if cell is alive, and number of neighbors is too small&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;             (less than 2) or too too much(more than 3), this cell&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;             will die, or it will be keep alive&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;          + if cell is dead, and number of neighbors is three, then&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;            cell will be alive&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;        &quot;&quot;&quot;&lt;/span&gt;
        &lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;code is hiden&lt;/span&gt;

    &lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;neighbors&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;, row, col):
        &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&quot;&quot;Compute number of alive neighbors around a cell.&quot;&quot;&quot;&lt;/span&gt;
        &lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;code is hiden&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
在这个类里，通过两个分别代表当前状态与将来状态的dict来进行状态的更新。在开始实现时犯了一个错误，就是在方法update()中，计算完self.next后，进行了一个错误的操作：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.now = &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: #729fcf;&quot;&gt;next&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
结果导致这两个类成员变量称为了同一个对象的引用，修改其中一者，另一者也发生改变，最后导致结果不正确。最后update()方法如下所示：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;update&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;):
  &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&quot;&quot;Update status of world by status before.&lt;/span&gt;

&lt;span style=&quot;color: #ad7fa8;&quot;&gt;  For each cell in world, do these things:&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;  1. look and find how many alive neighbors around,each cell&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;     have eight neighbors&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;  2. update status of cell according the number of its alive&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;     neighbors. The following are the rules&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;     + if cell is alive, and number of neighbors is too small&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;       (less than 2) or too too much(more than 3), this cell&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;       will die, or it will be keep alive&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;     + if cell is dead, and number of neighbors is three, then&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;       cell will be alive&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;  &quot;&quot;&quot;&lt;/span&gt;
  &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: #729fcf;&quot;&gt;next&lt;/span&gt; = &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.now.copy()
  &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; crow &lt;span style=&quot;color: #729fcf;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.row):
      &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; ccol &lt;span style=&quot;color: #729fcf;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.col):
          &lt;span style=&quot;color: #eeeeec;&quot;&gt;around&lt;/span&gt; = &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.neighbors(crow, ccol)
          &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (around &amp;lt; 2 &lt;span style=&quot;color: #729fcf;&quot;&gt;or&lt;/span&gt; around &amp;gt; 3):
              &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: #729fcf;&quot;&gt;next&lt;/span&gt;[crow, ccol] = &lt;span style=&quot;color: #e6a00f;&quot;&gt;False&lt;/span&gt;

          &lt;span style=&quot;color: #729fcf;&quot;&gt;elif&lt;/span&gt; ((&lt;span style=&quot;color: #729fcf;&quot;&gt;not&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.now[crow, ccol]) &lt;span style=&quot;color: #729fcf;&quot;&gt;and&lt;/span&gt;
                around == 3):
              &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: #729fcf;&quot;&gt;next&lt;/span&gt;[crow, ccol] = &lt;span style=&quot;color: #e6a00f;&quot;&gt;True&lt;/span&gt;

  &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.now = &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: #729fcf;&quot;&gt;next&lt;/span&gt;.copy()
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
图形前端的实现大致如下：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;ShowGOL&lt;/span&gt;(tk.Tk):
    &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&quot;&quot;Diasplay the Game of Life&lt;/span&gt;

&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    Use Tkinter to draw the world of cells and the changes in&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    the world.&lt;/span&gt;
&lt;span style=&quot;color: #ad7fa8;&quot;&gt;    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;__init__&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;, *args, **kwargs):
        &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&quot;&quot;Init resource and world&quot;&quot;&quot;&lt;/span&gt;
        &lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;init resource&lt;/span&gt;
        tk.Tk.__init__(&lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;, *args, **kwargs)
        &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.setup_members()    &lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;initialize class members&lt;/span&gt;
        &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.setup_window()     &lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;root window&lt;/span&gt;
        &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.setup_toolbar()    &lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;tool bar&lt;/span&gt;
        &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.setup_canvas()     &lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;canvas to draw world&lt;/span&gt;

        &lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;init world&lt;/span&gt;
        &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.create_world()

        &lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;make world alive&lt;/span&gt;
        &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.after(5, &lt;span style=&quot;color: #729fcf;&quot;&gt;lambda&lt;/span&gt;: &lt;span style=&quot;color: #729fcf;&quot;&gt;self&lt;/span&gt;.life(5))
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
另外一些类方法就不列出来了，无非是绘图啊、事件响应啊什么的。代码我放到了Github上，如果需要，可以到&lt;a href=&quot;https://github.com/linusp/pygol/&quot;&gt;这里&lt;/a&gt; 查看，或在本地执行：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;git clone git@github.com:Linusp/pygol
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;后记&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
老实说，我也算是生命游戏的忠实粉丝了——嗯，我不太喜欢&quot;粉丝&quot;这个词，不过姑且就这么用吧。以前也用ncurses库实现过一个简单的终端版本，也实现过兰顿蚂蚁(&lt;a href=&quot;http://en.wikipedia.org/wiki/Langton's_ant&quot;&gt;Langton's Ant&lt;/a&gt;)这个同为元胞自动机的例子。当然，要说我的实现，都是很简陋的，比如说生命游戏，在网上有非常多的相关实现，Linux下有一个名为gtklife的软件，内置了很多的模式，其中不乏一些复杂、绚丽的模式，这款软件也是被我列为Linux上必装的软件之一。
&lt;/p&gt;

&lt;p&gt;
现在虽然实现了图形化的生命游戏，但我不想止步于此。目前用的是Python的Tkinter库，这个库上手简单，但功能有限。所以我会继续完善这个生命游戏实现的！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>使用Inform7创作交互式小说</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/06/28/interactive-fiction-writing-with-inform7.html"/>
    <category term="IF" scheme="http://www.zmonster.me/categories.html#IF"/>
    <id>http://www.zmonster.me/2014/06/28/interactive-fiction-writing-with-inform7</id>
    <published>2014-06-28T00:00:00+00:00</published>
    <updated>2014-06-28T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


什么是交互式小说(Interactive Fiction, IF)
Inform

下载 &amp;amp; 安装
项目创建
开始创作
编译 &amp;amp; 运行

...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgd170f55&quot;&gt;什么是交互式小说(Interactive Fiction, IF)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org5bc0012&quot;&gt;Inform&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org568e58d&quot;&gt;下载 &amp;amp; 安装&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org061a9e0&quot;&gt;项目创建&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org2535503&quot;&gt;开始创作&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb9659a0&quot;&gt;编译 &amp;amp; 运行&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgea08498&quot;&gt;后记&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgd170f55&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgd170f55&quot;&gt;什么是交互式小说(Interactive Fiction, IF)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgd170f55&quot;&gt;
&lt;p&gt;
维基百科上对 &lt;b&gt;IF&lt;/b&gt; 的简介是：
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
Interactive fiction, often abbreviated IF, is software simulating environments in which players use text commands to control characters and influence the environment. Works in this form can be understood as literary narratives and as video games.In common usage, the term refers to text adventures, a type of adventure game where the entire interface can be &quot;text-only&quot;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
我就不翻译了。对于 &lt;b&gt;IF&lt;/b&gt; ，也有人称之为“交互式小说游戏”，日本的一些GAL Game，也被认为是这一类别的游戏。还有上世纪，在《传奇》等图形化网络游戏在国内兴起前的MUD也是这一类的作品——当然，MUD并非起源于中国，MUD最初是1978年出现在英国的一个文本界面联机游戏英文名称Multi-User Dungeon缩写，其后出现的类似系统沿用相同的缩写名，但赋予不同的全名，如&quot;Multi-User Dialogue&quot;。
&lt;/p&gt;

&lt;p&gt;
对于现在的大部分游戏玩家而言，MUD可能是从未听过的名词，当年大受欢迎的《北大侠客行》，大概也只有经历过那个年代的人，以及我这样对IF感兴趣的人有所了解了。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;IF&lt;/b&gt; 的历史我就不多说了，毕竟我也不太清楚。
&lt;/p&gt;

&lt;p&gt;
除了MUD和GAL，现在的Unix/Linux系统上也还有一些 &lt;b&gt;IF&lt;/b&gt; 存在，比如 &lt;b&gt;adventure&lt;/b&gt; ，这款游戏在任何一个Linux发行版上应该都可以获取到，这个游戏在《Hackers: Heroes of the Computer Revolution》一书中也被提到。
&lt;/p&gt;

&lt;p&gt;
在 &lt;b&gt;IF&lt;/b&gt; 中，通常可以用 &lt;b&gt;go&lt;/b&gt; 指令来移动，用 &lt;b&gt;take&lt;/b&gt; 或 &lt;b&gt;get&lt;/b&gt; 来获取物品，用 &lt;b&gt;look&lt;/b&gt; 来查看周围环境。 &lt;b&gt;IF&lt;/b&gt; 的魅力在于，世界的面貌除了靠作者的描写，还需要玩家用自己的记忆和联想使其丰富，它玩起来更不方便，但更有代入感。以下是我玩 &lt;b&gt;adventure&lt;/b&gt; 时的的一个记录：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/adventure.gif&quot; alt=&quot;adventure.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5bc0012&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org5bc0012&quot;&gt;Inform&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org5bc0012&quot;&gt;
&lt;p&gt;
&lt;a href=&quot;http://inform7.com/&quot;&gt;Inform&lt;/a&gt; 又是什么呢？
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
Inform is a design system for interactive fiction based on natural language. It is a radical reinvention of the way interactive fiction is designed, guided by contemporary work in semantics and by the practical experience of some of the world's best-known writers of IF.
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
没错，Inform是一个用于创作 &lt;b&gt;IF&lt;/b&gt; 的系统，它的一个优点是可以自然语言、在一定的规则约束下，进行 &lt;b&gt;IF&lt;/b&gt; 的创作。今天我初步体验了一下，感觉很不错，可惜只支持英文，等以后有空去研究一下它的实现吧。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org568e58d&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org568e58d&quot;&gt;下载 &amp;amp; 安装&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org568e58d&quot;&gt;
&lt;p&gt;
以Linux下的操作为例，就我个人体验而言，其安装比较简单，没有什么复杂的依赖，所以其他系统上的安装应该也差不多。
&lt;/p&gt;

&lt;p&gt;
首先到Inform的&lt;a href=&quot;http://inform7.com/&quot;&gt;官网&lt;/a&gt; 上下载，选择对应发行版的软件包安装即可。要注意的是，I7_6L02_Linux_all.tar.gz 这个软件包是命令行下的，如果需要图形界面，应该安装其后的以'gnome'开头的软件包。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org061a9e0&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org061a9e0&quot;&gt;项目创建&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org061a9e0&quot;&gt;
&lt;p&gt;
在菜单中点击后，会出现以下界面询问是创建新的项目还是打开已有的项目：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/inform-startup.png&quot; alt=&quot;inform-startup.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
选 'Start a new project' 开始一个新的项目，然后会出现以下提示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/inform-project-type.png&quot; alt=&quot;inform-project-type.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
选择 'new story'，然后选择项目目录，以及设定故事名称和作者名:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/inform-project-set.png&quot; alt=&quot;inform-project-set.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/inform-project-set2.png&quot; alt=&quot;inform-project-set2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org2535503&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org2535503&quot;&gt;开始创作&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org2535503&quot;&gt;
&lt;p&gt;
完成上述操作后，项目已经建立，接下来就是进行正式的创作了，以下是主界面的样式：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/inform-project-main.png&quot; alt=&quot;inform-project-main.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
左侧是创作区域，所谓的“创作”，就是在这里进行写作了；右侧是文档区，可以在里面查阅 &lt;b&gt;IF&lt;/b&gt; 创作的一些规则。
&lt;/p&gt;

&lt;p&gt;
首先呢，故事要有一个发生的地方，姑且是一个房间好了，开始的时候不妨格局小一点。然后在房间里放一个箱子，里面放一把大宝剑吧！于是，我写下这个：
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
Magi is a room.

The box is in the Magi. The box is a container. The box contains a sword.
&lt;/pre&gt;

&lt;p&gt;
然后，有了地点，还要有主角是吧：
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
player is in the Magi.
&lt;/pre&gt;

&lt;p&gt;
给主角戴个高帽子：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
player wears a top hat.
&lt;/pre&gt;

&lt;p&gt;
有了场景和主角，那么肯定要有情节了，先来个简单的吧，设想一下，既然房间里有大宝剑，在设定上，这肯定是送给主角的装备，所以主角会去拿嘛，既然主角会去拿，那么设定一下，在主角获取大宝剑的时候，发生一些事情：
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
Before taking the sword:
     if the player is wearing the hat:
    	 now the hat is in the box;
    	 say &quot;As you stoop down, your hat falls into the box.&quot;

After taking the sword:
 say &quot;The sword was ever owned by a hero in history.&quot;
&lt;/pre&gt;

&lt;p&gt;
好了，基本完成了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb9659a0&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgb9659a0&quot;&gt;编译 &amp;amp; 运行&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgb9659a0&quot;&gt;
&lt;p&gt;
创作完成后，点击界面上的运行按钮进行编译:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/inform-compile.gif&quot; alt=&quot;inform-compile.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
如果没有报错，那就可以运行了：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/inform-run.gif&quot; alt=&quot;inform-run.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
看见没？Wow!
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgea08498&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgea08498&quot;&gt;后记&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgea08498&quot;&gt;
&lt;p&gt;
我对 &lt;b&gt;IF&lt;/b&gt; 的兴趣，是从阅读了《Hackers: Heroes of the Computer Revolution》后产生的。虽然在此之前，对MUD以及GAL都有一定了解，但实在没太大兴趣。实际上，在阅读了《Hackers》后，也就是稍微玩了一下 adventure ，并没有产生&quot;啊，我也想做一个这样的游戏&quot;后的想法，直到后来自己构想的小说世界逐渐完善、丰富，渐渐的又有些奇怪的想法，于是开始想能不能将这些奇奇怪怪的想法通过 &lt;b&gt;IF&lt;/b&gt; 展现出来。
&lt;/p&gt;

&lt;p&gt;
Inform是个很棒的工具，不过对我来说，它并不能实现我需要的全部功能，有些功能，终究要我自己去实现。不过没关系，通过Inform，我可以先熟悉 &lt;b&gt;IF&lt;/b&gt; 的创作方式。
&lt;/p&gt;

&lt;p&gt;
另外，关于Inform的使用，其实有很多的内容，幸运的是，它也有丰富的文档。我会继续学习，并且将自己的心得分享出来。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>ucc源代码阅读(1):主体框架</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/06/09/source-reading-ucc-1.html"/>
    <category term="代码阅读" scheme="http://www.zmonster.me/categories.html#代码阅读"/>
    <id>http://www.zmonster.me/2014/06/09/source-reading-ucc-1</id>
    <published>2014-06-09T00:00:00+00:00</published>
    <updated>2014-06-09T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


ucc简介
主体框架

第一部分：参数检查：
第二部分：环境准备
第三部分：参数解析
第四部分：动作执行






ucc简介


ucc 是早些年一位...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;ucc简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;主体框架&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;第一部分：参数检查：&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;第二部分：环境准备&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;第三部分：参数解析&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline6&quot;&gt;第四部分：动作执行&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;ucc简介&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
&lt;a href=&quot;http://ucc.sourceforge.net/&quot;&gt;ucc&lt;/a&gt; 是早些年一位清华大学的学生编写的x86平台上的C语言编译器，遵从ANSI C89标准，能在Linux/Windows系统上正确编译自身并成功运行。它有以下特点：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;代码结构清晰，有详细的文档讲述它的实现(中英文皆有)&lt;/li&gt;
&lt;li&gt;使用三地址码作为中间码，构建了由基本块组成的控制流图，适合很多优化算法&lt;/li&gt;
&lt;li&gt;轻量级，编译速度快，词法分析器、语法分析器和目标代码生成器都是自行实现的&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
在学校学习编译原理课程的时候，在实现C语言词法分析器的时候借鉴过ucc的代码结构，当时ucc的简洁代码结构给我留下了非常深刻的映像，那是我第一次从别人的代码里体会到一种&quot;美感&quot;，所以一直都有打算细读一遍其实现，可惜也是一直未曾付诸实践。现在决定每天花点时间，一点一点完成这个目标吧。
&lt;/p&gt;

&lt;p&gt;
嗯，顺便把编译原理的东西复习一遍。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;主体框架&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
ucc.c是编译器的入口模块，其中的main函数如下所示：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt;;

    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (argc &amp;lt;= 1)
    {
        ShowHelp();
        exit(0);
    }

    Option.oftype = EXE_FILE;
    SetupToolChain();
    Command = Alloc((argc + 60) * &lt;span style=&quot;color: #729fcf;&quot;&gt;sizeof&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *));
    Command[0] = &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;;

    i = ParseCmdLine(--argc, ++argv);
    &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (; i &amp;lt; argc; ++i)
    {
        &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (argv[i][0] == &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'-'&lt;/span&gt;)
        {
            Option.linput = ListAppend(Option.linput, argv[i]);
        }
        &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt;
        {
            AddFile(argv[i]);
        }
    }

    &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (i = PP_FILE; i &amp;lt;= Option.oftype; ++i)
    {
        &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (InvokeProgram(i) != 0)
        {
            RemoveFiles();
            fprintf(stderr, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;ucc invoke command error:&quot;&lt;/span&gt;);
            PrintCommand();
            &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; -1;
        }
    }

    RemoveFiles();
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
可以很明显地发现，整个main函数可以细分为以下几部分：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;参数检查&lt;/li&gt;
&lt;li&gt;环境准备&lt;/li&gt;
&lt;li&gt;参数解析&lt;/li&gt;
&lt;li&gt;动作执行&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline3&quot;&gt;第一部分：参数检查：&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (argc &amp;lt;= 1)
{
    ShowHelp();
    exit(0);
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
这里只是通过参数个数来进行判断，如果运行时未带参数，则打印帮助信息。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline4&quot;&gt;第二部分：环境准备&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;Option.oftype = EXE_FILE;
SetupToolChain();
Command = Alloc((argc + 60) * &lt;span style=&quot;color: #729fcf;&quot;&gt;sizeof&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *));
Command[0] = &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
这里的 &lt;b&gt;Option&lt;/b&gt; 是一个全局变量，实际是一个结构对象，用来存放ucc编译C语言源代码过程中需要的一些选项，其中一部分是根据外部参数得到的。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;SetupToolChain()&lt;/b&gt; 用来设置工具链，ucc.c实际上并不是编译器的实际实现，而是一个和操作系统、ucc编译器进行适配的驱动器。ucc并没有实现预处理器、汇编器和链接器，仅实现了词法分析器、语法分析器和目标代码生成器，因此需要操作系统上的工具来做它所未做的事情。在Linux下，这个函数是空的，因为通常Linux系统都有完整的工具链，不需要再额外设置；在Windows下，这个函数会将VS的相关工具作为工具链。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Command&lt;/b&gt; 也是一个全局变量，从其名字可以很容易地猜想到它是用来存放要执行的命令的，事实上它也确实是。上面也说到了，在这个主模块中实际上是需要调用其他外部命令的，如系统的预处理器、汇编器和链接器，以及ucc自身的编译器实现ucl。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline5&quot;&gt;第三部分：参数解析&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;i = ParseCmdLine(--argc, ++argv);
&lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (; i &amp;lt; argc; ++i)
{
    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (argv[i][0] == &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'-'&lt;/span&gt;)
    {
        Option.linput = ListAppend(Option.linput, argv[i]);
    }
    &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt;
    {
        AddFile(argv[i]);
    }
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
参数解析时，这里并没有通过 &lt;b&gt;getopt&lt;/b&gt; 等函数来进行处理，而是逐个处理参数，将其分为选项或者文件名——看上面的代码，一目了然。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline6&quot;&gt;第四部分：动作执行&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline6&quot;&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (i = PP_FILE; i &amp;lt;= Option.oftype; ++i)
{
    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (InvokeProgram(i) != 0)
    {
        RemoveFiles();
        fprintf(stderr, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;ucc invoke command error:&quot;&lt;/span&gt;);
        PrintCommand();
        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; -1;
    }
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
这个部分的代码我觉得很有意思——主要是用循环来逐步执行编译的各阶段动作，换做是我的话，我可能会写如下的代码结构：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;ret&lt;/span&gt; = 0;
&lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;do some thing &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
ret = Preproc();
&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (ret &amp;lt; 0) {                  &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;error &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; ret;
}

ret = Lexana();
&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (ret &amp;lt; 0) {                  &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;error &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; ret;
};

&lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;... &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
当然，我这里给出的反面示例由于内容较少的缘故，可以很容易地发现可以用循环来简化代码，这正是ucc里做的。在这个循环里，通过循环变量i来控制这个进程，它的初值是 &lt;b&gt;PP_FILE&lt;/b&gt; ，这是一个枚举常量，其定义为：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;enum&lt;/span&gt; { &lt;span style=&quot;color: #eeeeec;&quot;&gt;C_FILE&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;PP_FILE&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;ASM_FILE&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;OBJ_FILE&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;LIB_FILE&lt;/span&gt;, &lt;span style=&quot;color: #eeeeec;&quot;&gt;EXE_FILE&lt;/span&gt; };
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
这些枚举常量的值，从大到小，正好对应了C语言源程序的完整编译过程中各个阶段的生成结果文件类型，因此通过这个循环就能完成整个流程了，而且进行到哪个阶段也可以简单地通过全局变量 &lt;b&gt;Option&lt;/b&gt; 的成员 &lt;b&gt;oftype&lt;/b&gt; 来进行控制——这个全局变量的成员的值可以通过执行ucc时的参数来控制。
&lt;/p&gt;

&lt;p&gt;
嗯，今天就到这里啦。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>(2014年5月)月底小结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/05/31/may-of-2014.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2014/05/31/may-of-2014</id>
    <published>2014-05-31T00:00:00+00:00</published>
    <updated>2014-05-31T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


工作
生活
阅读




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;工作&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;生活&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;阅读&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;工作&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
总的来说，我这个月的工作主要还是以下两个内容：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;实现说话人分割的API&lt;/li&gt;
&lt;li&gt;将说话人分割的API接入ASR系统&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
第一部分其实是挺简单的事情，因为流程在说话人分割的项目中都有，而我编写API，不过是进行整理并提供接口而已。但麻烦的是，原先使用了GMM-MAP框架，导致分割速度慢，而且正确率也不高。然后后来调整了几次方案，在进行说话人分割前先进行通过性别进行分割，而使用的男女识别的库也更换了两次。加上后来在API实现中加上了多线程，也是花费了不少时间。
&lt;/p&gt;

&lt;p&gt;
第二部分，原先的系统是通过调用java包来进行说话人分割，本来只需要替换成调用C++实现的API的，不过后来更改了流程，加上我对这个系统的代码和流程都不熟悉，在更改的时候出现了很多问题，不过也都一一解决了。在这个过程中，我没少麻烦我们项目组组长，每天我都一堆问题去问他，后来也渐渐觉得这样不太好——虽然说我对ASR系统的代码和流程确实不熟悉，但有些能通过自己思考和阅读(代码)解决的问题，还是应该尽量自己解决，毕竟他也有他的工作。在这点上我很感谢他，他非常和善，对我的问题一个一个很有耐心地进行解答，或许换个人可能就不会这样对我了吧。
&lt;/p&gt;

&lt;p&gt;
至于同事，自从调换了座位后，也对各个同事有了更多的了解。23号去了石门山一起游玩，也是拉近了彼此之间的距离。总的来说，我已经融入了这个群体，适应了工作的节奏。
&lt;/p&gt;

&lt;p&gt;
当然，在个人表现上，我对自己还有很多不满的地方，比如之前说到的提问题太多，还有就是我在这个领域的基础比较薄弱，在平常工作交流中，我能够理解其他同事说的内容，但却没法有自己的想法和认识。接下来的日子里，我会加紧学习，以做得更好。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;生活&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
还在试用期，不过工资能养活自己，而且足以支撑我每周去咖啡厅坐一下午。不过我还是比较宅，除了和首长一起去咖啡厅或别处，很少自己主动去别的地方，一来钱也不多想省着点，二来也焦虑自己的能力不足急切想提高自己，但实际由于没有合理规划，宅在住处时并不能有效率地进行学习。
&lt;/p&gt;

&lt;p&gt;
基本上每周都有和朋友一起聚餐，虽然我仍然不太会说话，但能够互相看到、近距离交谈，对我来说已经足够了，愿意去交谈，总比不交谈好。每周五下班的时候，走在上地十街上，我会从手机上的联系人里挑一个，然后打个电话过去聊聊天(唔，昨天没有)，一来始终有孤独感，希望和人交谈——虽然我并不厌烦也不畏惧这种感觉，二来也想尽量和还有联系的朋友将联系保持下去。
&lt;/p&gt;

&lt;p&gt;
总得来说，我过得不错，有事可做，心情放松、作息健康，除了缺乏锻炼。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;阅读&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
这个月读完了三本实体书，分别是：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;小王子&lt;/li&gt;
&lt;li&gt;海底两万里&lt;/li&gt;
&lt;li&gt;苏菲的世界&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
都是小书摊上掏的书，旧，但是我不介意。
&lt;/p&gt;

&lt;p&gt;
《小王子》是一晚上就看完了，作为一个童话故事确实是非常不错的，里面的一些词句也很有意思，但于我也就仅此而已了。
&lt;/p&gt;

&lt;p&gt;
《海底两万里》是凡尔纳的科幻小说，但对现在的科学水平而言，书中描述的场景已经不是&quot;幻想&quot;了，而是可以实现的东西。不过这不是重点。对于书中描述的种类繁多的海洋生物，我全然无知，但还是耐心一个一个看过去，在脑海里想象这些生物的身姿，同时也在想，为了写这么一本小说，凡尔纳当初是查阅了多少资料呢？或者凡尔纳自身就是书中主人公那样的&quot;博物学家&quot;，还是说他在不断的写作、收集资料的过程中成为了这样的&quot;博物学家&quot;？这些我不知道，但我感受到了一本有价值的书完成所经历的艰辛。此外，这书让我对海洋产生了极大的兴趣！
&lt;/p&gt;

&lt;p&gt;
《苏菲的世界》，嗯，是本很奇特的书，非常奇特。现在姑且是囫囵看过一遍，我还会回去看第二遍甚至更多遍，这一点我非常确定。它是一本哲学史简介，但也是情节构筑精巧奇妙的非常有趣味的小说，值得学习。
&lt;/p&gt;

&lt;p&gt;
此外我还在手机上看完了《地海》系列小说，是非常不错的奇幻小说系列。顺便一说，《地海》系列是与《魔戒》系列和《纳尼亚年代记》齐名的奇幻小说系列。这小说的文采非常好，虽然我读时是在手机上，也为之迷醉。同时其剧情即叙述风格也影响到了我构思中小说的设定和内容。
&lt;/p&gt;

&lt;p&gt;
目前在读的有果戈里的《死魂灵》以及李航的《统计学习方法》。
&lt;/p&gt;

&lt;p&gt;
我现在每天上班背个包，包里放着一本小说（以后可能会放不是小说的书籍），下班的时候就在途中进行阅读。至于IT类书籍，因为我现在阅读的这类书籍多涉及数学公式及其推导，对我来说是不适合在地铁里进行阅读的，因此都是在公司闲暇时或下班在住处进行阅读。
&lt;/p&gt;

&lt;p&gt;
继续努力，达成今年二十本阅读量的目标。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>参数类型不一致导致extern &quot;C&quot;不起作用</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/05/31/extern-c-do-not-work.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2014/05/31/extern-c-do-not-work</id>
    <published>2014-05-31T00:00:00+00:00</published>
    <updated>2014-05-31T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


extern &quot;C&quot;: 指示编译器以C形式进行链接
nm: 查看目标文件中的符号是C形式还是C++形式
&quot;undefined reference&quot;: 诡异...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;extern &quot;C&quot;: 指示编译器以C形式进行链接&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;nm: 查看目标文件中的符号是C形式还是C++形式&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;&quot;undefined reference&quot;: 诡异的错误&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;extern &quot;C&quot;: 指示编译器以C形式进行链接&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
某些时候，我们需要将一些C++的库封装成C风格的接口供外部使用，所谓“C风格”的接口，是指该接口的参数、返回值中不包含类、作用域等C++的元素，但其实现中是可以有的。比如说，我们有一个类 &lt;b&gt;Wav&lt;/b&gt; ，用来处理wave文件
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#if&lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; _WAV_H_
&lt;span style=&quot;color: #729fcf;&quot;&gt;#define&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;_WAV_H_&lt;/span&gt;

&lt;span style=&quot;color: #729fcf;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;Wav&lt;/span&gt;
{
&lt;span style=&quot;color: #729fcf;&quot;&gt;public&lt;/span&gt;:
    &lt;span style=&quot;color: #edd400;&quot;&gt;Wav&lt;/span&gt;();
    &lt;span style=&quot;color: #edd400;&quot;&gt;Wav&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;string&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;wav_file&lt;/span&gt;);
    &lt;span style=&quot;color: #729fcf;&quot;&gt;virtual&lt;/span&gt; ~&lt;span style=&quot;color: #edd400;&quot;&gt;Wav&lt;/span&gt;();
    &lt;span style=&quot;color: #8ae234;&quot;&gt;bool&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;load_wav&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;string&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;wav_file&lt;/span&gt;);
    &lt;span style=&quot;color: #729fcf;&quot;&gt;private&lt;/span&gt;:
    &lt;span style=&quot;color: #8ae234;&quot;&gt;short&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;data&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;sampel_rate&lt;/span&gt;;
};

&lt;span style=&quot;color: #729fcf;&quot;&gt;#endif&lt;/span&gt; &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;_WAV_H_ */&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后我们需要利用这个类实现几个音频处理接口，提供给 &lt;b&gt;C程序&lt;/b&gt; 使用，由于C语言中是没有“类”这个特性的，我们不能直接用C语言去实现这些接口，这个时候就要用到extern &quot;C&quot;了.
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#if&lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; _WAVPROC_H_
&lt;span style=&quot;color: #729fcf;&quot;&gt;#define&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;_WAVPROC_H_&lt;/span&gt;

&lt;span style=&quot;color: #729fcf;&quot;&gt;#ifdef&lt;/span&gt; __cplusplus
&lt;span style=&quot;color: #729fcf;&quot;&gt;extern&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;C&quot;&lt;/span&gt;{
&lt;span style=&quot;color: #729fcf;&quot;&gt;#endif&lt;/span&gt;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;read_wav&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;wav_file&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;double&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;data&lt;/span&gt;);
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;denoise&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;double&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;data&lt;/span&gt;);
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;cutscene&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;double&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;data&lt;/span&gt;);
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;feature_extract&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;double&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;data&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;double&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;feature&lt;/span&gt;);
&lt;span style=&quot;color: #729fcf;&quot;&gt;#ifdef&lt;/span&gt; __cplusplus
}
&lt;span style=&quot;color: #729fcf;&quot;&gt;#endif&lt;/span&gt;

&lt;span style=&quot;color: #729fcf;&quot;&gt;#endif&lt;/span&gt; &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;_WAVPROC_H_ &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后在&quot;wavproc.cpp&quot;中实现这些接口，此时在&quot;wavproc.cpp&quot;中是可以使用上面定义的类以及其他C++语言的特性的。实现以后以静态库/动态库的形式提供接口，对于使用接口的C程序来说，只需要
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;wavproc.h&lt;/li&gt;
&lt;li&gt;对应的静态库/动态库，如: libwavproc.a&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;nm: 查看目标文件中的符号是C形式还是C++形式&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
nm是一个查看目标文件中符号列表的工具，其具体使用这里不会详谈，只讲一下用nm来判断使用extern &quot;C&quot;是否起作用。举个栗子，对下面这个函数：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;fs.h&quot;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;file_size&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;file&lt;/span&gt;)
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;fs&lt;/span&gt; = 0;
    &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;do something&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; fs;
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
以上内容在&quot;fs.cpp&quot;中，其对应的头文件为：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#if&lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; _FS_H_
&lt;span style=&quot;color: #729fcf;&quot;&gt;#define&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;_FS_H_&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;file_size&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;file&lt;/span&gt;);

&lt;span style=&quot;color: #729fcf;&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
用g++将&quot;fs.cpp&quot;编译成目标文件后，用nm查看其中的符号信息：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;nm ~/test/cppcode/fs.o
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
得到的输出是：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
0000000000000000 T _Z9file_sizePKc
&lt;/pre&gt;

&lt;p&gt;
我们在&quot;fs.c&quot;中实现同样一个函数
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;fs.h&quot;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;file_size&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;file&lt;/span&gt;)
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;fs&lt;/span&gt; = 0;
    &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;do something &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; fs;
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
其对应的头文件与&quot;fs.cpp&quot;的头文件一样。然后用gcc将&quot;fs.c&quot;编译为目标文件后，同样用nm查看符号信息:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;nm ~/test/ccode/fs.o
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
得到结果为：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
0000000000000000 T file_size
&lt;/pre&gt;

&lt;p&gt;
可以看到，同样一个函数，在C++程序和C程序中，被编译后产生的符号类型是不一样的。C++为了支持重载，在编译的时候会对函数符号添加前缀和后缀，后缀是参数列表的缩写，用来区分重载；而C编译器则不会对函数符号添加其他信息。
&lt;/p&gt;

&lt;p&gt;
当我们需要将某些用C++实现的接口提供给C程序使用时，要在其头文件(接口定义)中用extern &quot;C&quot;来告诉编译器，按C的形式导出符号表——这个是之前提到过的，现在我们对&quot;fs.cpp&quot;的头文件&quot;fs.h&quot;进行这样的处理:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#if&lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; _FS_H_
&lt;span style=&quot;color: #729fcf;&quot;&gt;#define&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;_FS_H_&lt;/span&gt;

&lt;span style=&quot;color: #729fcf;&quot;&gt;#ifdef&lt;/span&gt; __cpulsplus
&lt;span style=&quot;color: #729fcf;&quot;&gt;extern&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;C&quot;&lt;/span&gt;{
&lt;span style=&quot;color: #729fcf;&quot;&gt;#endif&lt;/span&gt;

    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;file_size&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;file&lt;/span&gt;);

&lt;span style=&quot;color: #729fcf;&quot;&gt;#ifdef&lt;/span&gt; __cplusplus
}
&lt;span style=&quot;color: #729fcf;&quot;&gt;#endif&lt;/span&gt;

&lt;span style=&quot;color: #729fcf;&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
然后用g++将&quot;fs.cpp&quot;编译为目标文件，并使用nm查看符号信息：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;nm ~/test/cppcode/fs.o
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
得到的结果为：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
0000000000000000 T file_size
&lt;/pre&gt;
&lt;p&gt;
可以看到，这次得到的符号类型是C形式的符号了，是可以被C程序所使用的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;&quot;undefined reference&quot;: 诡异的错误&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
好了，终于到了标题提到的内容了。
&lt;/p&gt;

&lt;p&gt;
事情是这样的，我负责的一个项目A是C++实现的，然后需要将其中的一些功能以接口的形式提供给另外一个项目B使用——项目B是C实现的。那么，理所当然的，我为项目A编写API时，要用extern &quot;C&quot;去处理头文件。在实现好接口后，我以静态库的方式将接口提供给了项目B，然而在编译项目B时，总是报错：
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
undeined reference: xxxx
&lt;/pre&gt;

&lt;p&gt;
意即有一个函数是未定义的引用，而该函数是项目A的API中提供的接口函数中的一个。我折腾了近一天时间，始终无法找到这个问题的原因所在——这个时候我还不知道使用nm来进行检查的方法。无奈之下向老大请教，老大遂用nm查了一下提供的静态库，发现导出的符号还是C++形式的，但诡异的是，同一个头文件中提供的若干个函数，只有这一个的符号还是C++形式的，而其他的都被导出成C形式的符号了。
&lt;/p&gt;

&lt;p&gt;
老大也很迷惑，不过他说：先别怀疑编译器，应该还是有什么细节上处理不当。
&lt;/p&gt;

&lt;p&gt;
果然，后来经过几番检查，发现是由于头文件中函数的参数类型和实现中函数的参数类型不一致导致了这个问题，在头文件中，该函数为：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;InitDiarizationSpace&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;Dia&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;env&lt;/span&gt;, &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;file&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
而在实现中，该函数为：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;InitDiarizationSpace&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;Dia&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;env&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;file&lt;/span&gt;) {
    &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;...&lt;/span&gt;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
&amp;#x2026;&amp;#x2026;
&lt;/p&gt;

&lt;p&gt;
对此我表示很羞愧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>将局部变量地址作为线程函数参数导致bug</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/05/20/bug-because-of-pass-local-variable-to-thread.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2014/05/20/bug-because-of-pass-local-variable-to-thread</id>
    <published>2014-05-20T00:00:00+00:00</published>
    <updated>2014-05-20T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


问题
加锁
取消编译器优化
局部变量，循环变量




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;问题&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;加锁&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;取消编译器优化&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;局部变量，循环变量&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;问题&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
在测试自己写的一个使用了多线程的API时，我发现有时候会出现一些预期之外的结果。
&lt;/p&gt;

&lt;p&gt;
首先，这个API的实现中涉及多线程的部分大致是这样的：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
有一个全局初始化函数，循环创建多个线程，并将每个线程和一个线程号绑定(在pthread_create中作为第四个参数传入)
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;Init&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;thread_num&lt;/span&gt;) {
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;ret&lt;/span&gt; = 0;

    &lt;span style=&quot;color: #8ae234;&quot;&gt;pthread_t&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;thread_list&lt;/span&gt; = (&lt;span style=&quot;color: #8ae234;&quot;&gt;pthread_t&lt;/span&gt; *)calloc(thread_num, &lt;span style=&quot;color: #729fcf;&quot;&gt;sizeof&lt;/span&gt;(pthread_t));

    &lt;span style=&quot;color: #8ae234;&quot;&gt;pthread_attr_t&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;a&lt;/span&gt;;
    pthread_attr_init(&amp;amp;a);
    pthread_attr_setdetachstate(&amp;amp;a, PTHREAD_CREATE_DETACHED);

    &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt; = 0; i &amp;lt; thread_num; ++i) {
        ret = pthread_create(thread_list + i, &amp;amp;a, thread_func, (&lt;span style=&quot;color: #8ae234;&quot;&gt;void&lt;/span&gt; *)&amp;amp;i);

        &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt;(ret != 0) {
            &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; ret;
        }
    }

    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; ret;
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
不同的线程根据绑定的线程号不断查看一个全局变量数组中对应的表示任务状态的元素，当检测到状态为 &lt;b&gt;READY&lt;/b&gt; 时就执行一些任务
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;struct&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;Task&lt;/span&gt;{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;status&lt;/span&gt;;
    &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;other&lt;/span&gt;
};

&lt;span style=&quot;color: #8ae234;&quot;&gt;Task&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;tasks&lt;/span&gt;[MAX_TASK_NUM];

&lt;span style=&quot;color: #8ae234;&quot;&gt;void&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;thread_func&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;void&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;thread_id&lt;/span&gt;)
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt; = *((&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; *)thread_id);

    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;status&lt;/span&gt; = 0;

    &lt;span style=&quot;color: #729fcf;&quot;&gt;do&lt;/span&gt; {
        status = tasks[i].status;
        &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (status == READY) {

            &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;do something&lt;/span&gt;

            tasks[i].status = DONE;
        }
        &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt; {
            sleep(1);
        }
    }&lt;span style=&quot;color: #729fcf;&quot;&gt;while&lt;/span&gt; (status != QUIT);
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
一个模块初始化函数，用来初始化处理模块，这个处理模块会做一些预处理，然后通过线程来进行最后的操作，这个初始化函数接受一个线程号作为参数
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;struct&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;Env&lt;/span&gt;{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;thread_id&lt;/span&gt;;
    &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;other&lt;/span&gt;
};

&lt;span style=&quot;color: #8ae234;&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;Prepare&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;Env&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;env&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;thread_id&lt;/span&gt;)
{
    env-&amp;gt;thread_id = thread_id;
    &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;other&lt;/span&gt;
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
一个模块处理函数，在初始化一些环境、进行一些预处理后，将对应线程的状态置为 &lt;b&gt;READY&lt;/b&gt; ，然后等待直到对应线程处理完毕
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;Run&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;Env&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;env&lt;/span&gt;)
{
    &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;do preprocessing&lt;/span&gt;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt; = env-&amp;gt;thread_id;
    tasks[i].status = READY;

    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;status&lt;/span&gt;;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;do&lt;/span&gt; {
        sleep(1);
        status = tasks[i].status;
    } &lt;span style=&quot;color: #729fcf;&quot;&gt;while&lt;/span&gt; (status != DONE);
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
我遇到的问题就是，在将第 &lt;b&gt;i&lt;/b&gt; 个线程对应的状态置为 &lt;b&gt;READY&lt;/b&gt; 后，线程函数并没有进行相应的操作(偶尔)。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;加锁&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
一开始，我并没有对全局变量的读写进行加锁，因此怀疑是处理函数中对状态成员变量的修改没有成功。于是我将所有对全局变量数组中状态成员的读写操作都加了锁，但是问题仍然存在。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;取消编译器优化&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
考虑到对全局数组的状态成员的读、写操作有部分是在循环中进行的，因此怀疑gcc在编译器时对程序进行了优化，于是用 &lt;b&gt;volatile&lt;/b&gt; 修饰了状态成员
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;struct&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;Task&lt;/span&gt;{
    &lt;span style=&quot;color: #729fcf;&quot;&gt;volatile&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;status&lt;/span&gt;;
    &lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;other&lt;/span&gt;
};
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然而这个方法仍然无效。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline4&quot;&gt;局部变量，循环变量&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
和项目组组长讨论后，他也表示暂时没发现这个问题的根源，不过他建议我将 &lt;b&gt;线程函数&lt;/b&gt; 访问的 &lt;b&gt;全局数组元素的地址&lt;/b&gt; 与 &lt;b&gt;处理函数&lt;/b&gt; 中访问的 &lt;b&gt;全局数组元素的地址&lt;/b&gt; 打印出来对比一下。我听从了组长的建议，这样做了，然后果然发现了问题。
&lt;/p&gt;

&lt;p&gt;
在出错时，这两个地址是不一样的。随后，我将 &lt;b&gt;thread_func&lt;/b&gt; 函数与 &lt;b&gt;Run&lt;/b&gt; 函数中的变量 &lt;b&gt;i&lt;/b&gt; 的值打印出来，发现在出错的情况下，这两个值不相等。静下心来思考了一会后，我发现了问题的根源所在，即全局初始化函数 &lt;b&gt;Init&lt;/b&gt; 中创建线程这一段:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt; = 0; i &amp;lt; thread_num; ++i) {
    ret = pthread_create(thread_list + i, &amp;amp;a, thread_func, (&lt;span style=&quot;color: #8ae234;&quot;&gt;void&lt;/span&gt; *)&amp;amp;i);

    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt;(ret != 0) {
        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; ret;
    }
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;b&gt;pthread_create&lt;/b&gt; 函数接受的第四个参数是作为线程函数 &lt;b&gt;thread_func&lt;/b&gt; 的参数的，而在这里，我将既是 &lt;b&gt;局部变量&lt;/b&gt; 也是 &lt;b&gt;循环变量&lt;/b&gt; 的 &lt;b&gt;i&lt;/b&gt; 的 &lt;b&gt;地址值&lt;/b&gt; 作为 &lt;b&gt;pthread_create&lt;/b&gt; 函数的第四个参数。
&lt;/p&gt;

&lt;p&gt;
在测试时，为了方便，在执行 &lt;b&gt;Init&lt;/b&gt; 函数时，我只让它创建了一个线程，即对函数：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;Init&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;thread_num&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
传入的 &lt;b&gt;thread_num&lt;/b&gt; 参数的值为 &lt;b&gt;1&lt;/b&gt; 。
&lt;/p&gt;

&lt;p&gt;
首先，作为循环变量， &lt;b&gt;Init&lt;/b&gt; 中的变量 &lt;b&gt;i&lt;/b&gt; 在循环结束时值为 &lt;b&gt;1&lt;/b&gt; ，而在 &lt;b&gt;Run&lt;/b&gt; 函数中，表示线程号的变量 &lt;b&gt;i&lt;/b&gt; 的值则为 &lt;b&gt;0&lt;/b&gt; 。
&lt;/p&gt;

&lt;p&gt;
其次，主线程与子线程之间运行的先后次序是不确定的。
&lt;/p&gt;

&lt;p&gt;
最后， &lt;b&gt;Init&lt;/b&gt; 函数中的变量 &lt;b&gt;i&lt;/b&gt; 是局部变量，在 &lt;b&gt;Init&lt;/b&gt; 函数执行完后，其对应地址的值是不能保证的。
&lt;/p&gt;

&lt;p&gt;
总之这样的做法是大错特错的。在我将上述循环创建线程的代码段修改为如下内容后，本文所述的问题得到了彻底的解决：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt; = 0; i &amp;lt; thread_num; ++i) {
    tasks[i].thread_id = i;
    ret = pthread_create(thread_list + i, &amp;amp;a, thread_func, (&lt;span style=&quot;color: #8ae234;&quot;&gt;void&lt;/span&gt; *)&amp;amp;(tasks[i].thread_id));

    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt;(ret != 0) {
        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; ret;
    }
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
注意，这里的 &lt;b&gt;thread_id&lt;/b&gt; 是在 &lt;b&gt;Task&lt;/b&gt; 结构中新添加的 &lt;b&gt;int&lt;/b&gt; 类型成员
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>C++函数内部new操作并返回对象给外部导致的内存泄漏</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/05/09/mem-leak.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2014/05/09/mem-leak</id>
    <published>2014-05-09T00:00:00+00:00</published>
    <updated>2014-05-09T00:00:00+00:00</updated>
    <description>
    
      <p>
最近在为公司一个项目的一个模块写API，在API基本完成后，我写了几个demo把各种情况测试了一下。通过简单测试后，一时兴起，用valgrind进行了一下内存检查，真是不看不知道，一看吓一跳。


</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
最近在为公司一个项目的一个模块写API，在API基本完成后，我写了几个demo把各种情况测试了一下。通过简单测试后，一时兴起，用valgrind进行了一下内存检查，真是不看不知道，一看吓一跳。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/mem-leak.jpg&quot; alt=&quot;mem-leak.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
当时为了更快地看到结果，只拿了一个小的音频文件来进行处理，大概就几百个KB吧，然后内存泄漏的量就达到了3,481,396个字节！
&lt;/p&gt;

&lt;p&gt;
花了一两天的时间，借助valgrind以及代码阅读工具(sublime text + ctags)，我发现了内存泄漏的源头。
&lt;/p&gt;

&lt;p&gt;
一方面，有项目本身的代码编写不规范导致的泄漏；另一方面，也有项目使用的开源库自身的问题。
&lt;/p&gt;

&lt;p&gt;
项目本身存在的问题有：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;new/delete 操作不成对&lt;/li&gt;
&lt;li&gt;拷贝构造函数/赋值运算符重载 在进行拷贝时只进行了浅拷贝&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
项目本身的问题不太多，而且容易发现，所以被我优先解决了，此时内存泄漏的量减少了一半左右。
&lt;/p&gt;

&lt;p&gt;
接下来进入正题，在我们项目使用的开源库中，存在大量的同一个问题。
&lt;/p&gt;

&lt;p&gt;
对于下面这个类
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;A&lt;/span&gt;
{
&lt;span style=&quot;color: #729fcf;&quot;&gt;public&lt;/span&gt;:
    &lt;span style=&quot;color: #8ae234;&quot;&gt;A&lt;/span&gt; &amp;amp;&lt;span style=&quot;color: #edd400;&quot;&gt;create&lt;/span&gt;() {&lt;span style=&quot;color: #8ae234;&quot;&gt;A&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;p&lt;/span&gt; = &lt;span style=&quot;color: #729fcf;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;A&lt;/span&gt;; &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; *p;}
    &lt;span style=&quot;color: #729fcf;&quot;&gt;virtual&lt;/span&gt; ~&lt;span style=&quot;color: #edd400;&quot;&gt;A&lt;/span&gt;();
&lt;span style=&quot;color: #729fcf;&quot;&gt;private&lt;/span&gt;:
    &lt;span style=&quot;color: #edd400;&quot;&gt;A&lt;/span&gt;();
};
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
首先，对于类 &lt;b&gt;A&lt;/b&gt; 的方法 &lt;b&gt;create&lt;/b&gt; ，如果按下面的形式调用：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;A&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;a&lt;/span&gt;;
&lt;span style=&quot;color: #8ae234;&quot;&gt;A&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;b&lt;/span&gt; = a.create();
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
是必然会发生内存泄漏的，因为 b 不是引用类型，在赋值时发生的是拷贝操作， &lt;b&gt;create()&lt;/b&gt; 内部产生的指针已经被丢失了。所幸这种行为在项目以及项目使用的开源库中并没有发现。但在该开源库自身的代码中，大量存在另外一种错误。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;A&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;a&lt;/span&gt;;
&lt;span style=&quot;color: #8ae234;&quot;&gt;A&lt;/span&gt; &amp;amp;&lt;span style=&quot;color: #eeeeec;&quot;&gt;b&lt;/span&gt; = a.create();
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
使用引用对象来接受 &lt;b&gt;create()&lt;/b&gt; 返回的对象是正确的，但是，由于对象所使用的内存空间是通过 &lt;b&gt;new&lt;/b&gt; 得到的，也就是说，其占用的内存，是在堆上的，对于这样的内存空间，如果不手动进行回收，则在程序退出时也不会被回收。也就是说，下面的操作才是正确的：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C++&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;A&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;a&lt;/span&gt;;
&lt;span style=&quot;color: #8ae234;&quot;&gt;A&lt;/span&gt; &amp;amp;&lt;span style=&quot;color: #eeeeec;&quot;&gt;b&lt;/span&gt; = a.create();
&lt;span style=&quot;color: #888a85;&quot;&gt;// &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;...&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;delete&lt;/span&gt; &amp;amp;b;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
然而很不幸的是，这个开源库里面对于大量调用 &lt;b&gt;create()&lt;/b&gt; 及类似方法返回的对象，都没有进行回收，这是它自身的问题。如果要彻底解决目前我面临的内存泄漏问题，只能去修改这个开源库了，想想就觉得是一件很麻烦的事情_(:3」∠)_
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>asciinema: 便捷的终端录制与分享工具</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/05/07/asciinema.html"/>
    <category term="Linux" scheme="http://www.zmonster.me/categories.html#Linux"/>
    <id>http://www.zmonster.me/2014/05/07/asciinema</id>
    <published>2014-05-07T00:00:00+00:00</published>
    <updated>2014-05-07T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


asciinema简介
安装与使用
录制！分享！社交！




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgcb25698&quot;&gt;asciinema简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org34e7336&quot;&gt;安装与使用&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgb8c53e9&quot;&gt;录制！分享！社交！&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgcb25698&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgcb25698&quot;&gt;asciinema简介&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgcb25698&quot;&gt;
&lt;p&gt;
&lt;a href=&quot;https://asciinema.org&quot;&gt;Asciinema&lt;/a&gt; 是一款便捷的终端录制与分享工具，五一假期和两个朋友在五道口的咖啡厅喝咖啡聊天的时候，&lt;a href=&quot;http://wlwang41.github.io&quot;&gt;乌鸦&lt;/a&gt; 把这个工具分享给了我，这是一个非常赞的玩意，当然要进行分享了。
&lt;/p&gt;

&lt;p&gt;
下面是它在网站上对自己的介绍：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/asciinema.png&quot; alt=&quot;asciinema.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
它有以下几个特性：
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
操作简单，分享便捷
&lt;/p&gt;

&lt;p&gt;
要开始录制，运行：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-sh&quot;&gt;asciinema rec
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
即可，当要结束录制时，输入 &lt;b&gt;exit&lt;/b&gt; 或者在终端中按下 &lt;b&gt;&amp;lt;ctrl-d&amp;gt;&lt;/b&gt; 就可以。在结束时，它会提示 ”是否上传“ ，选择是后它会上传记录，并且返回一个 &lt;b&gt;URL&lt;/b&gt; ，通过这个 &lt;b&gt;URL&lt;/b&gt; ，可以非常方便的进行分享。
&lt;/p&gt;

&lt;p&gt;
当然了，和 &lt;b&gt;ttyrec&lt;/b&gt; 或者 &lt;b&gt;screen&lt;/b&gt; 相比，也是各有优劣， &lt;b&gt;ttyrec&lt;/b&gt; 是会生成一个文件，用 &lt;b&gt;ttyplay&lt;/b&gt; 可以播放它，在没有网络的情况下 &lt;b&gt;ttyrec&lt;/b&gt; 会更好一些。而在同一台主机上， &lt;b&gt;screen&lt;/b&gt; 那就是首选了。
&lt;/p&gt;

&lt;p&gt;
但现在的人们基本上都处在网络环境中，所以使用 &lt;b&gt;asciineme&lt;/b&gt; 还是很方便的。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
自由拷贝
&lt;/p&gt;

&lt;p&gt;
在播放记录时，可以自由地拷贝正在播放的记录中的命令，这一点上 &lt;b&gt;ttyrec&lt;/b&gt; 和 &lt;b&gt;screen&lt;/b&gt; 是无法相比的。
&lt;/p&gt;

&lt;p&gt;
当你在观看别人的记录时，如果有一些非常炫酷的命令，当然会心痒难耐想要自己亲手试一试，这个时候这个特性实在是不要太赞！
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
网页嵌入
&lt;/p&gt;

&lt;p&gt;
对于产生的记录，可以方便地嵌入到网页中，方法是在记录播放页面，在记录的右下方有一个 &lt;b&gt;Embed&lt;/b&gt; 字样的链接，点击一下，会弹出一个小框，显示出能嵌入到网页中的一行 html 代码，如下所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/embed.png&quot; alt=&quot;embed.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
下面是我的一个简单的录制：
&lt;/p&gt;
&lt;div class=&quot;HTML&quot;&gt;
&lt;p&gt;
&amp;lt;script type=&quot;text/javascript&quot; src=&quot;&lt;a href=&quot;https://asciinema.org/a/9415.js&quot;&gt;https://asciinema.org/a/9415.js&lt;/a&gt;&quot; id=&quot;asciicast-9415&quot; async&amp;gt;&amp;lt;/script&amp;gt;
&lt;/p&gt;

&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org34e7336&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org34e7336&quot;&gt;安装与使用&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org34e7336&quot;&gt;
&lt;p&gt;
虽然 &lt;b&gt;Asciinema&lt;/b&gt; 的安装与使用在其网站上都说得很清楚了，不过还是总结一下吧。
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
安装
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Asciinema&lt;/b&gt; 是用 python编写的工具，可以用 &lt;b&gt;pip&lt;/b&gt; 安装，如果机器上没有 &lt;b&gt;pip&lt;/b&gt; ，请先安装，用各自发行版的包管理器即可安装。然后执行
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-sh&quot;&gt;sudo pip install --upgrade asciinema
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
录制
&lt;/p&gt;

&lt;p&gt;
咦，好像之前说过了？那就不再说了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
帐号连接
&lt;/p&gt;

&lt;p&gt;
在 &lt;b&gt;Asciinema&lt;/b&gt; 的网站上，可以用自己的邮箱进行登录，同时，可以在本地通过运行：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-sh&quot;&gt;asciinema auth
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
来和帐号进行连接，这样你录制并上传的终端记录会被保存在你的帐号下面
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgb8c53e9&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgb8c53e9&quot;&gt;录制！分享！社交！&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgb8c53e9&quot;&gt;
&lt;p&gt;
由于 &lt;b&gt;Asciinema&lt;/b&gt; 将用户录制的终端记录上传并在网站上展示，同时还提供了和帐号连接的功能，所以也就成了一个非常好的社交平台，大家在上面展示自己的炫酷技巧，也不断地发现别人的与众不同，实在是非常之赞。
&lt;/p&gt;

&lt;p&gt;
还等什么，我已经用上了 :)
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>(2014年4月)月底小结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/05/01/april-of-2014.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2014/05/01/april-of-2014</id>
    <published>2014-05-01T00:00:00+00:00</published>
    <updated>2014-05-01T00:00:00+00:00</updated>
    <description>
    
      <p>
4月的我依然是不及格的呢。


</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
4月的我依然是不及格的呢。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/cloud-valley.jpg&quot; alt=&quot;cloud-valley.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
从4月14日起，我就正式在中关村软件园的一个公司里上班了。在这栋名为“云基地”的大楼的四层里的这些人，都是友好的，这点我很满足。两个多星期以来，我并没有做太多工作，除了学习相关理论、了解当前模块的结构和原理，剩下的就是为目前负责的这个模块编写API了。
&lt;/p&gt;

&lt;p&gt;
在这段时间里，对诸如GMM、MAP、EM、MLE、MFCC这些原本不熟悉的词有了足够的理解，有时下了班，也会想要不要就此写个笔记，但想到网上相关的文章随处可见，而且通俗易懂者也不在少数，自己如果写出来也不能比这些现有的文章更好，也就罢了。自己的理解，还是整理以后，放到&lt;a href=&quot;http://linusp.gitcafe.com/&quot;&gt;Linusp's Notes&lt;/a&gt;这个网站上去吧。如果真要写，我想能通过实践来示范这些算法的实际应用场景和实现技巧——这类的文章倒是相对少一些，值得一写。
&lt;/p&gt;

&lt;p&gt;
至于工作之外，每天下班后感觉还是挺累的——主要是颈椎不太舒服，眼睛比较疲劳。所以回来后也再懒得看代码或者写代码，一般就是打打游戏，然后在床上看会漫画就睡觉。最近主要是在看《剑风传奇》这部漫画，讲的是一个在破碎的世界例顽强挣扎的男人的故事。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/guts.jpg&quot; alt=&quot;guts.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
和小说与电影/电视的对比一样，有时候好的漫画未必能有好的动画制作——当然我不是说《剑风传奇》的动画制作很糟糕，但我看了以后还是觉得看漫画要好一些，毕竟像《虫师》这样动画、漫画都是精品的作品还是少。漫画和小说，可能不像影视作品那样能通过直接的视觉冲击和音效来产生直接而强烈的感受，但在阅读小说和漫画时，正因为这些要素的缺失，却更能感受到文字/绘画的美感，加上在阅读时候必须要通过自己主动的联想来完善作品中的故事、画面在心中的感受，使得这些作品要表达的东西能更深地被体会。
&lt;/p&gt;

&lt;p&gt;
惭愧的是，这段时间，既没有去写程序(工作之外)，也没有进行写作练习。至于Machine Learning课程，也只是把回归部分的习题完成了而已。究其原因，还是生活没有规划，导致懒散的习性显露无遗。
&lt;/p&gt;

&lt;p&gt;
总结的内容就到此为止吧，下面写一下五月的一些打算
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;首先，当然要尽快完成API的编写(工作)，至于完成后该做什么，这个我确实还不知道呢，所以工作上的事情，走一步看一步了&lt;/li&gt;
&lt;li&gt;开始我计划中的 &lt;b&gt;Magi&lt;/b&gt; 项目，至于这是一个什么项目，嘿嘿，暂不透露&lt;/li&gt;
&lt;li&gt;购买Tom Mitchell所著的《Machine Learning》和Bishop所著的《Pattern Recognition and Machine Learning》和 Peter Harrington所著的《Machine Learning in Action》这三本书&lt;/li&gt;
&lt;li&gt;完成Andrew Ng的 Machine Learning 课程以及相关练习&lt;/li&gt;
&lt;li&gt;每天早上起来后进行至少半小时的写作——我现在每天都醒得很早，导致6点钟醒了后就玩手机玩到快8点然后洗漱上班，所以与其把写作时间放到晚上，还是早上会好一点&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
暂时先写这么点吧，写多了怕做不完，在机器学习和写作上要花的功夫就不会少了，能做好一项是一项吧。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>Github建议将Pages Site的Markdown解析器替换为Kramdown</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/04/16/github-advice-user-to-use-kramdown-but-maruku.html"/>
    <category term="博客" scheme="http://www.zmonster.me/categories.html#博客"/>
    <id>http://www.zmonster.me/2014/04/16/github-advice-user-to-use-kramdown-but-maruku</id>
    <published>2014-04-16T00:00:00+00:00</published>
    <updated>2014-04-16T00:00:00+00:00</updated>
    <description>
    
      <p>
4月15日，Github向用户发出邮件，建议使用Github Pages服务的用户，应当将使用Github Pages服务搭建的站点的Markdown文件解析器替换成 Kramdown ——在...</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
4月15日，Github向用户发出邮件，建议使用Github Pages服务的用户，应当将使用Github Pages服务搭建的站点的Markdown文件解析器替换成 &lt;b&gt;Kramdown&lt;/b&gt; ——在此之前，应该有不少用户是使用 &lt;b&gt;Maruku&lt;/b&gt; 的，而据Github的邮件， &lt;b&gt;Maruku&lt;/b&gt; 已经过时。
&lt;/p&gt;

&lt;p&gt;
以下为Github邮件内容：
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
The page build completed successfully, but returned the following warning:
&lt;/p&gt;

&lt;p&gt;
Your site is using Maruku, the default Markdown interpreter. Maruku is now obsolete and may cause builds to fail for sites with invalid Markdown or HTML. See &lt;a href=&quot;https://help.github.com/articles/migrating-your-pages-site-from-maruku&quot;&gt;https://help.github.com/articles/migrating-your-pages-site-from-maruku&lt;/a&gt; for more information on upgrading to a newer Markdown interpreter.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
在2013年10月，Maruku的作者Benjamin Hollis在 &lt;a href=&quot;http://benhollis.net/blog/2013/10/20/maruku-is-obsolete/&quot;&gt;Maruku is obsolete&lt;/a&gt; 一文中说道：
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
All of the things I wanted to do in Maruku for 1.0.0 were in fact already done in Kramdown – better code organization, better modularity and extensibility, good documentation, a better parser, and improved performance
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
并且在Kramdown 1.0.0发布后，Benjamin Hollis自己也转向了使用Kramdown。从Github上的Commits记录来看，Maruku也已经有三个月没有任何更新了。所以说，嗯，Github说，是时候换个更好的Markdown解析器了，不然有可能你的网站可能会在解析的时候发生问题。
&lt;/p&gt;

&lt;p&gt;
修改方法也很简单，在_config.yml这个文件里进行修改，将：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
markdown: maruku
&lt;/pre&gt;
&lt;p&gt;
替换成：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
markdown: kramdown
&lt;/pre&gt;

&lt;p&gt;
一开始我收到邮件，有点诧异，因为我的文章都是用org-mode编写然后发布成html，所以我就没在_config.yml里设置Markdown解析器，查了一下，原来Maruku是Jekyll默认的Markdown解析器。所以你如果和我一样，保险起见，在_config.yml里显式地指定解析器为Kramdown吧。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>新工作，新生活</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/04/15/new-job-and-life.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2014/04/15/new-job-and-life</id>
    <published>2014-04-15T00:00:00+00:00</published>
    <updated>2014-04-15T00:00:00+00:00</updated>
    <description>
    
      <p>
三月份来北京找工作，接受了红点直播的offer，然后和封诚打了个招呼跑回家处理一些杂七杂八的事情去了。万万没想到有个公司在51job上看了我的简历，认可了我的能力，然后打了电话过来劝说我。


</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
三月份来北京找工作，接受了红点直播的offer，然后和封诚打了个招呼跑回家处理一些杂七杂八的事情去了。万万没想到有个公司在51job上看了我的简历，认可了我的能力，然后打了电话过来劝说我。
&lt;/p&gt;

&lt;p&gt;
这个公司就是我现在工作的地方，普强信息技术有限公司(Pachira)，一个从事语音识别的不大的公司。虽然挺喜欢红点直播和封诚，但我还是拒掉了，对我来说，一个能让我从事与模式识别、机器学习相关工作的机会，要比自由开放的氛围和解决可乐、住宿要重要得多。这是我选的路，我想能真正地走下去，而不只是想着走这条路。
&lt;/p&gt;

&lt;p&gt;
4月10日下午回到北京，然后在大兴睡了两晚，在周末的时候干脆地在沙河租了一间房子。这儿不太安静平和，热闹但有点乱糟糟，不过离地铁站近，到西二旗也就四站路，上班只要半小时。出了西二旗站，往南边走一点，然后顺着路往西直走就到了公司，也挺方便的。
&lt;/p&gt;

&lt;p&gt;
这两天还没接手正式的项目，只是在看一个同事的代码——这位同事还是大四学生，过段时间要回学校去。我不知道别人以什么标准来评价我，所以这两天一直有点紧张，此外我在人际上还是一如既往的一塌糊涂。今晚七点的时候，已经看不进去了，于是到七点半就收拾东西走人了，出了大楼，看到广场上有三五个人在玩轮滑，看他们腾挪辗转，羡慕而又受他们感染——我也会慢慢变成一个热爱生活的人的，因为我现在有这样的自由和空间了。
&lt;/p&gt;

&lt;p&gt;
有很多事情想做，有很多书想读，有很多地方想去。
&lt;/p&gt;

&lt;p&gt;
从今天起，恢复博客更新，恢复Machine Learning课程学习，恢复写作练习，恢复Lisp学习&amp;#x2026;
&lt;/p&gt;

&lt;p&gt;
说得好像以前有多坚持做这些事情一样:)
&lt;/p&gt;

&lt;p&gt;
想做的事情很多，好好计划，好好实行吧.
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>C语言字符串操作</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/03/06/string-operation-in-c.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2014/03/06/string-operation-in-c</id>
    <published>2014-03-06T00:00:00+00:00</published>
    <updated>2014-03-06T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


string.h
字符串拷贝(strcpy, strncpy)

strcpy
strncpy


字符串比较(strcmp, strncmp, strc...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;string.h&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;字符串拷贝(strcpy, strncpy)&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;strcpy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;strncpy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;字符串比较(strcmp, strncmp, strcasecmp, strncasecmp)&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline6&quot;&gt;strcmp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline7&quot;&gt;strncmp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline8&quot;&gt;strcasecmp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline9&quot;&gt;strncasecmp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline10&quot;&gt;字符串连接(strcat, strncat)&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline11&quot;&gt;strcat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline12&quot;&gt;strncat&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline13&quot;&gt;字符查找(strchr, strrchr, strchrnul, strpbrk)&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline14&quot;&gt;strchr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline15&quot;&gt;strrchr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline16&quot;&gt;strchrnul&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline17&quot;&gt;strpbrk&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline18&quot;&gt;字符串分割(strtok, strtok_r, strsep)&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline19&quot;&gt;strtok&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline20&quot;&gt;strtok_r&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline21&quot;&gt;strsep&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline22&quot;&gt;字符串匹配(strstr)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline23&quot;&gt;字符串副本创建(strdup, strndup, strdupa, strndupa)&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline24&quot;&gt;strdup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline25&quot;&gt;strndup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline26&quot;&gt;strdupa&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline27&quot;&gt;strndupa&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;string.h&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
其实在C语言的标准库中，也有非常丰富的字符串操作函数。当然了，由于C语言中 &lt;b&gt;字符串&lt;/b&gt; 并不是基本数据类型，也没有 &lt;b&gt;类&lt;/b&gt; 这个概念，相对来说操作上可能没有Python/Java之类的语言方便。不过了解一下C语言中的字符串操作还是有意义的。
&lt;/p&gt;

&lt;p&gt;
C语言中的字符串操作函数在 &lt;b&gt;string.h&lt;/b&gt; 中，不过要了解都有什么函数，阅读string.h并不是什么好的方式。如果是在Unix/Linux系统下，只要执行：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;man string
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
就可以了解都有哪些字符串操作函数了，如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/string_manual.png&quot; alt=&quot;string_manual.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
其中一些常用的函数及其大致功能如下(具体细节后面再细说)：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
字符串拷贝
&lt;/p&gt;

&lt;p&gt;
stcpy, strncpy
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
字符串比较
&lt;/p&gt;

&lt;p&gt;
strcmp, strncmp, strcasecmp, strncasecmp
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
字符串连接
&lt;/p&gt;

&lt;p&gt;
strcat, strncat
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
字符查找
&lt;/p&gt;

&lt;p&gt;
strchr, strrchr, strchrnul, strpbrk
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
建立字符串副本
&lt;/p&gt;

&lt;p&gt;
strdup, strndup, strdupa, strndupa
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
字符串分割
&lt;/p&gt;

&lt;p&gt;
strsep, strtok, strtok_r
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
字符串匹配
&lt;/p&gt;

&lt;p&gt;
strstr
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
下面根据功能的不同来展示各个函数的用法。这里我会用一些实例来进行示范，同时，其结果由org-babel对代码块求值得到。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;字符串拷贝(strcpy, strncpy)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline3&quot;&gt;strcpy&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;strcpy&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;dest&lt;/span&gt;, &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;src&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;dest&lt;/span&gt;[1024] = {0};
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;src&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;abcde&quot;&lt;/span&gt;;

    strcpy(dest, src);

    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;, dest);
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
abcde
&lt;/pre&gt;

&lt;p&gt;
strcpy()函数会将源字符串中的结束符('\0')也拷贝到目的字符串中。
&lt;/p&gt;

&lt;p&gt;
注意，strcpy()可能会导致溢出。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline4&quot;&gt;strncpy&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;strncpy&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;dest&lt;/span&gt;, &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;src&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;size_t&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;n&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
该函数从源字符串中拷贝n个字符到目的字符串；如果源字符串长度不足，则用 &lt;b&gt;NULL&lt;/b&gt; 填充，以保证将n个字符写入目的字符串中；如果源字符串中前n个字符不包含字符串结束符，函数不会为目的字符串添加上结束符。
&lt;/p&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;dest&lt;/span&gt;[7] = {0};
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;src&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;abcde&quot;&lt;/span&gt;;

    dest[5] = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'A'&lt;/span&gt;;
    strncpy(dest, src, 5);

    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;, dest);
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
abcdeA
&lt;/pre&gt;

&lt;p&gt;
所以如果有需要，应该在拷贝后自己在目的字符串尾部添加结束符。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline5&quot;&gt;字符串比较(strcmp, strncmp, strcasecmp, strncasecmp)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline6&quot;&gt;strcmp&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline6&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;strcmp&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s1&lt;/span&gt;, &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s2&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
如果s1小于s2，函数返回一个负数；如果s1等于s2，函数返回0；否则返回一个正数。
&lt;/p&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s1&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;abcde&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s2&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;abcef&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s3&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;ad&quot;&lt;/span&gt;;

    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;compare(%s, %s) -&amp;gt; %d\n&quot;&lt;/span&gt;, s1, s2, strcmp(s1, s2));
    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;compare(%s, %s) -&amp;gt; %d\n&quot;&lt;/span&gt;, s1, s3, strcmp(s1, s3));
    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;compare(%s, %s) -&amp;gt; %d\n&quot;&lt;/span&gt;, s2, s3, strcmp(s2, s3));

    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
compare(abcde, abcef) -&amp;gt; -1
compare(abcde, ad) -&amp;gt; -2
compare(abcef, ad) -&amp;gt; -2
&lt;/pre&gt;

&lt;p&gt;
从这个结果可以发现，strcmp()是根据字典序来对字符串进行比较的。进一步的，还可以发现strcmp()的返回值是比较过程中最后一次比较时两个字符的值的差，如比较&quot;abcde&quot;和&quot;abcef&quot;，有：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
a - a = 0
b - b = 0
c - c = 0
d - e = -1 #按字典序，大小已分，不再比较
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline7&quot;&gt;strncmp&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline7&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;strncmp&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s1&lt;/span&gt;, &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s2&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;size_t&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;n&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
和strcmp()的区别是，strncmp()只对s1和s2的前n个字节进行比较。
&lt;/p&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s1&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;abcde&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s2&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;abcfg&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s3&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;abd&quot;&lt;/span&gt;;

    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;compare(%s, %s, 4) -&amp;gt; %d\n&quot;&lt;/span&gt;, s1, s2, strncmp(s1, s2, 4));
    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;compare(%s, %s, 2) -&amp;gt; %d\n&quot;&lt;/span&gt;, s1, s3, strncmp(s1, s3, 2));
    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;compare(%s, %s, 3) -&amp;gt; %d\n&quot;&lt;/span&gt;, s2, s3, strncmp(s2, s3, 3));

    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
compare(abcde, abcfg, 4) -&amp;gt; -2
compare(abcde, abd, 2) -&amp;gt; 0
compare(abcfg, abd, 3) -&amp;gt; -1
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline8&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline8&quot;&gt;strcasecmp&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline8&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;strcasecmp&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s1&lt;/span&gt;, &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s2&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
strcasecmp()也是用来比较字符串的，和strcmp()有两点区别：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;使用strcasecmp()应该包含 &lt;b&gt;strings.h&lt;/b&gt; 而不是 &lt;b&gt;string.h&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;strcasecmp()在比较时不区分大小写&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;strings.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s1&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;AbcdE&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s2&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;abcdE&quot;&lt;/span&gt;;

    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;compare(%s, %s) with case -&amp;gt; %d\n&quot;&lt;/span&gt;, s1, s2, strcmp(s1, s2));
    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;compare(%s, %s) ignore case -&amp;gt; %d\n&quot;&lt;/span&gt;, s1, s2, strcasecmp(s1, s2));

    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
compare(AbcdE, abcdE) with case -&amp;gt; -32
compare(AbcdE, abcdE) ignore case -&amp;gt; 0
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline9&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline9&quot;&gt;strncasecmp&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline9&quot;&gt;
&lt;p&gt;
strncasecmp()之于strcasecmp()就如strncmp()之于strcmp()，不再赘述。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline10&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline10&quot;&gt;字符串连接(strcat, strncat)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline10&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline11&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline11&quot;&gt;strcat&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline11&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;strcat&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;dest&lt;/span&gt;, &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;src&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
strcat()首先会覆盖掉目的字符串的结束符，然后把源字符串的内容追加到后面，并在最后添加结束符。如果目的字符串缓冲区长度不够，将导致溢出。
&lt;/p&gt;

&lt;p&gt;
strcat()在操作完成后，返回目的字符串的首地址，这样可以方便地进行链式操作。
&lt;/p&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;dest&lt;/span&gt;[1024] = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;hello &quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;src&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;world!&quot;&lt;/span&gt;;

    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;, strcat(dest, src));

    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
hello world!
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline12&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline12&quot;&gt;strncat&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline12&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;strncat&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;dest&lt;/span&gt;, &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;src&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;size_t&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;n&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
strncat()将最多n个字节的内容追加到目的字符串尾部，并且会在追加后添加终止符号。
&lt;/p&gt;

&lt;p&gt;
同strcat()一样，它返回目的字符串的首地址。
&lt;/p&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;dest&lt;/span&gt;[1024] = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;hello &quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;src&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;world!lkjsdljsd&quot;&lt;/span&gt;;

    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;, strncat(dest, src, 6));

    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
hello world!
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline13&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline13&quot;&gt;字符查找(strchr, strrchr, strchrnul, strpbrk)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline13&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline14&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline14&quot;&gt;strchr&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline14&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;strchr&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;c&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
strchr()返回一个字符指针，指向指定字符在指定字符串中第一次出现的位置。如果在指定字符串中没有找到指定字符，则返回 &lt;b&gt;NULL&lt;/b&gt; 。该函数的第二个参数按理来说应当是一个字符，不过标准库中确实是int类型。
&lt;/p&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;hello world!&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;c&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'l'&lt;/span&gt;;

    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;, strchr(s, c));

    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
llo world!
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline15&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline15&quot;&gt;strrchr&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline15&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;strrchr&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;c&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
strrchr()和strchr()类似，但它返回的是指定字符在指定字符串中最后一次出现的位置。如果未找到，同样返回 &lt;b&gt;NULL&lt;/b&gt; 。
&lt;/p&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;hello world!&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;c&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'l'&lt;/span&gt;;

    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;, strrchr(s, c));

    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
ld!
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline16&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline16&quot;&gt;strchrnul&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline16&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;strchrnul&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;c&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
strchrnul()的功能和strchr()只有细微的区别，那就是，当没有找到指定字符时，strchrnul()不返回 &lt;b&gt;NULL&lt;/b&gt; ，而是返回字符串结束符的位置。
&lt;/p&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;abcde&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;c&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'m'&lt;/span&gt;;

    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%p, %p\n&quot;&lt;/span&gt;, s, strchrnul(s, c));

    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
0x40065c, 0x400661
&lt;/pre&gt;

&lt;p&gt;
这里由于strchrnul()的特性，没办法通过打印字符串来了解strchrnul()的操作，不过观察这两个指针的值，会发现：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
0x400661 - 0x40065c = 0x5
&lt;/pre&gt;
&lt;p&gt;
而字符串s的第六个元素(从0开始，5即第六个)，正好是结束符。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline17&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline17&quot;&gt;strpbrk&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline17&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;strpbrk&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt;, &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;accept&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
strpbrk()和strchr()的区别在于，strchr()是从字符串里搜索 &lt;b&gt;一个字符&lt;/b&gt; ，而strpbrk()则是在字符串里搜索 &lt;b&gt;一个字符集中的字符&lt;/b&gt; ，看第二个参数就明白了。strpbrk()遍历字符串，如果发现某个字符在指定的 &lt;b&gt;字符集&lt;/b&gt; 中，则立即返回指向该字符的指针。如果最后没有找到任何在指定字符集中的字符，则返回 &lt;b&gt;NULL&lt;/b&gt; 。
&lt;/p&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Hello World!&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;accept&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Wo&quot;&lt;/span&gt;;

    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;, strpbrk(s, accept));

    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
o World!
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline18&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline18&quot;&gt;字符串分割(strtok, strtok_r, strsep)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline18&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline19&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline19&quot;&gt;strtok&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline19&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;strtok&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;delim&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
strtok()根据第二个参数指定的分隔符(可能存在多个不同的分隔符)将指定字符串分割成多个子串。通过多次调用strtok()，可以依次获得字符串的多个子串的首地址。要注意的是，除了第一次调用时将待分割字符串作为第一个参数，后续的调用要将第一个参数置为 &lt;b&gt;NULL&lt;/b&gt; 。当字符串已经无法再分割时，strtok()返回 &lt;b&gt;NULL&lt;/b&gt; 。
&lt;/p&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt;[1024] = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;abc;lsdk:lskdj,;slsj&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;delm&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;;:,&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;result&lt;/span&gt; = &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;len&lt;/span&gt; = strlen(s);
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt; = 0;

    result = strtok(s, delm);
    &lt;span style=&quot;color: #729fcf;&quot;&gt;while&lt;/span&gt; (result != &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;) {
        printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Source:%s, Sub:%s\n&quot;&lt;/span&gt;, s, result);
        result = strtok(&lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;, delm);
    }

    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
Source:abc Sub:abc
Source:abc Sub:lsdk
Source:abc Sub:lskdj
Source:abc Sub:slsj
&lt;/pre&gt;

&lt;p&gt;
除了上面说过的strtok()的用法外，还要注意的是，作为待分割的字符串，它必须是 &lt;b&gt;可更改的&lt;/b&gt; 。否则虽然可以通过编译，但运行会出错。要理解这个现象，首先要了解strtok()的内部机制。
&lt;/p&gt;

&lt;p&gt;
了解其机制，没必要去寻找其实现源代码，只要对它的操作过程进行剖析就知道了。先看下面的代码：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;


&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt;[64] = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;To be or not to be&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;delm&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot; ,.&quot;&lt;/span&gt;;         &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#20998;&amp;#38548;&amp;#31526;&amp;#65306;&amp;#31354;&amp;#26684; &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;result&lt;/span&gt; = &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt; = 0, &lt;span style=&quot;color: #eeeeec;&quot;&gt;len&lt;/span&gt; = strlen(s);

    &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (i = 0; i &amp;lt; len; ++i) { &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#36880;&amp;#20010;&amp;#25171;&amp;#21360;s&amp;#20013;&amp;#30340;&amp;#23383;&amp;#31526; &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
        printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%c &quot;&lt;/span&gt;, s[i]);
    }
    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;\n&quot;&lt;/span&gt;);


    &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (i = 0; i &amp;lt; len; ++i) { &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#36880;&amp;#20010;&amp;#25171;&amp;#21360;s&amp;#20013;&amp;#23383;&amp;#31526;&amp;#30340;&amp;#25968;&amp;#20540; &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
        printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%d &quot;&lt;/span&gt;, (&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt;)s[i]);
    }
    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;\n&quot;&lt;/span&gt;);

    result = strtok(s, delm);
    &lt;span style=&quot;color: #729fcf;&quot;&gt;while&lt;/span&gt; (result != &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;) {    &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#35266;&amp;#23519;s&amp;#20013;&amp;#23383;&amp;#31526;&amp;#25968;&amp;#20540;&amp;#30340;&amp;#21464;&amp;#21270; &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;

        &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (i = 0; i &amp;lt; len; ++i) {
            printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%d &quot;&lt;/span&gt;, (&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt;)s[i]);
        }
        printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;\n&quot;&lt;/span&gt;);

        result = strtok(&lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;, delm);
    }
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果：
&lt;/p&gt;
&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;

&lt;col  class=&quot;org-right&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-right&quot;&gt;T&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;o&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;b&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;e&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;o&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;r&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;n&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;o&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;t&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;t&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;o&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;b&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;e&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-right&quot;&gt;84&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;32&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;98&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;101&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;32&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;114&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;32&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;110&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;116&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;32&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;116&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;32&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;98&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;101&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-right&quot;&gt;84&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;98&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;101&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;32&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;114&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;32&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;110&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;116&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;32&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;116&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;32&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;98&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;101&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-right&quot;&gt;84&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;98&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;101&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;114&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;32&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;110&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;116&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;32&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;116&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;32&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;98&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;101&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-right&quot;&gt;84&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;98&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;101&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;114&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;110&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;116&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;32&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;116&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;32&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;98&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;101&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-right&quot;&gt;84&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;98&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;101&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;114&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;110&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;116&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;116&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;32&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;98&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;101&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-right&quot;&gt;84&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;98&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;101&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;114&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;110&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;116&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;116&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;98&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;101&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-right&quot;&gt;84&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;98&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;101&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;114&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;110&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;116&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;116&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;111&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;0&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;98&lt;/td&gt;
&lt;td class=&quot;org-right&quot;&gt;101&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
可以看到，s中的分隔符，逐次地被置为'\0'即字符串结束符。这就是strtok()分割字符串的内部原理了。而strtok()返回的指针，其实就是s中各个子串的起始位置了。如果s指向的内容是无法被修改的，那么strtok()自然也就无法将原先的分隔符置为字符结束符了。
&lt;/p&gt;

&lt;p&gt;
当然了，由于源字符串会被修改，在实际中，如果需要，可以用strdup()来建立一个源字符串的副本。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline20&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline20&quot;&gt;strtok_r&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline20&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;strtok_r&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;delim&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; **&lt;span style=&quot;color: #eeeeec;&quot;&gt;saveptr&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
strtok_r()是Linux下的strtok()的可重入版本(线程安全版本)，它比strtok()多了一个参数 &lt;b&gt;saveptr&lt;/b&gt; ，这个参数用于在分割字符串时保存上下文。
&lt;/p&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt;[64] = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Hello world&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;delm&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot; &quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;result&lt;/span&gt; = &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;, *&lt;span style=&quot;color: #eeeeec;&quot;&gt;ptr&lt;/span&gt; = &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;;

    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Source:%p\n&quot;&lt;/span&gt;, s);
    result = strtok_r(s, delm, &amp;amp;ptr);
    &lt;span style=&quot;color: #729fcf;&quot;&gt;while&lt;/span&gt; (result != &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;) {
        printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Result:%p\t&quot;&lt;/span&gt;, result);
        printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Saveptr:%p\n&quot;&lt;/span&gt;, ptr);
        printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;---%s\t&quot;&lt;/span&gt;, result);
        printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;---%s\n&quot;&lt;/span&gt;, ptr);

        result = strtok_r(&lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;, delm, &amp;amp;ptr);
    }
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
Source:0x7fff180f3de0
Result:0x7fff180f3de0 Saveptr:0x7fff180f3de6
---Hello              ---world
Result:0x7fff180f3de6 Saveptr:0x7fff180f3deb
---world              ---
&lt;/pre&gt;
&lt;p&gt;
可以看到，saveptr这个指针在每次调用strtok_r()后就指向了未分割的部分的首地址。相对地，strtok()则是在内部有一个静态缓冲区，通过这个静态缓冲区来记录未处理的起始位置，所以strtok()不是线程安全的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline21&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline21&quot;&gt;strsep&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline21&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;strsep&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; **&lt;span style=&quot;color: #eeeeec;&quot;&gt;stringp&lt;/span&gt;, &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;delim&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
strsep()同样是字符串分割函数，它和strtok()的不同之处在于，它会直接修改待分割的指针的值，让它始终指向未处理部分的起始位置。
&lt;/p&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt;[64] = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;To be or not to be&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;source&lt;/span&gt; = s;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;delm&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot; &quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;result&lt;/span&gt; = &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;;

    &lt;span style=&quot;color: #729fcf;&quot;&gt;while&lt;/span&gt; (source != &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;) {
        printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Source:%s | &quot;&lt;/span&gt;, source);
        result = strsep(&amp;amp;source, delm);
        printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;result:%s\n&quot;&lt;/span&gt;, result);
    }
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
Source:To be or not to be | result:To
Source:be or not to be | result:be
Source:or not to be | result: or
Source:not to be | result: not
Source:to be | result: to
Source:be | result: be
&lt;/pre&gt;

&lt;p&gt;
因为和strtok()的这个不同之处，strsep不需要区分第一次调用后后续的连续调用，可以用统一的操作来对字符串进行分割。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline22&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline22&quot;&gt;字符串匹配(strstr)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline22&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;strstr&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;haystack&lt;/span&gt;, &lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;needle&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
strstr()返回字符串needle在字符串haystack中第一次出现的位置；如果没有匹配，则返回 &lt;b&gt;NULL&lt;/b&gt; 。
&lt;/p&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;To be or not to be.&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;p&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;be&quot;&lt;/span&gt;;

    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;, strstr(s, p));
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
be or not to be.
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline23&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline23&quot;&gt;字符串副本创建(strdup, strndup, strdupa, strndupa)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline23&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline24&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline24&quot;&gt;strdup&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline24&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;strdup&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
strdup()调用malloc()分配一块内存并将字符串s的内容拷贝进去，产生s的副本。要注意的是，在最后应该调用free()来释放副本。
&lt;/p&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;abcde&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;dup&lt;/span&gt; = strdup(s);
    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;, dup);
    free(dup);
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
abcde
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline25&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline25&quot;&gt;strndup&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline25&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;strndup&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;size_t&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;n&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
strndup()和strdup()类似，但最多只拷贝s的前n个字节。如果s的长度大于n，还会在副本后添加终止符。
&lt;/p&gt;

&lt;p&gt;
示例：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;argc&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;argv&lt;/span&gt;[])
{
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;abcde&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;dup&lt;/span&gt; = strndup(s, 4);

    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;, dup);

    free(dup);
    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
abcd
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline26&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline26&quot;&gt;strdupa&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline26&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;strdupa&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
strdupa()和strdup()类似，但在分配内存时，它使用alloca()而不是malloc()。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline27&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline27&quot;&gt;strndupa&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline27&quot;&gt;
&lt;p&gt;
函数原型：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #edd400;&quot;&gt;strndupa&lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;size_t&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;n&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
strndupa()之于strdupa()就如strndup()之于strdup()，不再赘述。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>(2014年2月)月底小结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/02/28/february-of-2014.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2014/02/28/february-of-2014</id>
    <published>2014-02-28T00:00:00+00:00</published>
    <updated>2014-02-28T00:00:00+00:00</updated>
    <description>
    
      <p>
二月份我只写了一篇博客(算上这篇的话时两篇)，没有完成任务。如果可以的话，三月份多写一点吧。


</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
二月份我只写了一篇博客(算上这篇的话时两篇)，没有完成任务。如果可以的话，三月份多写一点吧。
&lt;/p&gt;

&lt;p&gt;
我来北京的前一天晚上，北京下了雨，又刮北风，所以当我来到北京的时候，天空非常晴朗，就是有点冷。不过我知道，过几天，北京的天空中又会布满尘霾的，而我的生活，又什么时候才能出现一次晴空呢？
&lt;/p&gt;

&lt;p&gt;
今天下午去搜狐面试，一开始看错了时间，结果迟到了一刻钟；然后又太紧张，语无伦次，而且会的题目都没答对。面试完我就知道指定黄了。
&lt;/p&gt;

&lt;p&gt;
在我回住处的路上，高玩一直在微信上安慰鼓励我，挺感谢他的。从帮我内推开始，他一直非常热心地想帮助我，不过我还是辜负了这份希冀。
&lt;/p&gt;

&lt;p&gt;
情绪上多少有点低落，不过没什么，从失败中吸取经验为下一次尝试做好准备吧。至少现在我的情绪还没有到绝望的地步，我还会继续尝试，直到有一天我实在撑不住为止。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>在Org-mode中显示特殊字符</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/02/22/display-special-character-in-org-mode.html"/>
    <category term="Emacs" scheme="http://www.zmonster.me/categories.html#Emacs"/>
    <id>http://www.zmonster.me/2014/02/22/display-special-character-in-org-mode</id>
    <published>2014-02-22T00:00:00+00:00</published>
    <updated>2014-02-22T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


在Org-mode中编写数学公式
所见即所得:在org-mode中即时显示特殊字符、数学公式




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;在Org-mode中编写数学公式&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;所见即所得:在org-mode中即时显示特殊字符、数学公式&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;在Org-mode中编写数学公式&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
在Org-mode中可以编写符合Latex语法的数学符号及公式，并且在发布成网页时以易读的形式展示。
&lt;/p&gt;

&lt;p&gt;
比如下面这段语句：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-org&quot;&gt;$$e^{i\pi} + 1 = 0$$
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
会显示成：
\[e^{i\pi} + 1 = 0\]
&lt;/p&gt;

&lt;p&gt;
要启用这个功能，需要在发布成网页时在模板头部中包含：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-html&quot;&gt;&amp;lt;&lt;span style=&quot;color: #edd400;&quot;&gt;script&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;type&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;text/javascript&quot;&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;src&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;http://orgmode.org/mathjax/MathJax.js&quot;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&quot;color: #edd400;&quot;&gt;script&lt;/span&gt;&amp;gt;
&amp;lt;&lt;span style=&quot;color: #edd400;&quot;&gt;script&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;type&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;text/javascript&quot;&lt;/span&gt;&amp;gt;
  &lt;span style=&quot;color: #888a85;&quot;&gt;&amp;lt;!--&lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;/*&lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;--&amp;gt;&lt;/span&gt;&amp;lt;![CDATA[/*&amp;gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;lt;!--&lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;    MathJax.Hub.Config({&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;        // Only one of the two following lines, depending on user settings&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;        // First allows browser-native MathML display, second forces HTML/CSS&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;        //  config: [&quot;MMLorHTML.js&quot;], jax: [&quot;input/TeX&quot;],&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;            jax: [&quot;input/TeX&quot;, &quot;output/HTML-CSS&quot;],&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;        extensions: [&quot;tex2jax.js&quot;,&quot;TeX/AMSmath.js&quot;,&quot;TeX/AMSsymbols.js&quot;,&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;                     &quot;TeX/noUndefined.js&quot;],&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;        tex2jax: {&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;            inlineMath: [ [&quot;\\(&quot;,&quot;\\)&quot;] ],&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;            displayMath: [ ['$$','$$'], [&quot;\\[&quot;,&quot;\\]&quot;], [&quot;\\begin{displaymath}&quot;,&quot;\\end{displaymath}&quot;] ],&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;            skipTags: [&quot;script&quot;,&quot;noscript&quot;,&quot;style&quot;,&quot;textarea&quot;,&quot;pre&quot;,&quot;code&quot;],&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;            ignoreClass: &quot;tex2jax_ignore&quot;,&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;            processEscapes: false,&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;            processEnvironments: true,&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;            preview: &quot;TeX&quot;&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;        },&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;        showProcessingMessages: true,&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;        displayAlign: &quot;center&quot;,&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;        displayIndent: &quot;2em&quot;,&lt;/span&gt;

&lt;span style=&quot;color: #888a85;&quot;&gt;        &quot;HTML-CSS&quot;: {&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;             scale: 100,&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;             availableFonts: [&quot;STIX&quot;,&quot;TeX&quot;],&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;             preferredFont: &quot;TeX&quot;,&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;             webFont: &quot;TeX&quot;,&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;             imageFont: &quot;TeX&quot;,&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;             showMathMenu: true,&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;        },&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;        MMLorHTML: {&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;             prefer: {&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;                 MSIE:    &quot;MML&quot;,&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;                 Firefox: &quot;MML&quot;,&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;                 Opera:   &quot;HTML&quot;,&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;                 other:   &quot;HTML&quot;&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;             }&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;        }&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;    });&lt;/span&gt;
&lt;span style=&quot;color: #888a85;&quot;&gt;/*]]&amp;gt;*///&lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;--&amp;gt;&lt;/span&gt;
&amp;lt;/&lt;span style=&quot;color: #edd400;&quot;&gt;script&lt;/span&gt;&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
在将单个org-mode文档导出成网页时，模板中时默认有此内容的，可以不用进行特别的设置。不过在将一个目录作为项目发布成网页时，出于简洁的目的，可能会有如下设置：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(setq org-publish-project-alist
      '(
        (&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;blog-org&quot;&lt;/span&gt;
         ...
         &lt;span style=&quot;color: #729fcf;&quot;&gt;:html-head-include-scripts&lt;/span&gt; nil
         ...)
        ...))
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
这条语句会使项目在发布时去除默认模板中包含的一些js片段，这是需要注意的地方。如果需要在项目发布中也启用数学符号/公式显示的功能，最好将这个选项打开，或者自定义也可以(但应该包含上面所示的js片段)
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;所见即所得:在org-mode中即时显示特殊字符、数学公式&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
其实在org-mode文档中也能在编辑好特殊字符、数学符号及公式后即时地显示，实现真正的“所见即所得”。
&lt;/p&gt;

&lt;p&gt;
临时启用这个特性，只要在编辑org文档时执行：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
C-c C-x \
&lt;/pre&gt;
&lt;p&gt;
这个快捷键会调用命令：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
org-toggle-pretty-entities
&lt;/pre&gt;

&lt;p&gt;
效果如下：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/org-pretty-entities.gif&quot; alt=&quot;org-pretty-entities.gif&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
不过效果并不是非常好，和Texmacs还有区别。对于单个的特殊字符如希腊字母，效果是可以的，但对于一些复杂的数学公式，比如
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-org&quot;&gt;$$J(\theta) = \frac{1}{2m}\sum_{i=1}^{m}(\theta^{T}X_{i} - Y_{i})^2$$
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
理想的显示效果应该是：
\[J(\theta) = \frac{1}{2m}\sum_{i=1}^{m}(\theta^{T}X_{i} - Y_{i})^2\]
&lt;/p&gt;

&lt;p&gt;
但它的实际显示效果却是：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/actually-pretty-entities.png&quot; alt=&quot;actually-pretty-entities.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以看出org-mode的这个功能中对特殊字符的解析和Latex的语法并不一致，至于是否存在解决办法，这个就有待以后讨论吧。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>(2014年1月)月底小结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/01/31/january-of-2014.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2014/01/31/january-of-2014</id>
    <published>2014-01-31T00:00:00+00:00</published>
    <updated>2014-01-31T00:00:00+00:00</updated>
    <description>
    
      <p>
2014年的第一个31天就这么过去了，而这个月的最后一天，刚好又是农历新年的第一天。


</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
2014年的第一个31天就这么过去了，而这个月的最后一天，刚好又是农历新年的第一天。
&lt;/p&gt;

&lt;p&gt;
这31天里，《全球通史》我一页也没有翻过，日记多日未写，偶尔写写代码。总而言之，是很没有干劲的一个月。部分原因是临近过年家中事多，还有部分原因则是离家之日临近所带来的复杂心理状况吧。
&lt;/p&gt;

&lt;p&gt;
以下是本月所做的事情：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;解决改派及调档事宜&lt;/li&gt;
&lt;li&gt;复习了部分算法和数据结构&lt;/li&gt;
&lt;li&gt;读完了《TCP/IP Socket in C》，掌握了Socket编程的基础&lt;/li&gt;
&lt;li&gt;(游戏)在MCBBS服务器上定居并拥有了足够生存的资源&lt;/li&gt;
&lt;li&gt;和五位初中同学以及两位高中同学会面并交流&lt;/li&gt;
&lt;li&gt;在大年初一和七位朋友通电话传递新年祝福并“闲谈”&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
因为想为后面找工作做准备，前半个月直接就把学了一半的机器学习公开课丢下了；后半个月则基本没做什么对将来独立生活有直接意义的事情。当然了，指责自己是没什么意义的。
&lt;/p&gt;

&lt;p&gt;
只能对自己说加油吧。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>排序算法——堆排序</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/01/12/heap-sort.html"/>
    <category term="算法" scheme="http://www.zmonster.me/categories.html#算法"/>
    <id>http://www.zmonster.me/2014/01/12/heap-sort</id>
    <published>2014-01-12T00:00:00+00:00</published>
    <updated>2014-01-12T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


堆排序概述
堆排序实现

节点访问
建立大顶堆
实现堆排序


发散：TOP K问题




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;堆排序概述&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;堆排序实现&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;节点访问&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;建立大顶堆&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;实现堆排序&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline6&quot;&gt;发散：TOP K问题&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;堆排序概述&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
堆排序通过建立大顶堆(或小顶堆)来进行排序，要理解这个算法，首先要明白什么是 &lt;b&gt;大顶堆&lt;/b&gt; 或者 &lt;b&gt;小顶堆&lt;/b&gt; 。
&lt;/p&gt;

&lt;p&gt;
这里的堆是一种数据结构，它是一棵完全二叉树(除最后一层外，其他层都是满的)，且每个节点都具有同一种特性，那就是该节点的值大于子节点的值，或者节点的值小于子节点的值，前者被称为 &lt;b&gt;大顶堆&lt;/b&gt; ，后者被称为 &lt;b&gt;小顶堆&lt;/b&gt; 。大顶堆的根节点的值一定是整个堆中最大的，小顶堆的根节点的值一定是堆中最小的。利用这个特性，如果要对一个数组进行升序排序，那么可以按照以下步骤进行：
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;将数组元素视为一个堆，建立大顶堆&lt;/li&gt;
&lt;li&gt;将堆顶元素和堆尾元素交换，并出堆&lt;/li&gt;
&lt;li&gt;对堆进行处理，维持大顶堆性质&lt;/li&gt;
&lt;li&gt;重复2、3步(此时已出堆的元素不再处理)，直到堆中只有一个元素&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;堆排序实现&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
首先，要从逻辑上建立对堆的相关操作，在排序中并不需要建立一棵二叉树，而是将数组“视为”二叉树即可。对于二叉树而言，最起码的，应该有取得某个节点的父节点及子节点的功能。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline3&quot;&gt;节点访问&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
用python实现如下：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span class=&quot;linenr&quot;&gt; 1: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;parent&lt;/span&gt;(heap, node):
&lt;span class=&quot;linenr&quot;&gt; 2: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; node &amp;gt; 0:
&lt;span class=&quot;linenr&quot;&gt; 3: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; (node - 1) / 2
&lt;span class=&quot;linenr&quot;&gt; 4: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt;:
&lt;span class=&quot;linenr&quot;&gt; 5: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0
&lt;span class=&quot;linenr&quot;&gt; 6: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 7: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;lchild&lt;/span&gt;(node):
&lt;span class=&quot;linenr&quot;&gt; 8: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 2 * node + 1
&lt;span class=&quot;linenr&quot;&gt; 9: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;10: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;rchild&lt;/span&gt;(node):
&lt;span class=&quot;linenr&quot;&gt;11: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 2 * node + 2
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline4&quot;&gt;建立大顶堆&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
建立大顶堆要从最后一个具有子节点的节点上开始操作，将当前节点作为一个大顶堆的堆顶，进行堆性质维持的处理。并逐步往前对该节点的兄弟节点、父节点进行同样的操作。
&lt;/p&gt;

&lt;p&gt;
首先需要实现一个堆性质维持处理函数，实现如下：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span class=&quot;linenr&quot;&gt; 1: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;heapify&lt;/span&gt;(heap, root, size):
&lt;span class=&quot;linenr&quot;&gt; 2: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;max_index&lt;/span&gt; = root
&lt;span class=&quot;linenr&quot;&gt; 3: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;l&lt;/span&gt; = lchild(root)
&lt;span class=&quot;linenr&quot;&gt; 4: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;r&lt;/span&gt; = rchild(root)
&lt;span class=&quot;linenr&quot;&gt; 5: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt;  l &amp;lt; size &lt;span style=&quot;color: #729fcf;&quot;&gt;and&lt;/span&gt; heap[l] &amp;gt; heap[max_index]:
&lt;span class=&quot;linenr&quot;&gt; 6: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;max_index&lt;/span&gt; = l
&lt;span class=&quot;linenr&quot;&gt; 7: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;elif&lt;/span&gt; r &amp;lt; size &lt;span style=&quot;color: #729fcf;&quot;&gt;and&lt;/span&gt; heap[r] &amp;gt; heap[max_index]:
&lt;span class=&quot;linenr&quot;&gt; 8: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;max_index&lt;/span&gt; = r
&lt;span class=&quot;linenr&quot;&gt; 9: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;10: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; root != max_index:
&lt;span class=&quot;linenr&quot;&gt;11: &lt;/span&gt;        heap[root], &lt;span style=&quot;color: #eeeeec;&quot;&gt;heap&lt;/span&gt;[max_index] = heap[max_index], heap[root]
&lt;span class=&quot;linenr&quot;&gt;12: &lt;/span&gt;        heapify(heap, max_index)
&lt;span class=&quot;linenr&quot;&gt;13: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;14: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #e6a00f;&quot;&gt;None&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
用python实现如下：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span class=&quot;linenr&quot;&gt;1: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;build_heap&lt;/span&gt;(heap):
&lt;span class=&quot;linenr&quot;&gt;2: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;size&lt;/span&gt; = &lt;span style=&quot;color: #729fcf;&quot;&gt;len&lt;/span&gt;(heap)
&lt;span class=&quot;linenr&quot;&gt;3: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;last&lt;/span&gt; = size / 2 - 1
&lt;span class=&quot;linenr&quot;&gt;4: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; cur &lt;span style=&quot;color: #729fcf;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;range&lt;/span&gt;(last, -1, -1):
&lt;span class=&quot;linenr&quot;&gt;5: &lt;/span&gt;        heapify(heap, cur, size)
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline5&quot;&gt;实现堆排序&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;p&gt;
根据&lt;a href=&quot;#orgheadline1&quot;&gt;堆排序概述&lt;/a&gt;中的内容，可以大致将堆排序描述如下：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span class=&quot;linenr&quot;&gt; 1: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;hsort&lt;/span&gt;(arr):
&lt;span class=&quot;linenr&quot;&gt; 2: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;size&lt;/span&gt; = &lt;span style=&quot;color: #729fcf;&quot;&gt;len&lt;/span&gt;(arr)
&lt;span class=&quot;linenr&quot;&gt; 3: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;last&lt;/span&gt; = size - 1
&lt;span class=&quot;linenr&quot;&gt; 4: &lt;/span&gt;    build_heap(arr)
&lt;span class=&quot;linenr&quot;&gt; 5: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 6: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;while&lt;/span&gt; size &amp;gt; 1:
&lt;span class=&quot;linenr&quot;&gt; 7: &lt;/span&gt;        arr[0], &lt;span style=&quot;color: #eeeeec;&quot;&gt;arr&lt;/span&gt;[last] = arr[last], arr[0]
&lt;span class=&quot;linenr&quot;&gt; 8: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;last&lt;/span&gt; = last - 1
&lt;span class=&quot;linenr&quot;&gt; 9: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;size&lt;/span&gt; = size - 1
&lt;span class=&quot;linenr&quot;&gt;10: &lt;/span&gt;        heapify(arr, 0, size)
&lt;span class=&quot;linenr&quot;&gt;11: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;12: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #e6a00f;&quot;&gt;None&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结合前面实现的parent、lchild、rchild、heapify、build_heap几个函数，就可以实现一个完整的堆排序算法了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline6&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline6&quot;&gt;发散：TOP K问题&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline6&quot;&gt;
&lt;p&gt;
所谓的 &lt;b&gt;TOP K问题&lt;/b&gt; ，是指在大规模数据处理时常遇到的一类问题，要求在海量数据中找出最大的前K个数。这个问题可以通过建立小顶堆来解决——当然了，为了效率和资源的有效利用，这类问题通常还有整体方面的架构设计等工作需要做，远不是只建立一个小顶堆就能解决的，不过这些本文不作讨论。
&lt;/p&gt;

&lt;p&gt;
通过预先读入K个数据并建立小顶堆后，再逐个读入数据，将新元素和堆顶元素进行比较，如果新元素小于堆顶元素，就丢弃；如果新元素大于堆顶元素，则用新元素替代堆顶元素，并且重新调整堆使之保持小顶堆性质。
&lt;/p&gt;

&lt;p&gt;
这样处理后，总可以保证 &lt;b&gt;目前&lt;/b&gt; 读到的数据中最大的K个在小顶堆中。
&lt;/p&gt;

&lt;p&gt;
当我一开始接触到这个问题时，我幼稚地认为应该使用大顶堆，但实际上是错误的。用大顶堆可以保证堆顶元素是最大，但不能保证堆中元素是前K个最大的数。
&lt;/p&gt;

&lt;p&gt;
我误认为应该使用大顶堆的原因还有一个，那就是忽视了“海量数据”这个情境。
&lt;/p&gt;

&lt;p&gt;
对于小规模的TOP K问题，可以直接将数据进行排序，然后取出最大的K个数。但海量数据处理中，数据是不可能同时全部进入内存的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>排序算法——归并排序</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/01/11/merge-sort.html"/>
    <category term="算法" scheme="http://www.zmonster.me/categories.html#算法"/>
    <id>http://www.zmonster.me/2014/01/11/merge-sort</id>
    <published>2014-01-11T00:00:00+00:00</published>
    <updated>2014-01-11T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


归并排序
算法思想
完整实现
发散：外排序应用
References




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;归并排序&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;算法思想&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;完整实现&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;发散：外排序应用&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;References&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;归并排序&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
归并排序也是一种使用分治法来实现的有效排序算法，它是现代计算机创始人John von Neumann于1945年发明的。
&lt;/p&gt;

&lt;p&gt;
归并排序在众多排序算法中既是稳定排序，又有不错的效率，同时，归并排序不仅可以用于内排序，还可以用于外排序。所以说归并排序是非常值得学习的。
&lt;/p&gt;

&lt;p&gt;
本文将对归并排序的思想进行阐释，并给出完整的实现，然后对外排序进行探讨。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;算法思想&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
归并排序的思路如下(以二路归并为例)：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;将数组划均分为两个子数组；&lt;/li&gt;
&lt;li&gt;对两个字数组进行排序；&lt;/li&gt;
&lt;li&gt;将排序好的两个字数组归并。&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
所谓 &lt;b&gt;N路归并&lt;/b&gt; 是指将数组均分为N个子数组，将字数组排序后再归并。因此二路归并是归并排序的最一般的情况。
&lt;/p&gt;

&lt;p&gt;
这里是二路归并排序的一个图示：
&lt;img src=&quot;/assets/img/merge-sort.png&quot; alt=&quot;merge-sort.png&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;
二路归并排序用python描述如下：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span class=&quot;linenr&quot;&gt;1: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;msort&lt;/span&gt;(array):
&lt;span class=&quot;linenr&quot;&gt;2: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;length&lt;/span&gt; = &lt;span style=&quot;color: #729fcf;&quot;&gt;len&lt;/span&gt;(array)
&lt;span class=&quot;linenr&quot;&gt;3: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; length == 1:
&lt;span class=&quot;linenr&quot;&gt;4: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; array
&lt;span class=&quot;linenr&quot;&gt;5: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt;:
&lt;span class=&quot;linenr&quot;&gt;6: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;mid&lt;/span&gt; = length / 2
&lt;span class=&quot;linenr&quot;&gt;7: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;left&lt;/span&gt; = msort(array[0: mid])
&lt;span class=&quot;linenr&quot;&gt;8: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;right&lt;/span&gt; = msort(array[mid: length])
&lt;span class=&quot;linenr&quot;&gt;9: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; merge(left, right)
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
当然，这里描述的是递归版本的算法，实际情况中有时候也会为了效率而使用循环而不是递归来实现归并排序。下面是使用循环的算法描述：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span class=&quot;linenr&quot;&gt; 1: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;msort&lt;/span&gt;(array):
&lt;span class=&quot;linenr&quot;&gt; 2: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;length&lt;/span&gt; = &lt;span style=&quot;color: #729fcf;&quot;&gt;len&lt;/span&gt;(array)
&lt;span class=&quot;linenr&quot;&gt; 3: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;step&lt;/span&gt; = 1
&lt;span class=&quot;linenr&quot;&gt; 4: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;while&lt;/span&gt; step &amp;lt; length:
&lt;span class=&quot;linenr&quot;&gt; 5: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; left &lt;span style=&quot;color: #729fcf;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;range&lt;/span&gt;(0, length - step, 2 * step):
&lt;span class=&quot;linenr&quot;&gt; 6: &lt;/span&gt;            &lt;span style=&quot;color: #eeeeec;&quot;&gt;result&lt;/span&gt; = merge(array[left:left + step],
&lt;span class=&quot;linenr&quot;&gt; 7: &lt;/span&gt;                           array[left + step: &lt;span style=&quot;color: #729fcf;&quot;&gt;min&lt;/span&gt;(left + 2 * step,
&lt;span class=&quot;linenr&quot;&gt; 8: &lt;/span&gt;                                                  length)])
&lt;span class=&quot;linenr&quot;&gt; 9: &lt;/span&gt;            &lt;span style=&quot;color: #eeeeec;&quot;&gt;array&lt;/span&gt; = array[0:left] + result + array[&lt;span style=&quot;color: #729fcf;&quot;&gt;min&lt;/span&gt;(left + 2 *
&lt;span class=&quot;linenr&quot;&gt;10: &lt;/span&gt;                                                       step, length)]
&lt;span class=&quot;linenr&quot;&gt;11: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;step&lt;/span&gt; = step * 2
&lt;span class=&quot;linenr&quot;&gt;12: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; array
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
msort中的归并部分(merge)的思想是：分别取出字数组中最小的元素，取它们中较小的放入原数组中，然后重复这个过程。《算法导论》中将这个过程类比为整理扑克牌的过程，非常形象。想象一下，桌面上有两堆扑克，它们都朝下扣着，并且按照牌面点数从小到大放置，我们要的是把这两堆扑克都拿到手里，并且按照从小到大的顺序排好序，这个时候要怎么做？
&lt;/p&gt;

&lt;p&gt;
归并的思想可以用python描述如下：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span class=&quot;linenr&quot;&gt; 1: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;merge&lt;/span&gt;(left, right):
&lt;span class=&quot;linenr&quot;&gt; 2: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;llen&lt;/span&gt; = &lt;span style=&quot;color: #729fcf;&quot;&gt;len&lt;/span&gt;(left)
&lt;span class=&quot;linenr&quot;&gt; 3: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;lcur&lt;/span&gt; = 0
&lt;span class=&quot;linenr&quot;&gt; 4: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;rlen&lt;/span&gt; = &lt;span style=&quot;color: #729fcf;&quot;&gt;len&lt;/span&gt;(right)
&lt;span class=&quot;linenr&quot;&gt; 5: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;rcur&lt;/span&gt; = 0
&lt;span class=&quot;linenr&quot;&gt; 6: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;result&lt;/span&gt; = []
&lt;span class=&quot;linenr&quot;&gt; 7: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;while&lt;/span&gt; lcur &amp;lt; llen &lt;span style=&quot;color: #729fcf;&quot;&gt;and&lt;/span&gt; rcur &amp;lt; rlen:
&lt;span class=&quot;linenr&quot;&gt; 8: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;lone&lt;/span&gt; = left[lcur]
&lt;span class=&quot;linenr&quot;&gt; 9: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;rone&lt;/span&gt; = right[rcur]
&lt;span class=&quot;linenr&quot;&gt;10: &lt;/span&gt;        result.append(&lt;span style=&quot;color: #729fcf;&quot;&gt;min&lt;/span&gt;(lone, rone))
&lt;span class=&quot;linenr&quot;&gt;11: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; lone &amp;lt; rone:
&lt;span class=&quot;linenr&quot;&gt;12: &lt;/span&gt;            &lt;span style=&quot;color: #eeeeec;&quot;&gt;lcur&lt;/span&gt; += 1
&lt;span class=&quot;linenr&quot;&gt;13: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt;:
&lt;span class=&quot;linenr&quot;&gt;14: &lt;/span&gt;            &lt;span style=&quot;color: #eeeeec;&quot;&gt;rcur&lt;/span&gt; += 1
&lt;span class=&quot;linenr&quot;&gt;15: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;result&lt;/span&gt; += left[lcur:]
&lt;span class=&quot;linenr&quot;&gt;16: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;result&lt;/span&gt; += right[rcur:]
&lt;span class=&quot;linenr&quot;&gt;17: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; result
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;完整实现&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
下面是综合了非递归与递归版本的二路归并排序的完整实现，结果由org-babel对代码块求值得到。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span class=&quot;linenr&quot;&gt; 1: &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;-*- coding: utf-8 -*-&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 2: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;merge&lt;/span&gt;(left, right):
&lt;span class=&quot;linenr&quot;&gt; 3: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;llen&lt;/span&gt; = &lt;span style=&quot;color: #729fcf;&quot;&gt;len&lt;/span&gt;(left)
&lt;span class=&quot;linenr&quot;&gt; 4: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;lcur&lt;/span&gt; = 0
&lt;span class=&quot;linenr&quot;&gt; 5: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;rlen&lt;/span&gt; = &lt;span style=&quot;color: #729fcf;&quot;&gt;len&lt;/span&gt;(right)
&lt;span class=&quot;linenr&quot;&gt; 6: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;rcur&lt;/span&gt; = 0
&lt;span class=&quot;linenr&quot;&gt; 7: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;result&lt;/span&gt; = []
&lt;span class=&quot;linenr&quot;&gt; 8: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;while&lt;/span&gt; lcur &amp;lt; llen &lt;span style=&quot;color: #729fcf;&quot;&gt;and&lt;/span&gt; rcur &amp;lt; rlen:
&lt;span class=&quot;linenr&quot;&gt; 9: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;lone&lt;/span&gt; = left[lcur]
&lt;span class=&quot;linenr&quot;&gt;10: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;rone&lt;/span&gt; = right[rcur]
&lt;span class=&quot;linenr&quot;&gt;11: &lt;/span&gt;        result.append(&lt;span style=&quot;color: #729fcf;&quot;&gt;min&lt;/span&gt;(lone, rone))
&lt;span class=&quot;linenr&quot;&gt;12: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; lone &amp;lt; rone:
&lt;span class=&quot;linenr&quot;&gt;13: &lt;/span&gt;            &lt;span style=&quot;color: #eeeeec;&quot;&gt;lcur&lt;/span&gt; += 1
&lt;span class=&quot;linenr&quot;&gt;14: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt;:
&lt;span class=&quot;linenr&quot;&gt;15: &lt;/span&gt;            &lt;span style=&quot;color: #eeeeec;&quot;&gt;rcur&lt;/span&gt; += 1
&lt;span class=&quot;linenr&quot;&gt;16: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;result&lt;/span&gt; += left[lcur:]
&lt;span class=&quot;linenr&quot;&gt;17: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;result&lt;/span&gt; += right[rcur:]
&lt;span class=&quot;linenr&quot;&gt;18: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; result
&lt;span class=&quot;linenr&quot;&gt;19: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;20: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;msort_rec&lt;/span&gt;(array):
&lt;span class=&quot;linenr&quot;&gt;21: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;length&lt;/span&gt; = &lt;span style=&quot;color: #729fcf;&quot;&gt;len&lt;/span&gt;(array)
&lt;span class=&quot;linenr&quot;&gt;22: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; length == 1:
&lt;span class=&quot;linenr&quot;&gt;23: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; array
&lt;span class=&quot;linenr&quot;&gt;24: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt;:
&lt;span class=&quot;linenr&quot;&gt;25: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;mid&lt;/span&gt; = length / 2
&lt;span class=&quot;linenr&quot;&gt;26: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;left&lt;/span&gt; = msort_rec(array[0: mid])
&lt;span class=&quot;linenr&quot;&gt;27: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;right&lt;/span&gt; = msort_rec(array[mid: length])
&lt;span class=&quot;linenr&quot;&gt;28: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; merge(left, right)
&lt;span class=&quot;linenr&quot;&gt;29: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;30: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;msort_iter&lt;/span&gt;(array):
&lt;span class=&quot;linenr&quot;&gt;31: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;length&lt;/span&gt; = &lt;span style=&quot;color: #729fcf;&quot;&gt;len&lt;/span&gt;(array)
&lt;span class=&quot;linenr&quot;&gt;32: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;step&lt;/span&gt; = 1
&lt;span class=&quot;linenr&quot;&gt;33: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;while&lt;/span&gt; step &amp;lt; length:
&lt;span class=&quot;linenr&quot;&gt;34: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; left &lt;span style=&quot;color: #729fcf;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;range&lt;/span&gt;(0, length - step, 2 * step):
&lt;span class=&quot;linenr&quot;&gt;35: &lt;/span&gt;            &lt;span style=&quot;color: #eeeeec;&quot;&gt;result&lt;/span&gt; = merge(array[left:left + step],
&lt;span class=&quot;linenr&quot;&gt;36: &lt;/span&gt;                           array[left + step: &lt;span style=&quot;color: #729fcf;&quot;&gt;min&lt;/span&gt;(left + 2 * step,
&lt;span class=&quot;linenr&quot;&gt;37: &lt;/span&gt;                                                  length)])
&lt;span class=&quot;linenr&quot;&gt;38: &lt;/span&gt;            &lt;span style=&quot;color: #eeeeec;&quot;&gt;array&lt;/span&gt; = array[0:left] + result + array[&lt;span style=&quot;color: #729fcf;&quot;&gt;min&lt;/span&gt;(left + 2 *
&lt;span class=&quot;linenr&quot;&gt;39: &lt;/span&gt;                                                       step, length):]
&lt;span class=&quot;linenr&quot;&gt;40: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;step&lt;/span&gt; = step * 2
&lt;span class=&quot;linenr&quot;&gt;41: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; array
&lt;span class=&quot;linenr&quot;&gt;42: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;43: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;__name__&lt;/span&gt; == &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'__main__'&lt;/span&gt;:
&lt;span class=&quot;linenr&quot;&gt;44: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;L&lt;/span&gt; = [1, 4, 2, 6, 3, 5, 8, 7]
&lt;span class=&quot;linenr&quot;&gt;45: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&amp;#25490;&amp;#24207;&amp;#21069;: %r&quot;&lt;/span&gt; %(L)
&lt;span class=&quot;linenr&quot;&gt;46: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;R&lt;/span&gt; = msort_rec(L)
&lt;span class=&quot;linenr&quot;&gt;47: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&amp;#25490;&amp;#24207;&amp;#21518;(&amp;#36882;&amp;#24402;): %r&quot;&lt;/span&gt; %(R)
&lt;span class=&quot;linenr&quot;&gt;48: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;I&lt;/span&gt; = msort_iter(L)
&lt;span class=&quot;linenr&quot;&gt;49: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&amp;#25490;&amp;#24207;&amp;#21518;(&amp;#38750;&amp;#36882;&amp;#24402;): %r&quot;&lt;/span&gt; %(I)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
排序前: [1, 4, 2, 6, 3, 5, 8, 7]
排序后(递归): [1, 2, 3, 4, 5, 6, 7, 8]
排序后(非递归): [1, 2, 3, 4, 5, 6, 7, 8]
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline4&quot;&gt;发散：外排序应用&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
归并排序的思想可以用于外排序。外排序是相对内排序而言的。在常规的小规模排序过程中，都是直接在内存中对数据进行排序处理的，而对于数据量极大的排序问题，这种方式是不现实的。这个时候就要通过外排序来进行，先将数据划分成多个规模能在内存中处理的子集，对各个子集排序后存放在临时的磁盘文件上，然后再将这些子集归并到输出文件中。这个过程要使用到多路归并，如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/external-sort.png&quot; alt=&quot;external-sort.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
注：该图来自 &lt;a href=&quot;#orgheadline5&quot;&gt;References&lt;/a&gt; 中第一篇文章。
&lt;/p&gt;

&lt;p&gt;
那么来实现一下吧。
&lt;/p&gt;

&lt;p&gt;
首先要创建一个大文件，往里面写入大量的数据，该函数实现如下(因为python不方便读取单个数字，下面的东西都是用C写的):
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;linenr&quot;&gt; 1: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 2: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 3: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;time.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 4: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 5: &lt;/span&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;rand_file&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;file&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;num&lt;/span&gt;)
&lt;span class=&quot;linenr&quot;&gt; 6: &lt;/span&gt;{
&lt;span class=&quot;linenr&quot;&gt; 7: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt; = 0;
&lt;span class=&quot;linenr&quot;&gt; 8: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;now&lt;/span&gt;;
&lt;span class=&quot;linenr&quot;&gt; 9: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;FILE&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;f&lt;/span&gt; = fopen(file, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;w&quot;&lt;/span&gt;);
&lt;span class=&quot;linenr&quot;&gt;10: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;11: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (f == &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;) {
&lt;span class=&quot;linenr&quot;&gt;12: &lt;/span&gt;        perror(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;fopen&quot;&lt;/span&gt;);
&lt;span class=&quot;linenr&quot;&gt;13: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
&lt;span class=&quot;linenr&quot;&gt;14: &lt;/span&gt;    }
&lt;span class=&quot;linenr&quot;&gt;15: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;16: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (; i &amp;lt; num; ++i) {
&lt;span class=&quot;linenr&quot;&gt;17: &lt;/span&gt;        srand((&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt;)time(0));
&lt;span class=&quot;linenr&quot;&gt;18: &lt;/span&gt;        now = rand();
&lt;span class=&quot;linenr&quot;&gt;19: &lt;/span&gt;        fprintf(f, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%d &quot;&lt;/span&gt;, now);
&lt;span class=&quot;linenr&quot;&gt;20: &lt;/span&gt;    }
&lt;span class=&quot;linenr&quot;&gt;21: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;22: &lt;/span&gt;    fclose(f);
&lt;span class=&quot;linenr&quot;&gt;23: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; num;
&lt;span class=&quot;linenr&quot;&gt;24: &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
然后，我们需要一个将文件读入数组的函数和一个将数组内容写入文件的函数，实现如下：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;linenr&quot;&gt; 1: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 2: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 3: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 4: &lt;/span&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;read_to_mem&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;FILE&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;file&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;arr&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;len&lt;/span&gt;)
&lt;span class=&quot;linenr&quot;&gt; 5: &lt;/span&gt;{
&lt;span class=&quot;linenr&quot;&gt; 6: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt; = 0;
&lt;span class=&quot;linenr&quot;&gt; 7: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (file != &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;) {
&lt;span class=&quot;linenr&quot;&gt; 8: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (; !feof(file) &amp;amp;&amp;amp; i &amp;lt; len; ++i) {
&lt;span class=&quot;linenr&quot;&gt; 9: &lt;/span&gt;            fscanf(file, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%d&quot;&lt;/span&gt;, arr + i);
&lt;span class=&quot;linenr&quot;&gt;10: &lt;/span&gt;        }
&lt;span class=&quot;linenr&quot;&gt;11: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; i;
&lt;span class=&quot;linenr&quot;&gt;12: &lt;/span&gt;    }
&lt;span class=&quot;linenr&quot;&gt;13: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;14: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
&lt;span class=&quot;linenr&quot;&gt;15: &lt;/span&gt;}
&lt;span class=&quot;linenr&quot;&gt;16: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;17: &lt;/span&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;write_from_mem&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;FILE&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;file&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;arr&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;len&lt;/span&gt;)
&lt;span class=&quot;linenr&quot;&gt;18: &lt;/span&gt;{
&lt;span class=&quot;linenr&quot;&gt;19: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt; = 0;
&lt;span class=&quot;linenr&quot;&gt;20: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (file != &lt;span style=&quot;color: #e6a00f;&quot;&gt;NULL&lt;/span&gt;) {
&lt;span class=&quot;linenr&quot;&gt;21: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; ( ; i &amp;lt; len; ++i) {
&lt;span class=&quot;linenr&quot;&gt;22: &lt;/span&gt;            fprintf(file, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%d &quot;&lt;/span&gt;, arr[i]);
&lt;span class=&quot;linenr&quot;&gt;23: &lt;/span&gt;        }
&lt;span class=&quot;linenr&quot;&gt;24: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;25: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; i;
&lt;span class=&quot;linenr&quot;&gt;26: &lt;/span&gt;    }
&lt;span class=&quot;linenr&quot;&gt;27: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;28: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;29: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
&lt;span class=&quot;linenr&quot;&gt;30: &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
完成这些准备工作后，就可以开始实现外排序了。循环将大文件读入一部分到内存，然后对这一部分进行排序——此时的排序可以使用快速排序、归并排序等各种排序算法，并无限制。
&lt;/p&gt;

&lt;p&gt;
将各部分都排好序并保存为临时文件后的归并步骤是外排序的核心所在。多路归并的思路和二路归并是类似的。可以将归并模块实现为：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;linenr&quot;&gt; 1: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 2: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 3: &lt;/span&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;merge&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;File&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;out&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;File&lt;/span&gt; **&lt;span style=&quot;color: #eeeeec;&quot;&gt;flist&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;fnum&lt;/span&gt;)
&lt;span class=&quot;linenr&quot;&gt; 4: &lt;/span&gt;{
&lt;span class=&quot;linenr&quot;&gt; 5: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;i&lt;/span&gt; = 0;
&lt;span class=&quot;linenr&quot;&gt; 6: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;now&lt;/span&gt; = 0;                &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#29992;&amp;#20110;&amp;#20445;&amp;#23384;&amp;#24403;&amp;#21069;&amp;#26368;&amp;#23567;&amp;#30340;&amp;#20540; &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 7: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;fstaus&lt;/span&gt; = (&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; *)calloc(fnum, &lt;span style=&quot;color: #729fcf;&quot;&gt;sizeof&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt;)); &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#35760;&amp;#24405;&amp;#25991;&amp;#20214;&amp;#29366;&amp;#24577; &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 8: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;farr&lt;/span&gt; =(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; *)calloc(fnum, &lt;span style=&quot;color: #729fcf;&quot;&gt;sizeof&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt;));    &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#35760;&amp;#24405;&amp;#20174;&amp;#21508;&amp;#20010;&amp;#25991;&amp;#20214;&amp;#20013;&amp;#21462;&amp;#20986;&amp;#30340;&amp;#25968; &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 9: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;min&lt;/span&gt; = 0;                &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#35760;&amp;#24405;&amp;#24403;&amp;#21069;&amp;#20540;&amp;#26368;&amp;#23567;&amp;#30340;&amp;#25991;&amp;#20214;&amp;#32034;&amp;#24341; &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;10: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;11: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (; i &amp;lt; fnum; ++i) {     &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#26816;&amp;#26597;&amp;#21508;&amp;#20010;&amp;#25991;&amp;#20214;&amp;#25351;&amp;#38024;&amp;#30340;&amp;#29366;&amp;#24577; &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;12: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (feof(fscanf(flist[i], &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%d&quot;&lt;/span&gt;, farr + i))) {
&lt;span class=&quot;linenr&quot;&gt;13: &lt;/span&gt;            fstatus[i] = 0;
&lt;span class=&quot;linenr&quot;&gt;14: &lt;/span&gt;        }
&lt;span class=&quot;linenr&quot;&gt;15: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;else&lt;/span&gt; {
&lt;span class=&quot;linenr&quot;&gt;16: &lt;/span&gt;            fstatus[i] = 1;
&lt;span class=&quot;linenr&quot;&gt;17: &lt;/span&gt;        }
&lt;span class=&quot;linenr&quot;&gt;18: &lt;/span&gt;    }
&lt;span class=&quot;linenr&quot;&gt;19: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;20: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;while&lt;/span&gt; (1) {
&lt;span class=&quot;linenr&quot;&gt;21: &lt;/span&gt;        now = 0;
&lt;span class=&quot;linenr&quot;&gt;22: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (i = 0; i &amp;lt; fnum &amp;amp;&amp;amp; !fstatus[i]; ++i) {}
&lt;span class=&quot;linenr&quot;&gt;23: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (i &amp;gt;= fnum) {     &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#22914;&amp;#26080;&amp;#21487;&amp;#29992;&amp;#25991;&amp;#20214;&amp;#65292;&amp;#21017;&amp;#36864;&amp;#20986; &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;24: &lt;/span&gt;            &lt;span style=&quot;color: #729fcf;&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;linenr&quot;&gt;25: &lt;/span&gt;        }
&lt;span class=&quot;linenr&quot;&gt;26: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;27: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (; i &amp;lt; fnum; ++i) { &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#20174;&amp;#31532;&amp;#19968;&amp;#20010;&amp;#21487;&amp;#29992;&amp;#30340;&amp;#25991;&amp;#20214;&amp;#24320;&amp;#22987;&amp;#35835; &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;28: &lt;/span&gt;            &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (fstatus[i] &amp;amp;&amp;amp; farr[i] &amp;lt; now) {
&lt;span class=&quot;linenr&quot;&gt;29: &lt;/span&gt;                now = farr[i];
&lt;span class=&quot;linenr&quot;&gt;30: &lt;/span&gt;                min = i;
&lt;span class=&quot;linenr&quot;&gt;31: &lt;/span&gt;            }
&lt;span class=&quot;linenr&quot;&gt;32: &lt;/span&gt;        }
&lt;span class=&quot;linenr&quot;&gt;33: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;34: &lt;/span&gt;        fprintf(out, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%d &quot;&lt;/span&gt;, now); &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#23558;&amp;#26368;&amp;#23567;&amp;#20540;&amp;#20889;&amp;#20837;&amp;#36755;&amp;#20986;&amp;#25991;&amp;#20214; &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;35: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;36: &lt;/span&gt;        &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#35835;&amp;#21462;&amp;#35813;&amp;#25991;&amp;#20214;&amp;#19979;&amp;#19968;&amp;#20010;&amp;#25968;&amp;#65292;&amp;#24182;&amp;#26816;&amp;#26597;&amp;#26159;&amp;#21542;&amp;#35835;&amp;#23436; &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;37: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (feof(fscanf(flist[min], &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%d&quot;&lt;/span&gt;, farr + min))) {
&lt;span class=&quot;linenr&quot;&gt;38: &lt;/span&gt;            fstatus[min] = 0;
&lt;span class=&quot;linenr&quot;&gt;39: &lt;/span&gt;        }
&lt;span class=&quot;linenr&quot;&gt;40: &lt;/span&gt;    }
&lt;span class=&quot;linenr&quot;&gt;41: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;42: &lt;/span&gt;    free(farr);                 &lt;span style=&quot;color: #888a85;&quot;&gt;/* &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;&amp;#37322;&amp;#25918;&amp;#20869;&amp;#23384; &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;*/&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;43: &lt;/span&gt;    free(fstatus);
&lt;span class=&quot;linenr&quot;&gt;44: &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
完整的实现我就不写了，太累……写这篇文章就用了一整天。
&lt;/p&gt;

&lt;p&gt;
嗯，大概就是这个样子。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline5&quot;&gt;References&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://www.cnblogs.com/daoluanxiaozi/archive/2012/03/29/2423087.html&quot;&gt;《编程珠玑，字字珠玑》1234读书笔记——多路归并排序&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://diducoder.com/mass-data-topic-9-external-sort.html&quot;&gt;海量数据处理专题（九）——外排序&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.cnblogs.com/huangxincheng/archive/2012/12/19/2824943.html&quot;&gt;经典算法题每日演练——第十八题 外排序&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.csdn.net/v_JULY_v/article/details/6451990&quot;&gt;程序员编程艺术：第十章、如何给10^7个数据量的磁盘文件排序&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>排序算法——快速排序</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/01/10/quick-sort.html"/>
    <category term="算法" scheme="http://www.zmonster.me/categories.html#算法"/>
    <id>http://www.zmonster.me/2014/01/10/quick-sort</id>
    <published>2014-01-10T00:00:00+00:00</published>
    <updated>2014-01-10T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


快速排序
原理

数组划分
完整实现


发散




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;快速排序&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;原理&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;数组划分&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;完整实现&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;发散&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;快速排序&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
快速排序是一种广为使用的排序算法，其算法复杂度为O(NlogN)，从效率上来说是很不错的。
&lt;/p&gt;

&lt;p&gt;
刚接触排序算法的新手可能没有办法很快地把它实现出来，但其实在对它的原理有了透彻的了解后，这一步是不难做到的。
&lt;/p&gt;

&lt;p&gt;
不记得是在哪里看到的了，说熟悉算法的最好办法，就是反复地去实现它，写完删掉重写，知道能够不怎么思考就把它写出来就算是掌握了。我就是通过这个方法来掌握排序算法的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;原理&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
快速排序采用了“分治法”，关于分治法不想说太多，更多的细节可以参考&lt;a href=&quot;http://zh.wikipedia.org/wiki/%E5%88%86%E6%B2%BB%E6%B3%95&quot;&gt;维基百科&lt;/a&gt;。 具体来说，快速排序的思想是很简单的，分为两步：
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;将数组划分为以某个值为分界的两部分&lt;/li&gt;
&lt;li&gt;对划分好的两部分各自又进行快速排序&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
其中第二步就是“分治法”的体现，即所谓“分而治之”。而快速排序的实现工作大多花费在“划分”上。
&lt;/p&gt;

&lt;p&gt;
下面是快速排序的算法描述(python描述)
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span class=&quot;linenr&quot;&gt;1: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;qsort&lt;/span&gt;(array, low, high):
&lt;span class=&quot;linenr&quot;&gt;2: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; low &amp;lt; high:
&lt;span class=&quot;linenr&quot;&gt;3: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;mid&lt;/span&gt; = partition(array, low, high)
&lt;span class=&quot;linenr&quot;&gt;4: &lt;/span&gt;        qsort(array, low, mid - 1)
&lt;span class=&quot;linenr&quot;&gt;5: &lt;/span&gt;        qsort(array, mid + 1, high)
&lt;span class=&quot;linenr&quot;&gt;6: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; array
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline3&quot;&gt;数组划分&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
我对这一部分是非常感兴趣的，因为我发现这一部分不仅仅可以用在快速排序中。
&lt;/p&gt;

&lt;p&gt;
划分首先要选定一个值作为分界线。选取这个值的方法有随机选取和固定选取两种，随机选取就不说了，顾名思义；固定选取就是选取当前要划分的区域上特定位置的元素，比如第一个元素或者最后一个元素。本文以选取最后一个元素为例来进行说明。
&lt;/p&gt;

&lt;p&gt;
划分的思想就是，遍历数组，遇到比关键值小的元素，就放到数组前面。在这样的处理过程中，数组前部会有连续的一段空间，其中的所有元素都比关键值小，因此在处理的过程中通常要用一个游标来记录这段空间的最后一个位置，遇到新的小于关键值的元素要放过来时，就将其放到游标后面的位置，并更新游标。如下图所示
&lt;/p&gt;



&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/partition.png&quot; alt=&quot;partition.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
当然，我这里说的是将比关键值小的元素交换到数组前部，也有将大于关键值的元素交换到数组尾部以及结合这两种做法的。
&lt;/p&gt;

&lt;p&gt;
数组划分的算法描述为：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span class=&quot;linenr&quot;&gt; 1: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;partition&lt;/span&gt;(array, low, high):
&lt;span class=&quot;linenr&quot;&gt; 2: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;cur&lt;/span&gt; = low - 1
&lt;span class=&quot;linenr&quot;&gt; 3: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;key&lt;/span&gt; = array[high]
&lt;span class=&quot;linenr&quot;&gt; 4: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 5: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; index &lt;span style=&quot;color: #729fcf;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;range&lt;/span&gt;(low, high):
&lt;span class=&quot;linenr&quot;&gt; 6: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;elem&lt;/span&gt; = array[index]
&lt;span class=&quot;linenr&quot;&gt; 7: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; elem &amp;lt; key:
&lt;span class=&quot;linenr&quot;&gt; 8: &lt;/span&gt;            &lt;span style=&quot;color: #eeeeec;&quot;&gt;cur&lt;/span&gt; = cur + 1;
&lt;span class=&quot;linenr&quot;&gt; 9: &lt;/span&gt;            array[index], &lt;span style=&quot;color: #eeeeec;&quot;&gt;array&lt;/span&gt;[cur] = array[cur], array[index]
&lt;span class=&quot;linenr&quot;&gt;10: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;11: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;cur&lt;/span&gt; = cur + 1;
&lt;span class=&quot;linenr&quot;&gt;12: &lt;/span&gt;    array[cur], &lt;span style=&quot;color: #eeeeec;&quot;&gt;array&lt;/span&gt;[high] = array[high], array[cur]
&lt;span class=&quot;linenr&quot;&gt;13: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;14: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; cur;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline4&quot;&gt;完整实现&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
下面是一个完整的实现，以及对给定数组进行排序的示例。注明一下，这里的结果是通过org-babel对下面的代码块求值得到的。
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-python&quot;&gt;&lt;span class=&quot;linenr&quot;&gt; 1: &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;# &lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;-*- coding: utf-8 -*-&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 2: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;partition&lt;/span&gt;(array, low, high):
&lt;span class=&quot;linenr&quot;&gt; 3: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;cur&lt;/span&gt; = low - 1
&lt;span class=&quot;linenr&quot;&gt; 4: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;key&lt;/span&gt; = array[high]
&lt;span class=&quot;linenr&quot;&gt; 5: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 6: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; index &lt;span style=&quot;color: #729fcf;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #729fcf;&quot;&gt;range&lt;/span&gt;(low, high):
&lt;span class=&quot;linenr&quot;&gt; 7: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;elem&lt;/span&gt; = array[index]
&lt;span class=&quot;linenr&quot;&gt; 8: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; elem &amp;lt; key:
&lt;span class=&quot;linenr&quot;&gt; 9: &lt;/span&gt;            &lt;span style=&quot;color: #eeeeec;&quot;&gt;cur&lt;/span&gt; = cur + 1
&lt;span class=&quot;linenr&quot;&gt;10: &lt;/span&gt;            array[index], &lt;span style=&quot;color: #eeeeec;&quot;&gt;array&lt;/span&gt;[cur] = array[cur], array[index]
&lt;span class=&quot;linenr&quot;&gt;11: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;12: &lt;/span&gt;    &lt;span style=&quot;color: #eeeeec;&quot;&gt;cur&lt;/span&gt; = cur + 1;
&lt;span class=&quot;linenr&quot;&gt;13: &lt;/span&gt;    array[cur], &lt;span style=&quot;color: #eeeeec;&quot;&gt;array&lt;/span&gt;[high] = array[high], array[cur]
&lt;span class=&quot;linenr&quot;&gt;14: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;15: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; cur;
&lt;span class=&quot;linenr&quot;&gt;16: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;17: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;qsort&lt;/span&gt;(array, low, high):
&lt;span class=&quot;linenr&quot;&gt;18: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; low &amp;lt; high:
&lt;span class=&quot;linenr&quot;&gt;19: &lt;/span&gt;        &lt;span style=&quot;color: #eeeeec;&quot;&gt;mid&lt;/span&gt; = partition(array, low, high)
&lt;span class=&quot;linenr&quot;&gt;20: &lt;/span&gt;        qsort(array, low, mid - 1)
&lt;span class=&quot;linenr&quot;&gt;21: &lt;/span&gt;        qsort(array, mid + 1, high)
&lt;span class=&quot;linenr&quot;&gt;22: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;23: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; array
&lt;span class=&quot;linenr&quot;&gt;24: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;25: &lt;/span&gt;&lt;span style=&quot;color: #eeeeec;&quot;&gt;L&lt;/span&gt; = [5, 2, 7, 6, 3, 1, 8, 4]
&lt;span class=&quot;linenr&quot;&gt;26: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&amp;#25490;&amp;#24207;&amp;#21069;: %r&quot;&lt;/span&gt; %(L)
&lt;span class=&quot;linenr&quot;&gt;27: &lt;/span&gt;qsort(L, 0, 7)
&lt;span class=&quot;linenr&quot;&gt;28: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&amp;#25490;&amp;#24207;&amp;#21518;: %r&quot;&lt;/span&gt; %(L)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
结果
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
排序前: [5, 2, 7, 6, 3, 1, 8, 4]
排序后: [1, 2, 3, 4, 5, 6, 7, 8]
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline5&quot;&gt;发散&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;p&gt;
之前说了，快速排序算法中的数组划分其实不仅仅可用于快速排序，那么，它还可以用于什么地方呢？从我的认识来看，很多需要将数据一分为二的情境中都可以使用到这个算法，比如说 &lt;b&gt;删除字符串中的特定字符&lt;/b&gt; 以及这个问题的变形 &lt;b&gt;删除字符串中的重复字符&lt;/b&gt; 。将快速排序算法中的划分算法稍作修改，就能得到这两个问题的线性复杂度的解决办法。
&lt;/p&gt;

&lt;p&gt;
附上这两个问题的C语言代码
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
删除字符串中特定字符
&lt;/p&gt;

&lt;p&gt;
这里的结果同样是通过org-babel对下面的代码块求值得到的
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;linenr&quot;&gt; 1: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 2: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 3: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 4: &lt;/span&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;del_char&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;del&lt;/span&gt;)
&lt;span class=&quot;linenr&quot;&gt; 5: &lt;/span&gt;{
&lt;span class=&quot;linenr&quot;&gt; 6: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;cur&lt;/span&gt; = -1;
&lt;span class=&quot;linenr&quot;&gt; 7: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;index&lt;/span&gt; = 0;
&lt;span class=&quot;linenr&quot;&gt; 8: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;temp&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'\0'&lt;/span&gt;;
&lt;span class=&quot;linenr&quot;&gt; 9: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (; index &amp;lt; strlen(str); ++index) {
&lt;span class=&quot;linenr&quot;&gt;10: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (str[index] != del) {
&lt;span class=&quot;linenr&quot;&gt;11: &lt;/span&gt;            ++cur;
&lt;span class=&quot;linenr&quot;&gt;12: &lt;/span&gt;            temp = str[cur];
&lt;span class=&quot;linenr&quot;&gt;13: &lt;/span&gt;            str[cur] = str[index];
&lt;span class=&quot;linenr&quot;&gt;14: &lt;/span&gt;            str[index] = str[cur];
&lt;span class=&quot;linenr&quot;&gt;15: &lt;/span&gt;        }
&lt;span class=&quot;linenr&quot;&gt;16: &lt;/span&gt;    }
&lt;span class=&quot;linenr&quot;&gt;17: &lt;/span&gt;    ++cur;
&lt;span class=&quot;linenr&quot;&gt;18: &lt;/span&gt;    str[cur] = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'\0'&lt;/span&gt;;
&lt;span class=&quot;linenr&quot;&gt;19: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; cur;
&lt;span class=&quot;linenr&quot;&gt;20: &lt;/span&gt;}
&lt;span class=&quot;linenr&quot;&gt;21: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;22: &lt;/span&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;()
&lt;span class=&quot;linenr&quot;&gt;23: &lt;/span&gt;{
&lt;span class=&quot;linenr&quot;&gt;24: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt;[] = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;abcdaaaaab&quot;&lt;/span&gt;;
&lt;span class=&quot;linenr&quot;&gt;25: &lt;/span&gt;    del_char(s, &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'a'&lt;/span&gt;);
&lt;span class=&quot;linenr&quot;&gt;26: &lt;/span&gt;    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;, s);
&lt;span class=&quot;linenr&quot;&gt;27: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
&lt;span class=&quot;linenr&quot;&gt;28: &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
得到的结果为：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
bcdb
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
删除字符串中的重复字符，如将&quot;aabbccdd&quot;处理后得到&quot;abcd&quot;
&lt;/p&gt;

&lt;p&gt;
这里的结果同样是通过org-babel对下面的代码块求值得到的
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;linenr&quot;&gt; 1: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 2: &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 3: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt; 4: &lt;/span&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;del_dup&lt;/span&gt;(&lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; *&lt;span style=&quot;color: #eeeeec;&quot;&gt;str&lt;/span&gt;)
&lt;span class=&quot;linenr&quot;&gt; 5: &lt;/span&gt;{
&lt;span class=&quot;linenr&quot;&gt; 6: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;cur&lt;/span&gt; = 0;
&lt;span class=&quot;linenr&quot;&gt; 7: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;index&lt;/span&gt; = 1;
&lt;span class=&quot;linenr&quot;&gt; 8: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;temp&lt;/span&gt; = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'\0'&lt;/span&gt;;
&lt;span class=&quot;linenr&quot;&gt; 9: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;last&lt;/span&gt; = str[0];
&lt;span class=&quot;linenr&quot;&gt;10: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;11: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;for&lt;/span&gt; (; index &amp;lt; strlen(str); ++index) {
&lt;span class=&quot;linenr&quot;&gt;12: &lt;/span&gt;        &lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (str[index] != last) {
&lt;span class=&quot;linenr&quot;&gt;13: &lt;/span&gt;            ++cur;
&lt;span class=&quot;linenr&quot;&gt;14: &lt;/span&gt;            temp = str[cur];
&lt;span class=&quot;linenr&quot;&gt;15: &lt;/span&gt;            str[cur] = str[index];
&lt;span class=&quot;linenr&quot;&gt;16: &lt;/span&gt;            str[index] = str[cur];
&lt;span class=&quot;linenr&quot;&gt;17: &lt;/span&gt;        }
&lt;span class=&quot;linenr&quot;&gt;18: &lt;/span&gt;        last = str[index];
&lt;span class=&quot;linenr&quot;&gt;19: &lt;/span&gt;    }
&lt;span class=&quot;linenr&quot;&gt;20: &lt;/span&gt;    ++cur;
&lt;span class=&quot;linenr&quot;&gt;21: &lt;/span&gt;    str[cur] = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;'\0'&lt;/span&gt;;
&lt;span class=&quot;linenr&quot;&gt;22: &lt;/span&gt;}
&lt;span class=&quot;linenr&quot;&gt;23: &lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;24: &lt;/span&gt;&lt;span style=&quot;color: #8ae234;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;main&lt;/span&gt;()
&lt;span class=&quot;linenr&quot;&gt;25: &lt;/span&gt;{
&lt;span class=&quot;linenr&quot;&gt;26: &lt;/span&gt;    &lt;span style=&quot;color: #8ae234;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;s&lt;/span&gt;[] = &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;aabbccdd&quot;&lt;/span&gt;;
&lt;span class=&quot;linenr&quot;&gt;27: &lt;/span&gt;    del_dup(s);
&lt;span class=&quot;linenr&quot;&gt;28: &lt;/span&gt;    printf(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;, s);
&lt;span class=&quot;linenr&quot;&gt;29: &lt;/span&gt;    &lt;span style=&quot;color: #729fcf;&quot;&gt;return&lt;/span&gt; 0;
&lt;span class=&quot;linenr&quot;&gt;30: &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
得到的结果为：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
abcd
&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
可以看到，这两个函数&quot;del_char&quot;和&quot;del_dup&quot;和之前的qsort中的&quot;partition&quot;函数是非常相似的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>使用ox-freemind将org-mode文档导出成思维导图</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/01/06/freemind-with-org-mode.html"/>
    <category term="Emacs" scheme="http://www.zmonster.me/categories.html#Emacs"/>
    <id>http://www.zmonster.me/2014/01/06/freemind-with-org-mode</id>
    <published>2014-01-06T00:00:00+00:00</published>
    <updated>2014-01-06T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


思维导图
使用ox-freemind.el
ox-freemind.el中的bug




思维导图


思维导图是一个很好地整理知识、表达思维的工具。因...</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;思维导图&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;使用ox-freemind.el&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;ox-freemind.el中的bug&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;思维导图&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
思维导图是一个很好地整理知识、表达思维的工具。因为使用Linux，我更经常使用Freemind这么一个开源的思维导图工具。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/Free_Mind.png&quot; alt=&quot;Free_Mind.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
Freemind本身也是一款很优秀的软件，它能够将思维导图导出成html、flah、Java Applet、Open Office文档以及PNG和JPEG两种格式的图片，并且对思维导图的绘制提供的快捷键。
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://freemind.sourceforge.net/wiki/index.php/Main_Page&quot;&gt;这里&lt;/a&gt; 是Freemind的官网。
&lt;/p&gt;

&lt;p&gt;
我曾经用Freemind绘制过一张Emacs的思维导图，放到了百度的emacs贴吧里，受到了一些Emacs新手的欢迎。因为那张图存在一定的错误，于是后来我决定重新画一张，而且决心要将更全面的内容表达出来。这是个非常累人的活，我断断续续用了一天时间才完成。
&lt;/p&gt;

&lt;p&gt;
老实说Freemind已经很方便了，在熟悉了相关快捷键后，能够很高效地进行思维导图的绘制。
&lt;/p&gt;

&lt;p&gt;
不过我希望能在更熟悉的环境中来做这件事情，我希望不用再去学习另外一套操作方式，而是能在org-mode中来绘制思维导图。
&lt;/p&gt;

&lt;p&gt;
我的Org版本是8.2.3c，这个版本的org-mode中提供了ox-freemind.el来满足我这个要求。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;使用ox-freemind.el&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
所有Org的核心模块都在 &lt;b&gt;org/lisp/&lt;/b&gt; 目录下，但这个插件并不是Org的核心模块，它被放置在 &lt;b&gt;org/contrib/lisp&lt;/b&gt; 目录下，如果您没有在Emacs配置文件中将这个路径加入加载路径，那么先做好这件事，然后在配置文件中添加：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;require&lt;/span&gt; '&lt;span style=&quot;color: #e6a00f;&quot;&gt;ox-freemind&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
然后就可以使用 &lt;b&gt;org-freemind-export-to-freemind&lt;/b&gt; 来将Org文档导出成Freemind文档了。
&lt;/p&gt;

&lt;p&gt;
如，我新建了一个文件 &lt;i&gt;mind.org&lt;/i&gt; ，内容如下
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-org&quot;&gt;&lt;span style=&quot;color: #b3b3b3;&quot;&gt;#+TITLE:&lt;/span&gt; &lt;span style=&quot;color: #afeeee; font-weight: bold;&quot;&gt;Org-mode&lt;/span&gt;
&lt;span style=&quot;color: #101e2e;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #eeeeec;&quot;&gt;* &amp;#20889;&amp;#25991;&amp;#26723;&lt;/span&gt;
&lt;span style=&quot;color: #101e2e;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #eeeeec;&quot;&gt;* &amp;#21457;&amp;#24067;&amp;#25104;html&lt;/span&gt;
&lt;span style=&quot;color: #101e2e;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #eeeeec;&quot;&gt;* org-bable&lt;/span&gt;
&lt;span style=&quot;color: #101e2e;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #eeeeec;&quot;&gt;* &amp;#34920;&amp;#26684;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
执行 &lt;b&gt;org-freemind-export-to-freemind&lt;/b&gt; 并用Freemind打开导出成图像后，得到的结果是：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/mind.png&quot; alt=&quot;mind.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
生成的思维导图样式是在ox-freemind.el中的变量 &lt;b&gt;org-freemind-styles&lt;/b&gt; 中定义的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;ox-freemind.el中的bug&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
如果您使用和我一样版本的Org-mode，那么很可能会遇到和我一样的问题。在执行 &lt;b&gt;org-freemind-styles&lt;/b&gt; 后出错，出错信息为：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
org-freemind-export-to-freemind: Symbol's function definition is void: \,
&lt;/pre&gt;

&lt;p&gt;
最后我在Org-mode的邮件列表中找到了解决方法。原链接&lt;a href=&quot;http://lists.gnu.org/archive/html/emacs-orgmode/2013-11/msg01095.html&quot;&gt;在此&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
出错的原因是 &lt;b&gt;org-freemind-export-to-freemind&lt;/b&gt; 函数的定义中有一处错误。其原始内容为：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;span class=&quot;linenr&quot;&gt;1: &lt;/span&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;org-freemind-export-to-freemind&lt;/span&gt;
&lt;span class=&quot;linenr&quot;&gt;2: &lt;/span&gt;  (&lt;span style=&quot;color: #8ae234;&quot;&gt;&amp;amp;optional&lt;/span&gt; async subtreep visible-only body-only ext-plist)
&lt;span class=&quot;linenr&quot;&gt;3: &lt;/span&gt;    (interactive)
&lt;span class=&quot;linenr&quot;&gt;4: &lt;/span&gt;  (&lt;span style=&quot;color: #729fcf;&quot;&gt;let*&lt;/span&gt; ((extension (concat &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;.mm&quot;&lt;/span&gt; ))
&lt;span class=&quot;linenr&quot;&gt;5: &lt;/span&gt;         (file (org-export-output-file-name extension subtreep))
&lt;span class=&quot;linenr&quot;&gt;6: &lt;/span&gt;         (org-export-coding-system 'utf-8))
&lt;span class=&quot;linenr&quot;&gt;7: &lt;/span&gt;    (org-export-to-file 'freemind ,file
&lt;span class=&quot;linenr&quot;&gt;8: &lt;/span&gt;    async subtreep visible-only body-only ext-plist)))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
将倒数第二行中的
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
org-export-to-file 'freemind ,file
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
修改为
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
org-export-to-file 'freemind file
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
嗯，没错，作者多写了一个逗号。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>完成机器学习公开课第一部分练习</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2014/01/02/finish-ml004-first-exercise.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2014/01/02/finish-ml004-first-exercise</id>
    <published>2014-01-02T00:00:00+00:00</published>
    <updated>2014-01-02T00:00:00+00:00</updated>
    <description>
    
      <p>
12月断断续续地看着Andrew Ng的机器学习公开课视频，因为网速还有对细节太较真的毛病，进度一直很慢——当然这和我的基础比较薄弱以及还不适应全英文学习环境有关系。


</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
12月断断续续地看着Andrew Ng的机器学习公开课视频，因为网速还有对细节太较真的毛病，进度一直很慢——当然这和我的基础比较薄弱以及还不适应全英文学习环境有关系。
&lt;/p&gt;

&lt;p&gt;
这一阶段看的是回归问题。实际上这并不是一个复杂的问题，不过在学习的途中还要恶补相关的数学知识，花费的时间确实多了一点。
&lt;/p&gt;

&lt;p&gt;
今天把第一部分练习完成了——完成前真的很没有自信，写完那几行代码都不敢提交，:-)。不过一路提交下来都是一次通过，心里算是有了点底气，嗯，要把基础打好。
&lt;/p&gt;

&lt;p&gt;
回归问题的部分还有个逻辑回归没有看，不过从&lt;a href=&quot;http://blog.csdn.net/abcjennifer&quot;&gt;Rachel Zhang&lt;/a&gt; 的往年笔记来看，大都是我已经掌握的东西，看的时候过一遍就好，不要死抠细节了。我想快点看完回归问题的部分，因为很期待后面神经网络的部分。
&lt;/p&gt;

&lt;p&gt;
当然，越往后面就越难了啊，也许到后面就会慢慢遇到真正的困难，我希望自己能坚持下去。
&lt;/p&gt;

&lt;p&gt;
顺便说一下，利用Octave这样的工具来学习真的挺好的——当然，有Matlab更好，不过一来它是商业产品，能不用盗版产品最好就不用；二来它体积太大我的Mint分区塞不下。现在Octave能够满足我的需求，如果以后必须要用Matlab再说吧。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>修改键位+使用smex，告别Emacs小指综合症</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/12/31/use-smex.html"/>
    <category term="Emacs" scheme="http://www.zmonster.me/categories.html#Emacs"/>
    <id>http://www.zmonster.me/2013/12/31/use-smex</id>
    <published>2013-12-31T00:00:00+00:00</published>
    <updated>2013-12-31T00:00:00+00:00</updated>
    <description>
    
      <p>所谓“Emacs小指综合症”，是指由于长期使用Emacs导致左手小指疼痛的问题——嗯，没错，这是我下的定义——英文说法是 *Emacs Pinky Problem* 。这一问题的根源是因为Emacs的快捷键频繁使用键盘的 *ctrl* 键，而由于现在被普遍应用的 *QWERTY* 键盘布局上的 *ctrl* 键都只能用小指来按下(不过通常Emacser只使用左侧的 *ctrl* 键)，且在按下 *ctrl* 时小指的负荷很大。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;Emacs小指综合症&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;常规解决办法&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;修改键位或键盘布局&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;使用正确的姿势&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;使用合理的键盘&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline6&quot;&gt;使用smex插件&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;Emacs小指综合症&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
所谓“Emacs小指综合症”，是指由于长期使用Emacs导致左手小指疼痛的问题——嗯，没错，这是我下的定义——英文说法是 &lt;b&gt;Emacs Pinky Problem&lt;/b&gt; 。这一问题的根源是因为Emacs的快捷键频繁使用键盘的 &lt;b&gt;ctrl&lt;/b&gt; 键，而由于现在被普遍应用的 &lt;b&gt;QWERTY&lt;/b&gt; 键盘布局上的 &lt;b&gt;ctrl&lt;/b&gt; 键都只能用小指来按下(不过通常Emacser只使用左侧的 &lt;b&gt;ctrl&lt;/b&gt; 键)，且在按下 &lt;b&gt;ctrl&lt;/b&gt; 时小指的负荷很大。
&lt;/p&gt;

&lt;p&gt;
这个问题是Emacs被诟病的几个主要问题之一，不过严格来说，这并不是Emacs的错，因为Emacs被设计时考虑的键盘布局和现在是不一样的，那个时候的 &lt;b&gt;esc&lt;/b&gt; 键和 &lt;b&gt;ctrl&lt;/b&gt; 键都是在比较舒服的位置的，所以这是个历史遗留问题。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;常规解决办法&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline3&quot;&gt;修改键位或键盘布局&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
这种办法的核心思想是通过一些措施把 &lt;b&gt;ctrl&lt;/b&gt; 键映射到物理键盘上比较好按的键位上。常见的方法是将 &lt;b&gt;ctrl&lt;/b&gt; 键和 &lt;b&gt;caps lock&lt;/b&gt; 键交换，在&lt;a href=&quot;http://planet.emacsen.org/&quot;&gt;Planet Emacsen&lt;/a&gt; 上还提到了另外一种办法：将 &lt;b&gt;ctrl&lt;/b&gt; 键和回车键交换。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline4&quot;&gt;使用正确的姿势&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
在笔记本的键盘按左 &lt;b&gt;ctrl&lt;/b&gt; 键尤其难受，不过在笔记本键盘上，可以通过用手掌根部按压左 &lt;b&gt;ctrl&lt;/b&gt; 键来避免使左手小指受损。
&lt;/p&gt;

&lt;p&gt;
不过我并不习惯这种姿势。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline5&quot;&gt;使用合理的键盘&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;p&gt;
使用设计更加合理的、符合人体工程学的键盘是解决这个问题的好办法。这个方法不仅能避免Emacs导致的问题，还能减轻其他因为长期使用电脑/键盘而出现的健康问题。
&lt;/p&gt;

&lt;p&gt;
当然，为了健康而投入资金是必须的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline6&quot;&gt;使用smex插件&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline6&quot;&gt;
&lt;p&gt;
smex是Emacs的一个插件，&lt;a href=&quot;http://www.emacswiki.org/emacs/Smex&quot;&gt;这里&lt;/a&gt; 是相关说明。
&lt;/p&gt;

&lt;p&gt;
smex是一个&quot;M-x&quot;快捷键的增强工具，它能够使得在Emacs中调用各种命令更为方便，能更智能地对命令进行补全，还能根据使用者调用命令的频率来猜测用户可能会执行的命令。如下图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2013-12-31-smex-use.png&quot; alt=&quot;2013-12-31-smex-use.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
不少Emacs中的命令名字都很长，所以如果不使用smex的话，一来很多命令根本记不住，二来就算记住了输入时也要花费许多的时间——这也是为什么Emacs有如此多的快捷键的原因之一吧。
&lt;/p&gt;

&lt;p&gt;
smex的使用也很简单，下载smex并放置到Emacs的加载目录中后，在配置文件中添加这么几条语句：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(load &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;~/.emacs.d/site-lisp/smex.el&quot;&lt;/span&gt;)
(&lt;span style=&quot;color: #729fcf;&quot;&gt;require&lt;/span&gt; '&lt;span style=&quot;color: #e6a00f;&quot;&gt;smex&lt;/span&gt;)
(smex-initialize)
(global-set-key (kbd &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;M-x&quot;&lt;/span&gt;) 'smex)
(global-set-key (kbd &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;M-X&quot;&lt;/span&gt;) 'smex-major-mode-commands)
(global-set-key (kbd &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;C-c C-c M-x&quot;&lt;/span&gt;) 'execute-extended-command)
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;
我的办法呢，就是综合键位修改和使用smex两个方案。将 &lt;b&gt;ctrl&lt;/b&gt; 和 &lt;b&gt;caps lock&lt;/b&gt; 交换，然后绑定一些(少量)常用的命令到快捷键上，其他大部分的命令调用则使用smex。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>年末总结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/12/31/annual-summary.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2013/12/31/annual-summary</id>
    <published>2013-12-31T00:00:00+00:00</published>
    <updated>2013-12-31T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


经历
阅读
学习

人工智能
程序设计


2014年计划




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;经历&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;阅读&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;学习&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline4&quot;&gt;人工智能&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline5&quot;&gt;程序设计&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline6&quot;&gt;2014年计划&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
现在是2013年12月31日晚上，我敲下这句话时时间是21:41。一年又过去了，一年又来临了，2013年有很多快乐和无奈，我知道2014年还会有很多快乐以及无奈，生活大抵如此。
&lt;/p&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;经历&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
2013年开始的时候，我已经签约了科大讯飞，将要进入科大讯飞研究院进行语音方面的研究工作。
&lt;/p&gt;

&lt;p&gt;
2013年开始的时候，我还住在沁苑13栋，吃着东三食堂的饭，和室友局域网联机打CS或者WAR3。
&lt;/p&gt;

&lt;p&gt;
2013年开始的时候，选定了“图片文档中文字提取技术的研究”这么一个毕业设计课题，虽然最后烂尾，但我学到了我想学习的东西。
&lt;/p&gt;

&lt;p&gt;
2013年8月8日，因家庭原因，从讯飞辞职。
&lt;/p&gt;

&lt;p&gt;
2013年11月25日，参加国家公务员考试，虽然我其实并不想去当公务员。
&lt;/p&gt;

&lt;p&gt;
一年的事情，其实也就几句话而已。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;阅读&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
&lt;a href=&quot;http://book.douban.com/subject/10583099/&quot;&gt;《全球通史》&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
这本书现在还在读，进度还不到一半。书很不错，着眼于历史事件后面的社会发展规律。随着阅读的深入，除了了解历史规律，也还认识到其实历史规律和人生是有相似性的，至少有些历史规律是可以用来指导人生前进方向的。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
&lt;a href=&quot;http://book.douban.com/subject/2076886/&quot;&gt;《甲骨文》&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
这是一个外国人看到的中国，从他人的角度来看自己，能够更了解自己。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
&lt;a href=&quot;http://book.douban.com/subject/6048276/&quot;&gt;《民国就是这么生猛》&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
这本书让我得以一窥民国时代的详细景象以及教科书中语焉不详的细节，而且书中多有一针见血的言论。不过语言过于通俗，情绪上主观倾向比较明显，不过，我认为读历史在于了解历史规律、社会规律和人性，在这一点上这本书让我很满意。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
&lt;a href=&quot;http://book.douban.com/subject/1120732/&quot;&gt;《宇宙为家》&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
从自组织理论来看待生物发展的一本书。
&lt;/p&gt;

&lt;p&gt;
嗯，无论人也好，我们这个社会也好，不过都是在混沌边缘游离的耗散系统而已。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
当然，还有一些用于消遣的小说，以及大量的博客文章，这里就不一一记录了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;学习&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgheadline4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline4&quot;&gt;人工智能&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline4&quot;&gt;
&lt;p&gt;
做毕业设计的过程，让我了解了人工智能领域的大量知识，同时更加坚定地成为了联结主义者。
&lt;/p&gt;

&lt;p&gt;
12月陆陆续续地学习了机器学习的一些东西。
&lt;/p&gt;

&lt;p&gt;
对这个领域越深入，我就越发觉自己的无知。现在的我，充其量不过是站在门口，看到了大门里恢宏的景象，一心渴望踏进去，却又恐惧于其宽广，不知道该往哪里走。
&lt;/p&gt;

&lt;p&gt;
前阵子effyroth突然说他放弃了对DL的学习，我更加感到迷茫。我现在才明白，他在学校时候的水平就比现在的我高出了不少，而当时我还敢自大地跟他争论自己都不明白的东西——但是他却说他放弃了！我知道在这条路上走得越深入，就会碰到越多的困难，我还在门口徘徊所以我并没有感受到太多的艰难，而effyroth是一个很有主见、意志力强的人。这让我反思我是不是适合在这条路上走下去。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgheadline5&quot;&gt;程序设计&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgheadline5&quot;&gt;
&lt;p&gt;
5个月左右时间，我并没有写多少代码——这是因为头两个月时间一直在用游戏或小说来麻痹自己，接下来的两个月在准备公务员考试，而12月，又因为迷茫不知方向而毫无动力。
&lt;/p&gt;

&lt;p&gt;
断断续续又学了一点Common Lisp；在部署Github Pages博客的过程中对HTML/CSS有了比较全面的了解；花了几天时间系统地学习了Python，现在已经能够用Python编程了；在配置Emacs的过程中终于掌握了自己编写Emacs函数的细节。
&lt;/p&gt;

&lt;p&gt;
以上大概是着一个月来的微不足道的收获。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline6&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline6&quot;&gt;2014年计划&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline6&quot;&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;del&gt;找到一份工作，至少能养活自己&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;保持身体健康&lt;/li&gt;
&lt;li&gt;和至少十个朋友保持联络&lt;/li&gt;
&lt;li&gt;阅读二十本书&lt;/li&gt;
&lt;li&gt;每月至少写五篇博客&lt;/li&gt;
&lt;li&gt;学习数学，主要是线性代数、矩阵论以及概率论&lt;/li&gt;
&lt;li&gt;掌握机器学习的基本理论及实现方法，掌握常用的人工神经网络，编写一个C语言的神经网络库&lt;/li&gt;
&lt;li&gt;买一个树莓派，做点事情(做什么现在还没想好)&lt;/li&gt;
&lt;li&gt;研究Minecraft红石，至少能在Minecraft中构造出一个简单的时序逻辑电路&lt;/li&gt;
&lt;li&gt;学会做菜&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>Ghost.org开启博客托管服务</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/12/16/ghost-blog.html"/>
    <category term="博客" scheme="http://www.zmonster.me/categories.html#博客"/>
    <id>http://www.zmonster.me/2013/12/16/ghost-blog</id>
    <published>2013-12-16T00:00:00+00:00</published>
    <updated>2013-12-16T00:00:00+00:00</updated>
    <description>
    
      <p>今天收到了Ghost的邮件，通知说Ghost已经开启了博客托管服务，于是就去了解了一下。</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
晚上Gmail里出现了&lt;a href=&quot;http://ghost.org/&quot;&gt;Ghost&lt;/a&gt; 的邮件，说Ghost已经开启了博客托管服务，而我呢，“很荣幸”地成为了第一批有权限使用这个服务的人之一。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2013-12-16-mail-from-ghost.png&quot; alt=&quot;2013-12-16-mail-from-ghost.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
上面还自我吹嘘说：
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
Our hosted platform is a premium service which allows you to set up and run a Ghost blog in a matter of seconds. It's incredibly powerful, very easy to use, and is probably the best way of running any Ghost blog online.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
那就去看一看吧，如果用起来顺手的话可以考虑把放到Github上的博客转移过去呢——毕竟从上次自己在本地部署的Ghost使用体验来看，Ghost确实是一个风格简洁又不失美观的博客平台。
&lt;/p&gt;

&lt;p&gt;
结果呢，使用这个服务是需要付费的，最低的5美刀一月，只能建一个博客，每月10000次访问量上限(抱歉因为之后点击了试用结果无法再看到这个界面了，只能凭记忆描述了)，其他更高资费的当然是拥有更高的访问量上限和博客上限啦。
&lt;/p&gt;

&lt;p&gt;
而且呢，主题也是需要付费了的哟，看看，这价钱不错哦～～功底不错的Web前端可以考虑为Ghost写主题卖钱什么的，就是不知道Ghost要拿多少成的利润啊。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2013-12-16-ghost-market.png&quot; alt=&quot;2013-12-16-ghost-market.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
还好还有一个免费试用30天的服务，于是果断点击试用啊。获得了试用权限后，新建博客啊果然是很轻松的，这一点倒没说大话。
&lt;/p&gt;

&lt;p&gt;
总之……土豪们可以入手哟……我就算了，继续在github上死皮赖脸地混着。
&lt;/p&gt;

&lt;p&gt;
嘛，&lt;a href=&quot;http://dream-eater.ghost.io/&quot;&gt;这里&lt;/a&gt; 是我试用时建立的博客，权当demo而已。当然如果您在1月16号之后看到这篇文章，就没有必要点刚才的链接啦。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>org-mode导出项目时发布所有文件而不只是被修改的文件</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/12/15/republish-org-project.html"/>
    <category term="Emacs" scheme="http://www.zmonster.me/categories.html#Emacs"/>
    <id>http://www.zmonster.me/2013/12/15/republish-org-project</id>
    <published>2013-12-15T00:00:00+00:00</published>
    <updated>2013-12-15T00:00:00+00:00</updated>
    <description>
    
      <p>org-mode导出项目时会检查项目中的文件，然后仅发布被修改且未被发布过的文件，而有时候因为项目导出设置的变化，需要重新发布项目中的所有文件.</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;问题&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;解决方法&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;问题&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
使用org-mode，可以将一个目录下的所有org文件作为一个完整的项目进行导出，这个功能常常用于将写好的org文件以完整的网站结构导出成html文件。
&lt;/p&gt;

&lt;p&gt;
在这个过程中，有时候我们修改了项目的设置，比如说在 &lt;b&gt;org-publish-project-alist&lt;/b&gt; 中修改了 &lt;b&gt;html-preamble&lt;/b&gt; 或 &lt;b&gt;html-postamble&lt;/b&gt; 两个设置——这两个参数定义了项目中所有org文件导出成html时的模板。但如果修改后执行 &lt;b&gt;org-publish-project&lt;/b&gt; ，这个改变并不会被应用，因为org-mode导出项目时会检查项目中的文件，然后仅发布被修改或未被发布过的文件。这就是本文要解决的问题。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;解决方法&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
上述所说的org的特性——导出项目时仅对修改过或未被发布过的文件，是由org内置的变量 &lt;b&gt;org-publish-use-timestamps-flag&lt;/b&gt; 来决定的。
&lt;/p&gt;

&lt;p&gt;
通过快捷键 &lt;b&gt;C-h v&lt;/b&gt; 查看该变量的文档，可以看到它的描述是：
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
org-publish-use-timestamps-flag is a variable defined in 'ox-publish.el'.
Its value is t
&lt;/p&gt;

&lt;p&gt;
Documentation:
Non-nil means use timestamp checking to publish only changed files.
When nil, do no timestamp checking and always publish all files.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
根据文档，将这个变量设置为 &lt;b&gt;nil&lt;/b&gt; 就可以改变上述org在导出项目时的行为，但是注意 &lt;b&gt;always&lt;/b&gt; 这个词。如果在配置中将这个变量的值设置为了 &lt;b&gt;nil&lt;/b&gt; ，那么每次导出项目时，所有文件都会被重新发布！而我们需要的是在 &quot;需要的时候&quot; 重新发布所有文件，每次都重新发布会带来不必要的时间消耗，这不是我们想要的。
&lt;/p&gt;

&lt;p&gt;
我的解决办法是将 &lt;b&gt;org-publish-project&lt;/b&gt; 这个命令包装成 &lt;b&gt;publish-project&lt;/b&gt; ，每当这个命令执行时，它会询问是否要重新发布所有文件，如果是则将 &lt;b&gt;org-publish-use-timestamps-flag&lt;/b&gt; 这个变量置为 &lt;b&gt;nil&lt;/b&gt; ，待发布完后又重新设回 &lt;b&gt;t&lt;/b&gt; 。
&lt;/p&gt;

&lt;p&gt;
下面是我的实现方法：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;publish-project&lt;/span&gt; (project no-cache)
   (interactive &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;sName of project: \nsNo-cache?[y/n] &quot;&lt;/span&gt;)
      (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (or (string= no-cache &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;y&quot;&lt;/span&gt;)
          (string= no-cache &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Y&quot;&lt;/span&gt;))
          (setq org-publish-use-timestamps-flag nil))
   (org-publish-project project)
   (setq org-publish-use-timestamps-flag t))
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
我将这个函数绑定到了 &lt;b&gt;C-x p&lt;/b&gt; 这个快捷键上。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>开始学习一些东西</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/12/14/begin-to-learn-some-stuff.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2013/12/14/begin-to-learn-some-stuff</id>
    <published>2013-12-14T00:00:00+00:00</published>
    <updated>2013-12-14T00:00:00+00:00</updated>
    <description>
    
      <p>开始系统学习机器学习以及相关的人工智能领域的知识</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
今天继续看了百度的机器学习课程，觉得有点枯燥，于是跑到网易公开课上看Stanford的机器学习课程——Andrew Ng的CS229(2012)。虽然说第一讲讲到的都是我知道的东西，但我很喜欢Andrew Ng的讲课风格。
&lt;/p&gt;

&lt;p&gt;
一时兴起到CS229的课程主页上把今年的课程讲义都爬了下来，然后在Coursera注册了帐号观看Andrew Ng这个课程的网上课程，虽然只有英文字幕，但是勉强还能对着字幕听明白Andrew Ng说的话。
&lt;/p&gt;

&lt;p&gt;
于是打算系统地进行学习了。
&lt;/p&gt;

&lt;p&gt;
笔记照例放到gitcafe上去好了，嘿嘿。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>开始在电脑上写日记</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/12/12/diary-on-computer.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2013/12/12/diary-on-computer</id>
    <published>2013-12-12T00:00:00+00:00</published>
    <updated>2013-12-12T00:00:00+00:00</updated>
    <description>
    
      <p>
说实话，其实我还是更享受在纸上写日记的感觉。奈何现在大部分事情是在电脑上做的，通常做完就玩一会游戏睡觉，睡前经常记不起来要写日记，而每天其实都是有很多事情可以记录的。所以我想尝试在电脑上写日记...</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
说实话，其实我还是更享受在纸上写日记的感觉。奈何现在大部分事情是在电脑上做的，通常做完就玩一会游戏睡觉，睡前经常记不起来要写日记，而每天其实都是有很多事情可以记录的。所以我想尝试在电脑上写日记，至少能保证每天都能写——我打算在org-mode里写，那么在Emacs的日程表上加上一个周期性的任务就行了。
&lt;/p&gt;

&lt;p&gt;
日记这种东西相对私密，而且写作很随意，所以我也不想发到博客上或者里其他类似的平台，暂时丢到Dropbox里吧，最近系统空间不够经常把分区搞来搞去的，只放在本地说不定就什么时候被我干掉了。
&lt;/p&gt;

&lt;p&gt;
在org-mode里写日记，我的想法是简单就好，在org-capture的模板里加了一个diary的模板:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;d&quot;&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Diary&quot;&lt;/span&gt;
     entry (file
            &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;~/Dropbox/org/diary.org&quot;&lt;/span&gt;)
     &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;* %t\n&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
需要写的时候按下 &lt;b&gt;C-c c&lt;/b&gt; 然后选择 &lt;b&gt;d&lt;/b&gt; 就可以了，模板也没什么内容，就是一个日期而已。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>朋友要结婚了</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/12/09/friend-things.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2013/12/09/friend-things</id>
    <published>2013-12-09T00:00:00+00:00</published>
    <updated>2013-12-09T00:00:00+00:00</updated>
    <description>
    
      <p>有一个朋友要结婚了，不知道有没有邀请我呢。</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
在一个朋友的博客上看到，她已经定了结婚的日期，正在邀请朋友们。看到这里的时候，心里也会想一下，不知道有没有邀请我呢？
&lt;/p&gt;

&lt;p&gt;
说是朋友，不过也有三年多没见过了吧，平时联系也不多——事实上我跟谁联系都不多，我确实是个怪人。话说回来，就算她邀请了我，我还是会觉得要见到一堆的初中同学会难接受。
&lt;/p&gt;

&lt;p&gt;
说到底还是我不自信的缘故，而且，我把自己的过去都已经否定了，不愿意去想初中高中的事，也不想见到初中高中的人——这么说我确实是个孤僻的人。到底是什么事情让我变成这个样子呢？非要深究地话又要回过头去翻自己过去那堆杂乱的历史和思想了，那让我很难堪。
&lt;/p&gt;

&lt;p&gt;
我愿意正视我自己的问题，却不原意正视自己问题的根源。这是长久以来我一直不能干净利落解决问题的根源所在。
&lt;/p&gt;

&lt;p&gt;
有时候我会想，孤独也挺好的，不受打扰，可以专注于创造——但事实上这么想不过是自我安慰而已，我并没有花太多心思在真正的创造有价值的事物上面。
&lt;/p&gt;

&lt;p&gt;
或许我会变成现在这个样子有一个很简单的解释，那就是 &lt;b&gt;自我实现预言&lt;/b&gt; 。
&lt;/p&gt;

&lt;p&gt;
嗯，算了，偶尔多愁善感一下就行，还有项目要做，还要准备明年的工作，那才是重中之重。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>通俗化解释GFW工作原理</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/12/07/gfw-brief.html"/>
    <category term="数字生活" scheme="http://www.zmonster.me/categories.html#数字生活"/>
    <id>http://www.zmonster.me/2013/12/07/gfw-brief</id>
    <published>2013-12-07T00:00:00+00:00</published>
    <updated>2013-12-07T00:00:00+00:00</updated>
    <description>
    
      <p>通过形象通俗的方式来解释GFW的工作原理</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org313ba5d&quot;&gt;场景约定&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3711e13&quot;&gt;GFW(Great Firewall，中国互联网防火墙)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1381de4&quot;&gt;商店封锁计划(IP黑名单)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4e27cd1&quot;&gt;交警催眠计划(DNS劫持)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgbf925c4&quot;&gt;商品清单审查计划(内容审查)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org70cbd2e&quot;&gt;后记&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org313ba5d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org313ba5d&quot;&gt;场景约定&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org313ba5d&quot;&gt;
&lt;p&gt;
先对用户上网行为中的一些实体或行为做以下约定：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
A镇：中国互联网
&lt;/p&gt;

&lt;p&gt;
A镇是一个小镇子，四面环山、风景优美，人民淳朴善良、勤劳勇敢。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
镇外：国外互联网
&lt;/p&gt;

&lt;p&gt;
镇外有很多繁华的城市，丰富多彩的商品。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
居民：客户端(PC/智能终端等)
&lt;/p&gt;

&lt;p&gt;
居民是A镇的居民，他们每个人都有一个家。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
商店：网站
&lt;/p&gt;

&lt;p&gt;
居民们经常需要购买一些东西，这些东西就要到商店里去买，镇里镇外都有商店。居民一般是不能自己卖东西的，如果要卖东西，要经过工商局的许可，还要注册一个商店名称。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
商店名称：网站域名
&lt;/p&gt;

&lt;p&gt;
每个商店都有一个独一无二的名称，绝不重样。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
具体地址：IP
&lt;/p&gt;

&lt;p&gt;
每个居民的家以及商店都有一个具体的地址，如：xx街道xx号。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
购买：网络连接
&lt;/p&gt;

&lt;p&gt;
购买就是购买，可以购买镇内的东西，也可以购买镇外的东西。购买东西的时候，商店通常都会记下购买者的地址和对方购买的商品列表。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
管家：浏览器
&lt;/p&gt;

&lt;p&gt;
(实际上这个比拟不恰当，请不要深究)
&lt;/p&gt;

&lt;p&gt;
居民们很忙，没有空自己去买东西(有的商店也很远)，所以居民们把购买的事情交给管家去做，通常只告诉管家 &lt;b&gt;商店名称&lt;/b&gt; 和 &lt;b&gt;要买的东西&lt;/b&gt; 。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
道路：路由
&lt;/p&gt;

&lt;p&gt;
管家是走路去的商店的，有的也开车，但是这个世界没有飞行器。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
路口：路由器
&lt;/p&gt;

&lt;p&gt;
镇上道路四通八达，到达一个目的地有很多种走法。在每个路口都有路标，指示各个方向可以到达什么地方，比如说有一个路口的路标上有这么一句：
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
    向左拐可以到山麓百货商店
&lt;/pre&gt;

&lt;p&gt;
当然，其实向前走也可以，总之随便走，取决于管家对道路的熟悉程度了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
交警：DNS服务器
&lt;/p&gt;

&lt;p&gt;
管家有时候会不知道商店在哪个位置，不过没关系，他可以去问交警，交警博文强识、乐于助人，会告诉管家商店的具体地址的，然后管家就可以乐呵地去目的地了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
谨慎购买：TCP连接
&lt;/p&gt;

&lt;p&gt;
有些居民怕买东西上当，因为毕竟不是自己去嘛，所以又无情地压榨老管家的劳动力了(打倒资本主义!)。这是居民会先让管家按照某种规定和商店进行交流(TCP三次握手)，确定商店是可信的并且让商店也信任居民后，就可以进行谨慎购买了。这后面居民买东西时，就不用再报上自己的信息了，售货员暧昧地看了一眼老管家就知道，唔，又是这个家伙。而且，售货员会细心检查商品看有没有质量问题。
&lt;/p&gt;

&lt;p&gt;
在这种购买方式要结束时，居民会让老管家和商店说一声，这样商店知道这货不会再来买东西了。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
切口：TCP三次握手
&lt;/p&gt;

&lt;p&gt;
在进行谨慎购买时，要对交换三次密文，用来对答切口，确定对方是否可信任。
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
第一次，管家带着用明矾水写的密文前往商店，上面写着：
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
       天王盖地虎
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
到达商店后，售货员解读了密文后，也用明矾水写一张密文，内容是：
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
       宝塔镇河妖
       地振高岗，一派溪山千古秀
&lt;/pre&gt;

&lt;p&gt;
第一句是回应管家带来的切口，第二句则是要求购买方对答的切口。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
管家把密文带回居民家中，居民解读出密文，再制作一张密文，内容为：
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
       门朝大海，三河合水万年流
&lt;/pre&gt;
&lt;p&gt;
再让管家带过去，这时候售货员和居民都可以确定了：唔，自己人！
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
随意购买：UDP连接
&lt;/p&gt;

&lt;p&gt;
谨慎购买太麻烦了，所以有些人喜欢随意购买这种方式，告诉管家要买什么东西，到商店里拿了付钱走人就完了。不过这种情况，售货员不会帮管家检查商品质量，买回去有可能是次品(退货这种事情这里就不讨论了)。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3711e13&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3711e13&quot;&gt;GFW(Great Firewall，中国互联网防火墙)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3711e13&quot;&gt;
&lt;p&gt;
话说小镇是一个社会主义小镇——至少小镇管理委员会是这么说的，本来吧，小镇生活挺清苦的，后来有一任镇长看不下去了，就发动了代号为”改革开发“的运动，打通了一条通往外界的道路，从此小镇日新月异，蒸蒸日上。
&lt;/p&gt;

&lt;p&gt;
但是开放有开放的问题啊。万恶的资本主义趁机侵入了小镇。
&lt;/p&gt;

&lt;p&gt;
小镇管理委员会也很无奈啊，首先吧，确实需要万恶的资本主义商店来提升小镇的GDP；其次吧，没有万恶的资本主义商店，委员会的公仆们到哪里去买好吃的好玩的来调养身心为小镇建设做好身体和心理的准备呢？
&lt;/p&gt;

&lt;p&gt;
可是你们这些资本主义商店，我们高等的社会主义小镇给了你们为我们小镇贡献GDP和表现自我的机会，除了感恩戴德之外，怎么还把 &lt;b&gt;自由&lt;/b&gt; 、 &lt;b&gt;民主&lt;/b&gt; 之类的违禁品卖给我们淳朴善良的居民们呢？什么，你说那不是坏东西？我们说是就是！
&lt;/p&gt;

&lt;p&gt;
于是，在小镇召开的第十九届全镇代表大会上，代表了全镇居民们的代表们设立了 &lt;b&gt;小镇安全委员会&lt;/b&gt; 并制订了代号为 &lt;b&gt;GFW&lt;/b&gt; 的计划，并交给了小镇第三中学的方校长来执行。可怜的方校长不过是执行者，从此却被激进无脑的小镇居民恨之入骨，人家雨果不是说过了嘛：有罪的不是犯罪的人，而是制造黑暗的人。这就和一个色狼用手骚扰了地铁上漂亮姑娘之后，法庭宣判“判当事人的右手性骚扰罪成立”一样可笑嘛，不过随便了，小镇的人们太淳朴了，大智若愚，大愚若智啊！！！
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;GFW&lt;/b&gt; 计划具体有什么内容不得而知，从目前得到的信息来看，该计划至少包含以下三部分：商店封锁计划、交警催眠计划和商品清单审查计划。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1381de4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1381de4&quot;&gt;商店封锁计划(IP黑名单)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org1381de4&quot;&gt;
&lt;p&gt;
这个计划是这样的，对于一些不法的商店，直接封锁起来，谁也进不去——老管家当然进不去了。
&lt;/p&gt;

&lt;p&gt;
当然这个计划是有漏洞的，因为很多商店是连锁的呀！比如说谷姐百货，那连锁规模，都快赶上垃圾食品连锁店肯德鸭了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4e27cd1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4e27cd1&quot;&gt;交警催眠计划(DNS劫持)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org4e27cd1&quot;&gt;
&lt;p&gt;
之前说过了，老管家是会向交警去问路的。交警催眠计划呢，就是把交警催眠了，当管家问”谷姐百货怎么走“时，交警就会告诉他一个错误的地址。老管家被压榨得太久了，脑袋不灵活啊，交警告诉他怎么走，他就怎么走，结果走到那个地方一看，好家伙，只看到满地的残骸，还有那摇摇欲坠的危墙上大大的一个 &lt;b&gt;拆&lt;/b&gt; 字。
&lt;/p&gt;

&lt;p&gt;
老管家很郁闷，回家告诉居民：主人啊，找不到地址啊，说不定是个皮包商店呢。
&lt;/p&gt;

&lt;p&gt;
这种手段主要用于防止管家到镇外去买东西，因为通往镇外的路只有一条，把那条路上的交警催眠了就OK。
&lt;/p&gt;

&lt;p&gt;
镇外的世界啊，水深火热啊，不要去的好。
&lt;/p&gt;

&lt;p&gt;
对于镇内的商店，主要是用商品清单审查计划，当然，现在对镇外的购买行为也开始使用这个了，因为有些镇外商店还是不错的，违禁品比较少，稍微审查一下就好了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgbf925c4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgbf925c4&quot;&gt;商品清单审查计划(内容审查)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgbf925c4&quot;&gt;
&lt;p&gt;
这个计划是这样的。 &lt;b&gt;小镇安全委员会&lt;/b&gt; 派出了很多隐形人，偷窥到了老管家身上带的商品清单，如果居民的商品上有违禁品，隐形人就会报告 &lt;b&gt;小镇安全委员会&lt;/b&gt; ，委员会会派出一个人伪装成对应商店的售货员，告诉老管家，”老管家啊，你这个东西我们这里没有“或者”老管家啊，你这个清单格式不对啊，结尾要加上'此致敬礼'啊“之类的。
&lt;/p&gt;

&lt;p&gt;
老管家头脑不是不太好用嘛，就回去了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org70cbd2e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org70cbd2e&quot;&gt;后记&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org70cbd2e&quot;&gt;
&lt;p&gt;
写这个东西，是为了向非专业人士解释一下 &lt;b&gt;GFW&lt;/b&gt; 的工作原理，为以后向他们传播相关安全知识做个准备。
&lt;/p&gt;

&lt;p&gt;
另外，我的某个老大跟我说过，你要能把事情跟别人说明白才能说明自己是真的懂了。大概就是这么个意思。
&lt;/p&gt;

&lt;p&gt;
后面我会讲一下突破 &lt;b&gt;GFW&lt;/b&gt; 的常规手段。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>在Heroku上部署Tornado应用</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/12/06/tornado-on-heroku.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2013/12/06/tornado-on-heroku</id>
    <published>2013-12-06T00:00:00+00:00</published>
    <updated>2013-12-06T00:00:00+00:00</updated>
    <description>
    
      <p>在Heroku上部署Tornado应用需要在Procfile、requirements.txt中指定相关配置</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;Heroku&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;Tornado&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;部署Tornado&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;Heroku&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;

&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/heroku.jpg&quot; alt=&quot;heroku.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;a href=&quot;http://heroku.com/&quot;&gt;Heroku&lt;/a&gt; 是一个云平台(Platform as a Service, &lt;b&gt;PaaS&lt;/b&gt;)，提供“无需准备的部署服务”。在Heroku上托管应用，所需的只是对应用本身的开发和管理，应用运行的环境以及安全防护则会由Heroku来进行，此外Heroku上还有非常丰富的Add-ons，即一些扩展服务(有些是免费的有些是收费的)，对应用开发和管理非常有用。
&lt;/p&gt;

&lt;p&gt;
免费的Heroku应用只有64MB的内存和512MB的存储，如果想部署大型的应用，最好还是付费的好。不过话说回来，每个账户可以创建的应用好像没有限制。对于个人而言，在Heroku上部署一些小应用，或者个人博客，都是可以一试的——目前已经有不少朋友在上面部署自己的个人博客了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;Tornado&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
&lt;a href=&quot;http://www.tornadoweb.org/en/stable/&quot;&gt;Tornado&lt;/a&gt; 是一个Python的Web框架，也是一个python的异步网络库，最初由FriendFeed开发——FriendFeed现已被Facebook收购。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;部署Tornado&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
Heroku 支持Ruby、Python、Java等多种类型的应用，不过Heroku的官方文档上只有对部署Flask的示例，并没有部署Tornado的说明。而实际上，部署Tornado应用和部署其他类型的应用一样，也是很简单的。
&lt;/p&gt;

&lt;p&gt;
要部署Tornado应用到Heroku上，首先需要一个编写正确可用的Tornado应用(关于Heroku的使用将在另一文中细说)，在此基础上在应用根目录下准备好以下几个配置文件：
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
requirements.txt
&lt;/p&gt;

&lt;p&gt;
该配置文件用于指示Python应用的组件依赖，详细文档 &lt;a href=&quot;https://devcenter.heroku.com/articles/python-pip&quot;&gt;在此&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;requirements.txt&lt;/i&gt; 的内容应该为：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
Tornado==3.1.1     # 假定应用使用3.1.1版本的Tornado，注意这里是&quot;==&quot;而不是&quot;=&quot;
...                # 其他依赖
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Procfile
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Procfile&lt;/b&gt; 用于告诉Heroku处理类型以及要运行的命令，详细文档 &lt;a href=&quot;https://devcenter.heroku.com/articles/procfile&quot;&gt;在此&lt;/a&gt;。 其内容通常为如下形式：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
&amp;lt;process type&amp;gt;: command
&lt;/pre&gt;

&lt;p&gt;
假定要部署的Tornado应用的主模块为main.py，则Profile的内容可能为：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
web: python main.py --port=$PORT
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
runtime.txt
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;runtime.txt&lt;/b&gt; 用于指定Python应用使用的Python版本，举例来说，若要部署的Tornado应用要使用2.7.4版本的Python，则runtime.txt的内容应该为：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
python-2.7.4
&lt;/pre&gt;

&lt;p&gt;
Heroku支持的Python版本为：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;python-2.7.4&lt;/li&gt;

&lt;li&gt;python-3.3.2&lt;/li&gt;

&lt;li&gt;pypy-1.9 (我也不知道这是什么……)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
如果应用目录下没有runtime.txt，则Heroku默认使用python-2.7.4。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>国内外图床及其对比</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/12/06/image-host-service.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2013/12/06/image-host-service</id>
    <published>2013-12-06T00:00:00+00:00</published>
    <updated>2013-12-06T00:00:00+00:00</updated>
    <description>
    
      <p>图床是对图片托管服务的一种称呼，本文对国内外的主流图床进行了一些对比</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;图床是什么&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;国外图床&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;国内图床&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;图床是什么&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
&lt;b&gt;图床&lt;/b&gt; 这个词来源已不可考(至少我并没有找到这个词的出处)，这个词指的一种图片托管服务(Image Hosting Services)，通常被用于进行图片的云存储和分享，也被用于博客和论坛已减轻主机存储负荷。
&lt;/p&gt;

&lt;p&gt;
一个好的图床首先应该是有外链功能的，即图片的直接分享链接，这个链接可以用在&amp;lt;img&amp;gt;标签内用于显示图片；其次外链要稳定而且访问速度要有保证，这两点是至关重要的；满足了前面两点后，还可以考虑上传的便捷性、外链是否允许自定义、是否有上传限制等等其他细节。
&lt;/p&gt;

&lt;p&gt;
国外的图床比较多而且成熟，当然了，国内也有比较好的图床。下面分别对国外和国内的图床做一个简单的对比。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;国外图床&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;名称&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;注册需要&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;免费容量&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;流量限制&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;上传限制&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;API&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;图片/外链有效期&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;图片格式&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;其他&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Flickr&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;雅虎邮箱&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;1TB&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;lt;200MB(单张)&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;可用，支持python&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;永久&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;JPEG/PNG/GIF(非动画)&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Imgur&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;可不注册&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;lt;10MB,大于1MB将被压缩&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;可用，支持python&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;6月未访问则删除&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;JPEG/PNG/GIF/TIFF/BMP/PDF/XCFF&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;图片被压缩&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;ThumbSnap&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;不需要&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;lt;2MB(单张)&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;可用&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Photobucket&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;需要&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;2GB&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;10GB/月&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;可用&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Tinypic&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;可不注册&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;1600px(w,h)&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;plugin可用&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;90天未访问则删除&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;大部分格式&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Postimage&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;可不注册&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;提供一段js&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;500px&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;需要&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;lt;30MB(单张)&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;可用&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;永久&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;版权保护&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Picasaweb&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;需要&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;5GB&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;可用&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;永久&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;SkyDriver&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;需要&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;7GB&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;不支持直接外链&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Dropbox&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;需要&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;2GB&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;很少&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;流量过大会失效&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
国外的图片托管网站比较多，而且也比较成熟，服务品质有保证。如果是用作个人图床，如博客、论坛发帖，以上表格中的平台大部分都是可用的。至于SkyDriver和Dropbox不建议使用，因为这两者本来就不是专用于图片托管，将外链放到公开的地方会增大服务器的流量负荷，这对服务提供方是不利的，所以SkyDriver和Dropbox都有相应的措施。SkyDriver得到的外链并不是文件的直接链接，而是一个跳转链接，这个链接还会变化，用虽然能用，但并不能达到“图床”的目的；Dropbox则更阴险，如果外链流量大了，这个外链会直接失效。
&lt;/p&gt;

&lt;p&gt;
国外的图片托管网站有一个很大的优点是，不少网站都有非常丰富、完善的API，如Flickr、Imgur等等。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;国内图床&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;


&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;名称&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;注册需要&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;免费容量&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;流量限制&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;上传限制&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;API&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;图片/外链有效期&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;图片格式&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;其他&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Poco&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;需要&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;上传后被压缩&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;又拍云&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;可用，支持python&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;防盗链&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;盛大云&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;可用&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;防盗链&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;阿里云&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;可用&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;防盗链&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;七牛云存储&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;可用&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;付费&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;防盗链&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;六间房&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;已停止运营&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;百度云&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;需要&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;15GB&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;无限制&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;生成外链复杂&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
国内的图片托管服务，怎么说呢，因为社会环境不一样，免费的平台在整体服务质量上和国外无法相比，而且像Flickr这样的老牌网站不多，Poco算是一个，六间房也算一个(不过已经死了)。如果个人使用的话，其实还有很多网络相册类平台可以使用，比如免费的又拍相册、百度相册、网易相册、新浪微博相册等等等等，但是这些网络相册没法保证稳定的外链，而且外链的生成、提取一般也比较繁琐，有的还会带有水印。
&lt;/p&gt;

&lt;p&gt;
总而言之，国内的平台，如果需要图床，个人用途的，可选的方案很多，不过首推Poco。如果非个人用途，而是用于应用开发，为求稳定和安全，最好还是选择付费的云服务。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>Symbol t may not be buffer-local问题</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/12/02/terrible-conf-problem.html"/>
    <category term="Emacs" scheme="http://www.zmonster.me/categories.html#Emacs"/>
    <id>http://www.zmonster.me/2013/12/02/terrible-conf-problem</id>
    <published>2013-12-02T00:00:00+00:00</published>
    <updated>2013-12-02T00:00:00+00:00</updated>
    <description>
    
      <p>因为在配置文件中少写了一个逗号，而导致我被这一条出错信息折磨得差点疯掉</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
真是快要疯掉了……本来只是想配置好python的开发环境的，然后动了整理配置文件的念头，整理的时候更新了一些插件，结果插件和旧版本org-mode是冲突的，安装上新版本org-mode吧，因为emacs总会加载/usr/share/emacs/24.2/lisp/以及其他几个相关目录下的一些文件，而这些文件和org-mode有关的一部分又是按照旧版本来的，新旧版本一直冲突。一怒之下把这些文件全删了自己编译安装，但是编译安装的依然报错……
&lt;/p&gt;

&lt;p&gt;
当时真是要疯掉了……
&lt;/p&gt;

&lt;p&gt;
算了，说正事。
&lt;/p&gt;

&lt;p&gt;
后来我在ubuntu系统里把对应的目录复制过来用来进行恢复，总算才好了。但是，当我尝试进行publish的时候，就……
&lt;/p&gt;

&lt;p&gt;
一直一直一直一直一直一直报这个错误：
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
Symbol t may not be buffer-local
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
*Message*里只有这一条信息，没有出错位置，没有任何其他信息。Google了八百遍也找不到相关的issue，当时真的是把这个Linux Mint系统格了重装的心都有了……
&lt;/p&gt;

&lt;p&gt;
后来发现自己的搜索有点问题，我是直接把这条出错信息贴在搜索框里的，而这样Google是会把这句话拆分成多个关键字来进行搜索的，而不是用这整句话！尝试用双引号括起来后终于得到了一条稍微有点参考价值的结果:
&lt;img src=&quot;/assets/img/2013-12-02-search-symbol-t.png&quot; alt=&quot;2013-12-02-search-symbol-t.png&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;
这条信息向我指示了可能的出错位置:
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
make-local-variable should accept a quote instead var. otherwise, it would introduce error as “Symbol nil may not be buffer-local” and fail to start ESS.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
我的配置文件里有这么一条:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;my-lisp-style&lt;/span&gt; ()
  (highlight-parentheses-mode t)
  (hs-minor-mode t)
  (set (make-local-variable 'electric-pair-mode) nil))
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
而我漏写了 &lt;b&gt;electric-pair-mode&lt;/b&gt; 前面那个单引号。
&lt;/p&gt;

&lt;p&gt;
终于对上了，知道是哪里出了错，感觉真他妈好(偶尔爆个粗口)！
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>org-mode 8.x导出html时代码块不高亮问题</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/12/02/org8.x-export-source-code.html"/>
    <category term="Emacs" scheme="http://www.zmonster.me/categories.html#Emacs"/>
    <id>http://www.zmonster.me/2013/12/02/org8.x-export-source-code</id>
    <published>2013-12-02T00:00:00+00:00</published>
    <updated>2013-12-02T00:00:00+00:00</updated>
    <description>
    
      <p>将org-mode更换为8.x版本后，按照之前的经验，无论怎么设置，导出成html时都不能产生语法高亮效果</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;问题&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;解决方法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;吐槽&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;问题&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
在我将org-mode更换为8.x版本后，按照之前的经验，无论怎么设置，导出成html时都不能产生语法高亮效果.
&lt;/p&gt;

&lt;p&gt;
以前的做法通常都是在配置文件里加上这么两句:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;require&lt;/span&gt; '&lt;span style=&quot;color: #e6a00f;&quot;&gt;htmlize&lt;/span&gt;) &lt;span style=&quot;color: #888a85;&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;htmlize.el&lt;/span&gt;
(setq org-src-fontify-natively t)
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
但是这次这两句完全不起作用……
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;解决方法&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
最后在org-mode的网站上找到了相关的信息，那就是在设置org的导出项目时，要在对应的alist中添加一个 &lt;b&gt;:publishing-function&lt;/b&gt; 参数，并设置其值为非nil值，如下所示:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;(setq org-publish-project-alist
    '(
      (&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;project-name&quot;&lt;/span&gt;
       ......
   &lt;span style=&quot;color: #729fcf;&quot;&gt;:htmlized-source&lt;/span&gt; t
       ......
       )
       ......))
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;吐槽&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
org-mode 8.x的变化太多了……不知道官方有没有对这些改动之处做一个详细说明……虽然说文档都发生了改变，但到发生问题时再来找真的很费劲啊……
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>org-remember从org-mode中移除</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/12/02/org-remember-removed.html"/>
    <category term="Emacs" scheme="http://www.zmonster.me/categories.html#Emacs"/>
    <id>http://www.zmonster.me/2013/12/02/org-remember-removed</id>
    <published>2013-12-02T00:00:00+00:00</published>
    <updated>2013-12-02T00:00:00+00:00</updated>
    <description>
    
      <p>在org-mode 8.x中org-remember.el已经不复存在，其功能被org-capture.el替换，模板设置方式也发生了变化</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
因为&lt;a href=&quot;http://about.me/wlwang41&quot;&gt;Crow&lt;/a&gt; 的提议，我和他还有另外一个同学准备做一个开源项目，而在项目中需要使用python，因此这两天就在配置Emacs的python环境，同时把原来的Emacs配置文件整理了一下，这期间发生了不少问题。
&lt;/p&gt;

&lt;p&gt;
首先是为了使用最新的Emacs，在系统里添加了PPA下载了Damien Cassou维护的Emacs&lt;a href=&quot;https://launchpad.net/~cassou/+archive/emacs&quot;&gt;版本&lt;/a&gt; ，而&lt;a href=&quot;https://github.com/fgallina/python.el&quot;&gt;python.el&lt;/a&gt; 在该版本Emacs下会出问题。重新从源里安装了Emacs 24后这个问题得到了解决。但因为我对配置文件的大幅度调整，导致Emacs一直提示
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
Can't load library: org
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
找不到该问题源头所在的我，尝试着删除了Emacs24自带的org，用上了8.2.1的版本，不想问题就这样解决了——唔，我还是知其然不知其所以然。
&lt;/p&gt;

&lt;p&gt;
但后来又报错，说无法加载org-remember，我在org目录下一查找，发现居然没有了 &lt;b&gt;org-remember.el&lt;/b&gt; 这个文件，一时间很困惑。
&lt;/p&gt;

&lt;p&gt;
在Google上以 &lt;b&gt;org-remember&lt;/b&gt; 和 &lt;b&gt;org-mode8.x&lt;/b&gt; 为关键字，也只搜索到两条结果，不过这两条搜索结果告诉了我事实的真相。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2013-12-02-search-org.png&quot; alt=&quot;2013-12-02-search-org.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
原来org-mode 8已经不支持org-remember.el了。
&lt;/p&gt;

&lt;p&gt;
org-remember.el的功能是建立在remember.el之上的，而remember.el并不是org-mode的一部分，估计org-mode的开发人员是为了不依赖remember.el，而将org-remember.el从新版的org-mode中移除了，并以org-capture.el来替换它。
&lt;/p&gt;

&lt;p&gt;
因此，若要使用org-mode 8，相关的配置需要进行一定的更改
&lt;/p&gt;

&lt;p&gt;
我在配置文件中为 &lt;b&gt;org-remember&lt;/b&gt; 设置了快捷键，因此要将那条语句中的 &lt;i&gt;org-remember&lt;/i&gt; 修改为 &lt;i&gt;org-capture&lt;/i&gt; 。
&lt;/p&gt;

&lt;p&gt;
其次，org-remember模板和org-capture的模板格式不一样，需要将原先org-remember的模板进行修改，对应的变量名 &lt;i&gt;org-remember-templates&lt;/i&gt; 也要改为 &lt;i&gt;org-capture-templaes&lt;/i&gt; 。
&lt;/p&gt;

&lt;p&gt;
org-capture的模板格式可以到&lt;a href=&quot;http://orgmode.org/manual/Capture-templates.html#Capture-templates&quot;&gt;这里&lt;/a&gt; 进行详细地了解。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>月底小结</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/11/27/month-log.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2013/11/27/month-log</id>
    <published>2013-11-27T00:00:00+00:00</published>
    <updated>2013-11-27T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


公务员考试
后续计划




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;公务员考试&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;后续计划&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;公务员考试&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
24号是国家公务员考试的日期，我在23号乘坐汽车到了南昌，在离考场25分钟路程的地方开了150一晚的一间房。那儿环境良好，还附送早餐和一次正餐，一觉醒来还发现门缝里塞进来几张卡片，上面印着穿着制服摆着妖娆姿势的女人，旁边写着：在校大学生、高级白领、在职空姐……随心所欲，倾情相约……
&lt;/p&gt;

&lt;p&gt;
哈哈哈哈……第一次碰到这种事情……
&lt;/p&gt;

&lt;p&gt;
考试那天下了一整天大雨，我是穿着一双湿透的鞋去考试的。当日南昌二十三中附近道路拥堵无比。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;后续计划&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
首先，好好复习专业知识。
&lt;/p&gt;

&lt;p&gt;
其次，如果公务员没考上，明天过完年，我就离家找工作去——我可没脸一直待在家里。事实上我希望我不要考上，档案和党组织关系的问题太头疼了，而且我是真心想在”程序员“这条道上走下去的。理由不仅仅是我喜欢，而是我不想半途而废。首先会尝试一下争取百度研究院的实习机会，为此我要系统地把机器学习、神经网络这些AI领域的知识学习一下；如果失败，不管是同学帮忙内推还是自己海投，相关的笔试面试技巧、常用算法我还得去复习一遍，具体计划就要慢慢来了。
&lt;/p&gt;

&lt;p&gt;
另外，高玩拉起我和老徐，说想做个开源的WEB应用，所以这段时间除了头脑风暴，我还得学会python——这对后面我找工作也是有益的。
&lt;/p&gt;

&lt;p&gt;
除了这些，还得趁这段时间多读一些书——不知道能不能把《全球通史》这本大部头给啃完……而且现在不需要操心公务员考试了，清晨和晚上的写作练习也得坚持起来。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>《ANSI Common Lisp》第三章习题</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/11/12/acl-ch3-exercises.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2013/11/12/acl-ch3-exercises</id>
    <published>2013-11-12T00:00:00+00:00</published>
    <updated>2013-11-12T00:00:00+00:00</updated>
    <description>
    
      <p>

Show the following lists in box notation:


</p>
    
    </description>
    <content type="html">
      &lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
Show the following lists in box notation:
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
(a) (a b (c d))
(b) (a (b (c (d))))
(c) (((a b) c) d)
(d) (a (b . c) . d)
&lt;/pre&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;

&lt;p&gt;
(a) (a . (b . ((C . (D . NIL)) . NIL)))
&lt;/p&gt;

&lt;p&gt;
(b) (a . ((B . ((C . ((D . NIL) . NIL)) . NIL)) . NIL))
&lt;/p&gt;

&lt;p&gt;
(c) (((A . (B . NIL)) . (C . NIL)) . (D . NIL))
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Write a version of &lt;b&gt;union&lt;/b&gt; that preserves the order of the elements in the original lists:
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
&amp;gt; (new-union '(a b c) '(b a d))
(A B C D)
&lt;/pre&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;new-union&lt;/span&gt; (first second)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;dolist&lt;/span&gt; (obj second)
    (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (not (member obj first))
        (append first (list obj)))))
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Define a function that takes a list and returns a list indicating the number of times each (eql) element appears, sorted from most common element to least common:
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
&amp;gt; (occurrences '(a b a d a c d c a))
((A . 4) (C . 2) (D . 2) (B . 1))
&lt;/pre&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;occurrence&lt;/span&gt; (lst)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;let&lt;/span&gt; ((result nil))
    (&lt;span style=&quot;color: #729fcf;&quot;&gt;dolist&lt;/span&gt; (obj lst)
      (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (null (assoc obj result))
      (push (cons obj 1) result)
      (incf (cdr (assoc obj result)))
    ))
    (sort result #'(&lt;span style=&quot;color: #729fcf;&quot;&gt;lambda&lt;/span&gt; (a b) (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (&amp;gt; (cdr a) (cdr b)) t nil)))))
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Why does (member '(a) '((a) (b))) return nil?
&lt;/p&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;

&lt;p&gt;
因为每次产生cons调用时系统都会分配新的对象，所以'(a)和'((a) (b))中的第一个元素虽然具有同样的值，但却不是同一个对象，而member函数使用的判定函数是eql。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Suppose the function &lt;b&gt;pos+&lt;/b&gt; takes a list and returns a list of each element plus its position:
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
&amp;gt; (pos+ '(7 5 1 4))
&lt;/pre&gt;
&lt;p&gt;
Define this function using (a) recursion, (b) iteration, (c) mapcar.
&lt;/p&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;

&lt;p&gt;
(a) Recursive version
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;rec-pos-plus&lt;/span&gt; (lst pos)&lt;span style=&quot;color: #ffff00; background-color: #ff0000; font-weight: bold;&quot;&gt; &lt;/span&gt;
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (not (null lst))
      (&lt;span style=&quot;color: #729fcf;&quot;&gt;progn&lt;/span&gt;
    (incf (car lst) pos)
    (rec-pos-plus (cdr lst) (1+ pos)))))

(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;rec-pos+&lt;/span&gt; (lst)
  (rec-pos-plus lst 0)
  lst)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
(b) Iterative version
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;iter-pos+&lt;/span&gt; (lst)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;do&lt;/span&gt; ((i 0 (+ i 1)))
      ((= i (length lst)) lst)
    (incf (nth i lst) i)
    ))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
(c) Version using &lt;b&gt;mapcar&lt;/b&gt;
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;pos+&lt;/span&gt; (lst)
  (mapcar #'(&lt;span style=&quot;color: #729fcf;&quot;&gt;lambda&lt;/span&gt; (x) (incf x (position x lst)))
      lst))
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
After yeas of deliiberation, a government commission has decided that lists should be represented by using the cdr to point to the first element and the car to point to the rest of the list. Define the government versions of the following functions:
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
(a) cons
(b) list
(c) length (for lists)
(d) member (for lists; no keywords)
&lt;/pre&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;

&lt;p&gt;
(a) cons
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;cons&lt;/span&gt; (x y)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;let&lt;/span&gt; ((result '(nil . nil)))
    (setf (cdr result) x)
    (setf (car result) y)))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
(b) list
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;list&lt;/span&gt; (&lt;span style=&quot;color: #8ae234;&quot;&gt;&amp;amp;rest&lt;/span&gt; arg)
  arg)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
(c) length (for lists)
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;length&lt;/span&gt; (lst)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (null lst)
      0
      (+ 1 (length (car lst)))))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
(d) member (for lists; no keywords)
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;member&lt;/span&gt; (element list)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;cond&lt;/span&gt; ((null list) nil)
        ((eql element (cdr list)) list)
        (t (member element (car list)))))
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Modify the program in Figure 3.6 to use fewer cons cells. (Hing: Use dottedlists.)
&lt;/p&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;n-elts&lt;/span&gt; (elt n)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (&amp;gt; n 1)
      (cons n elt)
      elt))

(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;compr&lt;/span&gt; (elt n lst)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (null lst)
      (list (n-elts elt n))
      (&lt;span style=&quot;color: #729fcf;&quot;&gt;let&lt;/span&gt; ((next (car lst)))
    (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (eql next elt)
        (compr elt (+ n 1) (cdr lst))
        (cons (n-elts elt n)
          (compr next 1 (cdr lst)))))))

(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;compress&lt;/span&gt; (x)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (consp x)
      (compr (car x) 1 (cdr x))
      x))
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Define a function that takes a list and prints it in dot natation:
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
&amp;gt; (showdots '(a b c))
(A . (B . (C . NIL)))
NIL
&lt;/pre&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;showdots&lt;/span&gt; (list)
(&lt;span style=&quot;color: #729fcf;&quot;&gt;cond&lt;/span&gt; ((null list) nil)
  ((consp list) (&lt;span style=&quot;color: #729fcf;&quot;&gt;progn&lt;/span&gt;
         (format t &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;(&quot;&lt;/span&gt;)
         (showdots (car list))
         (format t &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot; . &quot;&lt;/span&gt;)
         (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (null (cdr list))
             (format t &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;NIL&quot;&lt;/span&gt;)
             (showdots (cdr list)))
         (format t &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;)&quot;&lt;/span&gt;)
         ))
  (t (format t &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;~a&quot;&lt;/span&gt; list))))
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Write a program to find the &lt;i&gt;longest&lt;/i&gt; finite path through a network represented as in Section 3.15. The network may contain cycles.
&lt;/p&gt;

&lt;p&gt;
My answer(对shortest-path的改写):
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;new-paths&lt;/span&gt; (path node net)
  (mapcar #'(&lt;span style=&quot;color: #729fcf;&quot;&gt;lambda&lt;/span&gt; (n)&lt;span style=&quot;color: #ffff00; background-color: #ff0000; font-weight: bold;&quot;&gt; &lt;/span&gt;
               (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (not (member n path)) &lt;span style=&quot;color: #888a85;&quot;&gt;;&amp;#21028;&amp;#26029;&amp;#19979;&amp;#19968;&amp;#23618;&amp;#33410;&amp;#28857;&amp;#26159;&amp;#21542;&amp;#21253;&amp;#21547;&amp;#22312;&amp;#36335;&amp;#24452;&amp;#20013;&amp;#20197;&amp;#21066;&amp;#38500;&amp;#29615;&amp;#30340;&amp;#24433;&amp;#21709;&lt;/span&gt;
                   (cons n path)))
          (cdr (assoc node net))))

(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;bfs&lt;/span&gt; (end quene net)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (null quene)
      nil
      (&lt;span style=&quot;color: #729fcf;&quot;&gt;let&lt;/span&gt; ((path (car quene)))
        (&lt;span style=&quot;color: #729fcf;&quot;&gt;let&lt;/span&gt; ((node (car path)))
          (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (eql node end)
              (reverse path)
              (bfs end
                   (sort (append (cdr quene) &lt;span style=&quot;color: #888a85;&quot;&gt;;&amp;#25490;&amp;#24207;&amp;#20197;&amp;#20445;&amp;#35777;&amp;#26368;&amp;#38271;&amp;#30340;&amp;#36335;&amp;#24452;&amp;#22312;&amp;#38431;&amp;#21015;&amp;#26368;&amp;#21069;&amp;#26041;&lt;/span&gt;
                                 (new-paths path node net))
                         #'&amp;gt;
                         &lt;span style=&quot;color: #729fcf;&quot;&gt;:key&lt;/span&gt; #'length)
                   net))))))

(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;longest-path&lt;/span&gt; (start end net)
  (bfs end (list (list start)) net))
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
= =写个题比拿半生不熟的英文来记笔记还累……
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>《ANSI Common Lisp》第二章习题</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/11/09/acl-ch2-exercises.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2013/11/09/acl-ch2-exercises</id>
    <published>2013-11-09T00:00:00+00:00</published>
    <updated>2013-11-09T00:00:00+00:00</updated>
    <description>
    
      <p>

Describe what happens when the following expressions are evaluated:


</p>
    
    </description>
    <content type="html">
      &lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
Describe what happens when the following expressions are evaluated:
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
(a) (+ (- 5 1) (+ 3 7))
(b) (list 1 (+ 2 3))
(c) (if (listp 1) (+ 1 2) (+ 3 4))
(d) (list (and (listp 3) t) (+ 1 2))
&lt;/pre&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;

&lt;p&gt;
(a) 14
&lt;/p&gt;

&lt;p&gt;
(b) (1 5)
&lt;/p&gt;

&lt;p&gt;
(c) 7
&lt;/p&gt;

&lt;p&gt;
(d) (NIL 3)
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Give three distinct cons expressions that return (a b c).
&lt;/p&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(cons 'a '(b c))
(cons 'a (cons 'b '(c)))
(cons 'a (cons 'b (cons 'c nil)))
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Using &lt;b&gt;car&lt;/b&gt; and &lt;b&gt;cdr&lt;/b&gt;,define a function to return the fourth element of a list.
&lt;/p&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;fourth&lt;/span&gt; (lst)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (listp lst)
    (car (cdr (cdr (cdr lst))))))
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Define a function that takes two arguments and returns the greater of the two.
&lt;/p&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;greater&lt;/span&gt; (a b)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (equal (type-of a)
             (type-of b))
      (&lt;span style=&quot;color: #729fcf;&quot;&gt;cond&lt;/span&gt; ((typep a 'number) (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (&amp;gt; a b) a b)
            ((typep a 'character) (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (char&amp;gt; a b) a b))
            ((typep a 'string) (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (string&amp;gt; a b) a b))
            (t nil)))
      nil))
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
What do hese functions do?
&lt;/p&gt;

&lt;p&gt;
(a)
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;enigma&lt;/span&gt; (x)
  (and (not (null x))
       (or  (null (car x))
            (enigma (cdr x)))))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
(b)
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;mystery&lt;/span&gt; (x y)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (null y)
      nil
      (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (eql (car y) x)
          0
          (&lt;span style=&quot;color: #729fcf;&quot;&gt;let&lt;/span&gt; ((z (mystery x (cdr y))))
            (and z (+ z 1))))))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;

&lt;p&gt;
(a) 该函数用于判断一个非空的list中是否含有 &lt;b&gt;NIL&lt;/b&gt; 元素.
&lt;/p&gt;

&lt;p&gt;
(b) 判断y中是否有元素和x相等(同一个对象)，若无则返回NIL，若有则返回该元素在y中的索引(以0为初始值).
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
What could occur in place of the &lt;b&gt;x&lt;/b&gt; in each of the following exchanges?
&lt;/p&gt;

&lt;pre class=&quot;example&quot;&gt;
(a) &amp;gt; (car (x (cdr '(a (b c) d))))
    B
(b) &amp;gt; (x 13 (/ 1 0))
    13
(c) &amp;gt; (x #'list 1 nil)
    (1)
&lt;/pre&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;

&lt;p&gt;
(a) cdr.
&lt;/p&gt;

&lt;p&gt;
(b) or.
&lt;/p&gt;

&lt;p&gt;
(c) apply.
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Using only operators introduced in this Chapter, define a function that takes a list as an argument and returns true if one of its elements is a list.
&lt;/p&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;have-list-member&lt;/span&gt; (lst)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (null lst)
      nil
      (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (listp (car lst))
          t
          (have-list-member (cdr lst)))))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
注：本章出现的操作符有：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
+ / - quote list cons car cdr third listp null not if and or defun &amp;gt; eql read format let defparameter defconstant setf remove do dolist progn function apply funcall lambda typep
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Give iterative and recursive definitions of a function that
&lt;/p&gt;

&lt;p&gt;
(a) takes a positive integer and prints that many dots.
&lt;/p&gt;

&lt;p&gt;
(b) takes a list and returns the number of times the symblo &lt;b&gt;a&lt;/b&gt; occurs in it.
&lt;/p&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;

&lt;p&gt;
(a) dot-plot
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
Iteractive version
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;dot-plot-iter&lt;/span&gt; (n)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;do&lt;/span&gt; ((n n (- n 1)))
      ((= n 0) 'done)
    (format t &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;.&quot;&lt;/span&gt;)))
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
Recursive version
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;dot-plot-rec&lt;/span&gt; (n)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (= n 0)
      'done
      (&lt;span style=&quot;color: #729fcf;&quot;&gt;progn&lt;/span&gt;
        (format t &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;.&quot;&lt;/span&gt;)
        (dot-plot-rec (- n 1)))))
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
(b) times-of-a
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
Iteractive version
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;bfs&lt;/span&gt; (lst)                     &lt;span style=&quot;color: #888a85;&quot;&gt;;&amp;#24191;&amp;#24230;&amp;#20248;&amp;#20808;&amp;#36941;&amp;#21382;&amp;#65292;&amp;#24471;&amp;#21040;lst&amp;#30340;&amp;#25152;&amp;#26377;&amp;#26641;&amp;#21494;&amp;#33410;&amp;#28857;&amp;#30340;&amp;#21015;&amp;#34920;&lt;/span&gt;
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;let&lt;/span&gt; ((stack (list lst))           &lt;span style=&quot;color: #888a85;&quot;&gt;;&amp;#36941;&amp;#21382;&amp;#25152;&amp;#38656;&amp;#26632;&lt;/span&gt;
        (leaves nil))                &lt;span style=&quot;color: #888a85;&quot;&gt;;&amp;#23384;&amp;#25918;&amp;#26641;&amp;#21494;&amp;#33410;&amp;#28857;&amp;#30340;&amp;#21015;&amp;#34920;&lt;/span&gt;
    (&lt;span style=&quot;color: #729fcf;&quot;&gt;do&lt;/span&gt; ()
        ((null stack) leaves)        &lt;span style=&quot;color: #888a85;&quot;&gt;;&amp;#24403;&amp;#26632;&amp;#31354;&amp;#26102;&amp;#65292;&amp;#36941;&amp;#21382;&amp;#32467;&amp;#26463;&lt;/span&gt;
      (&lt;span style=&quot;color: #729fcf;&quot;&gt;let&lt;/span&gt; ((now (pop stack)))       &lt;span style=&quot;color: #888a85;&quot;&gt;;&amp;#23558;&amp;#26632;&amp;#39030;&amp;#33410;&amp;#28857;&amp;#20986;&amp;#26632;&lt;/span&gt;
        (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (listp now)              &lt;span style=&quot;color: #888a85;&quot;&gt;;&amp;#33509;&amp;#20986;&amp;#26632;&amp;#33410;&amp;#28857;&amp;#19981;&amp;#20026;&amp;#26641;&amp;#21494;&amp;#33410;&amp;#28857;&amp;#26102;&amp;#65292;&amp;#23558;&amp;#20854;&amp;#23376;&amp;#26641;&amp;#20837;&amp;#26632;&lt;/span&gt;
            (&lt;span style=&quot;color: #729fcf;&quot;&gt;progn&lt;/span&gt; (push (car now) stack)
                   (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (not (null (cdr now)))   &lt;span style=&quot;color: #888a85;&quot;&gt;;&amp;#36825;&amp;#37324;&amp;#35201;&amp;#21028;&amp;#26029;cdr&amp;#26159;&amp;#21542;&amp;#20026;nil&amp;#65292;&amp;#21542;&amp;#21017;&amp;#23558;&amp;#20854;&amp;#20837;&amp;#26632;&amp;#21518;&lt;/span&gt;
                       (push (cdr now) stack))) &lt;span style=&quot;color: #888a85;&quot;&gt;;listp&amp;#23545;&amp;#20854;&amp;#21028;&amp;#26029;&amp;#30340;&amp;#32467;&amp;#26524;&amp;#20026;&amp;#30495;&amp;#65292;&amp;#23548;&amp;#33268;&amp;#26080;&amp;#31351;&amp;#36882;&amp;#24402;&lt;/span&gt;
            (push now leaves))))))   &lt;span style=&quot;color: #888a85;&quot;&gt;;&amp;#33509;&amp;#20986;&amp;#26632;&amp;#33410;&amp;#28857;&amp;#20026;&amp;#26641;&amp;#21494;&amp;#33410;&amp;#28857;&amp;#65292;&amp;#23558;&amp;#20854;&amp;#25918;&amp;#20837;leaves&amp;#21015;&amp;#34920;&amp;#20013;&lt;/span&gt;

(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;times-of-a-iter&lt;/span&gt; (lst)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;let&lt;/span&gt; ((leaves (bfs lst))
        (times 0))
    (&lt;span style=&quot;color: #729fcf;&quot;&gt;dolist&lt;/span&gt; (obj lst)
      (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (equal 'a obj)
          (setf times (+ times 1))))
    times))
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
Recursive version
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;times-of-a-rec&lt;/span&gt; (lst)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (null lst)
       0
      (&lt;span style=&quot;color: #729fcf;&quot;&gt;let&lt;/span&gt; ((now (car lst)))
        (+ (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (listp now)
               (times-of-a-rec now)
               (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (equal now 'a) 1 0))
           (times-of-a-rec (cdr lst))))))
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
A friend is trying to write a function that returns the sum of all the non-nil elements in a list. He has written two versions of this function, and neither of them work.Explain what's wrong with each, and give a correct version:
&lt;/p&gt;

&lt;p&gt;
(a)
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;summit&lt;/span&gt; (lst)
  (remove nil lst)
  (apply #'+ lst))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
(b)
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;summit&lt;/span&gt; (lst)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;let&lt;/span&gt; ((x (car lst)))
    (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (null x)
        (summit (cdr lst))
        (+ x (summit (cdr lst))))))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
My answer:
&lt;/p&gt;

&lt;p&gt;
(a) remove是没有副作用(side-effect)的，所以lst中的 &lt;b&gt;nil&lt;/b&gt; 元素还在 lst中，正确的代码应为
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;summit&lt;/span&gt; (lst)
  (apply #&amp;#8216;+ (remove nil lst)))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
(b) 没有递归终止条件，正确的代码应为：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #729fcf;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #edd400;&quot;&gt;summit&lt;/span&gt; (lst)
  (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (null lst)
      0
      (&lt;span style=&quot;color: #729fcf;&quot;&gt;let&lt;/span&gt; ((x (car lst)))
        (&lt;span style=&quot;color: #729fcf;&quot;&gt;if&lt;/span&gt; (null x)
            (summit (cdr lst))
            (+ x (summit (cdr lst)))))))
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;

    </content>
  </entry>
  
  <entry>
    <title>丧心病狂:用Emacs阅读PDF文档</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/11/06/emacs-pdf.html"/>
    <category term="Emacs" scheme="http://www.zmonster.me/categories.html#Emacs"/>
    <id>http://www.zmonster.me/2013/11/06/emacs-pdf</id>
    <published>2013-11-06T00:00:00+00:00</published>
    <updated>2013-11-06T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


DocViewMode
安装
感受




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;DocViewMode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;安装&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline3&quot;&gt;感受&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;DocViewMode&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
Emacs有个插件叫做&lt;a href=&quot;http://www.emacswiki.org/emacs/DocViewMode&quot;&gt;DocViewMode&lt;/a&gt;， 为Emacs提供了对PDF、PS等格式文件的支持，其原理是将这些文件转换成png格式的图片，并在Emacs中显示。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;安装&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
从Emacs 23开始，默认就安装了DocViewMode，不过为了能够正常工作，还需要在系统中安装这两个东西：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;xpdf&lt;/li&gt;
&lt;li&gt;ghostscript&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
安装好后，像打开常规文件那样打开PDF文件就行了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline3&quot;&gt;感受&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline3&quot;&gt;
&lt;p&gt;
怎么说呢……打开小的PDF文件还可以,比如说这个：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2013-11-06-emacs-pdf-view.png&quot; alt=&quot;2013-11-06-emacs-pdf-view.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
操作也简单，+/- 进行缩放，n/p进行翻页。
&lt;/p&gt;

&lt;p&gt;
然后我丧心病狂地按了C-x C-f后输入了：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
~/Dropbox/book/lisp/ANSI_Common_Lisp.pdf
&lt;/pre&gt;
&lt;p&gt;
然后就悲剧了……
&lt;/p&gt;

&lt;p&gt;
所以说某篇文章说的把Emacs设置成默认PDF阅读器这种事还是不要做的好。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>在Linux系统中屏蔽独立显卡</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/11/04/video-card.html"/>
    <category term="Linux" scheme="http://www.zmonster.me/categories.html#Linux"/>
    <id>http://www.zmonster.me/2013/11/04/video-card</id>
    <published>2013-11-04T00:00:00+00:00</published>
    <updated>2013-11-04T00:00:00+00:00</updated>
    <description>
    
      <p>对于Linux系统来说，双显卡一直都是一个很令人头疼的问题，本文提供了一种简单的办法来解决双显卡风扇狂转的问题</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;问题&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;解决方案&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;问题&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
对于Linux系统来说，显卡驱动一直都是一个很头疼的问题，更别说双显卡了。但是很不幸的，我的笔记本是双显卡，更不幸的是，还是Intel核心显卡+AMD独立显卡这种及其蛋疼的组合。
&lt;/p&gt;

&lt;p&gt;
在我还没有处理这个问题时，每次开机后，经常能够听到独立显卡风扇狂转的声音，但是实际上当时我并没有运行什么需要显卡进行大量计算的程序。这个问题不仅带来噪声问题（你说这声音要是一直在响，听习惯了也没什么，问题时它一会响一会不响，声音也一会大一会小），还对机器的散热带来了不好的影响。
&lt;/p&gt;

&lt;p&gt;
所以要解决它！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;解决方案&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
一种办法是安装独立显卡驱动，同时要做一些处理使得系统能够在独立显卡和集成显卡之间智能切换。这种方法能够彻底解决问题，也能够发挥独立显卡的性能，但这种方法非常费力，而且不一定能够成功。
&lt;/p&gt;

&lt;p&gt;
另外一种方法是屏蔽独立显卡——说真的，我在Linux下并没有太多需要用到独立显卡的时候——当然在Windows下玩盗版大型游戏的时候就需要了。屏蔽独立显卡也有两种方式，一种是通过BIOS屏蔽，另外一种是通过系统实现软屏蔽。
&lt;/p&gt;

&lt;p&gt;
很遗憾的是，笔记本的BIOS功能被阉割过，没有提供屏蔽独显的操作，而且BIOS进行了屏蔽的话，Windows系统同样也不能使用独立显卡了，这就不太满足期望了。所以最好的选择就是通过系统进行软屏蔽了。
&lt;/p&gt;

&lt;p&gt;
办法就是通过内核提供的 &lt;b&gt;vgaswitcheroo&lt;/b&gt; 组件来关闭独立显卡的电源。
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;首先切换到root用户（普通用户即使用sudo也不方便操作）&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
查看当前双显卡使用状态
&lt;/p&gt;

&lt;p&gt;
这一步要通过 &lt;b&gt;/sys/kernel/debug/vgaswitcheroo/switch&lt;/b&gt; 这个文件来进行。
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
cat /sys/kernel/debug/vgaswitcheroo/switch
&lt;/pre&gt;
&lt;p&gt;
这步是要读出 /sys/kernel/debug/vgaswitcheroo/switch 这一文件的信息。不出意外您可能会看到类似下面（但不完全相同）的内容：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
0:IGD:+:Pwr:0000:00:02.0
1:DIS: :Pwr:0000:01:00.0
&lt;/pre&gt;
&lt;p&gt;
其中 &lt;b&gt;IGD&lt;/b&gt; 表示集成显卡， &lt;b&gt;DIS&lt;/b&gt; 表示独立显卡， &lt;b&gt;+&lt;/b&gt; 号表示当前连接上的显卡， &lt;b&gt;Pwr&lt;/b&gt; 表示正在供电（若不供电则为 &lt;b&gt;Off&lt;/b&gt; ）。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
关闭独立显卡
&lt;/p&gt;

&lt;p&gt;
如果确实是上面所述的状态，那么执行：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
echo OFF &amp;gt; /sys/kernel/debug/vgaswitcheroo/switch
&lt;/pre&gt;
&lt;p&gt;
关闭未连接的显卡（即独显）的电源即可，不过这种方法只是暂时的方法，一旦重启就又会听到显卡风扇狂转了。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
开机关闭独立显卡
&lt;/p&gt;

&lt;p&gt;
将关闭独立显卡的命令写入系统启动时加载的脚本就能够在开机的时候关闭独立显卡的电源。如我的发行版是Linux Mint，将这三条命令写入/etc/init.d/rc.local中：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
echo ON &amp;gt; /sys/kernel/debug/vgaswitcheroo/switch
echo IGD &amp;gt; /sys/kernel/debug/vgaswitcheroo/switch
echo OFF &amp;gt; /sys/kernel/debug/vgaswitcheroo/switch
&lt;/pre&gt;
&lt;p&gt;
前两条命令是为了保证系统能够连接上集成显卡并供电。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
实际上也可以使用本文提供的方法对集显进行屏蔽。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>博客拆分完成</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/11/04/blog-plan-finished.html"/>
    <category term="博客" scheme="http://www.zmonster.me/categories.html#博客"/>
    <id>http://www.zmonster.me/2013/11/04/blog-plan-finished</id>
    <published>2013-11-04T00:00:00+00:00</published>
    <updated>2013-11-04T00:00:00+00:00</updated>
    <description>
    
      <p>之前说过，要将博客划分为三部分，分别通过site44、Gitcafe Paegs和Github Pages来进行发布。现在已经基本完成这一计划了，尚待改进的就是一些字体啊、布局啊的细微调整了。</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline1&quot;&gt;现状&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgheadline2&quot;&gt;问题&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgheadline1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline1&quot;&gt;现状&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline1&quot;&gt;
&lt;p&gt;
之前说过，要将博客划分为三部分，分别通过site44、Gitcafe Paegs和Github Pages来进行发布。现在已经基本完成这一计划了，尚待改进的就是一些字体啊、布局啊的细微调整了。
&lt;/p&gt;

&lt;p&gt;
没错，现在呢，依靠Dropbox和Github/Gitcafe，我写作的东西分别放到了三个不同的地方
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
&lt;a href=&quot;index.html&quot;&gt;Linusp's Blog&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
一旦有什么想法要去实验，或者有什么牢骚想要倾吐，我都会放到依靠Github Pages建立的博客上来，也就是本站了。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
&lt;a href=&quot;http://linusp.gitcafe.com/&quot;&gt;Linusp's Notes&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
所有我的学习、阅读笔记，我都会放到依靠Gitcafe Pages建立的个人网站上，在这个网站上，同一个主题的笔记都会集中在一个页面上，同时我会尽量做到让同一主题的笔记内容有条理。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
&lt;a href=&quot;http://linusp.site44.com/&quot;&gt;Linusp's Novels&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
最后，我的一些小说作品，会放到Dropbox上，同时通过site44应用来进行发布。目前来说，我写的东西还是比较——嗯，怎么说呢，非常的没有深度吧。不过我会继续努力的。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgheadline2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgheadline2&quot;&gt;问题&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgheadline2&quot;&gt;
&lt;p&gt;
现在来说，存在的尚待解决的问题有：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Linusp's Notes上的字体和颜色还需要调整（用的是&lt;a href=&quot;http://lifegoo.pluskid.org/wiki/index.html&quot;&gt;星黎殿&lt;/a&gt; 的模板）。&lt;/li&gt;
&lt;li&gt;Linusp's Novels上需要添加一个返回首页的导航按钮，我是希望它尽量简洁。&lt;/li&gt;
&lt;li&gt;Linusp's Notes和Linusp's Novels还没有做过SEO，也没有提供feed链接，这些都是以后要做的。&lt;/li&gt;
&lt;li&gt;Linusp's Blog上需要添加一个返回页面顶端的按钮。&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>伪语音合成(2)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/10/20/daily-shell-t2s2.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2013/10/20/daily-shell-t2s2</id>
    <published>2013-10-20T00:00:00+00:00</published>
    <updated>2013-10-20T00:00:00+00:00</updated>
    <description>
    
      <p>
今天实现了中英文的选择，当然，并没有对可能出现的错误情况进行处理，比如说选项指明是英文而文本内容是中文……


</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
今天实现了中英文的选择，当然，并没有对可能出现的错误情况进行处理，比如说选项指明是英文而文本内容是中文……
&lt;/p&gt;

&lt;p&gt;
首先，昨天写的那个脚本有点问题，先来看一下：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;!/bin/&lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;bash&lt;/span&gt;
&lt;span style=&quot;color: #edd400;&quot;&gt;t2s&lt;/span&gt;() {
    wget -q -U Mozilla -O $(&lt;span style=&quot;color: #fa8072;&quot;&gt;tr&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;' '&lt;/span&gt; _ &amp;lt;&amp;lt;&amp;lt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;$1&quot;&lt;/span&gt;| cut -b 1-15).mp3 &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;http://translate.google.com/translate_tts?ie=UTF-8&amp;amp;tl=en&amp;amp;q=$(&lt;/span&gt;&lt;span style=&quot;color: #fa8072;&quot;&gt;tr&lt;/span&gt;&lt;span style=&quot;color: #ad7fa8;&quot;&gt; ' ' + &amp;lt;&amp;lt;&amp;lt; &quot;&lt;/span&gt;$&lt;span style=&quot;color: #eeeeec;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;)&quot;&lt;/span&gt;;
}

&lt;span style=&quot;color: #eeeeec;&quot;&gt;FILE&lt;/span&gt;=$(&lt;span style=&quot;color: #fa8072;&quot;&gt;tr&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;' '&lt;/span&gt; _ &amp;lt;&amp;lt;&amp;lt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;$1&quot;&lt;/span&gt; | cut -b 1-15).mp3;
t2s $&lt;span style=&quot;color: #eeeeec;&quot;&gt;1&lt;/span&gt; &amp;amp;&amp;amp; play $&lt;span style=&quot;color: #eeeeec;&quot;&gt;FILE&lt;/span&gt; -q &amp;amp;&amp;amp; rm $&lt;span style=&quot;color: #eeeeec;&quot;&gt;FILE&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
当文本是用空格分开时，这个脚本会出错，原因是传递给函数的参数会严格按照空格进行划分，也就是说，类似
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
'how are you'
&lt;/pre&gt;
&lt;p&gt;
这样本来预期作为t2s函数的第一个参数会被分割成 how、are、you三个部分并将其作为t2s函数的 &lt;b&gt;三个参数&lt;/b&gt; ，导致错误。
&lt;/p&gt;

&lt;p&gt;
正确的做法是将$1用双引号包裹起来。
&lt;/p&gt;

&lt;p&gt;
这是今天修改后的脚本代码：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;!/bin/&lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;bash&lt;/span&gt;

&lt;span style=&quot;color: #eeeeec;&quot;&gt;FILE&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&quot;&lt;/span&gt;

&lt;span style=&quot;color: #edd400;&quot;&gt;t2s&lt;/span&gt;()
{
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;first&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;$1&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;lang&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;&quot;&lt;/span&gt;;
    &lt;span style=&quot;color: #eeeeec;&quot;&gt;FILE&lt;/span&gt;=$(&lt;span style=&quot;color: #fa8072;&quot;&gt;tr&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;' '&lt;/span&gt; _ &amp;lt;&amp;lt;&amp;lt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;$first&quot;&lt;/span&gt;| cut -b 1-15).mp3;

    &lt;span style=&quot;color: #729fcf;&quot;&gt;shift&lt;/span&gt;;

    &lt;span style=&quot;color: #729fcf;&quot;&gt;while &lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;getopts&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;ez&quot;&lt;/span&gt; arg
    &lt;span style=&quot;color: #729fcf;&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;case&lt;/span&gt; $&lt;span style=&quot;color: #eeeeec;&quot;&gt;arg&lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt; in&lt;/span&gt;
        e)
        &lt;span style=&quot;color: #eeeeec;&quot;&gt;lang&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;en&quot;&lt;/span&gt;;
        ;;
        z)
        &lt;span style=&quot;color: #eeeeec;&quot;&gt;lang&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;zh&quot;&lt;/span&gt;;
        ;;
        ?)
        &lt;span style=&quot;color: #729fcf;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;Usage : t2s &amp;lt;text&amp;gt; -e/-z&quot;&lt;/span&gt;;
        &lt;span style=&quot;color: #729fcf;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;   -e : in English&quot;&lt;/span&gt;;
        &lt;span style=&quot;color: #729fcf;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;   -z : in Chinese&quot;&lt;/span&gt;;
        &lt;span style=&quot;color: #729fcf;&quot;&gt;exit&lt;/span&gt; 1;
        ;;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;esac&lt;/span&gt;
    &lt;span style=&quot;color: #729fcf;&quot;&gt;done&lt;/span&gt;

    wget -q -U google-chrome -O $&lt;span style=&quot;color: #eeeeec;&quot;&gt;FILE&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;http://translate.google.com/translate_tts?ie=UTF-8&amp;amp;tl=$lang&amp;amp;q=$(&lt;/span&gt;&lt;span style=&quot;color: #fa8072;&quot;&gt;tr&lt;/span&gt;&lt;span style=&quot;color: #ad7fa8;&quot;&gt; ' ' + &amp;lt;&amp;lt;&amp;lt; &quot;$first&quot;)&quot;&lt;/span&gt;;
}

t2s &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;$1&quot;&lt;/span&gt; $&lt;span style=&quot;color: #eeeeec;&quot;&gt;2&lt;/span&gt; &amp;amp;&amp;amp; play $&lt;span style=&quot;color: #eeeeec;&quot;&gt;FILE&lt;/span&gt; -q &amp;amp;&amp;amp; rm $&lt;span style=&quot;color: #eeeeec;&quot;&gt;FILE&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
当然了……脚本参数的处理是很直接简单的处理方式。
&lt;/p&gt;

&lt;p&gt;
另外，Google的中文语音合成效果不怎么样啊，不过其他的语音产品貌似不提供像Google这样的API，那也没办法了。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>博客分拆计划</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/10/20/blog-plan.html"/>
    <category term="博客" scheme="http://www.zmonster.me/categories.html#博客"/>
    <id>http://www.zmonster.me/2013/10/20/blog-plan</id>
    <published>2013-10-20T00:00:00+00:00</published>
    <updated>2013-10-20T00:00:00+00:00</updated>
    <description>
    
      <p>
准备将博客分拆成三部分——笔记、小说和博客。当然了，这个博客实际上不包含笔记部分，这是我打算做的。


</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
准备将博客分拆成三部分——笔记、小说和博客。当然了，这个博客实际上不包含笔记部分，这是我打算做的。
&lt;/p&gt;

&lt;p&gt;
博客处于展示和正确指导别人的目的，在写作的时候会比较注重实践检验，也会注重可能存在的和读者的互动，在另一方面博客可能也会更碎片化；而笔记更多的是个人的总结以及对知识、经验的组织和整理，更多地作为对自己所知所学的归纳、总结以及归档备份，而不是展示；小说这类的&quot;文学性质&quot;的东西的话，不像写技术文章一样要插入代码、图片等东西，也不需要什么分类、标签，只要文本就OK，而且在这个为了在Github Pages上运行而牺牲了一部分org-mode功能的博客上，写作会受到影响。
&lt;/p&gt;

&lt;p&gt;
所以就决定这样拆分。
&lt;/p&gt;

&lt;p&gt;
博客还是会放在这里，这里会用来发布一些技术性的文章以及生活琐事、无病呻吟etc。
&lt;/p&gt;

&lt;p&gt;
小说计划放到site44上——org文件也会在Dropbox里，这样我就不用担心数据丢失的问题。
&lt;/p&gt;

&lt;p&gt;
同样，笔记的org文件将会在Dropbox里进行存储和备份，发布则计划通过gitcafe——我还是相信gitcafe能够长久生存下去的，那么用一下gitcafe的pages服务也挺好的。
&lt;/p&gt;

&lt;p&gt;
当然了，这三部分放到这个博客里其实也没什么，但是既然我有site44的帐号，又有gitcafe帐号，我想充分利用一下吧。
&lt;/p&gt;

&lt;p&gt;
或者以后博客也会改成更加简洁的风格——说实话，什么分类、标签什么的东西都是眼子，有时候一些文章实在不知道该怎么分类……
&lt;/p&gt;

&lt;p&gt;
就是这样.
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>伪语音合成(1)</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/10/19/daily-shell-text2speech.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2013/10/19/daily-shell-text2speech</id>
    <published>2013-10-19T00:00:00+00:00</published>
    <updated>2013-10-19T00:00:00+00:00</updated>
    <description>
    
      <p>
今天在commandlinefu.com 上面看到一个函数的定义，挺有意思的，来看一下：



</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
今天在&lt;a href=&quot;http://www.commandlinefu.com/commands/browse&quot;&gt;commandlinefu.com&lt;/a&gt; 上面看到一个函数的定义，挺有意思的，来看一下：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #edd400;&quot;&gt;t2s&lt;/span&gt;() { wget -q -U Mozilla -O $(&lt;span style=&quot;color: #fa8072;&quot;&gt;tr&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;' '&lt;/span&gt; _ &amp;lt;&amp;lt;&amp;lt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;$1&quot;&lt;/span&gt;| cut -b 1-15).mp3 &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;http://translate.google.com/translate_tts?ie=UTF-8&amp;amp;tl=en&amp;amp;q=$(&lt;/span&gt;&lt;span style=&quot;color: #fa8072;&quot;&gt;tr&lt;/span&gt;&lt;span style=&quot;color: #ad7fa8;&quot;&gt; ' ' + &amp;lt;&amp;lt;&amp;lt; &quot;&lt;/span&gt;$&lt;span style=&quot;color: #eeeeec;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;)&quot;&lt;/span&gt;; }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
下面注明了：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
Usage: t2s 'how are you?'
&lt;/pre&gt;

&lt;p&gt;
这个函数很有意思，首先看这个函数的名字：t2s。
&lt;/p&gt;

&lt;p&gt;
t2s是 &lt;b&gt;Text to Speech&lt;/b&gt; 的缩写，也就是 &lt;b&gt;语音合成&lt;/b&gt; 了，这个函数的功能正是语音合成，即将传入t2s函数的参数——文本，转换为语音。
&lt;/p&gt;

&lt;p&gt;
再看看函数体：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;wget -q -U Mozilla -O $(&lt;span style=&quot;color: #fa8072;&quot;&gt;tr&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;' '&lt;/span&gt; _ &amp;lt;&amp;lt;&amp;lt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;$1&quot;&lt;/span&gt;| cut -b 1-15).mp3 &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;http://translate.google.com/translate_tts?ie=UTF-8&amp;amp;tl=en&amp;amp;q=$(&lt;/span&gt;&lt;span style=&quot;color: #fa8072;&quot;&gt;tr&lt;/span&gt;&lt;span style=&quot;color: #ad7fa8;&quot;&gt; ' ' + &amp;lt;&amp;lt;&amp;lt; &quot;&lt;/span&gt;$&lt;span style=&quot;color: #eeeeec;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;)&quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
没什么太复杂的东西，就是一条wget命令，不过其参数稍微复杂。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;-q&lt;/b&gt; 选项是让wget以 &lt;b&gt;quiet&lt;/b&gt; 模式运行， &lt;b&gt;-U&lt;/b&gt; 指定浏览器（我也不知道为什么要指定，试了一下，不加的话结果会是错的……）， &lt;b&gt;-O&lt;/b&gt; 指定下载下来的文件名。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;-O&lt;/b&gt; 选项的参数是一条shell命令的输出结果和 &lt;b&gt;.mp3&lt;/b&gt; 这个后缀名的连接起来的结果：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;tr &lt;span style=&quot;color: #ad7fa8;&quot;&gt;' '&lt;/span&gt; _ &amp;lt;&amp;lt;&amp;lt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;$1&quot;&lt;/span&gt; | cut -b 1-15
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这条命令将函数t2s的第一个参数中的空格替换成下划线 &lt;b&gt;_&lt;/b&gt; ，然后最多取15个字符。
&lt;/p&gt;

&lt;p&gt;
重点是后面那个网络地址：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
http://translate.google.com/translate_tts?ie=UTF-8&amp;amp;tl=en&amp;amp;q=
&lt;/pre&gt;
&lt;p&gt;
这个是Google翻译的TTS的web api，通过它可以直接获取Google翻译界面的文本朗读功能对应的mp3文件。上面这个api要在后面加上要朗读的单词才是完整的——若有多个单词，则以 &lt;b&gt;+&lt;/b&gt; 号连接。
&lt;/p&gt;

&lt;p&gt;
然后我根据这个函数写了一个小脚本：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color: #888a85;&quot;&gt;!/bin/&lt;/span&gt;&lt;span style=&quot;color: #729fcf;&quot;&gt;bash&lt;/span&gt;
&lt;span style=&quot;color: #edd400;&quot;&gt;t2s&lt;/span&gt;() {
    wget -q -U Mozilla -O $(&lt;span style=&quot;color: #fa8072;&quot;&gt;tr&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;' '&lt;/span&gt; _ &amp;lt;&amp;lt;&amp;lt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;$1&quot;&lt;/span&gt;| cut -b 1-15).mp3 &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;http://translate.google.com/translate_tts?ie=UTF-8&amp;amp;tl=en&amp;amp;q=$(&lt;/span&gt;&lt;span style=&quot;color: #fa8072;&quot;&gt;tr&lt;/span&gt;&lt;span style=&quot;color: #ad7fa8;&quot;&gt; ' ' + &amp;lt;&amp;lt;&amp;lt; &quot;&lt;/span&gt;$&lt;span style=&quot;color: #eeeeec;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;)&quot;&lt;/span&gt;;
}

&lt;span style=&quot;color: #eeeeec;&quot;&gt;FILE&lt;/span&gt;=$(&lt;span style=&quot;color: #fa8072;&quot;&gt;tr&lt;/span&gt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;' '&lt;/span&gt; _ &amp;lt;&amp;lt;&amp;lt; &lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;$1&quot;&lt;/span&gt; | cut -b 1-15).mp3;
t2s $&lt;span style=&quot;color: #eeeeec;&quot;&gt;1&lt;/span&gt; &amp;amp;&amp;amp; play $&lt;span style=&quot;color: #eeeeec;&quot;&gt;FILE&lt;/span&gt; -q &amp;amp;&amp;amp; rm $&lt;span style=&quot;color: #eeeeec;&quot;&gt;FILE&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
我这里用了play命令来直接在终端中播放音频文件——play命令是sox工具包里的一个命令，要正确播放，还要安装mp3格式支持：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;sudo apt-get install libsox-fmt-mp3
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
之所以标题是 &lt;b&gt;伪语音合成&lt;/b&gt; ，就是因为我这里只是单纯地下载了对应的音频文件进行播放而已……真正的语音合成的工作都是Google做的。
&lt;/p&gt;

&lt;p&gt;
另外，这个脚本里的t2s函数只对英文语句起作用，所以下一步我想写一个功能更丰富的脚本，能处理中英文。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>基于Node.js的博客平台Ghost试用</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/10/15/node.js-blog-platform-ghost.html"/>
    <category term="博客" scheme="http://www.zmonster.me/categories.html#博客"/>
    <id>http://www.zmonster.me/2013/10/15/node.js-blog-platform-ghost</id>
    <published>2013-10-15T00:00:00+00:00</published>
    <updated>2013-10-15T00:00:00+00:00</updated>
    <description>
    
      <p>
&amp;#30446;&amp;#24405;


Ghost是什么
本地安装
使用
总结




</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org5b01e9b&quot;&gt;Ghost是什么&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org693ab17&quot;&gt;本地安装&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1d84d96&quot;&gt;使用&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org88b1d06&quot;&gt;总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org5b01e9b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org5b01e9b&quot;&gt;Ghost是什么&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org5b01e9b&quot;&gt;
&lt;p&gt;
Ghost是一个基于Node.js的博客平台，于昨日(2013/10/14)正式在Github上发布。
&lt;/p&gt;

&lt;p&gt;
Ghost源于John O'Nolan的想法——交互设计师John O'Nolan是WordPress UI组的核心成员。大概一年前，他有感于WordPress越来越脱离博客平台的初衷，变为一个CMS，决定开发新一代的博客平台。
&lt;/p&gt;

&lt;p&gt;
4月29日，项目在KickStarter上募集资金，轰动一时。最后在一个月内筹得近20万英镑。
&lt;/p&gt;

&lt;p&gt;
在Ghost正式发布前就已经有非常多的人在盼望着它出来了。
&lt;/p&gt;

&lt;p&gt;
一位网友是这么评价Ghost的
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
简单简洁, 响应式设计, 支持完全自定义, 免费, 专注博客
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
我的消息比较滞后，今天才得知这个东西——这还是Gmail里收到了Ghost团队的邮件才知道的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org693ab17&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org693ab17&quot;&gt;本地安装&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org693ab17&quot;&gt;
&lt;p&gt;
Ghost的本地安装非常简单。这里以linux平台为例（我才懒得在windows下折腾呢）
&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgbe3aa15&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;orgbe3aa15&quot;&gt;安装Node.js&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-orgbe3aa15&quot;&gt;
&lt;p&gt;
到&lt;a href=&quot;http://nodejs.org&quot;&gt;Node.js的官方网站&lt;/a&gt; 上下载Node.js并安装，源码包和二进制包都有，这里就不多嘴了。
&lt;/p&gt;

&lt;p&gt;
确认是否安装了Node.js，在终端里运行：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
node -v
&lt;/pre&gt;
&lt;p&gt;
和
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
npm -v
&lt;/pre&gt;
&lt;p&gt;
看看，如果有显示版本信息就说明安装好了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgcda2222&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;orgcda2222&quot;&gt;安装并运行Ghost&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-orgcda2222&quot;&gt;
&lt;p&gt;
不得不说安装真的是非常简单，先到&lt;a href=&quot;http://ghost.org&quot;&gt;Ghost的官网&lt;/a&gt; 上下载Ghost并解压到本地目录，进入到目录下后执行
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
npm install --production
&lt;/pre&gt;
&lt;p&gt;
就OK了。
&lt;/p&gt;

&lt;p&gt;
安装好后就可以执行
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
npm start
&lt;/pre&gt;
&lt;p&gt;
在本地的2368端口运行Ghost了。
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://docs.ghost.org/installation/linux/&quot;&gt;这里&lt;/a&gt; 是官方给出的安装文档，当然比我这里说的要详细一点，不过也没差了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1d84d96&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1d84d96&quot;&gt;使用&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org1d84d96&quot;&gt;
&lt;p&gt;
先说博客真正要能运行起来需要的环境吧。
&lt;/p&gt;

&lt;p&gt;
基本上来说有两种方案吧：
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;使用提供Ghost应用的云服务，官方给出了Bitnami、Rackspace deployments和DigitalOcean Droplet三个建议的选择。&lt;/li&gt;

&lt;li&gt;使用允许用户安装Node.js或者已经安装了Node.js的主机服务。&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org845cc25&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org845cc25&quot;&gt;博客设置&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org845cc25&quot;&gt;
&lt;p&gt;
在博客的根目录后面加上 &lt;i&gt;ghost&lt;/i&gt; 就可以进入到后台面板。如图所示：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;../../..//assets/img/2013-10-15-ghost-panel.png&quot; alt=&quot;2013-10-15-ghost-panel.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
能够设置博客标题、描述、每页文章数等常见参数。
&lt;/p&gt;

&lt;p&gt;
总的来说在设置上的确非常简洁。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org6a53f0f&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org6a53f0f&quot;&gt;博客主题&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org6a53f0f&quot;&gt;
&lt;p&gt;
目前来说Ghost官方提供了12个主题可供使用，这里是&lt;a href=&quot;http://marketplace.ghost.org/&quot;&gt;链接&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
主题的安装也很简单，将下载好的主题解压后放置到/content/themes/这个目录下，并重启Ghost，然后到后台面板上选择要使用的主题即可。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org39c948d&quot; class=&quot;outline-4&quot;&gt;
&lt;h4 id=&quot;org39c948d&quot;&gt;编写文章&lt;/h4&gt;
&lt;div class=&quot;outline-text-4&quot; id=&quot;text-org39c948d&quot;&gt;
&lt;p&gt;
在上面的那张有关博客设置的图里，可以看到后台面板有三个标签页，分别是： content， new posst和 settings。
&lt;/p&gt;

&lt;p&gt;
第一个可以查看文章列表，并进行修改、删除等操作。
&lt;/p&gt;

&lt;p&gt;
点击第二个就可以编写文章啦。
&lt;/p&gt;

&lt;p&gt;
不得不说，Ghost在文章编写上做的真是太棒了。看下面这个图：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2013-10-15-writing.png&quot; alt=&quot;2013-10-15-writing.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以右键，选择“在新标签页打开图片”看大图。
&lt;/p&gt;

&lt;p&gt;
正如你所见，Ghost提供这种“可视化”的编辑方式。左栏是Markdown语法的文章编辑区，右栏则可以实时预览文章显示效果，实在是太棒了。
&lt;/p&gt;

&lt;p&gt;
除此以外，也可以用自己喜爱的编辑器编辑md文件啦，不过既然Ghost提供了这样一种方式，相信这样做的人就会更少啦。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org88b1d06&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org88b1d06&quot;&gt;总结&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org88b1d06&quot;&gt;
&lt;p&gt;
确实很不错，特别是那个文章编辑方式，实在是很吸引人，不过——不能在Github Pages上跑，对我来说，吸引力就下降了，而且，虽然刚才说那个编辑方式很吸引人，不过我可是org-mode脑残粉，更何况前两天装上了real-auto-save这个插件，再也不用自己频繁按 &lt;b&gt;C-x C-f&lt;/b&gt; 了。
&lt;/p&gt;

&lt;p&gt;
所以说都是浮云。
&lt;/p&gt;

&lt;p&gt;
来，这是一个demo的展示——本地的只能截图了：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2013-10-15-ghost-demo.png&quot; alt=&quot;2013-10-15-ghost-demo.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以右键，选择“在新标签页打开图片”看大图。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>在Github Pages博客内容中插入liquid语句示例</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/10/14/liquid-in-post.html"/>
    <category term="博客" scheme="http://www.zmonster.me/categories.html#博客"/>
    <id>http://www.zmonster.me/2013/10/14/liquid-in-post</id>
    <published>2013-10-14T00:00:00+00:00</published>
    <updated>2013-10-14T00:00:00+00:00</updated>
    <description>
    
      <p>
由于Github Pages在后端使用jekyll来处理博客文件，对于文章内部插入的原本用来做示例的liquid语句，会被它解析而不是展示原本的内容，比如说，我在文中插入这样的示例(org-m...</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
由于Github Pages在后端使用jekyll来处理博客文件，对于文章内部插入的原本用来做示例的liquid语句，会被它解析而不是展示原本的内容，比如说，我在文中插入这样的示例(org-mode)：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
#+begin_example
{% for post in site.posts limit:5 %}
{{ post.title }}
{% endfor %}
#+end_example
&lt;/pre&gt;
&lt;p&gt;
最后得到的内容却会是这样的：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;

找工作啦

ZMonster's AI Notes(Alpha) #2：模型汤、推测解码、幻觉的类型与定义、GPT top_logprobs

我的年度总结所使用到的数据分析和可视化工具

我的2023

ZMonster's AI Notes(Alpha) #1

&lt;/pre&gt;
&lt;p&gt;
这显然不是我们想要的，解决办法也很简单，那就是在每一个liquid语句前后用
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
{% raw %}
&lt;/pre&gt;
&lt;p&gt;
和
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
{% endraw %}
&lt;/pre&gt;
&lt;p&gt;
包裹起来，这样liquid模板引擎会将内部的文本作为普通文本处理而不是按照liquid语法去解析它，下面是正确的示例：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
#+begin_example
{% raw %}{% for post in site.posts %}{% endraw %}
{% raw %}{{ post.title }}{% endraw %}
{% raw %}{% endfor%}{% endraw %}
#+end_example
&lt;/pre&gt;
&lt;p&gt;
就能够得到这样正确的示例结果：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
{% for post in site.posts %}
{{ post.title }}
{% endfor %}
&lt;/pre&gt;

&lt;p&gt;
不过，还没完呢，比如说，像
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
{% raw %}
&lt;/pre&gt;
&lt;p&gt;
这样的标签，又怎么在文中显示呢？用刚才说的方法是不行的，不信试试在文中直接这样写
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
{% raw %}
{% raw %}
{% endraw %}
&lt;/pre&gt;
&lt;p&gt;
本地运行
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-sh&quot;&gt;jekyll build
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
试试，没错，会得到一个错误。下面的写法同样会得到错误。
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
{% raw %}
{% endraw %}
{% endraw %}
&lt;/pre&gt;
&lt;p&gt;
究其原因，应该是liquid的 &lt;b&gt;raw/endraw&lt;/b&gt; 标签在匹配时按照就近原则吧——这个是我推测的。
&lt;/p&gt;

&lt;p&gt;
最后我在Stack Overflow上找到了一个&lt;a href=&quot;http://stackoverflow.com/questions/3426182/how-to-escape-liquid-template-tags&quot;&gt;解决方案&lt;/a&gt;。
&lt;/p&gt;

&lt;p&gt;
像这样：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
{{ &quot;{% raw &quot; }}%}
&lt;/pre&gt;
&lt;p&gt;
就可以得到：
&lt;/p&gt;
&lt;pre class=&quot;example&quot;&gt;
{% raw %}
&lt;/pre&gt;
&lt;p&gt;
的显示效果。
&lt;/p&gt;

&lt;p&gt;
也就是说，把 {% 和 %} 这一对标签的开闭符号分开了，一部分用双引号括起来并用 {{ 和 }} 包裹起来，另一部分则按照平常的方式书写。同样的， {{ 和 }} 也可以通过这种方式来处理。本文第五个示例就是这么得到的。
&lt;/p&gt;

&lt;p&gt;
自己动手试一试吧！
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>更换博客主题</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/10/13/change-theme.html"/>
    <category term="博客" scheme="http://www.zmonster.me/categories.html#博客"/>
    <id>http://www.zmonster.me/2013/10/13/change-theme</id>
    <published>2013-10-13T00:00:00+00:00</published>
    <updated>2013-10-13T00:00:00+00:00</updated>
    <description>
    
      <p>
今天更换了主题，其实就是jekyll-bootstrap的 twitter主题 。


</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
今天更换了主题，其实就是jekyll-bootstrap的 &lt;b&gt;twitter主题&lt;/b&gt; 。
&lt;/p&gt;

&lt;p&gt;
对于 &lt;a href=&quot;http://www.zhanxin.info/&quot;&gt;掌心&lt;/a&gt; 设计的主题 &lt;b&gt;The One&lt;/b&gt; ，我不能说不好，只是还是不太符合我的喜好，我这段时间花了大量的时间想自己写一个 &lt;b&gt;极致简洁&lt;/b&gt; 的模板，比如说&lt;a href=&quot;http://liutos.github.io/&quot;&gt;Liutos的博客&lt;/a&gt; 这样的风格，不过web知识太过匮乏，全凭自己在&lt;a href=&quot;http://www.w3school.com.cn/&quot;&gt;w3school在线教程&lt;/a&gt; 上对HTML/CSS 得到的丁点了解，而没有前端设计的理念，完全就是乱来（我自己倒是搞了个比较简单的模板出来，但是太丑了（╯‵□′）╯︵┴─┴ ）。
&lt;/p&gt;

&lt;p&gt;
之前我试用jekyll-bootstrap时它不能处理\_posts/目录下的html文件，这是我当时放弃它的主要原因——我可不想写markdown，今天一试居然可以了……我一定是记错了什么……
&lt;/p&gt;

&lt;p&gt;
不过我也没有把jekyll-bootstrap全部都拿过来用，而是把twitter主题的模板直接放到了\_layouts目录下，顺便也修改了一下css。
&lt;/p&gt;

&lt;p&gt;
还有，jekyll-bootstrap的twitter主题有一个问题，它的模板 &lt;b&gt;page.html&lt;/b&gt; 和 &lt;b&gt;post.html&lt;/b&gt; 中，本应显示页面/文章 标签的地方，一直显示的是
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
Supporting tagline
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
这是因为模板中的相应地方作者遗忘了一处细节，请看这段代码：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-html&quot;&gt;&amp;lt;&lt;span style=&quot;color: #edd400;&quot;&gt;div&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;page-header&quot;&lt;/span&gt;&amp;gt;
  &amp;lt;&lt;span style=&quot;color: #edd400;&quot;&gt;h1&lt;/span&gt;&amp;gt;更换博客主题 &amp;lt;&lt;span style=&quot;color: #edd400;&quot;&gt;small&lt;/span&gt;&amp;gt;&lt;span style=&quot;color: #eeeeec; background-color: #101e2e;&quot;&gt;Supporting tagline&lt;/span&gt;&amp;lt;/&lt;span style=&quot;color: #edd400;&quot;&gt;small&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&quot;color: #edd400;&quot;&gt;h1&lt;/span&gt;&amp;gt;
&amp;lt;/&lt;span style=&quot;color: #edd400;&quot;&gt;div&lt;/span&gt;&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
其中 &lt;b&gt;small&lt;/b&gt; 标签内部应该修改为

{{ page.tagline }}

&lt;/p&gt;

&lt;p&gt;
还有一个小问题是，模板的首页文件即 &lt;b&gt;index.md&lt;/b&gt; 设置了一个title为 &lt;b&gt;Hello World&lt;/b&gt; ，而由于 &lt;b&gt;default.html&lt;/b&gt; 这个模板将页面文件的tile设置为博客页面的title，这就有一个问题了。index.md生成的index.html会渲染为博客的首页，也就是说，博客首页的标题会被设置为index.md中指定的title，按照常理，首页的页面标题应该是和博客的标题一致的。接下来就有两种情况：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;将index.md中的title设置为博客标题，但这样和导航栏中的博客标题重复了，看起来有点多余&lt;/li&gt;
&lt;li&gt;将index.md中的title设置为非博客标题的内容，这样就和刚才说的 &lt;b&gt;常理&lt;/b&gt; 不符&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
我的做法是：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
修改default.html
&lt;/p&gt;

&lt;p&gt;
将以下内容
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-html&quot;&gt;&amp;lt;&lt;span style=&quot;color: #edd400;&quot;&gt;title&lt;/span&gt;&amp;gt;&lt;span style=&quot;font-weight: bold; text-decoration: underline;&quot;&gt;{{ page.title }}&lt;/span&gt;&amp;lt;/&lt;span style=&quot;color: #edd400;&quot;&gt;title&lt;/span&gt;&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
修改为：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-html&quot;&gt; &amp;lt;&lt;span style=&quot;color: #edd400;&quot;&gt;title&lt;/span&gt;&amp;gt;
&lt;span style=&quot;font-weight: bold; text-decoration: underline;&quot;&gt;   {% if page.title %}&lt;/span&gt;
&lt;span style=&quot;font-weight: bold; text-decoration: underline;&quot;&gt;   {{ page.title }}&lt;/span&gt;
&lt;span style=&quot;font-weight: bold; text-decoration: underline;&quot;&gt;   {% else %}&lt;/span&gt;
&lt;span style=&quot;font-weight: bold; text-decoration: underline;&quot;&gt;   {{ site.title }}&lt;/span&gt;
&lt;span style=&quot;font-weight: bold; text-decoration: underline;&quot;&gt;   {% endif %}&lt;/span&gt;
&amp;lt;/&lt;span style=&quot;color: #edd400;&quot;&gt;title&lt;/span&gt;&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
修改index.md
&lt;/p&gt;

&lt;p&gt;
删除其title，修改其模板为 default，在头部添加：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;

&lt;pre class=&quot;src src-html&quot;&gt;&amp;lt;&lt;span style=&quot;color: #edd400;&quot;&gt;div&lt;/span&gt; &lt;span style=&quot;color: #eeeeec;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #ad7fa8;&quot;&gt;&quot;page-header&quot;&lt;/span&gt;&amp;gt;
&amp;lt;&lt;span style=&quot;color: #edd400;&quot;&gt;h1&lt;/span&gt;&amp;gt;&amp;#25991;&amp;#31456;&amp;#21015;&amp;#34920; &amp;lt;&lt;span style=&quot;color: #edd400;&quot;&gt;small&lt;/span&gt;&amp;gt;&lt;span style=&quot;color: #eeeeec; background-color: #101e2e;&quot;&gt;{{ page.tagline }}&lt;/span&gt;&amp;lt;/&lt;span style=&quot;color: #edd400;&quot;&gt;small&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&quot;color: #edd400;&quot;&gt;h1&lt;/span&gt;&amp;gt;
&amp;lt;/&lt;span style=&quot;color: #edd400;&quot;&gt;div&lt;/span&gt;&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
要不要跟作者提提意见呢？嘿嘿
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>论信息自由</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/10/10/free-in-internet-time.html"/>
    <category term="生活" scheme="http://www.zmonster.me/categories.html#生活"/>
    <id>http://www.zmonster.me/2013/10/10/free-in-internet-time</id>
    <published>2013-10-10T00:00:00+00:00</published>
    <updated>2013-10-10T00:00:00+00:00</updated>
    <description>
    
      <p>
今年夏天我有了我的智能手机，仅仅是一台799价格的安卓手机而已。一度我为和大家一样能有一台智能设备而高兴，尝试着各种应用和游戏。但到今天我变得很担忧。


</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
今年夏天我有了我的智能手机，仅仅是一台799价格的安卓手机而已。一度我为和大家一样能有一台智能设备而高兴，尝试着各种应用和游戏。但到今天我变得很担忧。
&lt;/p&gt;

&lt;p&gt;
手机依赖这种东西我就不说了，都是说烂了的话题。
&lt;/p&gt;

&lt;p&gt;
我这个人对个人的信息安全比较敏感，而且也有点强迫症。自从我第一次安装应用看到提示里的一堆权限后我就有点在意，这两天我得知一个名为 &lt;b&gt;LBE安全大师&lt;/b&gt; 的应用可以管理手机应用的权限，于是就安装了并且对所有应用都进行了设置。这些游戏和应用拥有的涉及个人隐私的权限有：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
短信记录
&lt;/p&gt;

&lt;p&gt;
访问您的 &lt;b&gt;短信收件箱&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
联系人记录
&lt;/p&gt;

&lt;p&gt;
访问您的 &lt;b&gt;联系人&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
通话记录
&lt;/p&gt;

&lt;p&gt;
访问您的 &lt;b&gt;通话记录&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
定位
&lt;/p&gt;

&lt;p&gt;
通过网络或卫星对您的手机 &lt;b&gt;定位&lt;/b&gt; 
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
手机识别码
&lt;/p&gt;

&lt;p&gt;
获得您的手机识别码，包括IMEI、IMSI、 &lt;b&gt;本机号码&lt;/b&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
拍照和录音
&lt;/p&gt;

&lt;p&gt;
拍照和 &lt;b&gt;录音&lt;/b&gt; 
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
系统设置
&lt;/p&gt;

&lt;p&gt;
修改系统设置
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
发送短信
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;直接&lt;/b&gt; 发送短信
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
电话
&lt;/p&gt;

&lt;p&gt;
拨打、接听或挂断电话号码
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
通话状态
&lt;/p&gt;

&lt;p&gt;
获取手机来电、通话、挂断等状态
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
通话监听
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;监听通话内容&lt;/b&gt; 、控制音量等
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
我把我手机上的应用及其权限情况做了一张表（为了方便显示，这里用数字代表上面罗列的相对应的权限）
&lt;/p&gt;
&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;6&quot; rules=&quot;groups&quot; frame=&quot;hsides&quot;&gt;
&lt;caption class=&quot;t-above&quot;&gt;&lt;span class=&quot;table-number&quot;&gt;&amp;#34920;1&amp;nbsp;&lt;/span&gt; 本人手机应用权限标表&lt;/caption&gt;

&lt;colgroup&gt;
&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;

&lt;col  class=&quot;org-left&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;1&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;2&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;3&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;4&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;5&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;6&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;7&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;8&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;9&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;10&lt;/th&gt;
&lt;th scope=&quot;col&quot; class=&quot;org-left&quot;&gt;11&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;7x7&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;安智市场&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;安桌壁纸&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;百度贴吧&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;哔哩哔哩动画&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;布卡漫画&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;海词词典&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;超级蓝牙分享&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;今日头条&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;美乐时光&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;拇指玩&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;史上最牛的游戏2&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;手机云&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;书旗免费小说&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;搜狗输入法&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;拓词&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;天翼锁屏\_扫一扫&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;豌豆荚&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;网易公开课&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;我要早睡&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;微信&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;虾米音乐&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;相机360&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;小小盗贼&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;新浪公开课&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;印象笔记&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;优酷&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;游戏存档&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;自动启动清理&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;自动运行管理&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;A Ride&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Anyview&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Annine Taste&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Dropbox&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Flipboard&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Labyrinth&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;LBE安全大师&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;NewsZeit&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;QQ&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Reddit News&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;TinyFarm&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;Trollface Quest&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;UC浏览器&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&quot;org-left&quot;&gt;WiFi连接管理器&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;✔&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;td class=&quot;org-left&quot;&gt;&amp;#xa0;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
可以看到，大部分应用都有 &lt;b&gt;定位&lt;/b&gt; 和 &lt;b&gt;手机识别码&lt;/b&gt; 这两个权限，而其实大部分应用根本就不应该有这个权限。更为严重的是，有几款应用具备 &lt;b&gt;通话监听&lt;/b&gt; 的权限，这些应用包括：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;百度贴吧&lt;/li&gt;
&lt;li&gt;微信&lt;/li&gt;
&lt;li&gt;虾米音乐&lt;/li&gt;
&lt;li&gt;QQ&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
先不说别的，表中的 &lt;b&gt;手机云&lt;/b&gt; 应用是我的手机预装的一个应用，貌似也叫做 &lt;b&gt;天翼云桌面&lt;/b&gt; ，它有很多权限，可即使这样，它也没有 &lt;b&gt;通话监听&lt;/b&gt; 这一项权限。试问 &lt;b&gt;虾米音乐&lt;/b&gt; 这样一款应用，它要监听用户通话内容做什么呢？
&lt;/p&gt;

&lt;p&gt;
我说过我对个人信息安全比较敏感，于是我把上述应用的这些权限几乎全部关闭了，但是 &lt;b&gt;LBE安全大师&lt;/b&gt; 又真的信得过么？我真的不知道。
&lt;/p&gt;

&lt;p&gt;
让我下定决心写这篇文章是因为我今天实在是被烦得不行了。先是 &lt;b&gt;新浪微博&lt;/b&gt; 不停地尝试获取我的手机号码， LBE安全大师不停地在通知栏提示：
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
拒绝新浪微薄获取本机号码
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
忍无可忍，于是我就把它卸载了，这就是表格里没有它的原因。然后是百度贴吧不停地尝试修改系统设置，LBE频繁提示：
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
拒绝百度贴吧修改系统设置
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
最后，是我在豌豆荚上安装应用的时候，它给我推荐了一个应用： &lt;b&gt;华中大校园通&lt;/b&gt; 。它怎么知道我在哪个大学学习过？我并没有下载过相关的应用，刚下载的应用也和它推荐的应用无关，那只有一种解释，它通过我的社会关系获知我极有可能是该大学的学生。这些社会关系的获取途径可能有：手机通讯录、短信记录、通话记录、QQ好友。
&lt;/p&gt;

&lt;p&gt;
CCNIC《第30次中国互联网发展状况统计报告》显示，到2012年上半年，通过手机接入互联网的网民数量达到3.88亿，手机已经超越台式电脑成为第一大上网终端。而手机作为个人通讯工具，其中包含的个人隐私信息要比计算机多得多——注意，我这里说的是 &lt;b&gt;个人&lt;/b&gt; 。而且，电脑上的软件权限更好管理，不说linux，就说windows，至少也有UAC和防火墙在起作用，不像智能手机上，很多应用竟然默认就拥有了极其高的权限。更不说现在刷机成风，如果被某些目的不良的应用得到了root权限，后果不堪设想——安智市场和豌豆荚就会尝试获取root权限——对linux有所了解的人都明白root是什么概念，那是最后的底线。
&lt;/p&gt;

&lt;p&gt;
现在还只是智能手机，随着现在正在兴起的可穿戴设备以及即将到来的物联网时代的成熟，网络上会充斥着更多的个人信息，那时候的应用/服务提供方将会获得更为丰富庞大的个人信息，这些信息将不仅仅包括用户的姓名、年龄、性别、手机号码、社会关系，可能还会有身体信息、家庭住址、饮食起居习惯、行为模式，甚至更远一点，还可能会有指纹、声纹、瞳孔、DNA这些信息。
&lt;/p&gt;

&lt;p&gt;
这些互联网公司毫不掩饰地从智能终端上获取用户的身份、手机号码、位置、喜好等信息，用以为盈利准备数据。从某种程度上来说，我们已经渐渐地受控于这些互联网公司，目前它们只是为了盈利，所以它们控制我们的信息用以盈利，但如果政府或不法分子获取这些信息——不，就算这些信息不被用于其他途径，这种行径也不能忍受。
&lt;/p&gt;

&lt;p&gt;
信息的不对称将会导致新的阶级分化，每个人都应该有掌握自己信息自由的权利。
&lt;/p&gt;

&lt;p&gt;
我决定了，我必须进行网络安全知识的系统学习。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>使用elisp编写脚本</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/10/09/script-with-emacs-lisp.html"/>
    <category term="编程" scheme="http://www.zmonster.me/categories.html#编程"/>
    <id>http://www.zmonster.me/2013/10/09/script-with-emacs-lisp</id>
    <published>2013-10-09T00:00:00+00:00</published>
    <updated>2013-10-09T00:00:00+00:00</updated>
    <description>
    
      <p>为了简化在借助Github Pages建立的博客写博客的过程，我尝试使用elisp编写脚本来减少重复性的工作</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#orga68b643&quot;&gt;起因&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org4904ddf&quot;&gt;过程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1959484&quot;&gt;成果&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orga68b643&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga68b643&quot;&gt;起因&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga68b643&quot;&gt;
&lt;p&gt;
我通过Github Pages有了自己的一个静态博客，并且开始正儿八经地写博客。
&lt;/p&gt;

&lt;p&gt;
但我碰到了一个问题：每次我需要写博客，我要先打开emacs，按下C-x C-f，然后输入一长串路径名和文件名(org文件)，然后手动输入YAML Front Matter[1]。路径名每次都是一样的，YAML Front Matter也是一样的，这都是重复性的工作，并且我又是一个很懒的人，所以我就想偷懒了。
&lt;/p&gt;

&lt;p&gt;
起初是想写个shell脚本来简化步骤而已，开始写脚本后，我就想，应该把publish的步骤也通过脚本进行简化(虽然这并不是很复杂的步骤)，然后我发现shell不能做到这一点，唯一的选择是elisp。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org4904ddf&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4904ddf&quot;&gt;过程&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org4904ddf&quot;&gt;
&lt;p&gt;
用elisp写脚本？这事我听说过，但我没做过，也就是说我也是大姑娘上轿头一回了。
&lt;/p&gt;

&lt;p&gt;
照例google。
&lt;/p&gt;

&lt;p&gt;
基本形式没太大问题，将shell脚本Shebang[2]后面的 &lt;b&gt;/bin/bash&lt;/b&gt; 改成 &lt;b&gt;/usr/bin/emacs &amp;#x2013;script&lt;/b&gt; ，其他的东西嘛，随便就行不是么？（想当年某次实习招聘的时候我跟面试官说我会shell脚本，结果只会堆命令的真相还是被不留情面地揭穿了（╯‵□′）╯︵┴─┴ ）
&lt;/p&gt;

&lt;p&gt;
不过碰到了不少问题。
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
之所以用elisp，就是想简化publish么，但是在elisp script里写上的
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-lisp&quot;&gt;(org-publish-project &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;blog-linusp&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
完全不起作用。细想一下应该是shell脚本没有加载我的emacs相关配置。当时真是一筹莫展啊，后来发现其实这是一件不复杂的事情，在之前加上一句
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-lisp&quot;&gt;(load-file &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/.emacs&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
不过这样做太凶残了，什么auto-complete、yasnippet、slime、org2blog、metablog全被加载了（╯‵□′）╯︵┴─┴ 。
&lt;/p&gt;

&lt;p&gt;
好在我有将配置文件分类的习惯，org-mode的相关配置被我写在一个名为 &lt;b&gt;org.el&lt;/b&gt; 的文件里，于是加载它就OK了，不过这个文件里还有引用其他的一些emacs插件，于是也都加载了——好吧至少比之前更好是吧。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
如何传递参数给脚本？shell脚本接受参数的话还是懂的怎么做的，可是elisp脚本……
&lt;/p&gt;

&lt;p&gt;
照例google，然后发现Xah Lee[3]的博客上就有这个内容，原文点&lt;a href=&quot;http://ergoemacs.org/emacs/elisp_command_line_argv.html&quot;&gt;我&lt;/a&gt;。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
运行脚本后，发现总会有一堆的Loading message，就像下面这样：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2013-10-09-loading-message.png&quot; alt=&quot;2013-10-09-loading-message.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
（╯‵□′）╯︵┴─┴
&lt;/p&gt;

&lt;p&gt;
经google，该问题没有太好的解决问题，凑合吧。
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1959484&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1959484&quot;&gt;成果&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org1959484&quot;&gt;
&lt;p&gt;
嘛，虽然代码写得比较丑陋，至少能用，功能上达到了我的预期目标，所以代码的问题，以后再说吧。
&lt;/p&gt;

&lt;p&gt;
附脚本代码
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-lisp&quot;&gt;#!/usr/bin/emacs --script

(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;require&lt;/span&gt; '&lt;span style=&quot;color: #6699cc;&quot;&gt;calendar&lt;/span&gt;)
(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;defun&lt;/span&gt; &lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;blog&lt;/span&gt; (action &lt;span style=&quot;color: #6699cc;&quot;&gt;&amp;amp;rest&lt;/span&gt; rst)
  (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;cond&lt;/span&gt; ((string-equal action &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;post&quot;&lt;/span&gt;)
     (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;if&lt;/span&gt; (equal rst nil)
         (print &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Please input title&quot;&lt;/span&gt;)
       (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;let&lt;/span&gt; ((post-file (concat (format-time-string &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;%Y-%m-%d&quot;&lt;/span&gt;)
                     &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;-&quot;&lt;/span&gt;
                     (car rst)
                     &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;.org&quot;&lt;/span&gt;)))
         (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;progn&lt;/span&gt;
           (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;with-temp-file&lt;/span&gt; (concat &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/blog/org/_posts/&quot;&lt;/span&gt;
                       post-file)
         (insert (concat &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+begin_html\n&quot;&lt;/span&gt;
                 &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;---\n&quot;&lt;/span&gt;
                 &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;layout     : post\n&quot;&lt;/span&gt;
                 &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;title      : \n&quot;&lt;/span&gt;
                 &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;categories : \n&quot;&lt;/span&gt;
                 &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;tags       : \n&quot;&lt;/span&gt;
                 &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;excerpt    : \n&quot;&lt;/span&gt;
                 &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;---\n&quot;&lt;/span&gt;
                 &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;#+end_html\n&quot;&lt;/span&gt;)))
           (print (format &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Create post file %s in post directory&quot;&lt;/span&gt; post-file))
           (shell-command (concat &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;emacs &quot;&lt;/span&gt;
                      &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/blog/org/_posts/&quot;&lt;/span&gt;
                      post-file))))))
     ((string-equal action &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;publish&quot;&lt;/span&gt;)
      (&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;progn&lt;/span&gt;
        (org-publish-project &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;blog-linusp&quot;&lt;/span&gt;)
        (print &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Project has been published!&quot;&lt;/span&gt;)))
    (t (print &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;Action: post/publish&quot;&lt;/span&gt;))))

(load-file &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/.emacs.d/site-lisp/xml-rpc.el&quot;&lt;/span&gt;)
(load-file &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/.emacs.d/site-lisp/wc-mode.el&quot;&lt;/span&gt;)
(load-file &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/.emacs.d/myplugins/org.el&quot;&lt;/span&gt;)

(blog (elt argv 0) (elt argv 1))

&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
[1] &lt;a href=&quot;http://jekyllrb.com/docs/frontmatter/&quot;&gt;YAML Front Matter&lt;/a&gt;是用来告诉Jekyll使用什么模板并可以附带一些其他信息的文件头
&lt;/p&gt;

&lt;p&gt;
[2] Shebang是一个由'#'和'!'构成的字符串，在文件中存在Shebang的情况下，类Unix操作系统的程序载入器会分析Shebang后的内容，将这些内容作为解释器指令，并调用该指令，并将载有Shebang的文件路径作为该解释器的参数——来自&lt;a href=&quot;http://zh.wikipedia.org/wiki/Shebang&quot;&gt;维基百科&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
[3] Xah Lee是一位emacs大牛，emacs wiki上可是都有他的专门的页面哦
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>博客平台writings.io即将关闭</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/09/30/writings-io.html"/>
    <category term="博客" scheme="http://www.zmonster.me/categories.html#博客"/>
    <id>http://www.zmonster.me/2013/09/30/writings-io</id>
    <published>2013-09-30T00:00:00+00:00</published>
    <updated>2013-09-30T00:00:00+00:00</updated>
    <description>
    
      <p>博客平台writings.io即将关闭。其实我挺喜欢writings.io这个平台的</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
打开gmail邮箱，发现了一封邮件：
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/2013-09-30-mail.png&quot; alt=&quot;2013-09-30-mail.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
于是赶紧去writings.io的博客上去看看怎么回事。
&lt;/p&gt;

&lt;p&gt;
作者在&lt;a href=&quot;http://blog.chloerei.com/articles/79-writings-io-is-failure&quot;&gt;Writings.io 失败了&lt;/a&gt; 这篇文章里说了几点理由，其中最重要的一个应该是：
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
不足以成为商业模式
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
这一点吧，说到底是没有钱干下去了。
&lt;/p&gt;

&lt;p&gt;
其实我挺喜欢writings.io这个平台的，虽然我压根就没用过，只是在了解jekyll的时候去了解了其他一些静态博客平台的时候知道了writings.io并且注册了一个帐号。简洁、干净，这是我对writings.io的印象，也是我评判博客平台的一个重要标准（说的好像自己对博客平台有多了解一样）。
&lt;/p&gt;

&lt;p&gt;
挺可惜的。
&lt;/p&gt;

    </content>
  </entry>
  
  <entry>
    <title>简洁、轻便——静态博客写作方案</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/09/30/static-blog-way.html"/>
    <category term="博客" scheme="http://www.zmonster.me/categories.html#博客"/>
    <id>http://www.zmonster.me/2013/09/30/static-blog-way</id>
    <published>2013-09-30T00:00:00+00:00</published>
    <updated>2013-09-30T00:00:00+00:00</updated>
    <description>
    
      <p>纯静态博客写作有响应速度快等优势，本文总结了一些常见的静态博客写作方案</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org80778da&quot;&gt;静态博客写作的优势&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org80d87b3&quot;&gt;解决方案&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org138f9f2&quot;&gt;自购主机方案&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgfa1b48a&quot;&gt;Github Pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf453ebf&quot;&gt;Dropbox App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgc655fdf&quot;&gt;云平台方案&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org1f0add0&quot;&gt;其他一些话&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org80778da&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org80778da&quot;&gt;静态博客写作的优势&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org80778da&quot;&gt;
&lt;p&gt;
纯静态博客写作有以下优势：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
响应速度快（访问时）
&lt;/p&gt;

&lt;p&gt;
博客站点页面都是静态页面，访问时不需要查询数据库，因此自然就能够有较好的响应速度。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
最大限度的控制
&lt;/p&gt;

&lt;p&gt;
对于大部分静态博客写作方案而言，网站的每一个实现细节都是可以由自己来调整掌控的，这样虽然带来了一定的技术难度，但一来流行的解决方案在网上都有许多可用的模板，二来网站的可定制性非常高。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
更好的写作体验
&lt;/p&gt;

&lt;p&gt;
在解决了网站的外观后，就可以体验静态博客写作的最大好处了。常见的静态博客写作方案都支持在本地编写文章，这样的优势是可以自行选用最合适最顺手的编辑器，而不是那些常见博客平台上简陋的在线编辑器。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
更加方便进行备份
&lt;/p&gt;

&lt;p&gt;
静态博客写作方案都支持本地编写文章（甚至有的解决方案只能在本地编写文章），这样的好处是我们可以在本地有所有自己文章的一个备份，只要小心地使用你的计算机，这些数据就能够得到很好的保护，不放心的话还可以使用Dropbox之类的工具进行进一步的备份。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
省钱
&lt;/p&gt;

&lt;p&gt;
我不是开玩笑的，待会你就知道了。
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org80d87b3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org80d87b3&quot;&gt;解决方案&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org80d87b3&quot;&gt;
&lt;p&gt;
大致有三种解决方案，且看我一一道来。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org138f9f2&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org138f9f2&quot;&gt;自购主机方案&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org138f9f2&quot;&gt;
&lt;p&gt;
如果能够有条件购买主机空间，那么这是最理想的。试想一下，都有自己的主机空间了，想怎么折腾不行是不？想用Wordpress就用Wordpress，想自己写html就自己写html。这种情况下如果还是想构建静态博客，参看下一个解决方案。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgfa1b48a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgfa1b48a&quot;&gt;Github Pages&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgfa1b48a&quot;&gt;
&lt;p&gt;
Github Pages的介绍以及使用它来建立个人博客的内容可以看我之前的一篇文章&lt;a href=&quot;http://linusp.github.io/2013/09/14/blogging-with-jekyll-emacs.html&quot;&gt;使用Github Pages服务建立个人博客&lt;/a&gt; 。使用Github Pages的好处是不用花钱购买自己的主机空间，这后面的Dropbox方案同样如此。
&lt;/p&gt;

&lt;p&gt;
说到Github Pages，大部分人对其有所了解的人可能会第一时间联想到Jekyll。没错，Github Pages是在后端使用Jekyll来生成我们的静态博客，但我们在本地并不是只有Jekyll一个选择。
&lt;/p&gt;

&lt;p&gt;
Jekyll是一个静态博客生成器，事实上还有很多其他静态博客生成器供我们选择——它们和Github Pages合作得很好，因为其中的一些就是为了和Github Pages适配而开发出来的。
&lt;/p&gt;

&lt;p&gt;
此外还包括了一些基于某些静态博客生成器的框架也可以使用。
&lt;/p&gt;

&lt;p&gt;
这里列举一些比较流行的静态博客生成器或者静态博客框架：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
Jekyll
&lt;/p&gt;

&lt;p&gt;
Github Pages官方推荐产品，依赖ruby。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
Jekyll-bootstrap
&lt;/p&gt;

&lt;p&gt;
基于Jekyll的框架，提供了几种现成的外观主题。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
OctoPress
&lt;/p&gt;

&lt;p&gt;
基于Jekyll的框架，只用过短短几天时间，不予置评。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
hexo
&lt;/p&gt;

&lt;p&gt;
由Node.js驱动的博客框架，功能强大、使用简单。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
Pelican
&lt;/p&gt;

&lt;p&gt;
Python编写的静态博客生成器，对Python有爱的人不妨一用。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
OpooPress
&lt;/p&gt;

&lt;p&gt;
一个基于Java 的可用于博客的静态网站生成器。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
以上所有方案都支持Markdown语法。
&lt;/p&gt;

&lt;p&gt;
注：新兴的国内代码托管平台&lt;a href=&quot;https://gitcafe.com&quot;&gt;Gitcafe&lt;/a&gt; 现在也提供 &lt;b&gt;Pages&lt;/b&gt; 服务了，用同样的方法也可以在Gitcafe上搭建静态网站，&lt;a href=&quot;http://linusp.gitcafe.com&quot;&gt;这是&lt;/a&gt; 我在Gitcafe上搭建的笔记网站(2013-12-24更新)
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf453ebf&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf453ebf&quot;&gt;Dropbox App&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgf453ebf&quot;&gt;
&lt;p&gt;
DropBox 是一款非常优秀的免费网络文件同步工具，它有以下几个优点：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;全平台支持&lt;/li&gt;
&lt;li&gt;稳定，不用担心宕机&lt;/li&gt;
&lt;li&gt;第三方应用丰富&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
前两个特点是对于现在的云存储服务来说并无特殊之处，Dropbox的强大之处就在于第三点。这里有一篇&lt;a href=&quot;http://wangyueblog.com/2012/03/07/dropbox/&quot;&gt;文章&lt;/a&gt; 讲述了Dropbox的“另类”功用。
&lt;/p&gt;

&lt;p&gt;
文中第一条就是
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
使用Dropbox搭建一个网站或博客
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
没错，我们要的就是这个。
&lt;/p&gt;

&lt;p&gt;
以下应用可以用于和Dropbox一起来搭建个人博客：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
Scriptogr.am
&lt;/p&gt;

&lt;p&gt;
我尝试了一下Scriptogr.am，这里是我用它搭建的&lt;a href=&quot;http://scriptogr.am/zix&quot;&gt;博客&lt;/a&gt; 。
&lt;/p&gt;

&lt;p&gt;
Scriptogr.am只要求用户编写Markdown格式的文章即可，除了通用的在本地编写文章外，Scriptogr.am还提供了一个非常简洁的后台管理界面，在那里可以管理文章、编写文章，此外还能修改网站的css和html源代码。
&lt;/p&gt;
&lt;div class=&quot;html&quot;&gt;
&lt;p&gt;
&amp;lt;img src=&quot;/assets/img/2013-09-30-scriptogr-am.png&quot;/&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/p&gt;

&lt;/div&gt;

&lt;p&gt;
网站的默认外观干净、清爽，不过除了首页外，只有一个Archive页面，可能稍显美中不足。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
DropPages
&lt;/p&gt;

&lt;p&gt;
DropPages不同于Scriptogr.am，它会将网站的构成细节交由用户，用户可以自由地修改网站布局、外观等等，默认提供一个可用的主题，不过说实话，我不知道它用的是什么模板语言。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
site44
&lt;/p&gt;

&lt;p&gt;
site44和DropPages类似，但也有不同之处，DropPages生成的应用目录下并不是网站的完整结构，而是一些用户可以修改的文件；site44则不一样，它将对应的应用目录下的文件作为网站来进行发布，相对来说site44的自由度更高一些——此外，site44默认只有一个index.html，所以要想有一个功能完整、丰富的博客，还得下点功夫，可以考虑用之前提到的静态博客生成器来做这件事情。
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://linusp.site44.com&quot;&gt;这里&lt;/a&gt; 是我用site44这个应用配合Dropbox搭建的一个个人网站(请不要太在意内容)。
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
FarBox
&lt;/p&gt;

&lt;p&gt;
FarBox也是一款受到相关人群喜爱的Dropbox应用，其使用和Scriptogr.am类似，用户只要关心文章的撰写就可以了，至于外观，官方提供六种模板。相对Scriptogr.am来说，FarBox的后台管理功能更为强大，而且支持categories。另外，FarBox不仅可以和Dropbox一起使用，通过Google Drive同样可以利用FarBox进行博客写作。
&lt;/p&gt;

&lt;p&gt;
不知道是Bug还是什么，我在FarBox上写文时，插入的链接不能正常显示，看&lt;a href=&quot;http://linusp1024.farbox.com&quot;&gt;这里&lt;/a&gt; ——我保证我遵守了Markdown的语法。
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
事实上相关的Dropbox应用不止上述四个，只不过这四个是比较常用的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgc655fdf&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgc655fdf&quot;&gt;云平台方案&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orgc655fdf&quot;&gt;
&lt;p&gt;
云平台即 &lt;b&gt;PaaS&lt;/b&gt; (Platform as a Service)也是一个搭建个人博客的途径。当然，在云平台上搭建个人博客可以不限于静态博客，不过一般云平台的免费服务都有流量以及存储的限制，所以搭建静态博客可以更加有效地利用这些免费的资源。
&lt;/p&gt;

&lt;p&gt;
这里推荐几个云平台：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;p&gt;
Heroku
&lt;/p&gt;

&lt;p&gt;
Heroku的操作非常简洁，而且也是使用git来进行管理，非常方便。
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;Openshift&lt;/li&gt;

&lt;li&gt;Sae/Bae/&amp;#x2026;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
以上几个我只使用过Heroku，不过其他云平台上搭建博客的方法在网上也是非常普遍的，这里就不再细说了。总体来说，在云平台上搭建博客相对复杂一点。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org1f0add0&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1f0add0&quot;&gt;其他一些话&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org1f0add0&quot;&gt;
&lt;p&gt;
总的来说，可选的解决方案是很多的，选择何种方式就看自己喜好了，不过我想不应该太纠结于形式，一旦选定了一个平台，老实点多写点东西才是正道吧。
&lt;/p&gt;

&lt;p&gt;
完。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>使用Github Pages服务建立个人博客</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/09/14/blogging-with-jekyll-emacs.html"/>
    <category term="博客" scheme="http://www.zmonster.me/categories.html#博客"/>
    <id>http://www.zmonster.me/2013/09/14/blogging-with-jekyll-emacs</id>
    <published>2013-09-14T00:00:00+00:00</published>
    <updated>2013-09-14T00:00:00+00:00</updated>
    <description>
    
      <p>使用什么博客平台取决于个人的需求，如果追求简洁的话，可以使用Github Pages来建立个人博客</p>
    
    </description>
    <content type="html">
      &lt;div id=&quot;table-of-contents&quot;&gt;
&lt;h2&gt;&amp;#30446;&amp;#24405;&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org51eabe7&quot;&gt;为什么要使用Github Pages来建立个人博客&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org9110c33&quot;&gt;Github Pages是什么&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orgf248237&quot;&gt;环境准备&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org7a02e5e&quot;&gt;方案选择&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org35fe7eb&quot;&gt;行动纲领&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org3d57845&quot;&gt;Jekyll博客配置&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#org49e158c&quot;&gt;博客目录结构&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org9fed7b4&quot;&gt;博客模板&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org64951b7&quot;&gt;_config.yml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org6af55b5&quot;&gt;archives页面示例&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#orga0f7f58&quot;&gt;_site目录&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#org733f82f&quot;&gt;使用emacs的org-mode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org51eabe7&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org51eabe7&quot;&gt;为什么要使用Github Pages来建立个人博客&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org51eabe7&quot;&gt;
&lt;p&gt;
使用什么博客平台取决于个人的需求，因此，并不是所有人都适合使用本文介绍的这种形式，一般来说，追求简洁的一些程序员可能会使用这种方式。
&lt;/p&gt;

&lt;p&gt;
对于有以下需求的人来说，使用Github Pages建立博客是个好主意：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;希望能在本地编写文章&lt;/li&gt;
&lt;li&gt;追求简洁、轻便&lt;/li&gt;
&lt;li&gt;不想购买主机空间和域名&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
第一条，本地编写允许文章允许用户选择自己喜欢的编辑器来进行写作，而不是使用博客平台的编辑器——对于我等emacser来说，许多博客平台的编辑器功能实在是有点不够看。著名的博客平台&lt;a href=&quot;http://wordpress.org/&quot;&gt;WordPress&lt;/a&gt; 提供xml-rpc接口，允许用户通过相关软件在本地编写好文章后远程发布。说实话，我还是比较喜欢WordPress的，但它不满足后面三个需求。说到xml-rpc，早些年国内各大博客平台都是支持xml-rpc借口的（如CSDN，ChinaUnix等），但是后来据说是出于安全因素的考虑，似乎有些网站是关闭了这个接口，现在网上的相关搜索结果普遍是四五年前的讨论结果。新浪以前似乎也支持xml-rpc接口，但据我测试现在是无法进行发布了，CSDN貌似也有点问题，应该是关闭了接口。之所以要说xml-rpc，是因为emacs有一个插件org2blog能够通过xml-rpc接口来进行远程发布，顾名思义org2blog是使用org-mode作为major-mode的，熟悉org-mode并且正在使用WordPress的朋友一定会喜欢这个插件，如果需要，可以到这个&lt;a href=&quot;https://github.com/punchagan/org2blog&quot;&gt;链接&lt;/a&gt; 下载org2blog，此外org2blog依赖xml-rpc.el，点&lt;a href=&quot;http://www.emacswiki.org/emacs/xml-rpc.el&quot;&gt;这里&lt;/a&gt; 可以下载。
&lt;/p&gt;

&lt;p&gt;
第二条，还是说WordPress吧，WordPress是使用php编写的，使用mysql数据库来管理文章。从功能上来说WordPress是非常好的，它提供丰富的主题、插件以及拥有很多用户的论坛（好吧我不是在这里推荐WordPress的，不过我确实挺喜欢WordPress，之前也说过了），与此相对应的，为了完全了解WordPress，用户不得不去学习如何安装它的主题和插件、熟悉选项繁多的后台管理界面。至于国内的一些博客平台，外观暂且不说，一般都带有很多广告，我特别讨厌这一点。
&lt;/p&gt;

&lt;p&gt;
第三条，好吧这是我选择这一条路的主要理由，你懂得，我很穷，没有钱买主机空间和域名（求一个土豪朋友）。为什么我穷？因为我现在待业在家，没有工作——没有工作是因为我把工作辞了在家准备考公务员，至于这后面的故事就很复杂啦，如果有兴趣的话可以发邮件给我和我谈谈心哟。
&lt;/p&gt;

&lt;p&gt;
如果看到这里您对我的观点基本赞同的话，您可以继续读下去，否则我觉得您可以考虑一下WordPress或者其他平台。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org9110c33&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org9110c33&quot;&gt;Github Pages是什么&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org9110c33&quot;&gt;
&lt;p&gt;
&lt;a href=&quot;https://github.com&quot;&gt;Github&lt;/a&gt; 是一个用于使用Git版本控制系统项目的共享虚拟主机服务[1]。简单说，它是一个具有版本管理功能的代码仓库，每个项目都有一个主页，列出项目的源文件。
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;../../..//assets/img/github.png&quot; alt=&quot;github.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
但是对于一个新手来说，看到一大堆源码，只会让人头晕脑涨，不知何处入手。他希望看到的是，一个简明易懂的网页，说明每一步应该怎么做。因此，Github就设计了Pages功能，允许用户自定义项目首页，用来替代默认的源码列表。所以，Github Pages可以被认为是用户编写的、托管在Github上的静态网页。
&lt;/p&gt;

&lt;p&gt;
Github提供模板，允许站内生成网页，但也允许用户自己编写网页，然后上传。有意思的是，这种上传并不是单纯的上传，而是会经过Jekyll程序的再处理。这里的&lt;a href=&quot;http://jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt; 是一个静态站点生成器，它提供了模板、变量、插件等功能，所以实际上可以用来编写整个网站。它也是Github Pages的后端处理工具。
&lt;/p&gt;

&lt;p&gt;
利用Github Pages的这些特点，我们就可以搭建一个个人的博客——虽然是静态的网站，不过足够了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orgf248237&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf248237&quot;&gt;环境准备&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgf248237&quot;&gt;
&lt;p&gt;
对于想使用Github Pages服务来建立个人博客的朋友来说，您需要以下环境：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Github帐号&lt;/li&gt;
&lt;li&gt;配置好的本地git工具&lt;/li&gt;
&lt;li&gt;markdown编辑器或者其他的编辑器&lt;/li&gt;
&lt;li&gt;Jekyll(可选)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
前面两个我不想多说，相关的文章太多了，在这里重复那些内容没有什么意义。
&lt;/p&gt;

&lt;p&gt;
特别要说的是，建议使用linux系统，虽然理论上windows也可以使用msysgit来管理，但我不认为那是个好主意，当然如果愿意折腾，就无所谓了。
&lt;/p&gt;

&lt;p&gt;
至于markdown，它的语法简单明了，很快就能上手，因此不要担心这个问题，需要学习的话，可以到Github的首页，按下键盘的 &lt;b&gt;M&lt;/b&gt; 键进行学习。至于编辑器，简单的文本编辑器如gedit、leafpad甚至nano都可以，当然，本人选择使用emacs并且不使用markdown模式而是坚持使用org-mode，感兴趣的可以在文章尾部找到相关的配置以及使用方法。此外一些支持markdown语法的编辑器也是比较好的选择。
&lt;/p&gt;

&lt;p&gt;
最后的Jekyll为什么标注是可选呢？因为我们并不需要对相关的项目仓库做什么特别的事情，我们只需要写文章，然后commit-&amp;gt;push就是了，之所以需要Jekyll，是为了方便本地预览博客以及进行调试。怎么说也要保证自己的网站确实能够运行然后才去让别人阅览吧？总而言之，Jekyll并不是建立博客必须的部分，但它是帮助我们更好地进行管理的工具。
&lt;/p&gt;

&lt;p&gt;
Jekyll的安装：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-sh&quot;&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;&amp;#20197;debian&amp;#31995;linux&amp;#21457;&amp;#34892;&amp;#29256;&amp;#20026;&amp;#20363;&lt;/span&gt;
sudo apt-get install rubygems1.8
gem install jekyll liquid open4 maruku classifier rdiscount
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org7a02e5e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org7a02e5e&quot;&gt;方案选择&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org7a02e5e&quot;&gt;
&lt;p&gt;
可选的方案有三个：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://jekyllbootstrap.com/&quot;&gt;Jekyll-Bootstrap&lt;/a&gt; （简称JB-不信自己去看_includes目录）&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://octopress.org/&quot;&gt;Octopress&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;自己动手丰衣足食&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Jekyll-Bootstrap和Octopress是两个基于Jekyll的博客框架，使用它们能够快速地得到一个基本好看的、能够运行的博客系统，不过还是那个问题，因为已经够用了，所以你不会去关心它们到底干了什么怎么干的，直到你遇到问题。不过它们还是不错的，这是真心话。相对来说我个人比较推荐Jekyll-Bootstrap，因为它在Jekyll的基础上并没有作太大的改变，只是增加了主题和一些配置而已，Octopress干的事就多了。
&lt;/p&gt;

&lt;p&gt;
这里主要说一下第三种方案。
&lt;/p&gt;

&lt;p&gt;
自己动手呢，也分两种情况：
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;复用他人的博客模板&lt;/li&gt;
&lt;li&gt;自行编写每一行网站代码&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
显然第二种情况是如果不是对前端知识足够熟悉是比较困难的。因此复用他人的博客模板是比较好的选择，这里的复用并不是简单的拷贝然后使用（当然你想的话也可以），其他人的博客一般都会有一些细节无法满足自己，所以还需要自己进行修改、定制，这个过程就是意义所在。
&lt;/p&gt;

&lt;p&gt;
这个&lt;a href=&quot;https://github.com/mojombo/Jekyll/wiki/sites&quot;&gt;页面&lt;/a&gt; 收集了非常多Jekyll博客的链接及其源代码，我比较喜欢codepiano的风格，然后我最初用来学习的是唐九军的博客，唐九军的博客没有使用Jekyll-Bootstrap等其他东西，完全是自己编写的css和js，其文件结构也比较清晰——这两个人的博客和源代码链接都可以在刚才说的页面上找到，请善用快捷键 &lt;b&gt;Ctrl+F&lt;/b&gt; 。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org35fe7eb&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org35fe7eb&quot;&gt;行动纲领&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org35fe7eb&quot;&gt;
&lt;p&gt;
按照以下步骤进行：
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;在Github上建立一个名为&amp;lt;username&amp;gt;.Github.io的repo，其中的username为Github用户名.&lt;/li&gt;
&lt;li&gt;在本地建立对应的repo目录并设置好.&lt;/li&gt;
&lt;li&gt;将下载下来的模板拷贝到本地repo目录中.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
前期的工作就是这么三步,当然这里说得比较简略，详细的步骤可以到&lt;a href=&quot;https://help.github.com/categories/20/articles&quot;&gt;Github Pages的帮助页面&lt;/a&gt; 里进行了解。后面主要的工作集中在对自己的博客的配置中，下面将讲述博客配置的一些细节。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org3d57845&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3d57845&quot;&gt;Jekyll博客配置&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3d57845&quot;&gt;
&lt;p&gt;
之前说Jekyll并不是必须的，但这里为什么要说“Jekyll博客配置”呢？因为虽然我们可以不用Jekyll，但最终Github pages生成我们的博客时就是用的Jekyll，所以我们在配置上还是得按照Jekyll的规矩来。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org49e158c&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org49e158c&quot;&gt;博客目录结构&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org49e158c&quot;&gt;
&lt;p&gt;
首先明确一点，博客目录中不以下划线为命名开始的文件/文件夹都会在生成博客时复制过去，根据个人的不同喜好，博客的结构会不一样，这里只说一下Jekyll要求的一些结构：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-sh&quot;&gt;-- index.html         &amp;#32593;&amp;#31449;&amp;#39318;&amp;#39029;&amp;#25991;&amp;#20214;
-- _layouts           &amp;#21338;&amp;#23458;&amp;#27169;&amp;#26495;&amp;#30446;&amp;#24405;
   -- default.html
   --post.html
-- _posts             &amp;#25991;&amp;#31456;&amp;#23384;&amp;#25918;&amp;#30446;&amp;#24405;
   -- 2013-09-08-test.md
   -- 2013-09-08-test.html
   -- &amp;lt;other posts&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
除此以外其他文件都不是必须的，但光有这三个东西很难保证能生成一个足够完整的博客——事实上网站模板和文章目录也不是必须的，除了index.html，因为完全可以乱七八糟写一堆html文件然后自己在各个html文件之间理清关系。因此，通常的一个功能完整的Jekyll博客目录包含以下结构和文件：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-sh&quot;&gt;-- index.html         &amp;#32593;&amp;#31449;&amp;#39318;&amp;#39029;&amp;#25991;&amp;#20214;
-- archives.html      &amp;#25991;&amp;#31456;&amp;#23384;&amp;#26723;&amp;#39029;&amp;#38754;&amp;#25991;&amp;#20214;&amp;#65292;&amp;#25991;&amp;#20214;&amp;#21517;&amp;#21487;&amp;#25913;
-- categories.html    &amp;#25991;&amp;#31456;&amp;#20998;&amp;#31867;&amp;#39029;&amp;#38754;&amp;#25991;&amp;#20214;&amp;#65292;&amp;#25991;&amp;#20214;&amp;#21517;&amp;#21487;&amp;#25913;
-- tags.html          &amp;#25991;&amp;#31456;&amp;#26631;&amp;#31614;&amp;#39029;&amp;#38754;&amp;#25991;&amp;#20214;&amp;#65292;&amp;#25991;&amp;#20214;&amp;#21517;&amp;#21487;&amp;#25913;
-- about.html         &amp;#8220;&amp;#20851;&amp;#20110;&amp;#25105;&amp;#8221;&amp;#39029;&amp;#38754;&amp;#25991;&amp;#20214;&amp;#65292;&amp;#25991;&amp;#20214;&amp;#21517;&amp;#21487;&amp;#25913;
-- rss.xml&amp;#25110;atom.xml  &amp;#21338;&amp;#23458;feed&amp;#25991;&amp;#20214;&amp;#65292;&amp;#25991;&amp;#20214;&amp;#21517;&amp;#21487;&amp;#25913;
-- sitemap.xml        &amp;#21338;&amp;#23458;&amp;#22320;&amp;#22270;&amp;#65292;&amp;#20026;&amp;#21338;&amp;#23458;&amp;#20570;SEO&amp;#20248;&amp;#21270;&amp;#65292;&amp;#36825;&amp;#20010;&amp;#25105;&amp;#19981;&amp;#22826;&amp;#25026;
-- _config.yml        Jekyll&amp;#21338;&amp;#23458;&amp;#37197;&amp;#32622;&amp;#25991;&amp;#20214;
-- _layouts           &amp;#21338;&amp;#23458;&amp;#27169;&amp;#26495;&amp;#30446;&amp;#24405;
   -- default.html
   -- post.html
-- _includes          &amp;#21487;&amp;#22797;&amp;#29992;&amp;#30340;&amp;#20844;&amp;#29992;&amp;#27169;&amp;#26495;&amp;#25991;&amp;#20214;&amp;#30446;&amp;#24405;&amp;#65292;&amp;#20363;&amp;#22914;&amp;#21338;&amp;#23458;&amp;#30340;&amp;#23548;&amp;#33322;&amp;#26465;&amp;#12290;&amp;#19981;&amp;#26159;&amp;#24517;&amp;#39035;&amp;#30340;&amp;#65292;
                      &amp;#20294;&amp;#20998;&amp;#31163;&amp;#20986;&amp;#21508;&amp;#20010;&amp;#39029;&amp;#38754;&amp;#30340;&amp;#20844;&amp;#26377;&amp;#37096;&amp;#20998;&amp;#21487;&amp;#20197;&amp;#20351;&amp;#24471;&amp;#27169;&amp;#26495;&amp;#26356;&amp;#26131;&amp;#35835;&amp;#65292;&amp;#32467;&amp;#26500;&amp;#26356;&amp;#28165;&amp;#26224;
   -- footer.html
   -- footer.html
   -- &amp;lt;other file to include&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt; in&lt;/span&gt; template&amp;gt;
-- _posts             &amp;#25991;&amp;#31456;&amp;#23384;&amp;#25918;&amp;#30446;&amp;#24405;
   -- 2013-09-08-test.md
   -- 2013-09-08-test.html
   -- &amp;lt;other posts&amp;gt;
-- assets/            &amp;#20854;&amp;#20182;&amp;#21338;&amp;#23458;&amp;#25991;&amp;#20214;&amp;#23384;&amp;#25918;&amp;#30446;&amp;#24405;&amp;#65292;&amp;#22914;css&amp;#65292;&amp;#22270;&amp;#29255;&amp;#65292;js&amp;#25991;&amp;#20214;&amp;#65292;&amp;#30446;&amp;#24405;&amp;#32467;&amp;#26500;&amp;#20165;&amp;#20026;
                      &amp;#31034;&amp;#20363;&amp;#65292;&amp;#21487;&amp;#26681;&amp;#25454;&amp;#20010;&amp;#20154;&amp;#24847;&amp;#24895;&amp;#33258;&amp;#34892;&amp;#35774;&amp;#32622;
   -- css
      -- style.css
   -- img
      -- favicon.ico
   -- js
      -- blog.js
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org9fed7b4&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org9fed7b4&quot;&gt;博客模板&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org9fed7b4&quot;&gt;
&lt;p&gt;
正如上面的示例一样，博客模板一般包含一个default.html和一个post.html，正如其名字一样，default.html是博客的模板，而post.html一般是文章的生成模板。查看一些Jekyll博客的模板，您会发现其中会有
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;

{{ site.url }}


{{ for post in site.posts }}

&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
这样的语句，这是因为Jekyll使用&lt;a href=&quot;https://github.com/Shopify/liquid/wiki/Liquid-for-Designers&quot;&gt;liquid语法&lt;/a&gt; 来解析模板，诸如 &lt;b&gt;site.url&lt;/b&gt; 、 &lt;b&gt;site.posts&lt;/b&gt; 这样的部分是Jekyll内置的一些变量，关于Jekyll的变量的更多内容可以到&lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll的官网&lt;/a&gt; 上深入了解。
&lt;/p&gt;

&lt;p&gt;
有了模板文件后，其他的页面都可以通过Jekyll所谓的front-matter来使用模板，举例来说，撰写文章时，一般这样写：
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
&amp;#x2014;
layout     : post
title      : &amp;lt;文章标题&amp;gt;
categories : &amp;lt;分类&amp;gt;
tags       : &amp;lt;标签&amp;gt;
&amp;#x2014;
&amp;lt;正文&amp;gt;
&amp;#x2026;
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
这样在编写文章时就只需要关心文章内容了。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org64951b7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org64951b7&quot;&gt;_config.yml&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org64951b7&quot;&gt;
&lt;p&gt;
_config.yml文件是Jekyll博客的配置文件，用户可以在这个配置文件中设定博客名称、博客描述、作者名称等信息，并可以在模板中作为变量使用。
&lt;/p&gt;

&lt;p&gt;
我的配置文件如下所示：
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-html&quot;&gt;permalink:        /:year/:month/:day.html
markdown:         rdiscount
pygments:         true
paginate:         5

title:            &amp;#31548;&amp;#20013;&amp;#26790;
url:              http://linusp.Github.io/
feed:             /atom.xml
author:
    name:         &amp;#21457;&amp;#26465;&amp;#20820;&amp;#23376;
    email:        linusp1024@gmail.com
    description:  &quot;&amp;#21464;&amp;#25104;&amp;#20820;&amp;#23376;&amp;#30340;&amp;#38738;&amp;#34521;&quot;

follow:
    email:        linusp1024@gmail.com
    Github:       https://Github.com/Linusp


desc:      &amp;#21457;&amp;#26465;&amp;#20820;&amp;#23376;&amp;#30340;&amp;#19981;&amp;#23436;&amp;#20840;&amp;#25216;&amp;#26415;&amp;#21338;&amp;#23458;

indexContent:     true

style:            /assets/css/style.css
blogName:         &amp;#31548;&amp;#20013;&amp;#26790;
blogDesc:         &amp;#21457;&amp;#26465;&amp;#20820;&amp;#23376;&amp;#30340;&amp;#19981;&amp;#23436;&amp;#20840;&amp;#25216;&amp;#26415;&amp;#21338;&amp;#23458;
favicon:          /assets/img/favicon.ico
theme:            blue

disqus:           linuspb

copyright:        &amp;#169; 2013
test:             ok
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org6af55b5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org6af55b5&quot;&gt;archives页面示例&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org6af55b5&quot;&gt;
&lt;p&gt;
一个简单的archives页面[2]如下
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-html&quot;&gt;---
layout: default
title : Archives
---
&amp;lt;&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;ul&lt;/span&gt;&amp;gt;
  {% for post in site.posts %}
  &amp;lt;&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;li&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;a&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;href&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;{{ post.url }}&quot;&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;title&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;{{ post.title }}&quot;&lt;/span&gt;&amp;gt;
      &amp;lt;&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;span&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;date&quot;&lt;/span&gt;&amp;gt;
        &amp;lt;&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;span&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;day&quot;&lt;/span&gt;&amp;gt;{{ post.date | date: '&lt;span style=&quot;color: #ffcc66;&quot;&gt;%d&lt;/span&gt;' }}&amp;lt;/&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;span&lt;/span&gt;&amp;gt;
        &amp;lt;&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;span&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;month&quot;&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;abbr&lt;/span&gt;&amp;gt;{{ post.date | date: '&lt;span style=&quot;color: #ffcc66;&quot;&gt;%b&lt;/span&gt;' }}&amp;lt;/&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;abbr&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;span&lt;/span&gt;&amp;gt;
        &amp;lt;&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;span&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;year&quot;&lt;/span&gt;&amp;gt;{{ post.date | date: '&lt;span style=&quot;color: #ffcc66;&quot;&gt;%Y&lt;/span&gt;' }}&amp;lt;/&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;span&lt;/span&gt;&amp;gt;
      &amp;lt;/&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;span&lt;/span&gt;&amp;gt;
      &amp;lt;&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;span&lt;/span&gt; &lt;span style=&quot;color: #ffcc66;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;title&quot;&lt;/span&gt;&amp;gt;{{ post.title }}&amp;lt;/&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;span&lt;/span&gt;&amp;gt;
    &amp;lt;/&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;a&lt;/span&gt;&amp;gt;
  &amp;lt;/&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;li&lt;/span&gt;&amp;gt;
  {% endfor %}
&amp;lt;/&lt;span style=&quot;color: #f99157; background-color: #2d2d2d; font-weight: bold;&quot;&gt;ul&lt;/span&gt;&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
同样的，categories页面和tags页面的形式差不多，也是使用Jekyll内置的变量，当然要做得好看还是要费点功夫的，比如说本人这个博客的这两个页面还是一团糟（因为博客主题的作者并没有提供这两个页面，这就是所谓 &lt;b&gt;自己动手丰衣足食&lt;/b&gt; 啦）。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-orga0f7f58&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orga0f7f58&quot;&gt;_site目录&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-orga0f7f58&quot;&gt;
&lt;p&gt;
本地调试时，Jekyll会在目录下生成一个_site目录，目录就是真正生成的博客目录和文件，但这个文件对Github Pages是无意义的，仅仅是用来方便本地预览和调试，因此建议在.gitignore文件中添加该目录以在push时不用上传该目录及其中的文件。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;outline-container-org733f82f&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org733f82f&quot;&gt;使用emacs的org-mode&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org733f82f&quot;&gt;
&lt;p&gt;
对于emacser来说，使用org-mode来写作才是最幸福的事情，因此就有了这一部分。这一部分的绝大部分内容来自脚注2[2]中提到的文章，基本的配置过程和要点在文章中都已经说得很详细了，因此我在这里就简略地说几点。
&lt;/p&gt;

&lt;p&gt;
因为Jekyll可以识别markdown文件和html文件，所以使用emacs的org-mode将org文件publish成html文件就是我们要做的。值得一提的是Jekyll-Bootstrap在本地调试时直接无视_posts目录下后缀为html的文件，虽然说肯定有办法改变这种行为，但我找了一会没找到就放弃了，加之Jekyll-Bootstrap在Jekyll的基础上又多加了一些东西，所以导致我并没有去使用Jekyll-Bootstrap以及使用了Jekyll-Bootstrap的博客模板。
&lt;/p&gt;

&lt;p&gt;
我的方案：
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;建立一个目录，在其中建立两个子目录，一个名为 &lt;b&gt;org&lt;/b&gt; ，一个名为 &lt;b&gt;Jekyll&lt;/b&gt; 。后者是和username.Github.io这个repo对应的本地repo目录，前者是org格式的文章存放目录，注意org目录下再建立一个 &lt;b&gt;_posts&lt;/b&gt; 目录，将文章存放到 &lt;b&gt;org/_posts&lt;/b&gt; 下面，这样在执行 &lt;b&gt;org-publish-project&lt;/b&gt; 时才能保证生成到指定目录。&lt;/li&gt;

&lt;li&gt;使用org-mode 7.x。emacs23自带的org-mode版本为6.x，其中的bug会导致插入的front-matter在生成时发生错误。emacs24自带的org-mode工作良好。&lt;/li&gt;

&lt;li&gt;org-mode的publish参数中一定要加上 &lt;b&gt;:body-only t&lt;/b&gt; 否则就会生成完整的html文件，这不是我们想要的。&lt;/li&gt;

&lt;li&gt;编写文章时，在头部添加front matter，如下&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;example&quot;&gt;
#+BEGIN_HTML
---
layout     : post
title      : 使用Github Pages服务建立个人博客
categories : IT
tags       : Github emacs org-mode Jekyll
---
#+END_HTML

&lt;/pre&gt;
&lt;p&gt;
而不需要其他信息，并在之后编写正文。
&lt;/p&gt;

&lt;p&gt;
我的publish配置（仅供参考）
&lt;/p&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-lisp&quot;&gt;(&lt;span style=&quot;color: #99cc99; font-weight: bold;&quot;&gt;require&lt;/span&gt; '&lt;span style=&quot;color: #6699cc;&quot;&gt;org-publish&lt;/span&gt;)
(setq org-publish-project-alist
      '(
    (&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;org-linusp&quot;&lt;/span&gt;
     &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;; &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;Path to your org files.&lt;/span&gt;
     &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:base-directory&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/blog/org/&quot;&lt;/span&gt;
     &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:base-extension&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;org&quot;&lt;/span&gt;
     &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;; &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;Path to your Jekyll project.&lt;/span&gt;
     &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:publishing-directory&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/blog/Jekyll/&quot;&lt;/span&gt;
     &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:recursive&lt;/span&gt; t
     &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:publishing-function&lt;/span&gt; org-publish-org-to-html
     &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:headline-levels&lt;/span&gt; 4
     &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:html-extension&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;html&quot;&lt;/span&gt;
     &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:body-only&lt;/span&gt; t &lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;;; &lt;/span&gt;&lt;span style=&quot;color: #999999; font-style: italic;&quot;&gt;Only export section between &amp;lt;body&amp;gt; &amp;lt;/body&amp;gt;&lt;/span&gt;
     )
    (&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;org-static-linusp&quot;&lt;/span&gt;
     &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:base-directory&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/blog/org/&quot;&lt;/span&gt;
     &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:base-extension&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf\\|php&quot;&lt;/span&gt;
     &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:publishing-directory&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;~/blog/Jekyll/&quot;&lt;/span&gt;
     &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:recursive&lt;/span&gt; t
     &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:publishing-function&lt;/span&gt; org-publish-attachment
     )
    (&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;blog-linusp&quot;&lt;/span&gt; &lt;span style=&quot;color: #cc99cc; background-color: #2d2d2d;&quot;&gt;:components&lt;/span&gt; (&lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;org-linusp&quot;&lt;/span&gt; &lt;span style=&quot;color: #66cccc;&quot;&gt;&quot;org-static-linusp&quot;&lt;/span&gt;))
    ))
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
执行 &lt;b&gt;org-publish-project&lt;/b&gt; 时，选择 &lt;b&gt;blog-linusp&lt;/b&gt; 进行publish（按照我这个配置）。
&lt;/p&gt;

&lt;p&gt;
[1]详情见维基百科的&lt;a href=&quot;http://zh.wikipedia.org/zh/Github&quot;&gt;Github条目&lt;/a&gt;.
[2]来自&lt;a href=&quot;http://orgmode.org/worg/org-tutorials/org-Jekyll.html&quot;&gt;Using org to Blog with Jekyll&lt;/a&gt;.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

    </content>
  </entry>
  
  <entry>
    <title>第一篇博客</title>
    <link type="text/html" rel="alternate" href="http://www.zmonster.me/2013/09/11/first-post.html"/>
    <category term="博客" scheme="http://www.zmonster.me/categories.html#博客"/>
    <id>http://www.zmonster.me/2013/09/11/first-post</id>
    <published>2013-09-11T00:00:00+00:00</published>
    <updated>2013-09-11T00:00:00+00:00</updated>
    <description>
    
      <p>这是用Jekyll+Github搭建的博客上的第一篇文章，以作纪念</p>
    
    </description>
    <content type="html">
      &lt;p&gt;
这是用Jekyll+Github搭建的博客上的第一篇文章，这里就不多说什么了，仅仅是用来做个纪念，用Jekyll搭建静态博客并和emacs的org-mode有机结合的具体细节将会在下一篇文章中讲解。
&lt;/p&gt;

    </content>
  </entry>
  
</feed>
