2016-08-09 12 views
0

イムかなり確信してイム:のpython - 収量不適切な使用法が不適切利回りを使用して

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

import logging 
from gensim import corpora, models, similarities 
from collections import defaultdict 
from pprint import pprint # pretty-printer 
from six import iteritems 
import openpyxl 
import string 
from operator import itemgetter 

logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO) 

#Creating a stoplist from file 
with open('stop-word-list.txt') as f: 
    stoplist = [x.strip('\n') for x in f.readlines()] 

corpusFileName = 'content_sample_en.xlsx' 
corpusSheetName = 'content_sample_en' 

class MyCorpus(object): 
    def __iter__(self): 
     wb = openpyxl.load_workbook(corpusFileName) 
     sheet = wb.get_sheet_by_name(corpusSheetName) 
     for i in range(1, (sheet.max_row+1)/2): 
      title = str(sheet.cell(row = i, column = 4).value.encode('utf-8')) 
      summary = str(sheet.cell(row = i, column = 5).value.encode('utf-8')) 
      content = str(sheet.cell(row = i, column = 10).value.encode('utf-8')) 
      yield reBuildDoc("{} {} {}".format(title, summary, content)) 


def removeUnwantedPunctuations(doc): 
    "change all (/, \, <, >) into ' ' " 
    newDoc = "" 
    for l in doc: 
     if l == "<" or l == ">" or l == "/" or l == "\\": 
      newDoc += " " 
     else: 
      newDoc += l 
    return newDoc 

def reBuildDoc(doc): 
    """ 
    :param doc: 
    :return: document after being dissected to our needs. 
    """ 
    doc = removeUnwantedPunctuations(doc).lower().translate(None, string.punctuation) 
    newDoc = [word for word in doc.split() if word not in stoplist] 
    return newDoc 

corpus = MyCorpus() 

tfidf = models.TfidfModel(corpus, normalize=True) 

次の例では、あなたがXLSXファイルからコーパスを作成しようとしている私を見ることができます。 Imは、xlsxファイルから、タイトルの要約と内容である3行を読み込み、それらを大きな文字列に追加します。私のreBuildDoc()removeUnwantedPunctuations()関数は、その後、私のニーズに合わせてテキストを調整し、最後に大きな単語リストを返します。 (例のために:[hello, piano, computer, etc... ])最後に、私は結果をもたらすが、私は次のエラーを取得する:

Traceback (most recent call last): 
    File "C:/Users/Eran/PycharmProjects/tfidf/docproc.py", line 101, in <module> 
    tfidf = models.TfidfModel(corpus, normalize=True) 
    File "C:\Anaconda2\lib\site-packages\gensim-0.13.1-py2.7-win-amd64.egg\gensim\models\tfidfmodel.py", line 96, in __init__ 
    self.initialize(corpus) 
    File "C:\Anaconda2\lib\site-packages\gensim-0.13.1-py2.7-win-amd64.egg\gensim\models\tfidfmodel.py", line 119, in initialize 
    for termid, _ in bow: 
ValueError: too many values to unpack 

私は私が働いていた別の歩留まりのラインを持っていたため、エラーが降伏ラインから知っています。それはこのように見えた:

yield [word for word in dictionary.doc2bow("{} {} {}".format(title, summary, content).lower().translate(None, string.punctuation).split()) if word not in stoplist] 

あなたが最初の例で見ることができるように私はそれを変更したので、それにfunctionallityを置くためにABIT厄介で大変でした。

+0

サイドノート: 'removeUnwantedPunctuations'は非常に効率的に実装されていません。とにかく結果に' translate'コールを実行しているためです。あなたのコード 'unwanted_to_space、deletepunc = string.maketrans(r '\/<>'、 '')、string.punctuation.translate(None、r '\/<>')'の最上位レベルで、 'doc = doc.translate(unwanted_to_space、deletepunc).lower()'に 'doc = removeUnwantedPunctuations(doc).lower()。translate(None、string.punctuation)'を変更してください。シンプルなテストでは、実行時間が〜10-15倍に短縮されます。 – ShadowRanger

+0

また、 'string.maketrans(r '\/<>' + string.ascii_uppercase、 '+ string.ascii_lowercase)'で 'unwanted_to_space'を作ることでさらに多くの節約ができます(表示されていなければ、 'lower'への呼び出しを省略することができます(入力がASCIIでない場合は、' lower'を真にしたいが、ASCIIの 'str'に対しては、第二引数を導く文字列)。 'translate'コールは同等で無料です)、実行時に20倍以上節約できます。明らかに、あなたの入力が小さい場合、節約は重要ではありませんが、大きなデータの場合、入力を解析することは大きなコストになる可能性があります。 – ShadowRanger

答えて

1

問題は、それ自体yieldではないが、得られたされたもので、エラーがfor termid, _ in bowからこのラインはあなたがbowはタプルのリストや(1,2),[1,2],"12",...などのそれとまったく2の元素を含有する他のオブジェクトが含まれていることを期待していると言われましたそれにしたがって、明らかに2つ以上の要素を持つ文字列、エラーであるMyCorpusの結果を与える終わり、これが行う修正するfor termid in bowまたはMyCorpusのいずれかで行うyield reBuildDoc("{} {} {}".format(title, summary, content)), Noneので、このチェックを説明するために2オブジェクト

のタプルをもたらしますこの例

>>> def fun(obj): 
     for _ in range(2): 
      yield obj 


>>> for a,b in fun("xyz"): 
     print(a,b) 


Traceback (most recent call last): 
    File "<pyshell#11>", line 1, in <module> 
    for a,b in fun("xyz"): 
ValueError: too many values to unpack (expected 2) 
>>> for a,b in fun("xy"): 
     print(a,b) 


x y 
x y 
>>> for a,b in fun(("xy",None)): 
     print(a,b) 


xy None 
xy None 
>>> 
+0

あなたは正しいです、問題は他の機能にありました。ドキュメントを作成する前にdictionary.doc2bowをドキュメントに配置する必要がありました。あなたが書いたように、それはタプルを受け入れます。ありがとう! –

+1

この回答は最終的な症状の直接の原因を説明していますが、実際の解決策は単に「偽の第2要素を追加する」ことではなく、真の原因ははるかに高いレベルです。 'TfidfModel'は特定の形式で入力する必要があり、偽の第2要素を追加してもコードは動作しません。 – ShadowRanger

1

あなたの問題はTfidfModeldoc2bow出力(自分自身の二tuple秒のlist秒)のlistあるcorpusを期待していることであるように見えます。元の作業コードdoc2bowをプレーン文字列からコーパス形式に正しく変換するために、新しいコードが生の文字列で渡されます。TfidfModelの期待通りの "ベクトル"ではありません。

doc2bowread the tutorial on converting string to vectorsを使用すると、生の文字列が入力として無意味であることがわかります。