Mar 302017
 

节省编译时间的工具 Tools save compiling time 最近发现编译C++程序很花时间。 比如说仅仅编译一个用了模版库的程序需要花10秒。 为了加快开发速度,我想找一个能提高单机编译速度的程序。结果如下: 结论: 从编译速度来看,首次编译速度最快的是zapcc(不免费)和clang(免费),耗时~35秒左右,比g++快40%。 重复编译的时候ccache最快,提速10倍以上。 注:表中zapcc的用户时间很短,内容占用少,这是因为它是起动其他进程去真正编译,其他程序的用户时间和内存使用没有被计入。

Sep 302016
 

卡方检验的公式(2×2) A short-cut formula for Chi-square test a 2 by 2 table 最近发现一个快速计算卡方检验的公式。 对于2×2的表格 上式中 卡方检验的统计量是: 这个方法和R计算的结果(不要用continuity correction, e.g. chisq(…, correct = FALSE))是一致的。 -- February 17, 2017更新 -- 刚刚发现Matthew’s Correlation Coefficient (MCC)的定义和2×2 table的卡方检验有如下联系 因为MCC的范围是-1到1,因此的范围是0到

Apr 202016
 

Some Notes about Makefile 记录一下最近用Makefile的经验和教训 内容比较凌乱。放在这里供以后参考。 1. Target-specific variable的作用域 Target-specific variable指的是变量在某些特定目标下的值。用法是: target … : variable-assignment 注意这里的变量作用域只是在Recipe部分,而不能在目标(Target)或者依赖(Prerequisites)部分。 target … : prerequisites … recipe … … 就是说这个Target-specific变量的值仅在recipe中有效。 2. 除错的方法 用warning 函数,比如$(warning msg)。它可以出现在各个部分: 目标, 依赖,recipe,顶级变量, 都行 (参见[2]): $(warning A top-level warning) FOO := $(warning Right-hand side of a simple variable)bar BAZ = $(warning Right-hand side of a recursive […]

Dec 292015
 

解决一个奇怪的网络连接错误 Solve a strange network problem 我的服务器bunny最近出现了一个奇怪的网络连接错误:只有台式机和服务器能连接到bunny,笔记本就连不上。 假设网络IP如下: A. 服务器bunny:198.215.54.48 10G 网络 B. 服务器: 198.215.54.5 10G 网络 C. 服务器bronco: 129.112.7.169 1G 网络 D. 台式机:129.112.185.246 局域网 E. 笔记本:172.17.157.121 无线网 现在的问题是可以从B, C, D 连接到A,但不能从E连接到A。 解决思路如下: 1. 怀疑E->A的路由有问题 通过traceroute,发现E到A的最后一跳是*,状态是Host unavailable. 但进一步发现E->B,A和B在同一个子网,因此E->A的路由不大可能有问题 2. 检查A的防火墙设置 先关闭所有防火墙,用: ufw disable 但E仍然不能连A 3. 检查A的路由 > route -n Kernel IP routing table Destination Gateway […]

Sep 302015
 

建立SFTP共享账户 Create SFTP share account 做学术的时候往往需要交流数据。目前最安全简便的解决方案是用SFTP传输文件协议。 为此,需要配置Linux服务器,并为学术伙伴建立一个不能登录、只能用SFTP的账号。 下面是步骤: 1. 建立用户组 addgroup –system filetransfer 2. 设定用户目录和相应权限 以用户名username为例: mkdir /home/username mkdir /home/username/data chown root:root /home/username chown username:filetransfer /home/username/data chmod 755 /home/username chmod 700 /home/username/data 权限755可以允许sftp用户登录到其HOME目录/home/username 权限700可以防止上传的数据被其他用户访问 3. 建立用户 useradd -d /home/username -s /usr/lib/sftp-server -M -N -g filetransfer username -d 指定HOME目录 -s 指定登录shell -M 不创建HOME目录 -N 不创建以username为名的 用户组 […]

Aug 122015
 

R的诡异错误 (3) A pitfall in R (3) 下面的代码有两行,第一行计算Genotype的Minor Allele Frequency,第二行计算Weight matrix (用SKAT paper建议的Beta分布的weight)。 下面的代码有问题吗? 粗粗一看,上面的代码的思路是正确的,不过这里有两个坑。 第一个坑是缺失数据(Missing data),如果Genotype矩阵G有缺失数据,那么maf和w都会有缺失的数据; 第二个坑比较难看出来:当G只有一列的时候,maf也会是一个标量(Scalar),同样dbeta函数的返回值是标量。 你可能想diag函数作用在一个标量上,其返回值是一个1×1的矩阵。 但是,diag()的返回的是一个….不确定的结果,看个例子吧: 总之,第二个坑告诉我们,如果dbeta返回的是一个长度为1的数值,别指望w一定是1×1的矩阵。 继续吐槽: diag()这个函数设计的不好用。在R内部,标量就是被实现为长度为1的向量。 在现在的设计下,diag要求使用者同时考虑变量的类型(矩阵,向量,缺失)以及变量的长度和值(向量长度为1且大于等于0,向量长度为1且小于0,向量长度大于1)。 对于一个适应了使用有类型系统的编程语言的程序员,这种要求会增加使用者的脑力负担,同时阅读者在语义上也很容易出现混淆。 我建议的解决方案是:diag(向量)永远输出一个对角线是该向量的矩阵,同时定义一个新函数(可以叫diag_len,类比seq_len;或者叫eye,类比Matlab里的eye函数)专门用来生成单位矩阵。 最后总结一下,我觉得这样写比较

Jul 112015
 

深度学习MNIST数据 Deep learning on MNIST data 最近试了一下Deep Learning算法,在Kaggle的Digit Recognizer排行榜上目前排19名。 简单说说经验。 从工具上讲,建议先用Keras来做原型(代码简单,很容易构建复杂的网络,缺点是太占内存/显存),再用Caffe做更细致的调节(计算快,占内存/显存少,但用起来复杂,比如不支持RMSProp,需要手动把数据分成Training/Testing,要手动用proto buffer来构建神经网络)。此外,用GPU加速是必须的,我观察到GPU速度至少是CPU速度的60倍。 从模型上讲,基本上建立不同的Convolution Network。套路似乎都是重复这个结构:Convolution Layer + ReLU Layer + MaxPooling Layer。模型可以更Deep (层数更多),比如VGG网络,但是代价是参数数量多,计算量太大。对于MNIST这个整理好(Pre-processed)的数据,这些网络的效果很相似,一般默认设置都能达到98%正确率以上(用42k数据训练,28k数据测试)。如果要更好的成绩,基本上需要更多的输入数据(比如把原始的图像上下左右移动),更深的模型(比如增加层数),更多的模型(比如重复5遍,再Ensemble结果),这样一般能稳定达到99%以上的正确率。 目前能达到99.486%正确性的模型是:把已有的42k数据按照80%, 20%的比例分成training,testing数据,然后用Lenet(120 convolution layers [kernel = 5] + ReLU + MaxPooling + 200 convolution layer [kernel = 3] + ReLU + MaxPooling + InnerProduct [param = 200] + InnerProduct [param=10]), 迭代60,000次。然后这个过程重复15次,然后选多数Ensemble。 最后放几个神经网络识别起来费劲的图案供欣赏,还有一个介绍性质的Slides。   […]

Jun 162015
 

不要用C++11特性开发R包 Don’t use C++11 features to develop R packages 这是个教训。在我开发seqminer的时候浪费太多时间了。希望其他人不要重复我的错误。 C++11有不少有意思的特性,但为什么不要在开发R包的时候使用C++11的特性呢(这里指R 3.2)?下面有一些原因。 1. 没有清晰的文档 R对于C++11的支持写的很模糊。你需要看两个文档,Wring R Extensions和R Installation and Administration。 第一个文档提到你需要CXX_STD,第二个文档提到CXX1XFLAGS。这时候你知道应该设置一些变量,但怎么设置?没有文档告诉你。 这里我找到一个方案,可以凑合用。你需要改configure.ac文件。不过你仍会碰到下面提到的第3个问题。 2. 跨平台支持很艰难 当你把包提交到CRAN时,很有可能在Solaris系统上出现编译或运行的错误。 如果你使用了C++11的功能,你可能想在自己安装Solaris试试。 从我的经验来看,Solaris11 + Solaris Studio 12.4环境比较好搭建。 但CRAN上用的是很老的Solaris10 + Solaris Studio 12.3。 如果你想搭建这个系统,你需要从源代码编译R,然后你会发现,编译不了! 我发现blas库无法被链接。因此你在提交R包到CRAN时,最好明确说,我不支持Solaris。 3. 支持Linux系统也会出问题 在Linux系统上,也许gcc的版本很新,可以支持C++11,但如果安装R的时候没有设置C++11需要的一些变量,你还是用不了。 比如Ubuntu系统里, R是用apt安装的,这个版本的R是默认不知道你有没有支持C++11的编译器的。 这就是说,你在开发时使用的R,CRAN上的R都可以安装你的包,但不保证你的用户能安装。 怎么知道你的R是否支持C++11呢?你可以运行“R CMD config”: 然后看一下CXX1X的值, “R CMD config CXX1X”,如果这个值是空的。默认情况下没法编译安装你写的R包(install.packages())。 顺便说一下: CXX1XXPICFLGS是一个笔误,正确的拼写是CXX1XPICFLAGS (不是两个XX) […]

May 242015
 

安装GCC Install GCC 这是我找到的最简单的安装gcc,并且不需要root权限的方法 (https://gcc.gnu.org/wiki/InstallingGCC) 这个方法适用与GCC的多个版本(4.6,4.7,4.8,4.9) 第七行:如果只需要64位编译器,不需要32位的,可以加上–disable-multilib 第八行:可以用-j N参数指定N个进程同时编译

Apr 012015
 

R的诡异错误(2) A pitfall in R R里面的陷阱一个接一个,继上次说的诡异错误,最近我又跌进了另一个坑。 先创造一个叫df的data.frame, 如下所示: 我们统计一下val列在每组(group)的均值: res的结果如下: 困惑的地方来了,res[1,2]显示的是“100”, res[2,2]现实的是“9”, 为什么res[1,2] > res[2,2]的结果是FALSE? R肯定是认为100比9大。这显然是不对的。 那上面哪个地方有陷阱呢?再仔细看一下高亮显示的两行,看出问题了么? 陷阱在于第3-4行,当用c()来构造一个向量时,val被自动从数值型转成字符型。也就是说,存储的是“100”和“9”,不是100和9。 在字符型数值的比较中,“9”是会比“100”大的。因此order输出的是2 1. 从这个坑里爬出来,不由得吐槽一下,R的自动类型转换能减少程序的代码量,但是这种类型转换很容易引入错误。 也就是说R编程时不需要程序员去检查类型,但在底层R会自动的(有时也是自作聪明的)转换类型。 这就要求程序员额外费心考虑类型之间的自动转换,实际上加重了编程的负担。 如果不然,程序员放任R做自动的类型匹配和转换,就可能得到错误的结果,这在科学研究中实在是很危险。 既然R的坑这么多,我想过去试试新出的Julia或者Go语言。可惜现在这些语言都没有很好的支持统计计算,比如Julia目前缺少对缺失数据(missing data)的支持, 比较有希望的NumPy写起来语法繁杂,近期吸引不到大多数的统计学家(统计的用户太少,机器学习的用户多)。 要是能有一种计算工具,可以让统计学家很容易的使用,同时又有较强的类型系统,还能把大多数R包迁移过去,那这种工具必有远大前程。