2014-10-12 58 views
1

我正在構建用於SVM的我的詞n-gram訓練矢量。我跑了我的代碼,但花了我太多時間,超過10個小時。你有什麼方法讓它更快?如何讓我的Python代碼更有效?

def wordNgrams(s,n): 
    """Calculate word n-grams and return a dictionary""" 
    input = s.split(' ') 
    output = {} 
    for i in xrange(len(input)-n+1): 
     g = " ".join(input[i:i+n]).lower() 
     output.setdefault(g,0) 
     output[g] += 1 
    return output 

res是10000個字符串的列表,每個字符串平均有300個字。 global_vector是一個200000字2克的排序列表。

X = [] 
for i in xrange(10000): 
    word_dic = wordNgrams(res[i], 2) 
    vector1 = {key : 1 if key in word_dic else 0 for key in global_vector} 
    od = OrderedDict(sorted(vector1.items(), key = lambda t : t[0])) 
    X.append(od.values()) 

說實話,這是常見的,如果它需要2或3小時。但花了我10多個小時。我真的不該做我應該做的。請幫幫我。

+0

這似乎不是很有用。您追加到「X」的值將不會以任何特定順序(字典未排序)。我不確定'0'和'1'的任意排序列表是否適合。你能澄清一下具體的輸出應該是什麼嗎? – Blckknght 2014-10-12 09:00:06

+0

我編輯了這個問題。我想要做的是添加對應於排序詞n-gram列表global_vector的0和1的向量。但花了我10多個小時。你能給我一個更有效的方法嗎? – allenwang 2014-10-12 09:23:24

回答

1

我認爲sorted調用你在循環中運行是唯一可以優化的東西。其他一切看起來都是漸近最佳的(在不同的地方可以通過小因素改善事情,但不是大數量)。

如果您的global_vector已經排序,您可以通過直接創建結果列表來避免排序結果,而不是首先通過無序字典。下面是一個使用列表理解一個快速的版本:

X = [] 
for text in res: 
    word_dic = wordNgrams(text, 2) 
    X.append([1 if bigram in word_dic else 0 for bigram in global_vector]) 

這應該是O(M*N) + O(M*P)其中Mres長度,Nglobal_vector長度和P是文本的平均長度。由於額外的排序,您的原始代碼在第一學期中包含額外的log(N)因子。

+0

謝謝你的回答。你的意思是我不需要對vector1字典進行排序? – allenwang 2014-10-12 11:19:26

+0

我接受了你的回答。非常感謝你。但是,請你向我解釋爲什麼我不需要對字典vector1進行排序? X中的這些向量與global_vector對應的順序是對應的嗎? – allenwang 2014-10-12 11:58:05

+0

@ wanglan8498:使用字典丟棄了'global_vector'中的順序。但是,你從不真正需要字典。只需直接從一個列表('global_vector')到另一個列表('0和'1列表)。 – Blckknght 2014-10-12 23:23:09