質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.53%

  • Python 3.x

    6301questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • 機械学習

    678questions

    機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

  • 自然言語処理

    116questions

    自然言語処理は、日常的に使用される自然言語をコンピューターに処理させる技術やソフトウェアの総称です。

KeyError: '' が発生している場所がわからない

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,146

TarouKotani

score 32

下記エラーのKeyError: '' が発生している場所がわかりません。
辞書をどこで使っているかがはっきり特定する方法などがわかればと思います。

C:\Users\bluec>python bayes_test.py
2
Traceback (most recent call last):
File "bayes_test.py", line 21, in <module>
pre, scorelist = bf.predict("部品の交換を行いました")
File "C:\Users\bluec\bayes.py", line 60, in predict
score = self.score(words, category)
File "C:\Users\bluec\bayes.py", line 50, in score
score += math.log(self.word_prob(word, category))
File "C:\Users\bluec\bayes.py", line 82, in word_prob
n = self.get_word_count(word, category) + 1 # ---(*6a)
File "C:\Users\bluec\bayes.py", line 69, in get_word_count
if word in self.word_dict[category]:
KeyError: ''

**bayes_test.py**

from bayes import BayesianFilter
import csv

bf = BayesianFilter()
# テキストを学習
data = []
with open('format.csv', 'r', encoding='utf-8') as fp:
    lines = csv.reader(fp)
    for line in lines:
        data.append(line)
print(len(line))
bf.fit(line[0],line[1])
# 予測
pre, scorelist = bf.predict("部品の交換を行いました")
print("結果=", pre)
print(scorelist)

**bayes.py**

import math, sys
from janome.tokenizer import Tokenizer # 形態素解析用

class BayesianFilter:
    """ ベイジアンフィルタ """
    def __init__(self):
        self.words = set() # 出現した単語を全て記録
        self.word_dict = {} # カテゴリごとの単語出現回数を記録
        self.category_dict = {} # カテゴリの出現回数を記録

    # 形態素解析を行う --- (※1)
    def split(self, text):
        result = []
        t = Tokenizer()
        malist = t.tokenize(text)
        for w in malist:
            sf = w.surface   # 区切られた単語そのまま 
            bf = w.base_form # 単語の基本形
            if bf == '' or bf == "*": bf = sf
            result.append(bf)
        return result

    # 単語とカテゴリを数える処理 --- (※2)
    def inc_word(self, word, category):
        # 単語をカテゴリに追加
        if not category in self.word_dict:
            self.word_dict[category] = {}
        if not word in self.word_dict[category]:
            self.word_dict[category][word] = 0
        self.word_dict[category][word] += 1
        self.words.add(word)
    def inc_category(self, category):
        # カテゴリを加算する
        if not category in self.category_dict:
            self.category_dict[category] = 0
        self.category_dict[category] += 1

    # テキストを学習する --- (※3)
    def fit(self, text, category):
        """ テキストの学習 """
        word_list = self.split(text)
        for word in word_list:
            self.inc_word(word, category)
        self.inc_category(category)

    # カテゴリにおける単語リストのスコアを計算する --- (※4)
    def score(self, words, category):
        score = math.log(self.category_prob(category))
        for word in words:
            score += math.log(self.word_prob(word, category))
        return score

    # テキストのカテゴリ分けを行う --- (※5)
    def predict(self, text):
        best_category = None
        max_score = -sys.maxsize 
        words = self.split(text)
        score_list = []
        for category in self.category_dict.keys():
            score = self.score(words, category)
            score_list.append((category, score))
            if score > max_score:
                max_score = score
                best_category = category
        return best_category, score_list

    # カテゴリ内の単語出現数を得る
    def get_word_count(self, word, category):
        if word in self.word_dict[category]:
            return self.word_dict[category][word]
        else:
            return 0

    # カテゴリ/総カテゴリを計算
    def category_prob(self, category):
        sum_categories = sum(self.category_dict.values())
        category_v = self.category_dict[category]
        return category_v / sum_categories

    # カテゴリ内の単語の出現率を計算 --- (※6)
    def word_prob(self, word, category):
        n = self.get_word_count(word, category) + 1 # ---(*6a)
        d = sum(self.word_dict[category].values()) + len(self.words)
        return n / d
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+2

エラーが発生している場所は、メッセージより以下です。

# カテゴリ内の単語出現数を得る
    def get_word_count(self, word, category):
        if word in self.word_dict[category]: # ここ


category = ''であり、キー値(空文字)に対応する値word_dict['']が存在しないのでKeyErrorになっています。

以下のような単純化したコードで考えると理解しやすいかと思います。

word_dict = {'cat1':{'word1':1}}
def get_word_count(word, category):
    words = word_dict[category] # キーに対応する値が存在しなければKeyErrorが発生
    if word in words:
        print('OK')

get_word_count('word1', 'cat1') # OK
get_word_count('word1', '')     # KeyError: ''

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

+1

エラーを回避したいのであれば、
can110さんのコードから引き継いで、
python辞書の.get()メソッドのデフォルト値を与えればよいです。

words = word_dict.get(category, [])

word_dict = {'cat1':{'word1':1}}
def get_word_count(word, category):
    words = word_dict.get(category,[])
    if word in words:
        print('OK')
    else:
        print('NG')

get_word_count('word1', 'cat1') # OK
get_word_count('word1', '') # NG

ついでに、word_dict = {'cat1':{'word1':1}}と対応するように、デフォルトはリストではなく辞書を与える方がロジックが正しいです。

words = word_dict.get(category, {})

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/11 17:41

    can110さん,megrei3からいただきました通り修正すると,下記の通りのエラーになりました。
    下記の通りに定義しておりますと、また別な修正が必要でしょうか。

    Traceback (most recent call last):
    File "bayes.py", line 4, in <module>
    class BayesianFilter:
    File "bayes.py", line 74, in BayesianFilter
    get_word_count('word1', 'cat1') # OK
    File "bayes.py", line 70, in get_word_count
    words = word_dict.get(category,[]) # キーに対応する値が存在しなけ ればKeyErrorが発生
    NameError: name 'word_dict' is not defined

    #word_dictを定義してるところ
    def __init__(self):
    self.words = set() # 出現した単語を全て記録
    self.word_dict = {} # カテゴリごとの単語出現回数を記録
    self.category_dict = {} # カテゴリの出現回数を記録
    |
    |
    |
    |

    # カテゴリ内の単語出現数を得る
    word_dict = {'cat1':{'word1':1}}
    def get_word_count(word, category):
    words = word_dict.get(category,[]) # キーに対応する値が存在しなければKeyErrorが発生
    if word in words:
    print('OK')

    get_word_count('word1', 'cat1') # OK
    get_word_count('word1', '') # KeyError: ''

    キャンセル

  • 2017/12/11 17:57

    ご自身のコードに沿うように変更されていますか?

    def get_word_count(word, category)
    ではなく
    def get_word_count(self, word, category)

    words = word_dict.get(category, [])
    ではなく
    words = self.word_dict.get(category, [])

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.53%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    julius音声認識結果だけを取り出すpython言語プログラム

    前提・実現したいこと 今のコードを実行するとjulius規程の結果が帰って来ます。 そこで、文字列結果だけを取りたいですが、どうすればいいですか? 該当のソースコード

  • 解決済

    Python 辞書を作るとき

    最初のファンクションで得たテキストから単語を取り出して辞書を作り、最終的に辞書内の単語の出現頻度を表示するコードを書こうとしているのですが、どうしたら空白で区切られた単語を

  • 解決済

    Python Djangoモデルのリレーションについて分かりません。

    Djangoの色々と勉強しているものです。 モデルのリレーションについて質問があります。 ユーザーとイベントカテゴリーとエリアモデルを使い以下のことを行おうとしているのですが上

  • 解決済

    python3 単語を出てきた順で数えたい

    単語の出てきた順に単語数をカウントしたいのですが、collectionsのCounterを使うと単語の多い順で表示される。かといってOrderedDictを使うと入力の読み取りをし

  • 解決済

    文字列を区切り文字を含んだ状態で分割したい

    python3で区切り文字を含んだ状態で文字列を分割するにはどのようにしたらよいでしょうか? 例: 以下の文字列を [aaa] bbb 以下のように分解したい '

  • 解決済

    char型の配列変数にchar型の変数を代入したい

    使用言語 C 環境 Visual Studio 2017 初めての質問です。 独学でプログラミングを始めたのですがわからないところがあり困っています。 char型の配列変数の使い方

  • 解決済

    python3でのValueErrorを出力させるclassについて

    組み込みのdictで、keyがTuple型以外の場合にValueErrorを出すよう改変したclassであるTupledictをpython3で作成したいです。 なお、現時点に

  • 解決済

    存在する組み合わせを数えたい

    例えば下のような文字列がある場合 あいう あうえ い うい この4つの文字列のうち同じ文字の組み合わせをもつ文字列を数えたいです。 上の場合、たとえば「あ」と「う」があるのは「あい

同じタグがついた質問を見る

  • Python 3.x

    6301questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • 機械学習

    678questions

    機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

  • 自然言語処理

    116questions

    自然言語処理は、日常的に使用される自然言語をコンピューターに処理させる技術やソフトウェアの総称です。