您的位置:首页 > 其它

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

2015-08-23 20:31 459 查看
先吐槽一下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:

[code]import math

def 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次来看一下时间:

[code]import timeit  

lon1, lat1, lon2, lat2 = -72.345, 34.323, -61.823, 54.826
num = 10000000

t = 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:

[code]import math

def 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:

[code]from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

setup(
  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模块。

如下:

[code]import timeit

lon1, lat1, lon2, lat2 = -72.345, 34.323, -61.823, 54.826
num = 10000000

t = 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个线程看看速度多快,如下:

[code]#coding:utf-8
from time import clock
start=clock()
import word2vec
import os
import scipy

class 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系统了,哇哈哈。

总结:

就是学习有的问题,你已经解决到一半的话,就不要放弃了,还有的就是网上可能有时候会真的出现一点有用的方法,不要不去尝试。多多思考背后的原理。

呜呜~~~不多说了,我要去满足满足自己的成就感。<( ̄︶ ̄)>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: