windons 下如何使用c compiler加cython 加速 word2vec!!!

来源:互联网 发布:广电直播软件 编辑:程序博客网 时间:2024/06/05 22:38

先吐槽一下python 的word2ver在windons下是如此的慢,当节点数升到百以后会非常慢!加上一直出现这个让人不爽的提示,我用了3天时间去解决这个问题。
由于网上这个资料一直很少,所以现在集合这个帖子来做一下笔记!

第一节:

你要有python27,cython,numpy,scipy,gensim还有vs2010或vs2008,编辑器(eclipse)

接下来先让我们运行一个简单的程序:
这里写图片描述

如果是正常的话会爆下面烦人的提示:
这里写图片描述

嘿嘿,可能很多同学都知道这句话是叫你调用c来运行程序,提高速度,但是很多人都不知道是怎么解决,不用怕,现在一 一道来
b( ̄▽ ̄)d:

第二节:

先介绍一下cython的原理,cython其实说来不是一般的包。它有自己的格式跟语法, 兼容了c和python 的类型和格式。作用就是用cython改写一个要升速的py文件,再通过cy去编译。下面说一下如何用cython使一个python程序加速:
c1.py:

import mathdef great_circle(lon1,lat1,lon2,lat2):    radius = 3956 #miles    x = math.pi/180.0    a = (90.0-lat1)*(x)    b = (90.0-lat2)*(x)    theta = (lon2-lon1)*(x)    c = math.acos((math.cos(a)*math.cos(b)) +                  (math.sin(a)*math.sin(b)*math.cos(theta)))    return radius*c

这是计算沿地球表面两点之间的距离的问题。下面调用 10000000次来看一下时间:

import timeit  lon1, lat1, lon2, lat2 = -72.345, 34.323, -61.823, 54.826num = 10000000t = timeit.Timer("time1.great_circle(%f,%f,%f,%f)" % (lon1,lat1,lon2,lat2),                       "import time1")print "Pure python function", t.timeit(num), "sec"

一共是17.7秒,天哪这是多么宝贵的时间啊!
下面我们用cython格式重写它:
c2.pyx:

import mathdef great_circle(float lon1,float lat1,float lon2,float lat2):    cdef float radius = 3956.0    cdef float pi = 3.14159265    cdef float x = pi/180.0    cdef float a,b,theta,c    a = (90.0-lat1)*(x)    b = (90.0-lat2)*(x)    theta = (lon2-lon1)*(x)    c = math.acos((math.cos(a)*math.cos(b)) + (math.sin(a)*math.sin(b)*math.cos(theta)))    return radius*c

这是用cython格式写的pyx文件!!!!没错后缀是pyx!!~^_^~

然后再写一个setup.py文件,这个是用来编译上面的pyx文件成C和dll文件的,然后我们调用生成的lib文件就可以实现程序的加速!!!
setup.py:

from distutils.core import setupfrom distutils.extension import Extensionfrom Cython.Build import cythonizesetup(  name = 'cc',  ext_modules=cythonize([    Extension("cc", ["c2.pyx"]),    ]),)

接着在你的vs2010命令窗口cd 你的上面几个文件的路径,输入
python setup.py build
python setup.py install
记住,如果你是vs2010的先输入:SETVS90COMNTOOLS=%VS100COMNTOOLS%
正常如下:
这里写图片描述
这里写图片描述
完成这两步以后,呵呵,恭喜你,你已经在目录生成build文件夹,里面有一个cc.lib文件,直接在python中导入cc模块。
如下:

import timeitlon1, lat1, lon2, lat2 = -72.345, 34.323, -61.823, 54.826num = 10000000t = timeit.Timer("cc.great_circle(%f,%f,%f,%f)" % (lon1,lat1,lon2,lat2),                     "import cc")print "Cython function (still using python math)", t.timeit(num), "sec"

运行时间是10.7秒,他妈的这少了太多时间吧,这也太厉害了吧,天啊!!已经哭晕在厕所好吗~( ̄▽ ̄~)(~ ̄▽ ̄)~

第三节:

有了上面这个例子,相信很多同学都已经知道怎么加速word2vec了,然而这并没有什么卵用,也会有n多错误,在写这篇文章前我还差点不想搞下去了。
W( ̄_ ̄)W

下面简单说说会遇到哪些问题:
1.按照上面写的,我们要找gensim包下面的models的word2vec.pyx,我点进去一看,好吧,没有这个文件倒是有word2vec_inner.pyx,我试着写入一个setup.py,然后cmd python setup.py install,结果一大推错误提示

2.经过一段时间的折腾,我终于发现这个文件是不行的,然后我试着用同样的办法对word2vec.py进行强奸,结果居然出现了奇迹,生成了word2vec.lib这个孩子。

3.欣喜若狂的我以为就可以用上word2vec.lib,但是 不行,它还是提示那句话,我看仔细点原来还要重装一次gensim.

4.好吧,我重装了一次,发现还是出现问题,快哭了………提示如下:
RuntimeError: Broken toolchain: cannot link a simple C program
然后我上网查查了,说在msvc9compiler.py中,把minfo的赋值语句更改为minfo=None,即可。

好了,最后我抱着不成功就成仁的心态,试着重装:python setup.py install,半个小时内cmd应该跑完了,然后我再打开eclipse 运行下面程序,终于没有提示了,哈哈哈╭(′▽)╭(′▽)╯
这里写图片描述

下面试一试,输入5000个句子,神经节点等于500,开8个线程看看速度多快,如下:

#coding:utf-8from time import clockstart=clock()import word2vecimport osimport scipyclass MySentences(object):    def __init__(self, dirname):            self.dirname = dirname           def __iter__(self):             for fname in os.listdir(self.dirname):                    for line in open(os.path.join(self.dirname, fname)):                                yield line.split()sentences = MySentences('C:\da') model =word2vec.Word2Vec(sentences,min_count=20,size=1000,workers=8)print model.similarity('a','one')finish=clock()print '运行时间:','%f'%((finish-start)/10000)

这里写图片描述

简直抑制不住此刻内心的冲动,成就感爆棚有木有啊!妈妈再也不用担心我没有服务器,没有Linux系统了,哇哈哈。

总结:

就是学习有的问题,你已经解决到一半的话,就不要放弃了,还有的就是网上可能有时候会真的出现一点有用的方法,不要不去尝试。多多思考背后的原理。
呜呜~~~不多说了,我要去满足满足自己的成就感。<( ̄︶ ̄)>

0 0
原创粉丝点击