星期三, 十一月 25, 2015

基于深度LSTM的中文分词

本例尝试的用多层LSTM来玩中文分词,大部分代码和之前的文章是一样的。不一样的就是使用了更复杂的模型,用了多个LSTM叠加在一起。这对于句子这种有时序特征的数据更有帮助。在前面部分的代码是计算了字向量,但是发现是没有太大必要。除了用多层LSTM,后面还尝试了双向LSTM,效果也还可以。

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
view raw deep_lstm.ipynb hosted with ❤ by GitHub

星期二, 十一月 24, 2015

自夸


李舰和我合写的一本书在2015年的7月份上市了,今天来自推一下这本书。此书是面向于初学者,提供宽而浅的导论性质读物。

http://book.douban.com/subject/26576631/

数据科学是将数据转化为行动的艺术,是综合了统计学、计算机科学和领域知识的新兴学科。数据科学与很多传统学科的最大区别在于其为应用而生,因此本书一切从实际应用出发,以R语言为核心工具,介绍了各类分析方法的实现及其在各领域的应用情况。

如果是初学者,可以从“编程篇”开始阅读,了解R语言的基本特点。如果是程序员,在迅速掌握语法后,可以深入研究“模型篇”,学习如何用统计学和其他流行的分析方法来描绘复杂的数据世界。如果关心数据价值的落地,“应用篇”必不负你所望,金融、制药、文本挖掘、社交网络、地理信息、高性能计算、可重复研究,这些最热门的行业和应用领域的案例将会为你带来数据应用的最真实的体验。

本书适用于所有对数据应用感兴趣的读者,也适合作为统计和数据分析的实务操作型课程的教材。

星期六, 十一月 21, 2015

深度学习入门资源索引

深度学习(Deep Learning)属于非常前沿的学科,没有现成的的综合型教材,主要是通过阅读大量论文和代码练习来学习。值得读的经典论文很多,下面介绍的一些教程中多少都有提及,另外就是去google重要文献。代码方面推荐使用python为基础的theano框架,因为它比较偏底层,可以从细节掌握如何构建一个深度学习模块,而且方便结合python在数据领域的其它积累,例如numpy。当然到了生产环境你可以再考虑torch之类的框架。从代码角度切入学习的好处是,理解起来不会像理论切入那么枯燥,可以很快做起一个好玩的东西。当然,最后你还是得补充理论的。下面精选介绍一些本人在学习时遇到的好教程。

1、入门首选:
http://deeplearning.net/tutorial/
该站提供了一系列的theano代码示范,通过研究模仿,就可以学会包括NN/DBN/CNN/RNN在内的大部分主流技术。其中也有很多文献连接以供参考。

2、BP神经网络:
http://neuralnetworksanddeeplearning.com/
第1部分的教程中,神经网格的参数是theano自动求导的,如果想深入了解细节,还得手动推导加代码实现一遍。该教程对BP神经网络的理论细节讲的非常好。

3、理论补充:
http://goodfeli.github.io/dlbook/
该书内容比较广泛,虽未最终完成,但已初见气象。用来完善理论知识是再好不过。

4、图像处理中的卷积神经网络:
http://vision.stanford.edu/teaching/cs231n/syllabus.html
前面三部分相当于导论,比较宽泛一些,该教程则是专注于卷积神经网络在图像视觉领域的运用,CNN方面知识由此深入。

5、自然语言处理中的深度学习:
http://cs224d.stanford.edu/
本教程则偏重于深度学习在自然语言处理领域的运用,词向量等方面知识由此深入。

6、递归神经网络:
http://www.wildml.com/
该博客讲的RNN是非常棒的系列,不可不读。

7、keras框架:
http://keras.io/
keras框架是基于theano的上层框架,容易快速出原型,网站中提供的大量实例也是非常难得的研究资料。

8、深度学习和NLP
https://github.com/nreimers/deeplearning4nlp-tutorial/tree/master/2015-10_Lecture
该教程是第5部分的补充,理论讲的不多,theano和keras代码讲的很多,附带的代码笔记很有参考价值。

9、机器学习教程
https://www.cs.ox.ac.uk/people/nando.defreitas/machinelearning/
牛津大学的机器学习课程,讲到了大量深度学习和强化学习的内容,适合于复习过一遍。

10、搭建硬件平台
http://xccds1977.blogspot.com/2015/10/blog-post.html
到这里,你的理论和代码功力应该差不多入门了,可以组个GPU机器来大干一场了。可以参考笔者这个博客来攒个机器。

11、去kaggle实战玩玩吧
http://www.kaggle.com/

12、最后补充一个比较新的资源,udacity上的一门深度学习公开课
https://www.udacity.com/course/deep-learning--ud730

星期四, 十一月 19, 2015

使用深度学习库keras做文本分类

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
view raw keras_cnn.ipynb hosted with ❤ by GitHub

星期六, 十月 17, 2015

如何搭建一台深度学习服务器

在计算机时代的早期,一名极客的满足感很大程度上来源于能DIY一台机器。到了深度学习的时代,前面那句话仍然是对的。

缘起
在2013年,MIT科技评论将深度学习列为当年十大科技突破之首。其原因在于,模型有其为庞大的网络结构,参数够多,学习能力够强,能配合大数据达到惊人的效果。而且,能自动学习特征,避免了“特征工程”这种繁琐的手工劳动。对于图像、音频和文字处理领域有极大的意义。因为最近在尝试用深度学习做文本挖掘,所以需要一台深度学习服务器(相信我,如果用CPU来跑,你的人生显得好短)。

那么就有三个选择项:
A、购买组装好的服务器,例如NVIDIA DIGITS DEVBOX
B、购买云服务,例如Amazon的GPU服务
C、自己攒一台深度学习服务器。
A项从性价比上不合算,而且不一定买的到。B项的云服务对于研究探索性质工作而言也比较贵,机器配置也不一定合适,所以我们就C项了。

硬件选择:基本思路是单显卡机器,保留升级空间

显卡选择:
先解释一点,深度学习为什么需要显卡计算?
GPU 是为大规模的并行运算而优化;
GPU 上则更多的是运算单元(整数、浮点的乘加单元,特殊运算单元等等);
GPU 往往拥有更大带宽的显存,因此在大吞吐量的应用中也会有很好的性能。
这里有一个很有趣的解释视频,解释了GPU和CPU的计算区别。

所以显卡选择最重要,因为准备基于CUDA计算(CUDA (Compute Unified Device Architecture) 是NVIDIA开发的GPU并行计算环境。),所以只能选择Nvida系列的。在英伟达产品系列中,有消费领域的GeForce系列,有专业绘图领域的Quadro系列,有高性能计算领域的Tesla系列,如何选择?

有论文研究,太高的精度对于深度学习的错误率是没有提升的,而且大部分的环境框架都只支持单精度,所以双精度浮点计算是不必要,Tesla系列都去掉了。从显卡效能的指标看,CUDA核心数要多,GPU频率要快,显存要大,带宽要高。这样,最新Titan X算是价格便宜量又足的选择。

CPU选择:
在深度学习任务中,CPU并不负责主要任务,单显卡计算时只有一个核心达到100%负荷,所以CPU的核心数量和显卡数量一致即可,太多没有必要,但是处理PCIE的带宽要到40。

主板选择:
需要支持X99架构,支持PCIe3.0,还要支持4通道DDR4内存架构。如果要搞四显卡并行,PCIE带宽支持要达到40,并且支持4-Way NVIDA SLI技术。

内存:
达到显存的二倍即可,当然有钱的话越大越好。

电源问题:一个显卡的功率接近300W,四显卡建议电源在1500W以上,为了以后扩展,选择了1600W的电源。

机箱散热:
因为各种部件相当庞大,需要有良好散热功能的大机箱,选择了Tt Thermaltake Core V51机箱,标配3个12cm风扇。未来如果需要还可以加装水冷设备。

以上就是主要硬件环境的选择和安装。

软件环境安装:

主要安装了Ubuntu系统,CUDA环境,以及theano、keras环境

1、安装ubuntu 14.04(不要安装麒麟版本)
通过官网下载iso文件刻录U盘安装,在SSD硬盘上自动安装完成。
2、安装cuda 7.5 deb文件(自带显卡驱动)
2.1 获取CUDA安装包,在NVidia官网下载local deb文件。
2.2执行如下命令安装:
    $ sudo dpkg -i cuda-repo-ubuntu1410-7-0-local_7.0-28_amd64.deb
    $ sudo apt-get update
    $ sudo apt-get install cuda
2.3设置环境变量:sudo gedit /etc/profile
    $ export PATH=/usr/local/cuda-7.5/bin:$PATH
    $ export LD_LIBRARY_PATH=/usr/local/cuda-7.5/lib64:$LD_LIBRARY_PATH
2.4重启机器:用其中一个样例进行验证测试
    $ cuda-install-samples-7.5.sh ~
    $ cd ~/NVIDIA_CUDA-Samples_7.5/5_Simulations/nbody
    $ make
    $ ./nbody
    或者在sample目录中make测试项目1_utility,再运行./deviceQuery

3、安装python以及theano工具
3.1 直接下载安装anaconda套件64位版本。
    下载后用conda升级到最新。anaconda自带openblas,使numpy和theano计算能达到最大效能
3.2 修改了theano配置文件,使之缺省由gpu运算
在主目录下新建.theanorc文件
.theanorc中输入下面的内容
[cuda]
root=/usr/local/cuda/bin/
[global]
floatX = float32
device = gpu0
[nvcc]
fastmath = True
3.3 安装完成后参考如下地址进行测试
THEANO_FLAGS=floatX=float32,device=gpu python `python -c "import os, theano; print os.path.dirname(theano.__file__)"`/misc/check_blas.py
3.4 安装keras
    通过anaconda安装pip install keras
    注意keras依赖的theano是dev版本的,需要从github下源码来安装。注意本系统此时有两个python,所以要写路径
    sudo /home/user/anaconda/bin/python setup.py develop

4、设置远程服务器调用
4.1 安装ssh,启动服务
4.2 设置notebook server
在ipython中如下命令设置密码:
from IPython.lib import passwd
passwd()
记下生成的字符串。
创建一个ipython配置文件,比如起名叫myserver
ipython profile create myserver
vim ~/.ipython/profile_myserver/ipython_notebook_config.py
编辑文件,加入下面几项:
c = get_config()
c.IPKernelApp.pylab = 'inline' #启动inline模式
c.NotebookApp.ip = '*'
c.NotebookApp.open_browser = False
c.NotebookApp.password = u'sha1:yourhashedpassword'  #把第二步的密码考进来
c.NotebookApp.port = 6868   #自己设一个端口号
启动服务
ipython notebook --profile=myserver

4.3 远程浏览器调用
远程中浏览器登陆http://192.168.3.31:6868/,输入密码,即可进入ipython notebook。
如果需要保持连接,则
nohup ipython notebook --profile=myserver
杀掉连接
lsof nohup.out
kill -9 "PID"

完工!

最后的硬件配置:
CPU: Intel X99平台 i7 5960K
内存: DDR4 2800 32G(8G*4)
主板: GIGABYTE X99-UD4
显卡: GTX Titan X
硬盘: SSD+普通硬盘

系统和软件
操作系统: Ubuntu 14.04.3 x64
CUDA: 7.5
Anaconda 2.3
Theano 7.0
Keras 2.0

参考资料:
http://timdettmers.com/2014/08/14/which-gpu-for-deep-learning/
http://timdettmers.com/2015/03/09/deep-learning-hardware-guide/
http://graphific.github.io/posts/running-a-deep-learning-dream-machine/
http://docs.nvidia.com/cuda/cuda-quick-start-guide/index.html#ubuntu-x86_64-deb
http://deeplearning.net/software/theano/tutorial/using_gpu.html#cuda

之前网上找到另一种安装theano方式是自行安装组件。但尝试未成功,有可能是因为CPU等硬件不同,可能需要自行编译安装openblas,numpy, scipy, theano等环境,极为繁琐。最后还是直接用Anaconda方便。

星期四, 八月 27, 2015

基于深度学习的中文分词尝试

最近折腾deeplearning和NLP比较多,其实就是在看Stanford的cs224d课程啦。抽空尝试了一下使用词向量和神经网络做中文分词。

使用的数据是参考资料中的中文分词资源,即Bakeoff中微软研究院的中文语料库,它的训练文本带有每个字的标注(BEMS),同时带有测试文本和测试脚本。此外使用了补充的语料库,即sogou新闻语料库,不带字标注,但可用来学习字向量。

使用的工具是python中的gensim库和keras库,gensim可用于学习词向量,keras是基于theano的深度学习库。在本例中只使用了普通的MLP方法。

整体工作的步骤如下:
- 步骤1:使用sogou的语料库建立初始的字向量,向量维度为100,迭代50次。
- 步骤2:读入有标注的训练语料库,处理成keras需要的数据格式。
- 步骤3:根据训练数据建模,使用左右各3个字做为上下文,7*100个神经元为输入层,隐藏层为100,输出层为4,神经网络结构为[700->100->4],总共进行了约50次迭代。
- 步骤4:读入无标注的测试语料库,用训练得到的神经网络进行分词标注
- 步骤5:使用自动脚本检查最终的效果

最终测试脚本输出的summary如下,F值为0.913。
=== SUMMARY:
=== TOTAL INSERTIONS: 2872
=== TOTAL DELETIONS: 2896
=== TOTAL SUBSTITUTIONS: 6444
=== TOTAL NCHANGE: 12212
=== TOTAL TRUE WORD COUNT: 106873
=== TOTAL TEST WORD COUNT: 106849
=== TOTAL TRUE WORDS RECALL: 0.913
=== TOTAL TEST WORDS PRECISION: 0.913
=== F MEASURE: 0.913
=== OOV Rate: 0.026
=== OOV Recall Rate: 0.673
=== IV Recall Rate: 0.919

具体代码可以参见github

后续折腾畅想:
- 本例中带标注的语料库相当大,可以直接在这个上面先训练字向量试试。
- 有空时还可以测试下jieba分词的效果评估。
- 用RNN等其它的方法试试效果。

参考资料:
[中文分词资源]
[中文分词标注法]
[word2vec原理]
[基于word2vec的中文分词]

星期五, 五月 22, 2015

使用word2vec进行文本分类

用代码来理解boosting方法

提升方法是集成学习中预测能力最强的一种方法。在R和Python中都有相应的扩展库和丰富的函数。不过对于初学者来讲,理解这种方法不是很容易。本文基于R的决策树包实现两种基本的提升树,即回归提升树和分类提升树。有助于理解提升方法的原理,以及各项参数的作用。公式推导可以见这篇文章

# Learn Gradient Boosting Model by coding
# good slide
# http://www.ccs.neu.edu/home/vip/teach/MLcourse/4_boosting/slides/gradient_boosting.pdf
# http://cran.r-project.org/web/packages/gbm/gbm.pdf
#1 Gradient Boosting for Regression
# generate data
generate_func = function(n=1000,size=0.5){
# n: how many data points
# size: hold 50% of all data as train
set.seed(1)
x = seq(0,2*pi,length=n) # generate x
noise = rnorm(n,0,0.3)
y = sin(x) + noise # generate y
select_index = sample(1:n,size=size*n,replace = F)
# split data into train and test
train_x = x[select_index]
train_y = y[select_index]
test_x = x[-select_index]
test_y = y[-select_index]
data = list('train_x'=train_x,
'train_y'=train_y,
'test_x'=test_x,
'test_y'=test_y)
return(data)
}
data = generate_func()
objects(data)
# train boosting regression tree
GBR = function(x,y,rate=1,iter=100){
# iter is iterate number, higher is better, but be carefule overfit.
# rate is learning speed, lower is better, but too slow will cause longer time.
library(rpart)
max_depth=1 # tree stump
mu = mean(y) # start with an initial model
dy = y - mu # residuals or error, These are the parts that existing model cannot do well.
learner = list() # define a learners holder
for (i in 1:iter) {
# use a weak model to improve
learner[[i]] = rpart(dy~x, # error is target variable
control=rpart.control(maxdepth=max_depth,cp=0)) # cp=0 means to growth a tree with any cost
# modify residuals for next iter
dy = dy - rate*predict(learner[[i]])
}
result = list('learner'=learner,
'rate'=rate,
'iter'=iter)
return(result)
}
model = GBR(data$train_x,data$train_y,iter=1000)
objects(model)
# predict function
predict_GBR = function(x,y,model){
predict_y = list() # hold predict result
mu = mean(y) # initial model
n = length(y)
iter = model$iter
rate = model$rate
predict_y[[1]] = rep(mu,n)
learner = model$learner
for (i in 2:iter) {
# add pre-model prediction to predict y
predict_y[[i]] = predict_y[[i-1]] + rate * predict(learner[[i-1]],newdata=data.frame(x))
}
# mean sqare error
mse = sapply(predict_y,function(pre_y) round(mean((y-pre_y)^2),3))
result = list('predict_y'=predict_y,
'mse'= mse)
return(result)
}
# predict train data
predict_train = predict_GBR(data$train_x,data$train_y,model=model)
objects(predict_train)
# more trees get less error
plot(predict_train$mse,type='l')
# plot the effect of boosing tree
plotfunc = function(x,y,predict,num){
library(ggplot2)
pre = predict$predict_y[[num]]
plotdf = data.frame(x=x,y=y,pre = pre)
mse = round(mean((y-pre)^2),3)
p = ggplot(plotdf,aes(x,y)) +
geom_point(alpha=0.5)
p = p + geom_line(aes(x,pre)) + xlab(paste0('mse=',mse))
plot(p)
}
# use mean of y to predict data
plotfunc(data$train_x,data$train_y,predict_train,num=1)
# add another tree model
plotfunc(data$train_x,data$train_y,predict_train,num=2)
# add more tree getter more result
plotfunc(data$train_x,data$train_y,predict_train,num=10)
plotfunc(data$train_x,data$train_y,predict_train,num=100)
# predict test data
predict_test = predict_GBR(data$test_x,data$test_y,model=model)
plot(predict_test$mse,type='l')
plotfunc(data$test_x,data$test_y,predict_test,10)
plotfunc(data$test_x,data$test_y,predict_test,100)
# compare different parametter
# create 2 models with different rate
model_1 = GBR(data$train_x,data$train_y,rate=1,iter=500)
model_2 = GBR(data$train_x,data$train_y,rate=0.1,iter=500)
# use train and test data, we have 4 results
predict_train_1 = predict_GBR(data$train_x,data$train_y,model=model_1)
predict_train_2 = predict_GBR(data$train_x,data$train_y,model=model_2)
predict_test_1 = predict_GBR(data$test_x,data$test_y,model=model_1)
predict_test_2 = predict_GBR(data$test_x,data$test_y,model=model_2)
# take out mse of these 4 results
train_error_1 = predict_train_1$mse
train_error_2 = predict_train_2$mse
test_error_1 = predict_test_1$mse
test_error_2 = predict_test_2$mse
iter = 1:model_1$iter
# compare these mse
plotdf = data.frame(iter,train_error_1,test_error_1,train_error_2,test_error_2)
p = ggplot(plotdf)+
geom_line(aes(x=iter,y=train_error_1),color='blue')+
geom_line(aes(x=iter,y=test_error_1),color='red') +
geom_line(aes(x=iter,y=train_error_2),linetype=2,color='blue')+
geom_line(aes(x=iter,y=test_error_2),linetype=2,color='red')
print(p)
# test error is better model performance.
# less rate is better but need more iter
which.min(train_error_1)
which.min(train_error_2)
which.min(test_error_1)
which.min(test_error_2)
# 2. Gradient Boosting for Classification
# read data
data = subset(iris,Species!='virginica',select = c(1,2,5))
data$y = ifelse(data$Species == 'setosa',1,-1)
data$Species = NULL
names(data)[1:2] = c('x1','x2')
head(data)
p = ggplot(data,aes(x1,x2,color=factor(y)))+
geom_point()
print(p)
# train boosting tree for classification
GBC = function(data,rate=0.1,iter=100){
library(rpart)
max_depth=1
learner = list()
mu = mean(data$y==1)
# start with an initial model
# mu=p(y=1) -> f=w*x = log(mu/(1-mu))
f = log(mu/(1-mu))
data$dy = data$y/(1+exp(data$y*f)) # dy is negtive gradient of log loss funtion
for (i in 1:iter) {
# use a weak model to improve
learner[[i]] = rpart(dy~x1+x2,data=data,
control=rpart.control(maxdepth=max_depth,cp=0))
# improve model
f = f + rate *predict(learner[[i]])
# modify dy
data$dy = data$y/(1+exp(data$y*f))
}
result = list('learner'=learner,
'rate'=rate,
'iter'=iter)
return(result)
}
model = GBC(data,rate=0.1,iter=1000)
objects(model)
# predict function
predict_GBC = function(data,model){
predict_y = list()
mu = mean(data$y==1)
f = log(mu/(1-mu))
n = nrow(data)
iter = model$iter
rate = model$rate
predict_y[[1]] = rep(f,n)
learner = model$learner
for (i in 2:iter) {
predict_y[[i]] = predict_y[[i-1]] + rate *predict(learner[[i-1]],newdata=data)
}
mse = sapply(predict_y,function(pre_y) sum(log(1+exp(-data$y*pre_y)))) # logistic loss function
result = list('predict_y'=predict_y,
'mse'= mse)
return(result)
}
# predict data
predict_train = predict_GBC(data,model=model)
objects(predict_train)
plot(predict_train$mse,type='l')
final = predict_train$predict_y[[1000]]
y_p = 1/(1+exp(-final))
y_pred = ifelse(y_p>0.5,1,-1)
table(data$y, y_pred)
# # plot
plotfunc2 = function(data,num,rate=0.1){
library(ggplot2)
model = GBC(data,rate=rate,iter=num)
predict_train = predict_GBC(data,model=model)
final = predict_train$predict_y[[num]]
y_p = 1/(1+exp(-final))
data$y_pre = ifelse(y_p>0.5,1,-1)
tree_f = sapply(model$learner,function(x){
temp = x$splits
return(row.names(temp)[1])
})
tree_v = sapply(model$learner,function(x){
temp = x$splits
return(temp[1,'index'])
})
x1value = tree_v[tree_f=='x1']
x2value = tree_v[tree_f=='x2']
p = ggplot(data,aes(x=x1,y=x2))
p = p + geom_point(aes(color=factor(y_pre)),size=5) +
geom_point(aes(color=factor(y)),size=3)+
geom_vline(xintercept = x1value,alpha=0.4) +
geom_hline(yintercept = x2value,alpha=0.4) +
scale_colour_brewer(type="seq", palette='Set1') +
theme_bw()
print(p)
}
plotfunc2(data,num=10)
plotfunc2(data,num=20)
plotfunc2(data,num=60)
plotfunc2(data,num=100)
plotfunc2(data,num=1000)
view raw gbm.R hosted with ❤ by GitHub

星期六, 四月 18, 2015

用非负矩阵分解对文本词项矩阵降维

在前年的一个贴子中,谈到了使用奇异值分解来对一个文本词项矩阵进行降维。本文是使用同样的数据,但是使用不同的工具来处理,也就是非负矩阵分解。nmf的好处在于比svd更容易解释,而且自带正则功能。

星期五, 四月 17, 2015

R和python的整合

以前写的一个东西,贴上来给需要的朋友看看。

星期六, 四月 04, 2015

中国政治坐标系数据的一点分析

清明节有点空闲,凑巧又看到一份很有趣的数据,下文是对这份数据的一点点分析结果。

1、数据整理
整体数据并不大,读到R里面首先做了点处理。
- 将选项("强烈同意","同意","反对","强烈反对") 映射为分值(2,1,-1,-2)
- 对出生年份进行转换,计算出在2015年的年龄并分为10个年龄组(0,18,22,25,30,35,40,50,60,70,120)
- 怀疑70岁以上的人可能是乱写的,删除之。
- 将其它字符型也转为数字编号
- 将18岁以下而填写过高学历和过高收入的数据删除。
- 删除有缺失的数据。

2、有趣的发现
这个数据可以做的分析点有很多,我只做了其中一小部分,观察各种题目的相关性如何。因为已经是离散数据了,所以使用了标准化后的互信息来计算变量之间的相关性。这个数字应该是在0-1之间,发现大部分的回答中这个值并不高,多在0.1以下。不过均通过了联列表检验,说明还是存在相关性的。

- 在50个问题中,哪两个问题的回答之间最相关?
发现第3题和第6题的回答相关性最高(0.13)。
[1] "发生重大社会安全事件时.即使认为信息公开会导致骚乱的风险.政府仍应该开放信息传播."
[2] "由高校自主考试招生比全国统一考试招生更好."

- 哪个问题和学历的相关性最高?
第41题相关性较高,得到相关性为0.009
[1] "两个成年人之间自愿的性行为是其自由.无论其婚姻关系为何."

- 哪个问题和年龄的相关性最高?
第35题相关性较高,为0.01。而且这个题目和收入的相关性也是最高的。
[1] "那些关系到国家安全.以及其他重要国计民生的领域.必须全部由国有企业掌控."

- 哪个问题和性别的相关性最高?
第30题相关性较高,为0.077。让人比较惊奇的是,女性回答不给予补贴的比例比男性高。
[1] "改善低收入者生活的首要手段是国家给予财政补贴和扶持."

- 哪些问题和收入有相关性?
这次使用了GBM模型,计算了问题回答对收入的重要性。发现如下三个问题是最重要的。(除了年龄、学历、性别因素之外)
[1] "条件允许的话应该武力统一台湾." (负相关)
[2] "两个成年人之间自愿的性行为是其自由.无论其婚姻关系为何."(正相关)
[3] "国家领导人及开国领袖的形象可以作为文艺作品的丑化对象." (正相关)

3、其它
最后还做了一个总体的分布图。根据出题者的思路,1-20题为政治方面,21-40题为经济方面,41-50题为文化方面,可以计算每个人在这三个方面的平均得分。我尝试将这三个维度进行散点图绘制。基本上是一个略有点扁的圆形。大部分人在中间,少数人在边缘。

当然后续有兴趣的同学也可以继续搞点聚类之类的事。或者是按照不同属性(收入、时间)来看看圆形的变化。以上全部参考代码在此

这份数据除了能了解国人整体的政治观点之外,还有两个奇特的用法。一个是用坐标距离来大致判断两个人是否可以做朋友。还可以用于大致判断某个人未来的收入。所以女性同胞们,千万不要去找那些要武力统一台湾的当自己男朋友。

星期四, 三月 12, 2015

树莓派折腾第一季:建立私人NAS

1、实验条件:

- 树莓派B+
- micro SD卡
- 读卡器
- 无线网卡
- 5V2A电源
- 移动硬盘
- USB hub
- HDMI转VGA
- 显示器
- 键盘
- 鼠标
- Mac book air

2、实验步骤:

- 烧录系统到SD上。
参考官网步骤,但注意读卡器有时会出问题,选择高质量的设备。
- 启动设置Raspbian系统(raspi-config)
设置各种参数,例如ssh enable之类的,方面后面远程登陆。
注意:把locale设置好,否则后面你还得用dpkg-reconfigure locales
- 配置以修正显示的问题
参考地址:http://www.chengxuyuans.com/Windows/61812.html
注意:多次尝试以适合自己的显示器
- 配置无线网卡
参考地址:http://rpi.linux48.com/rpi-wlan.html
http://blog.appdevp.com/archives/188
注意:要买正确的网卡,再设置一下静态网址。
- 进X看是否可以上网了,再试一下ssh, scp之类的。
- 安装samba
参考地址:http://xwlogic.github.io/2014/08/NAS/
注意:先要更新软件源;挂载移动硬盘的时候得有电;设置samba很多参数,得保证可写。
- 设置挂载方式
参考地址:http://blog.sciencenet.cn/blog-430991-692444.html
注意:如果移动硬盘的格式不是linux,而是exfat之类这种,分享出来的没有写权限,用chomd也不能修改,此时需要特别在fstab中设置挂载细节。
- 其它平台登陆服务器
这样就可以在mac book中的finder里登陆这个服务器 smb://192.168.1.10
也可以在安卓手机上使用软件来登陆这个服务器。安卓上好用的软件是ES文件浏览器
- 增加下载工具
  还需要在树莓派上安装一个下载工具,使之变成一个自动下载器。
  参考地址:http://www.linuxidc.com/Linux/2014-02/96269.htm
  注意: 安装aria2还是很方便的,配合百度网盘转aria2的chrom插件更是如虎添翼。

3、实验小结

- 一开始的设备一定要全,后面可以不需要键盘鼠标,只用ssh了。
- X窗口不是很顺滑,机器在终端玩比较好。
- Raspcherry pi cookbook这本书不错。
- 机器自带mathematica这种逆天神器,再配合linux/python。教小孩数学、计算机的确不错。

星期日, 二月 08, 2015

在ipython notebook上运行spark

周末无事,看到了这篇文章。于是照猫画虎尝试了一番,顺便把官网上的文档看了一些。记录以下以备忘。(目前只尝试了spark在单机上的运行)

安装spark
只需要去官网下载预编译好的最新版本即可,然后回来解压
tar -xzf spark-1.2.0-bin-hadoop2.4.tgz
放到自己选定的目录中,加一个软链接
ln -s /srv/spark-1.2.0 /srv/spark
然后设置环境变量,~/.bash_profile or ~/.profile
export SPARK_HOME=/srv/spark
export PATH=$SPARK_HOME/bin:$PATH

之后在终端上运行pyspark应该可以看到欢迎画面了。

设置notebook
为了在ipython notebook中运行spark需要设置一个启动文件。先设置一个profile
ipython profile create spark
在路径下加一个py文件 $HOME/.ipython/profile_spark/startup/00-pyspark-setup.py

文件中放如下内容,注意和自己的目录有关。
import os
import sys
# Configure the environment
if 'SPARK_HOME' not in os.environ:
    os.environ['SPARK_HOME'] = '/srv/spark'
# Create a variable for our root path
SPARK_HOME = os.environ['SPARK_HOME']
# Add the PySpark/py4j to the Python Path
sys.path.insert(0, os.path.join(SPARK_HOME, "python", "build"))
sys.path.insert(0, os.path.join(SPARK_HOME, "python"))

之后在启动notebook时要加一个profile参数
ipython notebook --profile spark

hello world
在notebook中尝试了spark的hello world任务,即word count。
from pyspark import  SparkContext
sc = SparkContext( 'local[4]')
lines = sc.textFile("some.txt")
words = lines.flatMap(lambda line: line.split())
pairs = words.map(lambda s: (s, 1))
counts = pairs.reduceByKey(lambda a, b: a + b)
result = counts.collect()
#counts.saveAsTextFile("wc")

后面有空再去研究如何用spark做数据分析和机器学习。

星期日, 二月 01, 2015

python数据挖掘模型的API部署

前文谈到了如何把一个R语言的挖掘模型进行在线部署,也就是生成一个API。本文则是同样的思路,只不过是来尝试将python的数据挖掘模型部署成一个API。由于python是通用型的编程语言,部署起来方便一些。下面的例子仍是一个简单的模型,用来预测iris种类。在mac系统中完成,使用了python的几个包:

flask 一个轻量级的web框架
flask.ext.restful 快速生成restful api
numpy 数值计算包
pickle 用来保存模型
sklearn 用来建模

只需要四个步骤:

步骤1:建立模型
步骤2:模型写入pickle文件
步骤3:构建一个基于flask的API
步骤4:通过API调用模型

第一步是用sklearn建模。

from sklearn.tree import DecisionTreeClassifier
import pandas as pd
from pickle import dump
df = pd.read_csv('iris.csv')
X = df.ix[:,:4].values
y = df.ix[:,4].values
model = DecisionTreeClassifier()
model.fit(X,y)

第二步是将模型写入到pickle文件中

dump(model, open('model.pickle','wb'))

第三步是构建一个API,写一个server.py文件

from flask import Flask, request
from flask.ext.restful import Resource, Api
import pandas as pd
from pickle import load

app = Flask(__name__)
api = Api(app)
model = load(open('model.pickle','rb'))

class Model(Resource):
    def post(self):
     res = pd.DataFrame(request.json,index=[0]) # df
    res = model.predict(res) # array
    res = res.tolist()[0] # str
    res = {'Species':res} # dict
        return res

api.add_resource(Model, '/')

if __name__ == '__main__':
    app.run(debug=True)

保存好py文件后启用它。
python server.py

API会在如下地址监听
Running on http://127.0.0.1:5000/

第四步是调用这个API。另开一个终端,输入
curl -H "Content-type: application/json"  -X POST http://127.0.0.1:5000/ -d '{"Sepal_Length":4.9,"Sepal_Width":3,"Petal_Length":1.4,"Petal_Width":0.2}'

成功返回
{
    "Species": "virginica"

}
也可以在python中实验。
from requests import post
import json

url = 'http://127.0.0.1:5000'
data = '{"Sepal_Width": 3, "Petal_Width": 0.2, "Sepal_Length": 4.9, "Petal_Length": 1.4}'
headers = {'content-type':'application/json'}
post(url, data=json.dumps(data), headers=headers).json()

上面的代码是用了flask的一个扩展库,如果直接用原生的flask也可以写
from flask import Flask, request, jsonify
import numpy as np
import pandas as pd
from pickle import load

app = Flask(__name__)

model = load(open('model.pickle','rb'))

from flask import Flask, request,json
app = Flask(__name__)

@app.route('/model', methods = ['POST'])
def api_message():
    if request.headers['Content-Type'] == 'application/json':
    res = pd.DataFrame(request.json,index=[0]) # df
    res = model.predict(res) # array
    res = res.tolist()[0] # str
    res = {'Species':res} # dict
        return jsonify(res)
    else:
        return "415 Unsupported Media Type ;)"

if __name__ == '__main__':
    app.run(debug=True)

最后在shell中执行curl测试,那么将是输入json,输出json了
curl -H "Content-type: application/json"  -X POST http://127.0.0.1:5000/model -d '{"Sepal_Length":4.9,"Sepal_Width":3,"Petal_Length":1.4,"Petal_Width":0.2}'

星期六, 一月 31, 2015

基于opencpu构建R语言的RESTful API

一个R语言模型的落地应用有几种方式:可能是一个简单的分析报告,可能是将预测结果输出到数据库,即离线模型,也可能需要实时读入数据进行实时预测输出。第三种情况是最有用,也最难处理的情况。因为要把R和其它通用型语言进行整合并不容易。例如使用Rserve在java中整合R代码就需要开发人员即懂java也懂R,开发量会比较高。一种比较好的思路是将R计算部分作为一个API,其它语言时通过API来调用R的部分。

下面的例子就是一个很简单的预测iris种类。在mac系统中,基于opencpu框架完成,opencpu能将R语言的对象转为http的资源,极大的方便了R语言模型的部署。一共只需要四个步骤。

步骤1:建立模型
步骤2:模型写入R包
步骤3:将R包安装到opencpu服务器上
步骤4:通过API远程调用模型

第一步是R语言建模。
library(rpart)
m = rpart(Species~., data = iris)
save(m, file='model.rda')
模型保存为一个rda文件在硬盘上。

第二步是写一个R包,如今用rstudio写一个R包是非常简单的事了,建立好一个新项目test之后,在R代码中写入预测函数如下。
library(rpart)
predfunc = function(input){
  input = as.data.frame(input)
  result = predict.rpart(m,newdata = input,type='class')
  as.character(result)
}
可以在R里面验证一下函数是否正常。
newx = data.frame(Sepal.Length=5.1,
                  Sepal.Width=3.5,
                  Petal.Length=1.4,
                  Petal.Width=0.2)
predfunc(newx)
然后新建一个data目录,将rda文件放入目录中,build&reload去建立这个名为test的R包。

第三步是安装R包到opencpu服务器上,我事先在本机上安装了opencpu,只需要像安装普通R包一样安装即可。
install.packages(opencpu)
这样在第二步reload时就直接安装好了test的R包。

第四步是实验API调用是否成功。在终端里进R,调用opencpu,即library(opencpu)会自动启动服务,并显示
[httpuv] http://localhost:4678/ocpu
OpenCPU single-user server ready.

调用模型时,用curl实验即可。另开一个终端,输入
curl http://localhost:4678/ocpu/library/test/R/predfunc/json -H "Content-Type: application/json" -d '{"input" :[ {"Sepal.Length":1.1, "Sepal.Width" : 2.5, "Petal.Length":0.4, "Petal.Width":0.9}]}'

成功返回
[
    "setosa"
]

如果需要把这个模型提供给远程调用,需要安装服务器版本的opencpu。具体参见https://www.opencpu.org/posts/scoring-engine/