Talking Hatを䟋に、研究から実装たでのデヌタサむ゚ンスプロゞェクト


1か月前、レンタは、同じハリヌポッタヌトヌキングハットが 、4぀の孊郚のいずれかに゜ヌシャルネットワヌクぞのアクセスを提䟛する参加者を特定するコンテストを開始したした。 競争はうたく行われ、異なる発音の名前は異なる孊郚によっお決定され、同様の英語ずロシア語の名前ず姓が同様の方法で配垃されたした。 分垃が名ず姓のみに䟝存しおいるかどうか、そしお友人の数や他の芁因が䜕らかの圢で考慮されおいるかどうかはわかりたせんが、この競争はこの蚘事のアむデアを瀺唆したした分類噚をれロから蚓緎しお、ナヌザヌを異なる孊郚に配垃できるようにしたす。


この蚘事では、名前ず姓に応じお、ハリヌポッタヌの郚眲に人々を配垃する簡単なMLモデルを䜜成したす。CRISPの方法論に埓っお小さな調査プロセスを実行したした。 ぀たり、私たち




このタスクは簡単に思えるかもしれないので、プロセス党䜓2時間未満およびこの蚘事読み取り時間が15分未満に远加の制限を課したす。


すでにデヌタサむ゚ンスの矎しい玠晎らしい䞖界に没頭しおいお、Kaggliteが絶えず芋られない堎合、たたは神が犁じおいる同僚ずのミヌティング䞭にHadupの長さを枬定したい堎合、蚘事は単玔で興味をそそられないように芋えたす。 たた、最終モデルの品質はこの蚘事の䞻な䟡倀ではありたせん。 譊告したした。 行こう


この蚘事で䜿甚されおいるコヌドを含むgithubリポゞトリは、奜奇心の匷い読者にも利甚できたす。 ゚ラヌが発生した堎合は、PRを開いおください。


問題を定匏化する


明確な刀断基準を持たない問題を無限に解決するこずは可胜です。そのため、入力された行に応答しお、「Gryffindor」、「Ravenclaw」、「Hufflepuff」、たたは「Slytherin」の答えを埗るこずができる゜リュヌションを埗たいずすぐに刀断したす。


実際、ブラックボックスを取埗する必芁がありたす。


" " => [?] => Griffindor 

元の黒い垜子は、性栌ず個人的な資質に応じお、若いりィザヌドを郚門に配垃したした。 タスクの条件に応じたキャラクタヌず性栌に関するデヌタは利甚できないため、参加者の名前ず姓を䜿甚したす。本のキャラクタヌを本の出身の孊郚に察応する孊郚に分配する必芁があるこずを忘れないでください。 そしお、私たちの決定がハリヌをハッフルパフたたはレむノンクロヌに配垃した堎合、ポテロマニアは間違いなく動揺したすしかし、本の粟神を䌝えるためにハリヌをグリフィンドヌルずスリザリンに等しい確率で送るべきです。


確率に぀いお話しおいるので、より厳密な数孊甚語で問題を圢匏化したす。 デヌタサむ゚ンスの芳点から、分類問題を解決したす。぀たり、特定のクラスのオブゞェクト名前ず姓の圢匏の文字列を割り圓おたす実際には、ラベルたたはラベルです。これは、yes / no倀を持぀数倀たたは4぀の倉数です  少なくずもハリヌの堎合、グリフィンドヌルずスリザリンの2぀の答えを䞎えるのが正しいこずを理解しおいたす。そのため、垜子が定矩する特定の孊郚を予枬しない方がよいでしょうが、この孊郚に人が割り圓おられる確率は、ある皮の機胜


f<名前><姓>=Pgriffindor;Pravenclaw;Phufflpuff;Pslitherin


指暙ず品質評䟡


タスクず目暙が定匏化され、 今、私たちはそれを解決する方法を考えたす しかし、それだけではありたせん。 調査を開始するには、品質指暙を入力する必芁がありたす。 ぀たり、2぀の異なる゜リュヌションを盞互に比范する方法を決定したす。


人生のすべおが良くおシンプルです-スパム怜出噚は受信メッセヌゞに最小限のスパムを枡す必芁があり、必芁な文字を最倧限に枡す必芁があるこずを盎感的に理解しおいたす。


実際には、すべおがより耇雑であり、 これの確認は、どのようにどのようなメトリックが䜿甚されるかを説明する倚数の 蚘事です。 緎習はこれを最もよく理解するのに圹立ちたすが、それに぀いおは別の投皿を曞き、誰もが実際にこれがどのように異なるかを理解しお理解できるように、オヌプンなテヌブルを䜜成するこずをお玄束したす。


私たちにずっお䞖垯は「最高のものを遞びたしょう」がROC AUCです。 これは、この堎合のメトリックに必芁なものです。誀怜知が少なく、実際の予枬が正確であればあるほど、ROC AUCが倧きくなりたす。


理想的なROCモデルの堎合、AUCは1であり、クラスを絶察的にランダムに定矩する理想的なランダムモデル-0.5です。


ROC AUC in[0.5;1]


アルゎリズム


ブラックボックスでは、本のヒヌロヌの分垃を考慮し、入力ずしお別の名前ず姓を䜿甚し、結果を提䟛する必芁がありたす。 分類の問題を解決するには、さたざたな機械孊習アルゎリズムを䜿甚できたす。


ニュヌラルネットワヌク、因数分解マシン、線圢回垰、たたはSVMなど。


䞀般的な信念に反しお、デヌタサむ゚ンスはニュヌラルネットワヌクだけに限定されず、このアむデアを普及させるために、この蚘事ではニュヌラルネットワヌクは奜奇心reader盛な読者ぞの挔習ずしお残されおいたす。 デヌタ分析で単䞀のコヌス特に䞻芳的に優れたコヌス-ODSを受講しなかった人 、たたはアマチュア持垫の雑誌にも掲茉されおいる機械孊習やAIに関するn個のニュヌスを単に読んだ人は、おそらくアルゎリズムの䞀般的なグルヌプの名前を満たしたしたバギング、ブヌスティング、サポヌトベクトル法SVM、線圢回垰。 問題を解決するために䜿甚するのはそれらです。


そしお、より正確に、比范したす



Hogwartsの各孊生を孊郚の1぀に配垃する問題は、圌に察応する孊郚を定矩するこずで解決できたすが、厳密に蚀えば、この問題は各クラスが個別に属するかどうかを刀断する問題を解決するこずになりたす。 したがっお、この蚘事のフレヌムワヌクでは、各孊郚に1぀ず぀、4぀のモデルを取埗するずいう目暙を蚭定したした。


デヌタ


トレヌニングのための適切なデヌタセット、さらに重芁なこずには、適切な目的で䜿甚するための合法的なデヌタセットを芋぀けるこずは、デヌタサむ゚ンスで最も耇雑で時間のかかるタスクの1぀です。 私たちのタスクでは、ハリヌ・ポッタヌの䞖界に関するりィキアからデヌタを取埗したす。 たずえば、このリンクでは、グリフィンドヌルの孊郚で孊んだすべおのキャラクタヌを芋぀けるこずができたす。 この堎合、非営利目的でデヌタを䜿甚するこずが重芁です。したがっお、このサむトのラむセンスに違反したせん。



デヌタサむ゚ンティストはこんなにクヌルだず思う人のために、デヌタサむ゚ンティストに行っお教えたす。デヌタのクリヌニングず準備などのステップがあるこずを思い出させおください。 たずえば、「グリフィンドヌルの䞃番目の知事」を削陀し、「グリフィンドヌルの未知の少女」を半自動で削陀するには、ダりンロヌドしたデヌタを手動で管理する必芁がありたす。 実際の䜜業では、タスクの比䟋的に倧きな郚分は垞に、デヌタセット内の欠損倀の準備、クリヌニング、および埩元に関連付けられおいたす。


少しctrl + cctrl + vを出力するず、英語ずロシア語の2぀の蚀語の文字の名前を含む4぀のテキストファむルが埗られたす。


収集したデヌタを調査したすEDA、探玢的デヌタ分析


この段階では、孊郚の孊生の名前を含む4぀のファむルがありたす。詳しく芋おいきたす。


 $ ls ../input griffindor.txt hufflpuff.txt ravenclaw.txt slitherin.txt 

各ファむルには、孊生の名前ず姓ある堎合が1行に1぀ず぀含たれおいたす。


 $ wc -l ../input/*.txt 250 ../input/griffindor.txt 167 ../input/hufflpuff.txt 180 ../input/ravenclaw.txt 254 ../input/slitherin.txt 851 total 

収集されたデヌタの圢匏は次のずおりです。


 $ cat ../input/griffindor.txt | head -3 && cat ../input/griffindor.txt | tail -3      Charlie Stainforth Melanie Stanmore Stewart 

私たちの党䜓の考えは、ブラックボックスたたはブラックハットが区別するこずを孊ぶこずができる名前ず姓に類䌌したものがあるずいう仮定に基づいおいたす。


アルゎリズムはそのたた行を送るこずができたすが、基本モデルは「Draco」ず「Harry」の違いを自分で理解できないため、結果は良くありたせん。そのため、名前ず姓から蚘号を抜出する必芁がありたす。


デヌタの準備機胜゚ンゞニアリング


暙識 たたは英語の 機胜からの機胜 -プロパティは、オブゞェクトの際立ったプロパティです。 過去1幎間に転職した回数、巊手の指の数、゚ンゞンの゚ンゞン容量、走行距離が100,000 kmを超えるかどうか。 暙識のあらゆる皮類の分類は非垞に倚くの発明者によっお考案されたものであり、この点に関しお単䞀のシステムは存圚せず、単䞀のシステムになるこずもできないため、暙識の䟋を次に瀺したす。


  1. 有理数
  2. カテゎリヌ最倧12、12-18たたは18+
  3. バむナリヌ倀最初のロヌンを返したかどうか
  4. 日付、色、株匏など

フィヌチャ の怜玢 たたは圢成 英語の フィヌチャ゚ンゞニアリング は、デヌタ分析の専門家の研究たたは䜜業における独立した段階ずしお際立っおいるこずがよくありたす。 実際、垞識、経隓、仮説テストが実際に行われおいるず、プロセス自䜓に圹立ちたす。 正しい兆候をすぐに掚枬するこずは、完党な手ず基本的な知識ず運を組み合わせるこずの問題です。 時にはシャヌマニズムがありたすが、䞀般的なアプロヌチは非垞に単玔です思い぀いたこずを実行し、新しい蚘号を远加しお゜リュヌションを改善できるかどうかを確認する必芁がありたす。 たずえば、タスクのサむンずしお、名前にシュヌずいう音の数を含めるこずができたす。


モデルの最初のバヌゞョン実際のデヌタサむ゚ンス研究-傑䜜ずしおは決しお完成できないためでは、名前ず姓に次の機胜を䜿甚したす。


  1. 1および単語の最埌の文字-母音たたは子音
  2. 二重母音ず子音
  3. 母音、子音、聎芚障害者、有声の数
  4. 名前の長さ、姓の長さ
  5. ...

これを行うために、 このリポゞトリを基瀎ずしお、ラテン文字に䜿甚できるようにクラスを远加したす。 これにより、各文字の発音を刀断する機䌚が埗られたす。


 >> from Phonetic import RussianLetter, EnglishLetter >> RussianLetter('').classify() {'consonant': True, 'deaf': False, 'hard': False, 'mark': False, 'paired': False, 'shock': False, 'soft': False, 'sonorus': True, 'vowel': False} >> EnglishLetter('d').classify() {'consonant': True, 'deaf': False, 'hard': True, 'mark': False, 'paired': False, 'shock': False, 'soft': False, 'sonorus': True, 'vowel': False} 

これで、統蚈を蚈算するための簡単な関数を定矩できたす。䟋


 def starts_with_letter(word, letter_type='vowel'): """   ,    . :param word:  :param letter_type: 'vowel'  'consonant'.   . :return: Boolean """ if len(word) == 0: return False return Letter(word[0]).classify()[letter_type] def count_letter_type(word): """       . :param word:  :param debug:    :return: :obj:`dict` of :obj:`str` => :int:count """ count = { 'consonant': 0, 'deaf': 0, 'hard': 0, 'mark': 0, 'paired': 0, 'shock': 0, 'soft': 0, 'sonorus': 0, 'vowel': 0 } for letter in word: classes = Letter(letter).classify() for key in count.keys(): if classes[key]: count[key] += 1 return count 

これらの関数を䜿甚するず、すでに最初の兆候を取埗できたす。


 from feature_engineering import * >> print("  («»): ", len(""))   («»): 5 >> print(" («»)   : ", starts_with_letter('', 'vowel'))  («»)   : False >> print(" («»)   : ", starts_with_letter('', 'consonant'))  («»)   : True >> count_Harry = count_letter_type("") >> print ("     («»): ", count_Harry['paired'])      («»): 1 

厳密に蚀えば、これらの関数を䜿甚しお、文字列のベクトル衚珟を取埗できたす。぀たり、マッピングを取埗したす。


f<Name><Surname>=>lengthname、lengthsurnames、...、numberof vowelssurnames


これで、機械孊習アルゎリズムに入力できるデヌタセットの圢匏でデヌタを提瀺できたす。


 >> from data_loaders import load_processed_data >> hogwarts_df = load_processed_data() >> hogwarts_df.head() 


さらに、その結​​果、各生埒に次のようなサむンが衚瀺されたす。


 >> hogwarts_df[hogwarts_df.columns].dtypes 

受け取ったサむン
 name object surname object is_english bool name_starts_with_vowel bool name_starts_with_consonant bool name_ends_with_vowel bool name_ends_with_consonant bool name_length int64 name_vowels_count int64 name_double_vowels_count int64 name_consonant_count int64 name_double_consonant_count int64 name_paired_count int64 name_deaf_count int64 name_sonorus_count int64 surname_starts_with_vowel bool surname_starts_with_consonant bool surname_ends_with_vowel bool surname_ends_with_consonant bool surname_length int64 surname_vowels_count int64 surname_double_vowels_count int64 surname_consonant_count int64 surname_double_consonant_count int64 surname_paired_count int64 surname_deaf_count int64 surname_sonorus_count int64 is_griffindor int64 is_hufflpuff int64 is_ravenclaw int64 is_slitherin int64 dtype: object 

最埌の4列は察象ずされおいたす-孊生がどの孊郚に登録されおいるかに関する情報が含たれおいたす。


アルゎリズムトレヌニング


䞀蚀で蚀えば、アルゎリズムは人々ず同じように蚓緎されたす。圌らは間違いを犯し、そこから孊びたす。 どれだけミスを犯したかを理解するために、アルゎリズムぱラヌ関数損倱関数、 英語の 損倱関数 を䜿甚したす。


原則ずしお、孊習プロセスは非垞に単玔であり、いく぀かのステップで構成されおいたす。


  1. 予枬を行いたす。
  2. ゚ラヌを評䟡したす。
  3. モデルパラメヌタを修正したす。
  4. 目暙に達するか、プロセスが停止するか、デヌタが終了するたで1〜3を繰り返したす。
  5. 結果のモデルの品質を評䟡したす。


    もちろん、実際には、すべおが少し耇雑です。 たずえば、 過剰適合の珟象がありたす。アルゎリズムは、どの特城が答えに察応するかを文字通り芚えるこずができ、したがっお、圌が蚓緎されたものず類䌌しおいないオブゞェクトの結果を悪化させるこずができたす。 これを回避するために、さたざたな手法ずハッキングがありたす。



䞊蚘のように、4぀の問題を解決したす各孊郚に1぀。 したがっお、スリザリンのデヌタを準備したす。


 #  ,     - : >> data_full = hogwarts_df.drop( [ 'name', 'surname', 'is_griffindor', 'is_hufflpuff', 'is_ravenclaw' ], axis=1).copy() #    ,   : >> X_data = data_full.drop('is_slitherin', axis=1) #     ,   1    >> y = data_full.is_slitherin 

孊習䞭、アルゎリズムはその結果を実際のデヌタず垞に比范したす。デヌタセットのこの郚分は怜蚌に割り圓おられおいるためです。 良いトヌンのルヌルは、アルゎリズムがたったく芋なかった個別のデヌタでアルゎリズムの結果を評䟡するためにも考慮されたす。 したがっお、サンプルを70/30の割合で分割し、最初のアルゎリズムをトレヌニングしたす。


 from sklearn.cross_validation import train_test_split from sklearn.ensemble import RandomForestClassifier #      >> seed = 7 #    >> test_size = 0.3 >> X_train, X_test, y_train, y_test = train_test_split(X_data, y, test_size=test_size, random_state=seed) >> rfc = RandomForestClassifier() >> rfc_model = rfc.fit(X_train, y_train) 

できた これで、このモデルの入力にデヌタを送信するず、結果が生成されたす。 これは楜しいので、たずはハリヌのモデルがスリザリンを認識しおいるかどうかを確認したす。 これを行うには、たずアルゎリズムの予枬を取埗するために関数を準備したす。


コヌドを衚瀺
 from data_loaders import parse_line_to_hogwarts_df import pandas as pd def get_single_student_features (name): """      :param name: string     :return: pd.DataFrame     """ featurized_person_df = parse_line_to_hogwarts_df(name) person_df = pd.DataFrame(featurized_person_df, columns=[ 'name', 'surname', 'is_english', 'name_starts_with_vowel', 'name_starts_with_consonant', 'name_ends_with_vowel', 'name_ends_with_consonant', 'name_length', 'name_vowels_count', 'name_double_vowels_count', 'name_consonant_count', 'name_double_consonant_count', 'name_paired_count', 'name_deaf_count', 'name_sonorus_count', 'surname_starts_with_vowel', 'surname_starts_with_consonant', 'surname_ends_with_vowel', 'surname_ends_with_consonant', 'surname_length', 'surname_vowels_count', 'surname_double_vowels_count', 'surname_consonant_count', 'surname_double_consonant_count', 'surname_paired_count', 'surname_deaf_count', 'surname_sonorus_count', ], index=[0] ) featurized_person = person_df.drop( ['name', 'surname'], axis = 1 ) return featurized_person def get_predictions_vector (model, person): """    :param model:   :param person: string   :return: list    """ encoded_person = get_single_student_features(person) return model.predict_proba(encoded_person)[0] 

次に、アルゎリズムの結果を考慮するために小さなテストデヌタセットを蚭定したす。


 def score_testing_dataset (model): """      . :param model:   """ testing_dataset = [ " ", "Kirill Malev", " ", "Harry Potter", " ", " ","Severus Snape", " ", "Tom Riddle", " ", "Salazar Slytherin"] for name in testing_dataset: print ("{} — {}".format(name, get_predictions_vector(model, name)[1])) score_testing_dataset(rfc_model) 

   — 0.5 Kirill Malev — 0.5   — 0.0 Harry Potter — 0.0   — 0.75   — 0.9 Severus Snape — 0.5   — 0.2 Tom Riddle — 0.5   — 0.2 Salazar Slytherin — 0.3 

結果は疑わしかった。 このモデルによれば、孊郚の創蚭者でさえ孊郚にはいたせん。 したがっお、厳栌な品質を評䟡する必芁がありたす。最初に尋ねたメトリックを芋おください。


 from sklearn.metrics import accuracy_score, roc_auc_score, classification_report predictions = rfc_model.predict(X_test) print("Classification report: ") print(classification_report(y_test, predictions)) print("Accuracy for Random Forest Model: %.2f" % (accuracy_score(y_test, predictions) * 100)) print("ROC AUC from first Random Forest Model: %.2f" % (roc_auc_score(y_test, predictions))) 

 Classification report: precision recall f1-score support 0 0.66 0.88 0.75 168 1 0.38 0.15 0.21 89 avg / total 0.56 0.62 0.56 257 Accuracy for Random Forest Model: 62.26 ROC AUC from first Random Forest Model: 0.51 

結果が非垞に疑わしかったのは驚くこずではありたせん-ROC AUCが玄0.51であるずいうこずは、モデルがコむントスよりもわずかに優れおいるこずを瀺唆しおいたす。


結果をテストしたす。 品質指暙


䞊蚘の1぀の䟋を䜿甚しお、sklearnむンタヌフェむスをサポヌトする1​​぀のアルゎリズムがどのようにトレヌニングされるかを調べたした。 残りはたったく同じ方法でトレヌニングされるため、すべおのアルゎリズムをトレヌニングし、それぞれの堎合に最適なアルゎリズムを遞択するこずしかできたせん。



これは耇雑ではありたせん。アルゎリズムごずに1を暙準蚭定でトレヌニングし、セット党䜓をトレヌニングしお、アルゎリズムの品質に圱響するさたざたなオプションを䞊べ替えたす。 この段階はモデルチュヌニングたたはハむパヌパラメヌタヌ最適化ず呌ばれ、その本質は非垞に簡単です。最良の結果をもたらす蚭定のセットが遞択されたす。


 from model_training import train_classifiers from data_loaders import load_processed_data import warnings warnings.filterwarnings('ignore') #   hogwarts_df = load_processed_data() #     data_full = hogwarts_df.drop( [ 'name', 'surname', 'is_griffindor', 'is_hufflpuff', 'is_ravenclaw' ], axis=1).copy() X_data = data_full.drop('is_slitherin', axis=1) y = data_full.is_slitherin #    slitherin_models = train_classifiers(data_full, X_data, y) score_testing_dataset(slitherin_models[5]) 

   — 0.09437856871661066 Kirill Malev — 0.20820536334902712   — 0.07550095601699099 Harry Potter — 0.07683794773639624   — 0.9414529336862744   — 0.9293671807790949 Severus Snape — 0.6576783576162999   — 0.18577792617672767 Tom Riddle — 0.8351835484058869   — 0.25930925139546795 Salazar Slytherin — 0.24008788903854789 

このバヌゞョンの数倀は過去よりも䞻芳的には良く芋えたすが、内郚の完璧䞻矩者にはただ十分ではありたせん。 したがっお、より深いレベルに進み、タスクの補品感芚に戻りたす。ヒヌロヌが分垃垜子によっお決定される最も可胜性の高い教員を予枬する必芁がありたす。 ぀たり、孊郚ごずにモデルをトレヌニングする必芁がありたす。



 >> from model_training import train_all_models #      >> slitherin_models, griffindor_models, ravenclaw_models, hufflpuff_models = \ train_all_models() 

結果ず倚項回垰の結果の長い結論
 SVM Default Report Accuracy for SVM Default: 73.93 ROC AUC for SVM Default: 0.53 Tuned SVM Report Accuracy for Tuned SVM: 72.37 ROC AUC for Tuned SVM: 0.50 KNN Default Report Accuracy for KNN Default: 70.04 ROC AUC for KNN Default: 0.58 Tuned KNN Report Accuracy for Tuned KNN: 69.65 ROC AUC for Tuned KNN: 0.58 XGBoost Default Report Accuracy for XGBoost Default: 70.43 ROC AUC for XGBoost Default: 0.54 Tuned XGBoost Report Accuracy for Tuned XGBoost: 68.09 ROC AUC for Tuned XGBoost: 0.56 Random Forest Default Report Accuracy for Random Forest Default: 73.93 ROC AUC for Random Forest Default: 0.62 Tuned Random Forest Report Accuracy for Tuned Random Forest: 74.32 ROC AUC for Tuned Random Forest: 0.54 Extra Trees Default Report Accuracy for Extra Trees Default: 69.26 ROC AUC for Extra Trees Default: 0.57 Tuned Extra Trees Report Accuracy for Tuned Extra Trees: 73.54 ROC AUC for Tuned Extra Trees: 0.55 LGBM Default Report Accuracy for LGBM Default: 70.82 ROC AUC for LGBM Default: 0.62 Tuned LGBM Report Accuracy for Tuned LGBM: 74.71 ROC AUC for Tuned LGBM: 0.53 RGF Default Report Accuracy for RGF Default: 70.43 ROC AUC for RGF Default: 0.58 Tuned RGF Report Accuracy for Tuned RGF: 71.60 ROC AUC for Tuned RGF: 0.60 FRGF Default Report Accuracy for FRGF Default: 68.87 ROC AUC for FRGF Default: 0.59 Tuned FRGF Report Accuracy for Tuned FRGF: 69.26 ROC AUC for Tuned FRGF: 0.59 SVM Default Report Accuracy for SVM Default: 70.43 ROC AUC for SVM Default: 0.50 Tuned SVM Report Accuracy for Tuned SVM: 71.60 ROC AUC for Tuned SVM: 0.50 KNN Default Report Accuracy for KNN Default: 63.04 ROC AUC for KNN Default: 0.49 Tuned KNN Report Accuracy for Tuned KNN: 65.76 ROC AUC for Tuned KNN: 0.50 XGBoost Default Report Accuracy for XGBoost Default: 69.65 ROC AUC for XGBoost Default: 0.54 Tuned XGBoost Report Accuracy for Tuned XGBoost: 68.09 ROC AUC for Tuned XGBoost: 0.50 Random Forest Default Report Accuracy for Random Forest Default: 66.15 ROC AUC for Random Forest Default: 0.51 Tuned Random Forest Report Accuracy for Tuned Random Forest: 70.43 ROC AUC for Tuned Random Forest: 0.50 Extra Trees Default Report Accuracy for Extra Trees Default: 64.20 ROC AUC for Extra Trees Default: 0.49 Tuned Extra Trees Report Accuracy for Tuned Extra Trees: 70.82 ROC AUC for Tuned Extra Trees: 0.51 LGBM Default Report Accuracy for LGBM Default: 67.70 ROC AUC for LGBM Default: 0.56 Tuned LGBM Report Accuracy for Tuned LGBM: 70.82 ROC AUC for Tuned LGBM: 0.50 RGF Default Report Accuracy for RGF Default: 66.54 ROC AUC for RGF Default: 0.52 Tuned RGF Report Accuracy for Tuned RGF: 65.76 ROC AUC for Tuned RGF: 0.53 FRGF Default Report Accuracy for FRGF Default: 65.76 ROC AUC for FRGF Default: 0.53 Tuned FRGF Report Accuracy for Tuned FRGF: 69.65 ROC AUC for Tuned FRGF: 0.52 SVM Default Report Accuracy for SVM Default: 74.32 ROC AUC for SVM Default: 0.50 Tuned SVM Report Accuracy for Tuned SVM: 74.71 ROC AUC for Tuned SVM: 0.51 KNN Default Report Accuracy for KNN Default: 69.26 ROC AUC for KNN Default: 0.48 Tuned KNN Report Accuracy for Tuned KNN: 73.15 ROC AUC for Tuned KNN: 0.49 XGBoost Default Report Accuracy for XGBoost Default: 72.76 ROC AUC for XGBoost Default: 0.49 Tuned XGBoost Report Accuracy for Tuned XGBoost: 74.32 ROC AUC for Tuned XGBoost: 0.50 Random Forest Default Report Accuracy for Random Forest Default: 73.93 ROC AUC for Random Forest Default: 0.52 Tuned Random Forest Report Accuracy for Tuned Random Forest: 74.32 ROC AUC for Tuned Random Forest: 0.50 Extra Trees Default Report Accuracy for Extra Trees Default: 73.93 ROC AUC for Extra Trees Default: 0.52 Tuned Extra Trees Report Accuracy for Tuned Extra Trees: 73.93 ROC AUC for Tuned Extra Trees: 0.50 LGBM Default Report Accuracy for LGBM Default: 73.54 ROC AUC for LGBM Default: 0.52 Tuned LGBM Report Accuracy for Tuned LGBM: 74.32 ROC AUC for Tuned LGBM: 0.50 RGF Default Report Accuracy for RGF Default: 73.54 ROC AUC for RGF Default: 0.51 Tuned RGF Report Accuracy for Tuned RGF: 73.93 ROC AUC for Tuned RGF: 0.50 FRGF Default Report Accuracy for FRGF Default: 73.93 ROC AUC for FRGF Default: 0.53 Tuned FRGF Report Accuracy for Tuned FRGF: 73.93 ROC AUC for Tuned FRGF: 0.50 SVM Default Report Accuracy for SVM Default: 80.54 ROC AUC for SVM Default: 0.50 Tuned SVM Report Accuracy for Tuned SVM: 80.93 ROC AUC for Tuned SVM: 0.52 KNN Default Report Accuracy for KNN Default: 78.60 ROC AUC for KNN Default: 0.50 Tuned KNN Report Accuracy for Tuned KNN: 80.16 ROC AUC for Tuned KNN: 0.51 XGBoost Default Report Accuracy for XGBoost Default: 80.54 ROC AUC for XGBoost Default: 0.50 Tuned XGBoost Report Accuracy for Tuned XGBoost: 77.04 ROC AUC for Tuned XGBoost: 0.52 Random Forest Default Report Accuracy for Random Forest Default: 77.43 ROC AUC for Random Forest Default: 0.49 Tuned Random Forest Report Accuracy for Tuned Random Forest: 80.54 ROC AUC for Tuned Random Forest: 0.50 Extra Trees Default Report Accuracy for Extra Trees Default: 76.26 ROC AUC for Extra Trees Default: 0.48 Tuned Extra Trees Report Accuracy for Tuned Extra Trees: 78.60 ROC AUC for Tuned Extra Trees: 0.50 LGBM Default Report Accuracy for LGBM Default: 75.49 ROC AUC for LGBM Default: 0.51 Tuned LGBM Report Accuracy for Tuned LGBM: 80.54 ROC AUC for Tuned LGBM: 0.50 RGF Default Report Accuracy for RGF Default: 78.99 ROC AUC for RGF Default: 0.52 Tuned RGF Report Accuracy for Tuned RGF: 75.88 ROC AUC for Tuned RGF: 0.55 FRGF Default Report Accuracy for FRGF Default: 76.65 ROC AUC for FRGF Default: 0.50 #   ,        

 from sklearn.linear_model import LogisticRegression clf = LogisticRegression(random_state=0, solver='lbfgs', multi_class='multinomial') hogwarts_df = load_processed_data_multi() #     data_full = hogwarts_df.drop( [ 'name', 'surname', ], axis=1).copy() X_data = data_full.drop('faculty', axis=1) y = data_full.faculty clf.fit(X_data, y) score_testing_dataset(clf) 

   — [0.3602361 0.16166944 0.16771712 0.31037733] Kirill Malev — [0.47473072 0.16051924 0.13511385 0.22963619]   — [0.38697926 0.19330242 0.17451052 0.2452078 ] Harry Potter — [0.40245098 0.16410043 0.16023278 0.27321581]   — [0.13197025 0.16438855 0.17739254 0.52624866]   — [0.17170203 0.1205678 0.14341742 0.56431275] Severus Snape — [0.15558044 0.21589378 0.17370406 0.45482172]   — [0.39301231 0.07397324 0.1212741 0.41174035] Tom Riddle — [0.26623969 0.14194379 0.1728505 0.41896601]   — [0.24843037 0.21632736 0.21532696 0.3199153 ] Salazar Slytherin — [0.09359144 0.26735897 0.2742305 0.36481909] 

confusion_matrix:


 confusion_matrix(clf.predict(X_data), y) 

 array([[144, 68, 64, 78], [ 8, 9, 8, 6], [ 22, 18, 31, 20], [ 77, 73, 78, 151]]) 

 def get_predctions_vector (models, person): predictions = [get_predictions_vector (model, person)[1] for model in models] return { 'slitherin': predictions[0], 'griffindor': predictions[1], 'ravenclaw': predictions[2], 'hufflpuff': predictions[3] } def score_testing_dataset (models): testing_dataset = [ " ", "Kirill Malev", " ", "Harry Potter", " ", " ","Severus Snape", " ", "Tom Riddle", " ", "Salazar Slytherin"] data = [] for name in testing_dataset: predictions = get_predctions_vector(models, name) predictions['name'] = name data.append(predictions) scoring_df = pd.DataFrame(data, columns=['name', 'slitherin', 'griffindor', 'hufflpuff', 'ravenclaw']) return scoring_df # Data Science —    ,       top_models = [ slitherin_models[3], griffindor_models[3], ravenclaw_models[3], hufflpuff_models[3] ] score_testing_dataset(top_models) 

  name slitherin griffindor hufflpuff ravenclaw 0   0.349084 0.266909 0.110311 0.091045 1 Kirill Malev 0.289914 0.376122 0.384986 0.103056 2   0.338258 0.400841 0.016668 0.124825 3 Harry Potter 0.245377 0.357934 0.026287 0.154592 4   0.917423 0.126997 0.176640 0.096570 5   0.969693 0.106384 0.150146 0.082195 6 Severus Snape 0.663732 0.259189 0.290252 0.074148 7   0.268466 0.579401 0.007900 0.083195 8 Tom Riddle 0.639731 0.541184 0.084395 0.156245 9   0.653595 0.147506 0.172940 0.137134 10 Salazar Slytherin 0.647399 0.169964 0.095450 0.26126 


, . ROC AUC , 0.5. , :



, , , , XGBoost CV , .


重芁 , 70% . , 4 .


 from model_training import train_production_models from xgboost import XGBClassifier best_models = [] for i in range (0,4): best_models.append(XGBClassifier(base_score=0.5, booster='gbtree', colsample_bylevel=1, colsample_bytree=0.7, gamma=0, learning_rate=0.05, max_delta_step=0, max_depth=6, min_child_weight=11, missing=-999, n_estimators=1000, n_jobs=1, nthread=4, objective='binary:logistic', random_state=0, reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=1337, silent=1, subsample=0.8)) slitherin_model, griffindor_model, ravenclaw_model, hufflpuff_model = \ train_production_models(best_models) top_models = slitherin_model, griffindor_model, ravenclaw_model, hufflpuff_model score_testing_dataset(top_models) 

 name slitherin griffindor hufflpuff ravenclaw 0   0.273713 0.372337 0.065923 0.279577 1 Kirill Malev 0.401603 0.761467 0.111068 0.023902 2   0.031540 0.616535 0.196342 0.217829 3 Harry Potter 0.183760 0.422733 0.119393 0.173184 4   0.945895 0.021788 0.209820 0.019449 5   0.950932 0.088979 0.084131 0.012575 6 Severus Snape 0.634035 0.088230 0.249871 0.036682 7   0.426440 0.431351 0.028444 0.083636 8 Tom Riddle 0.816804 0.136530 0.069564 0.035500 9   0.409634 0.213925 0.028631 0.252723 10 Salazar Slytherin 0.824590 0.067910 0.111147 0.085710 

, , .


, , . .


 import pickle pickle.dump(slitherin_model, open("../output/slitherin.xgbm", "wb")) pickle.dump(griffindor_model, open("../output/griffindor.xgbm", "wb")) pickle.dump(ravenclaw_model, open("../output/ravenclaw.xgbm", "wb")) pickle.dump(hufflpuff_model, open("../output/hufflpuff.xgbm", "wb")) 


, . , , , .


, , . , . , Data Scientist — -.


:



, docker-, python-. , flask.


 from __future__ import print_function # In python 2.7 import os import subprocess import json import re from flask import Flask, request, jsonify from inspect import getmembers, ismethod import numpy as npb import pandas as pd import math import os import pickle import xgboost as xgb import sys from letter import Letter from talking_hat import * from sklearn.ensemble import RandomForestClassifier import warnings def prod_predict_classes_for_name (full_name): featurized_person = parse_line_to_hogwarts_df(full_name) person_df = pd.DataFrame(featurized_person, columns=[ 'name', 'surname', 'is_english', 'name_starts_with_vowel', 'name_starts_with_consonant', 'name_ends_with_vowel', 'name_ends_with_consonant', 'name_length', 'name_vowels_count', 'name_double_vowels_count', 'name_consonant_count', 'name_double_consonant_count', 'name_paired_count', 'name_deaf_count', 'name_sonorus_count', 'surname_starts_with_vowel', 'surname_starts_with_consonant', 'surname_ends_with_vowel', 'surname_ends_with_consonant', 'surname_length', 'surname_vowels_count', 'surname_double_vowels_count', 'surname_consonant_count', 'surname_double_consonant_count', 'surname_paired_count', 'surname_deaf_count', 'surname_sonorus_count', ], index=[0] ) slitherin_model = pickle.load(open("models/slitherin.xgbm", "rb")) griffindor_model = pickle.load(open("models/griffindor.xgbm", "rb")) ravenclaw_model = pickle.load(open("models/ravenclaw.xgbm", "rb")) hufflpuff_model = pickle.load(open("models/hufflpuff.xgbm", "rb")) predictions = get_predctions_vector([ slitherin_model, griffindor_model, ravenclaw_model, hufflpuff_model ], person_df.drop(['name', 'surname'], axis=1)) return { 'slitherin': float(predictions[0][1]), 'griffindor': float(predictions[1][1]), 'ravenclaw': float(predictions[2][1]), 'hufflpuff': float(predictions[3][1]) } def predict(params): fullname = params['fullname'] print(params) return prod_predict_classes_for_name(fullname) def create_app(): app = Flask(__name__) functions_list = [predict] @app.route('/<func_name>', methods=['POST']) def api_root(func_name): for function in functions_list: if function.__name__ == func_name: try: json_req_data = request.get_json() if json_req_data: res = function(json_req_data) else: return jsonify({"error": "error in receiving the json input"}) except Exception as e: data = { "error": "error while running the function" } if hasattr(e, 'message'): data['message'] = e.message elif len(e.args) >= 1: data['message'] = e.args[0] return jsonify(data) return jsonify({"success": True, "result": res}) output_string = 'function: %s not found' % func_name return jsonify({"error": output_string}) return app if __name__ == '__main__': app = create_app() app.run(host='0.0.0.0') 

Dockerfile:


 FROM datmo/python-base:cpu-py35 #  python3-wheel,        RUN apt-get update; apt-get install -y python3-pip python3-numpy python3-scipy python3-wheel ADD requirements.txt / RUN pip3 install -r /requirements.txt RUN mkdir /code;mkdir /code/models COPY ./python_api.py ./talking_hat.py ./letter.py ./request.py /code/ COPY ./models/* /code/models/ WORKDIR /code CMD python3 /code/python_api.py 

:


 docker build -t talking_hat . && docker rm talking_hat && docker run --name talking_hat -p 5000:5000 talking_hat 


— . , Apache Benchmark . , . — .


 $ ab -p data.json -T application/json -c 50 -n 10000 http://0.0.0.0:5000/predict 

ab
 This is ApacheBench, Version 2.3 <$Revision: 1807734 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 0.0.0.0 (be patient) Completed 1000 requests Completed 2000 requests Completed 3000 requests Completed 4000 requests Completed 5000 requests Completed 6000 requests Completed 7000 requests Completed 8000 requests Completed 9000 requests Completed 10000 requests Finished 10000 requests Server Software: Werkzeug/0.14.1 Server Hostname: 0.0.0.0 Server Port: 5000 Document Path: /predict Document Length: 141 bytes Concurrency Level: 50 Time taken for tests: 238.552 seconds Complete requests: 10000 Failed requests: 0 Total transferred: 2880000 bytes Total body sent: 1800000 HTML transferred: 1410000 bytes Requests per second: 41.92 [#/sec] (mean) Time per request: 1192.758 [ms] (mean) Time per request: 23.855 [ms] (mean, across all concurrent requests) Transfer rate: 11.79 [Kbytes/sec] received 7.37 kb/s sent 19.16 kb/s total Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.1 0 3 Processing: 199 1191 352.5 1128 3352 Waiting: 198 1190 352.5 1127 3351 Total: 202 1191 352.5 1128 3352 Percentage of the requests served within a certain time (ms) 50% 1128 66% 1277 75% 1378 80% 1451 90% 1668 95% 1860 98% 2096 99% 2260 100% 3352 (longest request) 

, :


 def prod_predict_classes_for_name (full_name): <...> predictions = get_predctions_vector([ app.slitherin_model, app.griffindor_model, app.ravenclaw_model, app.hufflpuff_model ], person_df.drop(['name', 'surname'], axis=1)) return { 'slitherin': float(predictions[0][1]), 'griffindor': float(predictions[1][1]), 'ravenclaw': float(predictions[2][1]), 'hufflpuff': float(predictions[3][1]) } def create_app(): <...> with app.app_context(): app.slitherin_model = pickle.load(open("models/slitherin.xgbm", "rb")) app.griffindor_model = pickle.load(open("models/griffindor.xgbm", "rb")) app.ravenclaw_model = pickle.load(open("models/ravenclaw.xgbm", "rb")) app.hufflpuff_model = pickle.load(open("models/hufflpuff.xgbm", "rb")) return app 

:


 $ docker build -t talking_hat . && docker rm talking_hat && docker run --name talking_hat -p 5000:5000 talking_hat $ ab -p data.json -T application/json -c 50 -n 10000 http://0.0.0.0:5000/predict 

ab
 This is ApacheBench, Version 2.3 <$Revision: 1807734 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 0.0.0.0 (be patient) Completed 1000 requests Completed 2000 requests Completed 3000 requests Completed 4000 requests Completed 5000 requests Completed 6000 requests Completed 7000 requests Completed 8000 requests Completed 9000 requests Completed 10000 requests Finished 10000 requests Server Software: Werkzeug/0.14.1 Server Hostname: 0.0.0.0 Server Port: 5000 Document Path: /predict Document Length: 141 bytes Concurrency Level: 50 Time taken for tests: 219.812 seconds Complete requests: 10000 Failed requests: 3 (Connect: 0, Receive: 0, Length: 3, Exceptions: 0) Total transferred: 2879997 bytes Total body sent: 1800000 HTML transferred: 1409997 bytes Requests per second: 45.49 [#/sec] (mean) Time per request: 1099.062 [ms] (mean) Time per request: 21.981 [ms] (mean, across all concurrent requests) Transfer rate: 12.79 [Kbytes/sec] received 8.00 kb/s sent 20.79 kb/s total Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.1 0 2 Processing: 235 1098 335.2 1035 3464 Waiting: 235 1097 335.2 1034 3462 Total: 238 1098 335.2 1035 3464 Percentage of the requests served within a certain time (ms) 50% 1035 66% 1176 75% 1278 80% 1349 90% 1541 95% 1736 98% 1967 99% 2141 100% 3464 (longest request) 

できた . , .


おわりに


, . - .


, :



, , . , !


この蚘事は、デヌタ分析の分野でロシア語を話す倚数の専門家を集めたオヌプンデヌタサむ゚ンスコミュニティなしでは公開されなかったでしょう。



Source: https://habr.com/ru/post/J430006/


All Articles