Git Cheat sheet

Set up an empty server repository and Use it locally

On Server For an empty repository

$ mkdir /srv/git/my_repository

$ cd /srv/git/my_repository

$ git init –bare

On Server From an Existing repository

$ cd /srv/git

$ git clone –bare https://github.com/rainbowrun/lim.git lim.git

On Client, Initial Change

<… Set up SSH access to server as user@server properly …>

$ git clone ssh://user@server/srv/git/my_repository

$ cd my_repository

<… Make some change and commit locally …>

$ git push origin master   # For the first time push, create ‘master’ branch on server.

$ git push # For the subsequent push

$ git pull  # Get the server’s change and merge locally.

Notes

After this setup, the local branch ‘master’ is tracking the remote branch ‘origin/master’.

Branch Locally

$ git branch testing  # Add a new branch named testing.

$ git checkout branch # Checkout ‘testing’ branch

$ git checkout master # Checkout default ‘master’ branch

  • Merge the work in ‘testing’ into master

$ git checkout master

$ git merge testing

$ git branch -d ‘testing’

Remote Branch

$ git branch show origin   # Show remote branches

$ git branch -vv  # Local branch, which is tracking which remote.

  •   Create a local branch ‘testing’, tracking remote ‘testing’

$ git pull

$ git checkout –track origin/testing

Git 总体印象

  • 分布式的版本管理确实很新颖,用起来比集中式的方便。
  • Branch 的概念很好,Track, Pull, Merge。
  • 功能强大,同时也很复杂
    • staging area in working tree,可以选择提交部分工作
    • stash,可以把当前的工作环境封存起来
    • rebase,把两个Branch变成一个,而不是merge。

离线电脑上的写作感悟

很长一段时间,自己都苦于意志力薄弱,注意力差,不能够在自己想要深耕的领域有足够的学习时间,相反却总是被新闻网站、色情网站以及围棋游戏浪费了大量的时间。我想了很多办法来克服这个问题,从封禁网站,封存设备、坚持工作列表到邀请孩子们帮忙监督等等,但是都是成效不大。离线电脑是自己最新的办法,主要的考虑如下:

  • 很多学习只能在电脑上展开,所以必须有一个电脑。
  • 电脑如果不能上网,那就不会花时间在前面那些无谓消耗时间的事情上了。

一念及此,就行动起来。为了避免额外的花销,自己最终选择了 Acer C871 Chromebook 作为实际的机器,在家庭路由器上禁掉这个机器的 Mac Address,然后在机器上装上 Linux Virtual Machine,就这样开始了。

这样搞了一段时间,我发现离线电脑确实能够达到前面所说的两个好处,在电脑上看了不少书籍、论文,实验了很多程序,学到了很多东西,是个不错的主意。很自然的,我就继续扩展这个主意,把更多的事情拿到电脑上来做,首当其冲的就是想要在离线电脑上浏览以前写的文章,或者是写新的文章。

按道理说,Google Docs 是一个现成的选择,特别是它的离线同步功能做的非常的好,但是 Google Docs 有两个比较明显的缺陷:

  • 它的公式编辑功能比起 Latex 来说那实在是差得太远了。我有很多文章都要写公式,这样可不行。
  • Google Docs 把所有的内容都存在 Google Cloud 上面,没有办法把文章发到自己的博客上。特别在这次 Trump 总统被禁言后,我对于把内容都存放在云端更是多了很多警惕,这些大公司信不过啊。

下来的方案就是用一些先天支持离线编辑的静态站点生成工具,最有名的就是 Jykell。这个东西我用过一阵子,一看就是给技术人士做的,全部都是命令行界面,不过好处也非常明显:

  • git-based 版本管理,完美支持离线操作。
  • static web page,安全快速。
  • github host service,不需要自己花钱租虚拟机。

但是自己还是有些犹豫,自己对于 Ruby 语言以及 Gemfile 这套东西一点都不熟悉,相比之下,Wordpress 虽然很老,但是它并不会很快就消亡,相反,因为庞大的用户群和悠久的历史,这些老软件都很稳定,而且自己也花了很多时间学习和使用这个平台,不应该就这样轻易放弃,再说自己也还没有深入使用 Jykell,对于它的缺点也不了解,不过最少可以想见:

  • 现有文章的迁移是个费时费力的工作。
  • 插件不够丰富,比如如果要自己的围棋能够显示,需要手动做不少工作。

相反,对于Wordpress:

  • 技术架构和源代码自己比较熟悉
  • 有很多文章积累 (已经 600+)
  • 插件支持丰富,围棋、音乐、数学公式,国际象棋,一应俱全。

当然啦,各自的优点就是对方的缺点。通算下来,要把 600+的文章移到 Jekyll 上,花掉的时间实在不值得。一咬牙,自己开始着手开发一个 WordPress Sync Script,期间经历了诸多困难:

  • PHP 的代码自己并不熟悉,连什么是数组都搞不清楚。
  • XMLRPC 的文档奇缺,而且其实现以及Python 接口库有各种各样的 Bug。
  • WordPress 的 Mysql Database Schema 并没有设计为支持同步,好多设计都需要妥协,比如用文章的 Title 而不是用 id 来判断两个文章是否应该同步。

开发过程中经历了各种各样的坎坷,再加上 Jykell 的吸引,数度想要放弃,过程不堪回首。在数天挣扎中,最大的一点体会就是没有什么事情能够一蹴而就,都是要经历一番艰难险阻才能实现,过不去那就是遗憾,过去了就是财富。终于在假期最后一天晚上1点钟明白了为什么自己上传的文件名总是被 WordPress 改名之后,手动修改它的程序,成功的把两个Wordpress 站点的媒体库同步起来了,心里真是高兴。

邓总原来有一句话,叫做“黑猫白猫,抓住老鼠就是好猫”。胡总也有一句类似的话,叫做“不折腾”。大体意思都是说:要抓住主要目的,把大家的物质生活搞上去,把我们的综合国力搞上去,不要管太多意识形态,建设道路等方面虚的东西。 软件工程上把重复别人做的基础工作叫做“重新发明轮子”。 WordPress 虽然老土,但是自己会用,也比较懂,而且现有的东西(博客文章,部分插件、云端主机等等)都已经建好,就比其他看上去高大上的东西(比如 Github Page, Jykell 等等)要好。就坚持这条道路吧。

西方的言论太自由了吗?

这次美国的社交媒体纷纷关闭现任总统 Trump 的账号,特别是 Amazon 干脆拒绝为Pamler提供云计算平台,对 Trump 赶尽杀绝,使得一贯对于西方言论自由抱有强大信心的人们大跌眼镜。以前常听人说起的格言:“我不同意你说的话,但是我誓死捍卫你说话的权利”。好像现在也不管用了。想起我的朋友 Yitwah 从美国搬到中国生活了数年以后跟我说:美国的问题就是言论太自由了,也不好。当时并不理解他的话,但是印象非常深刻,毕竟Yitwah 从小在西方长大,自由民主的价值观应该是根深蒂固,没有想到他却是这样想。特别是这是出自一位朋友的切身体会,而不是出自媒体的宣传,那是完全可以相信的。

难道是现在的问题是西方的言论已经太自由了,到了矫枉过正的时候了吗?

从作为预测的模型到作为概率分布的模型 (Model: From Prediction to Distribution)

作为机器学习的实践者,自己对于模型的理解就是 Predict:从一组输入信号来计算目标变量,也就是:

(1)   \begin{equation*} y = F(x_1, x_2, x_3, ... x_n) \end{equation*}

但是在机器学习的理论学习中,我常常看到教材上提到模型也描述了概率分布,并从这个角度有很多理论上的推导,比如在分类模型中,Maximum Likelihood Estimation 和 Cross Entropy 是等价的,再比如如果假定观测误差符合正态分布的话,那么Maximum Likelihood Estimation 和 Mean Square Error 在回归模型中也是等价的,等等。在我看来,如果我们已经有了m个训练数据:

(2)   \begin{equation*} \begin{split} (x_{11}, x_{12}, ... x_{1n}, y_1), \\ (x_{21}, x_{22}, ... x_{2n}, y_2), \\ ..., \\ (x_{m1}, x_{m2}, ... x_{mn}, y_m) \end{split} \end{equation*}

那么训练数据的概率分布已经可以使用计数的方法(也就是 Empirical Distribution)直接计算了,为什么还需要一个模型呢?

直到最近,我才对于这个问题有了一些更深刻的认识:所谓模型描述了概率分布,指的是在给定输入条件 x_1, x_2, ..., x_n 的情况下,模型给出预测值 y,以及确认该值是 y 的概率。也就是下面的条件概率密度函数

(3)   \begin{equation*} p(y | x_1, x_2, x_3, ..., x_n) \end{equation*}

对于分类模型,上面的描述比较好理解:假定我们有 C 个 class,那么在最后一层网络中一般有 C 个输出,经过 Softmax 归一化处理以后,我们把 (p_1, p_2, ..., p_c) 就当做当前用例属于每一类的概率,这确实是一个概率分布。只不过在实践中我们需要取出概率最大的一个作为模型的输出值(Predict a Class)而已。

对于回归模型,上面的描述的意义就不是那么明显了,下面一段分析引用自 Maximum Likelihood Estimation 和 Mean Square Error

假定我们根据实验观察,得到了大量的训练数据。因为总是有不可知因素能够影响 y的最终取值,但是却没有被我们包含在 x_1, x_2, ..., x_m 当中,不难想象,在这种情况下,我们会发现某些训练数据的输入信号部分是完全一样的,但是 y却不一样。同时我们的模型只能够预测一个值,这个时候模型应该预测那一个值呢?如果我们把模型看做对于目标数据的概率密度函数,那么对于和模型预测值相同的那些值,它们的条件概率是1吗?和模型预测值不同的那些值,它们的条件概率是0吗?

对于模型应该预测的值,训练数据的平均值是一个明显正确的选择。但是后面两个问题,我们不应该采用非0即1的答案。统计学指出,在上面的情况下,我们应当假定在相同的输入信号下所有的目标变量y的概率分布符合正态分布(Normal Distribution),其分布的中心就是所有目标变量的平均值,这个值也是我们的模型的预测值(Predict)。但是对于和这个预测值相同的y值,其概率并不是1,和这个预测值不同的y值,其概率也不是0,而是符合正态分布。在这个前提下,我们就可以说模型描述了给定了条件 x_1, x_2, ..., x_m<img class="ql-img-inline-formula quicklatex-auto-format" title="Rendered by QuickLaTeX.com" src="https://zhangxiaopan.net/wp-content/ql-cache/quicklatex.com-38461fc041e953482219abf5d4cce1cb_l3.svg" alt="y" width="9" height="12" /> 的概率分布:

(4)   \begin{equation*} p(y | x_1, x_2, ..., x_m) = \mathcal{N} (y; \overline{y}(x_1, x_2, ..., x_m, \theta), \sigma ^2) \end{equation*}

上式中 \theta 表示模型的具体参数,\overline{y} 表示模型预测的具体值,\sigma^2 可以暂时先使用一个任意指定的固定数值。这样我们的模型就表示了给定了条件 x_1, x_2, ..., x_m,某个 y 出现的概率。

综上所述,模型描述的概率分布是一个条件概率,它隐含了训练模型时使用的Cost Function。

通常意义上的概率分布指的是目标变量的概率分布,也就是:

(5)   \begin{equation*} p(y) \text{over all possible} (x_1, x_2, x_3, ... x_n) \end{equation*}

如果我们有一个模型,给定一个输入X就可以计算相应的目标变量y。在所有可能的输入信号上使用模型计算一遍,我们就可以计算出目标变量y概率分布,但是这受到输入信号 X 的概率分布的直接影响。如果所有可能的输入信号是概率相等的,那么使用模型在这些输入上执行一遍就可以计算目标变量y的概率分布。如果输入信号 X 的概率分布不是均匀分布但是是已知的,我们依然可以使用其概率作为权重来计算目标变量y的概率分布。如果输入信号 X 的概率分布是未知的,那么仅靠模型就无法有效的预测目标变量的概率分布了。但是我们需要明确:输入信号 X 的概率分布是另外一个问题,这个概率分布和能够从输入X预测目标变量y的模型是完全不同的,我们建立的目标变量y的模型本身并不包含X的概率分布,它本身倒是可以描述一个条件概率分布。

大屏幕下的《帝国时代 I》

《帝国时代 I》是自己上学时候特别着迷的一款游戏,很多个周末都和朋友在机房联网打这个游戏度过。这个游戏背景题材基于历史,着眼宏大,画面逼真,兵种设计丰富全面,打起来很好玩。电脑AI 喜欢作弊但是整体战略很傻,这一点甚至得到了我们的喜爱,几个人团结起来打电脑,利用电脑的漏洞才能取胜。美中不足的是这个游戏当时最大只有 800 * 600 的分辨率,指挥大部队作战的时候,常常前队已经开出很远和敌人遭遇了,后队还在家里排队,地图移来移去真是麻烦。

因为一个偶然的原因,我发现这个游戏在2018年发行了大屏幕版本,就在 Steam 上下载了一份,发现有很多惊喜:

  • 最大支持 4k 屏幕,前面所说的问题完全不存在了。
  • 现在农民可以自动开始重新种地了,实在是太好了。
  • 最大人口提高到 250 人,战斗场面更加宏大。
  • 新版本的元素图形和老版本完全一致,特别适合我这种怀旧的老鸟。

自己又尝试了一把先造围墙迷惑敌人并从容发展,然后箭塔配合僧侣在狭窄处伏击敌人主力,最后大批投石车和战车弓箭手平推敌人基地的经典战术,大屏幕下真是爽啊。

过滤低质量的训练数据

过滤低质量的训练数据是提高训练精度的一个好办法。理论上来讲,训练用例分为正例和反例,但是在实践中这并不是非黑即白。自己现在做的 Dual Encoder,虽然图片周围的实体都可以被当作正例,但是实践中实体的标注实际上就有一个 Confidence Score,这个 Confidence Score 如果太小,那就不把它当作正例即可,这就起到了过滤部分低质量训练数据的效果。

以前的工程师用了一个模型来给训练数据打分,自己一直觉得不需要这么复杂,直接使用Confidence Score就应该很好了。这次大胆地把模型去掉,没有想到训练的效果差了很多,自己很是吃了一惊。仔细研究之下,结果发现就是因为直接使用实体的Confidence Score时,因为分数分布的缘故,比起原来用一个模型,过滤掉的低质量训练数据一下子少了很多,因此训练效果就变差了。提高Confidence Score Threshold以后问题就解决了。真好。

苹果电脑近年来的一些奇葩决定

自己在2014年左右上了苹果的贼船,刚开始觉得很好,用了这么多年下来,才发现苹果用心险恶,总是在谋求对于用户的全面控制,为了长期的稳定,尽量还是要远离苹果的产品。下面列出我自己收集的近年苹果的一些奇葩决定:

  • 两下空格变成一个句号。这是从手机搬到电脑上的一个特性,完全无用,却又默认打开,啊。
  • 出现一个 Siri,要你对它讲话。这么用电脑也实在太奇怪了。
  • Touch-bar,用了几年下来,除了调整一下音量或者屏幕亮度,就没有发现有用的时候。每次看着各种提示候选在Touch-bar上显示,真是无法理解,白白浪费电池。
  • 为了打通云端系统开始收钱,强迫登录 Apple ID,然后向云端同步一大堆无用的图片、视频。一旦默认空间快要用完,就开始积极的向你弹窗提示,快快缴费!
  • 为了能够卖出iPad,笔记本从来不带触摸屏。
  • 为了能够卖出更多的iPad,从来不支持多用户。
  • 不停的提示你需要更新系统,好向你推送更多可以收费的机会。

Setup SiteSync For WordPress

自从搞了一个不上网的笔记本,我就一直琢磨着怎么才能 Offline 写博客。期间尝试了无数的办法,包括:

  • 切换到 Jekyll:这个软件就是为Offline写博客准备的,按说应该是完美的选择,但是在实践中这是一个大坑,最后有几点让我放弃了。
    • Jekyll 的插件不够丰富,特别的,没有围棋的支持。
    • Jekyll 不支持私有的文章。
    • 最后,把所有的文章从 WordPress 迁移到 Jekyll 是个浩大的工程,我还专门试了试Jekyll自带的导入工具,结果跑出来的格式都需要手动调整,最少需要几天时间。
  • Offline Blog Write Tool:按说这个不难,但是不知道为什么,在Linux上就是没有能够用的工具。在 https://wordpress.org/support/article/weblog-client/ 上列出的工具,不是不能运行,就是长久以来没有人维护了。
  • Offline 写在Google Docs中,然后再把 Google Docs 嵌入到帖子中:这个问题就是太难看了,实在不愿意。
  • WordPress Desktop:本来我对这个报了极高的希望,折腾了很长时间,甚至还安装 JetPack 插件,最后这个软件只是通过桌面来远程操作Wordpress站点,但是还是需要上网,大失所望!
  • 还有一个比较搞笑的地方就是我的笔记本是一个Chromebook上面安装的Linux。这个Linux的奇怪地方是所有的程序中文输入法的支持都有问题:Terminal Vim 输入中文屏幕显示一塌糊涂,X-window Based Vim 干脆没有办法切换到中文输入,只有在Chrome 浏览器里输入中文还算正常,这也给了我试图建立Offline 编辑的想法当头一棒,唉。

在尝试了多种办法均失败以后,最后我看到了一个叫做 WPSiteSync 的插件,号称可以在两个站点之间同步文章。我想了想,如果按照这个办法,第一不用学习新的博客软件,第二Offline编辑的环境也和原来一样,看上去还可以,我就一咬牙,在我的笔记本上架起了完整的Wordpress (幸好上次迁移的时候写了一个攻略,正好用上),然后再安装和设置好同步插件,结果真的工作了!

这样我就可以 Offline Edit 我的博客文章了,几天以来的辛苦工作终于有了回报,很开心。

儿子教我弹会了《致爱丽丝》

《致爱丽丝》是一首经典的古典曲目,自己觉得很好听,可是从来没有想过自己试一试。在我的潜意识里,我也就弹弹流行通俗歌曲,对于古典曲目那是肯定拿不下来的,就不用浪费时间了。

儿子自己不知深浅,倒是常常对着 Youtube 上的视频练习。有一天儿子突然对我说他已经学会了这首曲子,然后要教我弹。我抱着陪他游戏一下的心情,就让他开始教我。没有想到前奏部分不是很难,我很快就学的像模像样了,儿子开始是自己背了一些指法,后来我们两个人又从网上找来曲谱打印出来认真学习,结果我花了一周时间,就把前奏学完了。以前只是想想,现在可以自己弹了,真好!

感谢本!

不用f前缀但是像fstring一样Print (fstring print without f-prefix)

Python 早期的Print语句受到 C 的直接影响,在把变量嵌入到输出的字符串时采用了占位符语法。使用这种打印语句,程序员需要在脑子里把所有的变量处理两次,一次是它们在字符串中的位置,一次是它们的具体名称。这样处理实际上比较繁琐而且容易出错的:

name = 'Bob'
age = '60'
print('%s is % years old.' % (name, age))

新的f-string 语法可以直接把变量嵌入到字符串中,算是朝正确的方向前进了一大步:

print(f'{name} is {age} years old.')

现在的问题是,我们总是要加上 f 这个恼人的前缀,特别是如果输出的消息是多行的话,每一行都要写上这个前缀,更是麻烦。我琢磨了很久,终于搞明白怎样在正常的字符串中嵌入变量名处理了,真是不错:

def Print(message):
  import inspect
  frame = inspect.stack()[1][0]
  print(message.format_map({**frame.f_globals, **frame.f_locals}))

name = 'Bob'
age = '60'
Print('{name} is {age} years old. - Print magic')

长久以来的一个心病终于解决了。