Becomin' Charles

算法 | LNMP | Flutter | Mac

Becomin' Charles

故事是这样的,在我的业务模型里,有些东西是常态并且固定化的,比如User,这是一个网站的用户,有一张用户表与其对应。但是有些东西,却不是那么常态,比如我们的网站要经常搞活动,搞活动的时候,临时开发一个功能,加一个表来存储活动数据,日后,活动下线了,这个表也就没有用了,可能会被删除。活动频次非常高,所以不同的开发都会快速地进行开发,于是出现了命名不一致的情况,比如大家都是要关联User(活动跟用户有关,非常自然),在表A中,代表用户的字段叫user_id,表示User的主键,但是在表B里面,因为习惯使然,代表用户的字段叫uid,然后问题就产生了,当表A和表B需要联表查询时候,怎么设置这个relations呢?

阅读全文 »

今天闲着没事,我将手机升级到iOS 8.1后,尝试了下国人出的越狱,据说,这是第一次由中国人率先出品了越狱的版本,盘古。

越狱过程流畅无比,但是看完越狱后的界面,一朵阴云已经浮上我的心头。在越狱的开始界面上,我明显去掉了“支持盘古,安装PP助手”的选项,然而越狱结果页面,赫然安装了PP助手。接着,我开始在Cydia中安装软件,莫名奇妙,突然打开了App Store,是游戏刀塔传奇的页面。

10分钟后,当App Store再次无故启动,定位到携程的页面的时候,我知道,我在自己的手机里,安装了一个巨大的流氓软件,而且还获得了root权限。我还傻傻的使用它的重置OpenSSH密码功能,我重置的任何密码,都会被它知道,不是么?

技术的运用,真的是存乎一心之间。盘古这种丧心病狂的行为,我已经不能多说什么了,你们势必在自取灭亡的道路上越走越远。以这种方式去运用技术来谋取商业利益,我也只能说,我羞于与这样的人为伍。

祝盘古早日倒闭。

我所在的企业,是一家中国知名互联网企业。我的团队,专门从事企业产品的研发。

说起大数据、机器学习,就像老师说的那样,这几个概念,真是一座山峰的不同侧面。其实从学术上看,这些东西难免高深难懂,有很多严谨的数学定义。但是,在企业的实践中,往往并没有那么神秘,也没有多难,我加入课程群,看到很多同学,都是在校学生,所以,我就在这里分享一下,我所在的企业,到底在哪些地方,用怎样的方法,运用了机器学习和数据挖掘。因为我也没有成体系学习过,只是入门选手,我就想到什么说什么了。

阅读全文 »

其实,这个是一类问题,在SVN里面,处理这个问题相对简单和直观,因为SVN的结构简单,只有工作副本和版本库副本两个副本,你要做的事情,无非就是处理工作副本,要么就是处理版本库副本。关于位置的概念,只有两个,工作副本,都是本地镜像,版本库副本,都在中心服务器上。commit能且只能保存在服务器上。回滚,本质上,只有两个情况,一个是没有commit,怎么回滚,一个是已经commit了,怎么回滚。

所以,在SVN中,回滚一个代码,事实上只有一个命令而已。svn revert。不指定版本号作为参数的话,就是放弃未提交的修改,指定版本号的话,就是回滚到指定的版本号(rev),但是实际上已经提交的更改,是不可以抹除的,你只能将一个文件回滚到某个过去的版本,然后重新提交来覆盖之前的变更。

到了Git里面,回滚这个事情,变复杂了。首先,我认为,工作副本的概念没有了,因为去中心化的设计,每个人本地硬盘上拥有的,都直接是版本库副本,没有所谓的本地副本的概念了,所有的人持有的都是版本库本身。就算在研发实践中,设置了中央版本库,但是中央版本库和本地版本库,在逻辑概念上是完全对等的。谁是中央,谁不是中央,其实是人为赋予的抽象地位。

另外一个显著的不同是,Git里的commit,都是直接提交到本地版本库的,这也就是commit速度飞快的原因。

在Git里,回滚这件事情,就一下子多出来好多的情况。

如果是一个人,直接通过git init在本地建立repository,不与任何人协作,有且仅有一个版本库。那么,情况只有两种:

  1. 未提交的变更
  2. 已经提交的变更

第一种情况,可以使用命令 git clean -fd ,来实现直接将所有的未提变化(untracked files)删除,-f的含义是force,强制,-d的意思是未提交的目录和文件都删除。

第二种情况,在单人开发的时候,也比较简单。很多处理方法,比如完全抹去这个commit(这在SVN里是做不到的),就像历史上从未发生过此事一样。要做到这一点,估计有好多种做法,但是我只掌握了一种,就是使用 git rebase -i HEAD2,这个命令的含义本身不是干这个事情的,只是我碰巧发现这么可以。-i的含义是interact,交互式,HEAD2的含义是,从最新的提交开始,显示两次提交的内容,然后你会在编辑页面看到两行提交的log,旧的在上面,新的在下面。如果你需要完全抹去最新的提交,就把下面的那行给删掉就行了。

这种情况下,根据我的实践经验来看,如果是一系列提交,要抹去中间的某个提交,十有八九不会顺利成功,原因也很简单,比如某a文件,你提交了10次,然后你想抹去第6次提交,那么git将极有可能不知道原来的第7次到第10次提交,应该怎么作用在a文件上,这时候,rebase过程被打断,你要手动处理冲突,才能完成任务。但是我想,一般我们不会干这种事情,因为,多数情况下,我们需要处理的都是最新几次连续的提交,比如想都放弃掉。

如果是跟他人协作开发的话,比如有一个管理员,设置了一个中央版本库,然后大家都以中央版本库的代码为基准,事情就将变得更加复杂一点,在上述两种情况之外,又会多出一些情况:

  1. 已经提交了,但是没有push到中央版本库
  2. 已经提交了,但是已经push到中央版本库

第一种情况,跟单人开发时候,第二种情况处理方法一样的。但是,你要非常小心的确认这件事情。该commit确实没有被push过。这种情况下,你甚至可以抹掉该commit,或者合并几个同样没有push的commit,都行。

第二种情况,你就要非常谨慎了。因为即使已经push过了,git不会阻止试图抹掉一个commit的行为,也不会阻止试图合并一些commit的行为。但是,你可能为此付出非常惨痛的代价,光是merge,就能累死你。这种情况下,我的建议,就是根本不要尝试去做。老老实实去checkout一个你认为没问题的版本,通过diff工具,将你想删掉的变更去掉,然后将这个作为一个新的commit附加到历史的洪流中。

如果你正在斯坦福、Coursera或者可汗学院学习在线课程,那么这种开始方式,已经很好了。

你可能还需要尽可能多地去学习数学(包括统计),因为数学是机器学习的基础。

我非常推荐的一本书是Programming Collective Intelligence。这本书的数学很浅,只需要基本理解Python就可以通读此书而没有什么障碍。如果你已经在学习大学级别的机器学习课程,你可能会觉得这本书对你来说太过基础了一点。

Programming Collective Intelligence: Building Smart Web 2.0 Applications: Toby Segaran

对于一些更高级的话题,你可以试试如下的书,基本按照需要数学知识的多少来排序:

Amazon.com: Risk Assessment and Decision Analysis with Bayesian Networks (9781439809105): Norman Fenton, Martin Neil: Books

Artificial Intelligence: A Modern Approach (3rd Edition): Stuart Russell, Peter Norvig: 9780136042594: Amazon.com: Books

Learning Bayesian Networks: Richard E. Neapolitan: 9780130125347: Amazon.com: BooksEdit

Quoar原帖

Updated:

另一个回帖的人,认为学习Machine Learning没那么简单,并提出该学科是一个高度交叉学科,想要深入,需要准备好很多先修课程的知识,包括但是不限于:

  1. 微积分。最好所有的知识都具备,极限(Limits),differentiation,integration。
  2. 线性代数。甚至要理解最简单的回归模型,都需要它的知识。通常是机器学习课程最先教的东西。
  3. 统计学。超级重要。机器学习其实是一族统计分析的方法,所以它是在统计学的根基上发展起来的。对所有的统计分析方法,有一个很好的掌握,是绝对必须的。
  4. 计算机科学基本知识。具体说,算法,包括数值算法(从牛顿法,到蒙特卡洛模拟技术)。这与机器学习在很多地方是重合的,而且经常被用于机器学习的一些基础算法。
  5. 编程。机器学习是一个应用学科,你需要掌握一门编程语言来运行算法。Python学习简单,在机器学习专家中,应用广泛。

想要把丢掉的东西捡起来,还是很辛苦啊,今天我就发现,我连char* 和 char []的区别都不知道。

1
2
3
4
5
6
7
8
9
10
11

#include

int main(int argc, char* argv[]) {
char* buf1 = "this is a test";
char buf2[] = "this is a test";
printf("size of buf1: %d\n", sizeof(buf1));
printf("size of buf2: %d\n", sizeof(buf2));
return 0;
}

结果是:

1
2
3
4
5

$ > ./main
size of buf1: 4
size of buf2: 15

购买了Linode的同学,一般都会在Linode上安装部署各类技术解决方案,解决程序员的信息查找和咨询访问问题。这类方案里,本人首推使用shadowsocks,简单、轻量、稳定易用。但是在某些特殊的场合,非VPN不能解决问题。在各式各类的VPN方案里,我首推L2TP over IPSec,协议加密,内容加密,给未来还是要留个出路的,不然都被扫出来封掉,那太悲催了,我不忍细想。

如果安装的的Debian系统,那么整个部署流程会很方便愉快,但是最近这个问题,困扰我将近半年之久了,就是这个突然不工作了,多方查找才知道,是openswan版本存在bug,导致不兼容,致使L2TP over IPSec的方案无法尽功。有问题的版本如下:

1
2
3
4
5
6
7
8
9
10

# aptitude show openswan
Package: openswan
State: installed
Automatically installed: no
Version: 1:2.6.37-3+deb7u1
Priority: optional
Section: net
Maintainer: Rene Mayrhofer

想要恢复正常也比较简单,降级即可:

1
2
3

# apt-get install openswan=1:2.6.37-3

将openswan的版本降级后,重启IPSec,一切恢复了正常,世界清净了!

如果购买Linode,可以考虑使用我的referral code,算是对我的支持,谢谢:f268347f24b5221e45c9a1048cb8b8db0f0c241a

在Mac上,管理命令行软件包,使用Homebrew,它的原理主要就是将软件安装在一个固定的目录,然后将二进制文件的路径,加入到系统的PATH中,
这样,系统就可以正确识别到命令。PATH的顺序会影响到系统搜索命令的顺序。

brew使用的/usr/local/bin默认已经在Mac系统的PATH里了,但是在最后面。通过 echo $PATH命令可以查看。

但是对于想要使用新版本的人来说,这就不方便了。所以,就要想办法调整PATH的顺序。

sudo vi /etc/paths

就可以在里面调整PATH的搜索顺序了,这个我特意去Linux系统里看了一下,不是这样的,看来是Mac系统特有的。
一般在Linux系统里调整PATH顺序都是在 .bash_profile或者 .bashrc里面,执行

export PATH=/usr/local/bin:$PATH