分析とデータ処理の理論の研究を始めたとき、あなたは分類アルゴリズムを研究した最初の人の一人です。 その本質は簡単です。特定の観察結果(データポイント)に関する情報が取得され、この結果に基づいて特定のグループまたはクラスに属します。
良い例は、電子メールスパムフィルターです。 着信文字(つまり、観測結果)を「スパム」または「スパムではない」としてマークし、文字に関する情報(送信者、大文字で始まる単語の数など)に焦点を当てる必要があります。

これは良い例ですが、退屈です。 スパムの分類は、講義、プレゼンテーション、会議で例として引用されているので、おそらく既に何度も聞いたことがあるでしょう。 しかし、別のより興味深い分類アルゴリズムについて話したらどうでしょうか? 奇妙な何か? もっと...魔法?
そうです! 今日はハリー・ポッター・ソーティング・ハットについてお話します。 ネットワークからデータを取得し、分析して、キャラクターをさまざまな部門に分類する分類子を作成します。 楽しいはずです!
注:
分類器はそれほど複雑ではありません。 したがって、ネットワークからテキストを抽出して分析するためのいくつかの基本的な手法を示して、問題を解決するための「プライマリアプローチ」と見なすべきです。 さらに、サンプルサイズが比較的小さいため、 クロス検証などの従来のトレーニング手法は使用しません。 特定のデータを収集し、ルールに基づいて単純な分類子を構築し、結果を評価するだけです。
2番目の注:
この投稿のアイデアは、 PyData Chicago 2016カンファレンスでのBrian Langの優れたプレゼンテーションに触発されました。 ビデオ録画はこちら 、スライドはこちら 。
ステップ1:ネットワークからデータを取得する
過去20年を洞窟で過ごした場合:配布用帽子は、グリフィンドール、スリザリン、ハフパフ、およびレイブンクローの4つのホグワーツ学部に学生を配置する魔法の帽子です。 各学部には独自の特徴があります。 学生の頭に帽子をかぶると、彼女は彼の心を読み、どの教授陣が彼に最も適しているかを判断します。 この定義によれば、分布帽子は、スパムフィルターであるバイナリ分類子(厳密に2つのグループで並べ替える)とは異なり、マルチクラス分類子(3つ以上のグループで並べ替える)です。
学生を学部に割り当てるには、学生に関する特定の情報を知る必要があります。 幸いなことに、十分なデータがharrypotter.wikia.comで入手できます。 このサイトには、学生や学部の説明など、ハリー・ポッターの世界のほぼすべての側面に関する記事が含まれています。 素晴らしいボーナス:サイトマネージャーであるFandomは、使いやすいAPIと膨大なドキュメントを提供します 。 やった!

pandas
と
requests
インポートすることから始めましょう。 前者はデータの整理に使用され、後者はデータを受信するためのAPIリクエストに使用されます。
また、Hogwartsのすべての生徒を適切に調べて、Distributionの帽子で散らばっている学部を書き留める必要があります(これらは、ソートの結果を比較する「実際のデータ」になります)。 このサイトでは、記事はホグワーツの学生と映画のように分類されています。 APIを使用すると、特定のカテゴリ内の記事のリストを作成できます。
Ravenclawを例として取り上げます。 すべてのデータを
info
変数にドロップしてから、Pandas Data Frameに入れます。
# import pandas as pd import requests # category = 'Ravenclaws' url = 'http://harrypotter.wikia.com/api/v1/Articles/List?expand=1&limit=1000&category=' + category requested_url = requests.get(url) json_results = requested_url.json() info = json_results['items'] ravenclaw_df = pd.DataFrame(info) print('Number of articles: {}'.format(len(info))) print('') ravenclaw_df.head()
記事:158

Rodeoを使用して完全な分析を追跡できます!
注:
Python IDEのRodeoを使用している場合は、上記のコードをコピーしてエディターまたはターミナルに貼り付けてください。 結果は[履歴]または[ターミナル]ウィンドウに表示されます。 ボーナス:マウスでウィンドウをドラッグするだけで、場所とサイズを変更できます。

このデータに基づいて、次のことがわかります。
- リストの最初の項目はRavenclawの個別情報ボックスです。 これは学生ではないため、「タイプ」列で結果をフィルタリングする必要があります。
- 残念ながら、
ravenclaw_df
は記事の内容を示すものではなく、説明のみを示しています。 コンテンツを取得するには、別のタイプのAPIリクエストを使用し、記事のIDに基づいてデータをリクエストする必要があります。 - また、サイクルを作成し、すべての学部を通過して、必要なすべてのデータを含む1つのフレームを取得することもできます。
# houses = ['Gryffindor', 'Hufflepuff', 'Ravenclaw', 'Slytherin'] mydf = pd.DataFrame() # ID , URL for house in houses: url = "http://harrypotter.wikia.com/api/v1/Articles/List?expand=1&limit=1000&category=" + house + 's' requested_url = requests.get(url) json_results = requested_url.json() info = json_results['items'] house_df = pd.DataFrame(info) house_df = house_df[house_df['type'] == 'article'] house_df.reset_index(drop=True, inplace=True) house_df.drop(['abstract', 'comments', 'ns', 'original_dimensions', 'revision', 'thumbnail', 'type'], axis=1, inplace=True) house_df['house'] = pd.Series([house]*len(house_df)) mydf = pd.concat([mydf, house_df]) mydf.reset_index(drop=True, inplace=True) # print('Number of student articles: {}'.format(len(mydf))) print('') print(mydf.head()) print('') print(mydf.tail())
学生に関する記事の数:748

記事のコンテンツを取得する
記事のIDを使用して、コンテンツのリクエストを開始できます。 しかし、記事のいくつかは巨大であり、信じられないほどの詳細が含まれています。 ハリー・ポッターとヴォルデモートに関する記事をご覧ください!

すべての主要キャラクターに関する記事には、「個性とキャラクターの特徴」というセクションがあります。 ここから、ディスペンシングハットが意思決定に使用する情報を抽出することは論理的です。 しかし、そのようなセクションはすべての記事に含まれているわけではないため、そのセクションのみに注目すると、文字数が大幅に減少します。
以下のコードは、各記事から「人格と性格特性」セクションを抽出し、その長さ(文字数)を計算します。 次に、IDに基づいて、このデータを最初のmydfデータフレームと結合します(少し時間がかかります)。
# " " # - , # text_dict = {} for iden in mydf['id']: url = 'http://harrypotter.wikia.com/api/v1/Articles/AsSimpleJson?id=' + str(iden) requested_url = requests.get(url) json_results = requested_url.json() sections = json_results['sections'] contents = [sections[i]['content'] for i, x in enumerate(sections) if sections[i]['title'] == 'Personality and traits'] if contents: paragraphs = contents[0] texts = [paragraphs[i]['text'] for i, x in enumerate(paragraphs)] all_text = ' '.join(texts) else: all_text = '' text_dict[iden] = all_text # DataFrame " " text_df = pd.DataFrame.from_dict(text_dict, orient='index') text_df.reset_index(inplace=True) text_df.columns = ['id', 'text'] text_df['text_len'] = text_df['text'].map(lambda x: len(x)) # mydf_all = pd.merge(mydf, text_df, on='id') mydf_all.sort_values('text_len', ascending=False, inplace=True) # DataFrame , " " mydf_relevant = mydf_all[mydf_all['text_len'] > 0] print('Number of useable articles: {}'.format(len(mydf_relevant))) print('') mydf_relevant.head()
対象記事の数:94

ステップ2:NLTKを使用して教員特性を取得する
学生の数がわかったので、学部に学生を分散させる必要があります。 これを行うには、各学部の特性のリストを作成します。 harrypotter.wikia.comから収集を始めましょう。
trait_dict = {} trait_dict['Gryffindor'] = ['bravery', 'nerve', 'chivalry', 'daring', 'courage'] trait_dict['Slytherin'] = ['resourcefulness', 'cunning', 'ambition', 'determination', 'self-preservation', 'fraternity', 'cleverness'] trait_dict['Ravenclaw'] = ['intelligence', 'wit', 'wisdom', 'creativity', 'originality', 'individuality', 'acceptance'] trait_dict['Hufflepuff'] = ['dedication', 'diligence', 'fairness', 'patience', 'kindness', 'tolerance', 'persistence', 'loyalty']
すべての単語は名詞であることに注意してください。 これはいいです。 キャラクターの特徴を記述する際には一貫性が必要です。 それらのいくつかは名詞として提示されなかったので、一般的な順序にそれらをもたらします:
- 「野心的」(形容詞)-「野心」に簡単に置き換えることができます
- 「骨の折れる仕事」、「公正な遊び」、「労苦を恐れない」-これらのフレーズは、単一単語の名詞に簡単に置き換えることもできます。
- 「大変な仕事」->「勤勉」
- 「フェアプレイ」->「フェアネス」
- 「労苦を恐れない」->「永続性」
各学部の特性のリストを受け取ったら、「テキスト」列をスキャンして、文字の説明で対応する単語が使用された回数を計算できます。 簡単そうですね。

残念ながら、それだけではありません。 Neville Longbottomについての「 人格と性格特性 」セクションのフレーズを次に示します。
彼が若かったとき、ネヴィルは不器用で、物忘れで、恥ずかしがり屋で、多くの人が彼がti病に見えたのでグリフィンドールの教授陣には適さないと考えていました。
彼がとても献身的だった友人の支援のおかげ; Remus Lupine教授の3年目の研究で彼の恐怖に立ち向かうインスピレーション。 そして、彼の両親の拷問者が自由に歩き回るという事実は、ネヴィルは勇敢になり、彼自身により自信を持ち、ヴォルデモートと彼の死喰い人との戦いで無私無欲になりました。
(彼が若かったとき、ネヴィルは不器用で、物忘れで、恥ずかしがり屋だった。
彼は非常に忠実だった彼の友人の支援により、レムス・ルパン教授が3年目の恐怖に直面するように励まし、両親の拷問が緩んでいることを知る動機付けで、ネヴィルはより勇敢になり、ヴォルデモートLordと彼のデスイーターとの戦いに専念し、 献身的に取り組んでいます。)
強調表示された単語は、一部の学部に有利に数えられるべきですが、形容詞であるため数えられません。 また、「勇敢に」や「勇気」などの単語はカウントされません。 分類アルゴリズムが正しく機能するためには、同義語、反意語、その他の単語形式を識別する必要があります。
同義語
nltkモジュール(NLTK-Natural Language Toolkit)に含まれている英語の語彙データベースであるWordNetの
synsets
関数を使用して、同義語を
synsets
ことができます。 「シンセット」は「同義語セット」、同義語のコレクション、または「補題」です。
synsets
関数は、特定の単語に関連付けられている同義語のセットを返します。
困った? コードを実行してから解析してみましょう。
from nltk.corpus import wordnet as wn # foo1 = wn.synsets('bravery') print("Synonym sets associated with the word 'bravery': {}".format(foo1)) foo2 = wn.synsets('fairness') print('') print("Synonym sets associated with the word 'fairness': {}".format(foo2)) foo3 = wn.synsets('wit') print('') print("Synonym sets associated with the word 'wit': {}".format(foo3)) foo4 = wn.synsets('cunning') print('') print("Synonym sets associated with the word 'cunning': {}".format(foo4)) foo4 = wn.synsets('cunning', pos=wn.NOUN) print('') print("Synonym sets associated with the *noun* 'cunning': {}".format(foo4)) print('') # (""), synset foo_list = [foo1, foo2, foo3, foo4] for foo in foo_list: for synset in foo: print((synset.name(), synset.lemma_names()))
「勇気」という言葉に関連付けられた同義語セット:[Synset( 'courage.n.01')、Synset( 'fearlessness.n.01')]
単語「fairness」に関連付けられた同義語セット:[Synset( 'fairness.n.01')、Synset( 'fairness.n.02')、Synset( 'paleness.n.02')、Synset( 'comeliness.n .01 ')]
単語「wit」に関連付けられた同義語セット:[Synset( 'wit.n.01')、Synset( 'brain.n.02')、Synset( 'wag.n.01')]
「cunning」という単語に関連付けられた同義語セット:[Synset(「craft.n.05」)、Synset(「cunning.n.02」)、Synset(「cunning.s.01」)、Synset(「crafty.s」 .01 ')、Synset(' clever.s.03 ')]
名詞「cunning」に関連付けられた同義語セット:[Synset( 'craft.n.05')、Synset( 'cunning.n.02')]
(「勇気.n.01」、「「勇気」、「勇気」、「勇気」、「勇気」」)(「fearlessness.n.01」、[「勇気」、「勇気」])(「公平さ。 n.01 '、['公平性 '、'公平性 '])(' fairness.n.02 '、['公平性 '、'公平性 '、'率直さ '、'率直性 '))('淡さ.n。 02 '、['青白さ '、'金髪 '、'公平性 '])(' comeliness.n.01 '、['面白さ '、'公平性 '、'愛らしさ '、'美人 '])(' wit.n. 01 '、['ウィット '、'ユーモア '、'ユーモア '、'ウィティティズム '、'ウィティネス '])(' brain.n.02 '、[' brain '、' brainpower '、' learning_ability '、' mental_capacity ' 、 'mentality'、 'wit'])( 'wag.n.01'、['wag'、 'wit'、 'card'])( 'craft.n.05'、['craft'、 'craftiness' 、「c」、「fox」、「gu」、「s」、「 '」])(「cunning.n.02」、[「c」))
そのため、多くの出力が得られました。 いくつかのポイントと潜在的な問題を考慮してください。
-
wn.synsets('bravery')
は同義語の2つのセットに関連付けられています。1つはcourage.n.01
、もう1つはcourage.n.01
用です。 これが何を意味するのか見てみましょう: - 最初の部分(「勇気」と「恐れ知らず」)は、同義語の具体的なセット全体が構築される言葉です。 私たちはそれを「中心」の言葉と呼びます。 つまり、このセットのすべての同義語(「補題」)は、意味が中心の単語に似ています。
- 2番目の部分( 'n')は「名詞」(「名詞」)を意味します。 たとえば、「cunning」という単語に関連付けられているセットには、
crafty.s.01
およびclever.s.03
(形容詞)が含まれます。 ここに登場したのは、「ずるい」という言葉が名詞でも形容詞でもあるからです。 名詞のみを残すには、wn.synsets('cunning', pos=wn.NOUN)
指定できます。 - 3番目の部分( '01')は、中心語の特定の意味を示します。 たとえば、「公正」とは、「ルールと基準を順守する」ことと「差別や不正直さなしに判断を下すこと」の両方を意味します。
お気づきかもしれませんが、
synset
関数は不要な同義語のセットを提供する場合があります。 たとえば、
paleness.n.02
(「自然で
comeliness.n.01
肌を持つ」)と
comeliness.n.01
(「見栄えが良くて魅力的」)は、「公平」という言葉にも関連付けられています。 これらの特性は明らかにハッフルパフとは関係ありません( ネヴィルロングボトムはハンサムに成長しましたが)ので、分析からそのようなセットを手動で除外する必要があります。
翻訳:同義語を取得するのは思ったより難しい

反意語と単語形式
すべての同義語を収集した後、反意語とさまざまな単語の形式に注意する必要があります(たとえば、「勇気」-「勇敢」、「勇敢」、「勇敢」に関連して)。 nltkでは多くのハードワークを行うことができますが、分詞と形容詞を比較/最上級で手動で入力する必要があります。
# (), "bravery" foo1 = wn.synsets('bravery') for synset in foo1: for lemma in synset.lemmas(): print("Synset: {}; Lemma: {}; Antonyms: {}; Word Forms: {}".format(synset.name(), lemma.name(), lemma.antonyms(), lemma.derivationally_related_forms())) print("")
シンセット:courage.n.01; 補題:勇気; 反意語:[補題( 'cowardice.n.01.cowardice')]; Word Forms:[補題( 'brave.a.01.courageous')]
シンセット:courage.n.01; 補題:勇気; 反意語:[]; Word Forms:[補題( 'brave.a.01.courageous')]
シンセット:courage.n.01; 補題:勇気; 反意語:[]; Wordフォーム:[]
シンセット:courage.n.01; 補題:勇気; 反意語:[]; 単語形式:[補題( 'brave.a.01.brave')、補題( 'audacious.s.01.brave')]
シンセット:fearlessness.n.01; 補題:大胆不敵; 反意語:[補題( 'fear.n.01.fear')]; 単語形式:[補題( 'audacious.s.01.fearless')、補題( 'unafraid.a.01.fearless')]
シンセット:fearlessness.n.01; 補題:勇気; 反意語:[]; Wordフォーム:[]
すべてをまとめる
次のコードは、学部の各機能の同義語、反意語、単語形式のリストを作成します。 完全を期すために、一部の単語のスペルが正しくない場合があります。
# , relevant_synsets = {} relevant_synsets['Ravenclaw'] = [wn.synset('intelligence.n.01'), wn.synset('wit.n.01'), wn.synset('brain.n.02'), wn.synset('wisdom.n.01'), wn.synset('wisdom.n.02'), wn.synset('wisdom.n.03'), wn.synset('wisdom.n.04'), wn.synset('creativity.n.01'), wn.synset('originality.n.01'), wn.synset('originality.n.02'), wn.synset('individuality.n.01'), wn.synset('credence.n.01'), wn.synset('acceptance.n.03')] relevant_synsets['Hufflepuff'] = [wn.synset('dedication.n.01'), wn.synset('commitment.n.04'), wn.synset('commitment.n.02'), wn.synset('diligence.n.01'), wn.synset('diligence.n.02'), wn.synset('application.n.06'), wn.synset('fairness.n.01'), wn.synset('fairness.n.01'), wn.synset('patience.n.01'), wn.synset('kindness.n.01'), wn.synset('forgivingness.n.01'), wn.synset('kindness.n.03'), wn.synset('tolerance.n.03'), wn.synset('tolerance.n.04'), wn.synset('doggedness.n.01'), wn.synset('loyalty.n.01'), wn.synset('loyalty.n.02')] relevant_synsets['Gryffindor'] = [wn.synset('courage.n.01'), wn.synset('fearlessness.n.01'), wn.synset('heart.n.03'), wn.synset('boldness.n.02'), wn.synset('chivalry.n.01'), wn.synset('boldness.n.01')] relevant_synsets['Slytherin'] = [wn.synset('resourcefulness.n.01'), wn.synset('resource.n.03'), wn.synset('craft.n.05'), wn.synset('cunning.n.02'), wn.synset('ambition.n.01'), wn.synset('ambition.n.02'), wn.synset('determination.n.02'), wn.synset('determination.n.04'), wn.synset('self-preservation.n.01'), wn.synset('brotherhood.n.02'), wn.synset('inventiveness.n.01'), wn.synset('brightness.n.02'), wn.synset('ingenuity.n.02')] # , def get_forms(lemma): drfs = lemma.derivationally_related_forms() output_list = [] if drfs: for drf in drfs: drf_pos = str(drf).split(".")[1] if drf_pos in ['n', 's', 'a']: output_list.append(drf.name().lower()) if drf_pos in ['s', 'a']: # + "-ness" + & if len(drf.name()) == 3: last_letter = drf.name()[-1:] output_list.append(drf.name().lower() + last_letter + 'er') output_list.append(drf.name().lower() + last_letter + 'est') output_list.append(drf.name().lower()+'ness') output_list.append(drf.name().lower()+'ly') elif drf.name()[-4:] in ['able', 'ible']: output_list.append(drf.name().lower()+'r') output_list.append(drf.name().lower()+'st') output_list.append(drf.name().lower()+'ness') output_list.append(drf.name()[:-1].lower()+'y') elif drf.name()[-1:] == 'e': output_list.append(drf.name().lower()+'r') output_list.append(drf.name().lower()+'st') output_list.append(drf.name().lower()+'ness') output_list.append(drf.name().lower()+'ly') elif drf.name()[-2:] == 'ic': output_list.append(drf.name().lower()+'er') output_list.append(drf.name().lower()+'est') output_list.append(drf.name().lower()+'ness') output_list.append(drf.name().lower()+'ally') elif drf.name()[-1:] == 'y': output_list.append(drf.name()[:-1].lower()+'ier') output_list.append(drf.name()[:-1].lower()+'iest') output_list.append(drf.name()[:-1].lower()+'iness') output_list.append(drf.name()[:-1].lower()+'ily') else: output_list.append(drf.name().lower()+'er') output_list.append(drf.name().lower()+'est') output_list.append(drf.name().lower()+'ness') output_list.append(drf.name().lower()+'ly') return output_list else: return output_list # # , , , import copy new_trait_dict = copy.deepcopy(trait_dict) antonym_dict = {} # () ; ( ) for house, traits in trait_dict.items(): antonym_dict[house] = [] for trait in traits: synsets = wn.synsets(trait, pos=wn.NOUN) for synset in synsets: if synset in relevant_synsets[house]: for lemma in synset.lemmas(): new_trait_dict[house].append(lemma.name().lower()) if get_forms(lemma): new_trait_dict[house].extend(get_forms(lemma)) if lemma.antonyms(): for ant in lemma.antonyms(): antonym_dict[house].append(ant.name().lower()) if get_forms(ant): antonym_dict[house].extend(get_forms(ant)) new_trait_dict[house] = sorted(list(set(new_trait_dict[house]))) antonym_dict[house] = sorted(list(set(antonym_dict[house]))) # print("Gryffindor traits: {}".format(new_trait_dict['Gryffindor'])) print("") print("Gryffindor anti-traits: {}".format(antonym_dict['Gryffindor'])) print("")
グリフィンドール仕様:['bold'、 'bolder'、 'boldest'、 'boldly'、 'boldness'、 'brass'、 'brassier'、 'brassiest'、 'brassily'、 'brassiness'、 'brassy'、 'brave 「、」勇敢、「勇気」、「勇敢」、「勇気」、「勇敢」、「頬」、「チーキー」、「チーキー」、「チーキー」、「チーキー」、「生意気」、「騎士道」、 「勇気」、「勇気」、「勇気」、「勇気」、「勇気」、「勇気」、「大胆」、「顔」、「大胆不敵」、「大胆不敵」、「大胆不敵」、「大胆不敵」、「大胆不敵」 '、' gallantry '、' hardihood '、' hardiness '、' heart '、' mettle '、' nerve '、' nervier '、' nerviest '、' nervily '、' nerviness '、' nervy '、' politesse '、 「spunk」、「spunkier」、「spunkiest」、「spunkily」、「spunkiness」、「spunky」]
グリフィンドールの反特性:['co病'、 '恐怖'、 '、病'、 'tim病者'、 'チミデスト'、 'tim病'、 'tim病'、 'tim病']
# , from itertools import combinations def test_overlap(dict): results = [] house_combos = combinations(list(dict.keys()), 2) for combo in house_combos: results.append(set(dict[combo[0]]).isdisjoint(dict[combo[1]])) return results # ; "False" print("Any words overlap in trait dictionary? {}".format(sum(test_overlap(new_trait_dict)) != 6)) print("Any words overlap in antonym dictionary? {}".format(sum(test_overlap(antonym_dict)) != 6))
文字特性辞書に繰り返しはありますか? 偽
反意語の辞書の繰り返し? 偽

ステップ3:学部ごとに学生を配布する
学部ごとに学生を配布する時が来ました! 分類アルゴリズムは次のように機能します。
- 各生徒の「人格と性格特性」セクションの各単語を通過します。
- 特定の学部に固有の特性のリストに単語がある場合、その学部のスコアに1が追加されます。
- 特定の学部に固有のアンチキャラクターのリストに単語がある場合、その学部のスコアから1が引かれます。
- 学生は教員に割り当てられ、ほとんどのポイントを獲得します。
- 引き分けがある場合は、「タイ!」と書くだけです。
「人格と性格特性」セクションに「アリスは勇敢だった」という文だけがあるとします。 その後、アリスはグリフィンドールで1ポイント、残りの学部で0ポイントを獲得します。 したがって、アリスはグリフィンドールに陥ります。
# "word_tokenize", from nltk import word_tokenize # , def sort_student(text): text_list = word_tokenize(text) text_list = [word.lower() for word in text_list] score_dict = {} houses = ['Gryffindor', 'Hufflepuff', 'Ravenclaw', 'Slytherin'] for house in houses: score_dict[house] = (sum([True for word in text_list if word in new_trait_dict[house]]) - sum([True for word in text_list if word in antonym_dict[house]])) sorted_house = max(score_dict, key=score_dict.get) sorted_house_score = score_dict[sorted_house] if sum([True for i in score_dict.values() if i==sorted_house_score]) == 1: return sorted_house else: return "Tie!" # print(sort_student('Alice was brave')) print(sort_student('Alice was British'))
グリフィンドールネクタイ!
機能が機能しているようです。 それをデータに適用し、何が起こるかを確認します!
# pd.options.mode.chained_assignment = None mydf_relevant['new_house'] = mydf_relevant['text'].map(lambda x: sort_student(x)) mydf_relevant.head(20)

print("Match rate: {}".format(sum(mydf_relevant['house'] == mydf_relevant['new_house']) / len(mydf_relevant))) print("Percentage of ties: {}".format(sum(mydf_relevant['new_house'] == 'Tie!') / len(mydf_relevant)))
マッチ:0.2553191489361702
引き分け:0.32978723404255317

うん 他の結果を期待していました。 ヴォルデモートがハッフルパフに来た理由を調べてみましょう。

# -- tom_riddle = word_tokenize(mydf_relevant['text'].values[0]) tom_riddle = [word.lower() for word in tom_riddle] # , words_dict = {} anti_dict = {} houses = ['Gryffindor', 'Hufflepuff', 'Ravenclaw', 'Slytherin'] for house in houses: words_dict[house] = [word for word in tom_riddle if word in new_trait_dict[house]] anti_dict[house] = [word for word in tom_riddle if word in antonym_dict[house]] print(words_dict) print("") print(anti_dict)
{'スリザリン':['野望']、 'レイブンクロー':['インテリジェント'、 'インテリジェント'、 'メンタル'、 '個人'、 'メンタル'、 'インテリジェント']、 'ハフパフ':['種類'、 'loyalty'、 'true'、 'true'、 'true'、 'loyalty']、 'Gryffindor':['brave'、 'face'、 'bold'、 'face'、 'bravery'、 'brave'、 「勇気」、「勇気」]}
{'スリザリン':[]、 'Ravenclaw':['common']、 'Hufflepuff':[]、 'Gryffindor':['fear'、 'fear'、 'fear'、 'fear'、 'fear'、 「恐怖」、「co病」、「恐怖」、「恐怖」]}
ご覧のとおり、スリザリンの得点(1-0)= 1ポイント、レイブンクロー-(6-1)= 5、ハッフルパフ-(6-0)= 6、グリフィンドール-(8-9)= -1
すべての学生の中で最も長いヴォルデモートの「個性と特性」のセクションでは、辞書と一致したのは31語のみでした。 これは、おそらく他の学生との試合が多かったことを意味します。 つまり、データが少なすぎることに基づいて分類を決定します。これは、エラーの割合が高く、描画が多いことを説明しています。
結論
作成した分類器はうまく機能しません(推測するよりも少し正確ですが)が、アプローチが単純化されたことを忘れないでください。 最近のスパムフィルターは非常に複雑で、特定の単語の存在に基づいて分類されません。 したがって、より多くの情報を考慮に入れるように、アルゴリズムを改善できます。 :
API nltk, . , Python, .
