{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Báo cáo BTL môn Học máy\n- Mã lớp: 2021II_INT3405_20 (GV: Trần Quốc Long)\n- Sinh viên: Trần Tuấn Anh\n- MSSV: 18020149","metadata":{}},{"cell_type":"markdown","source":"# Mô tả bài toán\n\nQuora là một nền tảng cho phép mọi người học hỏi lẫn nhau. Trên Quora, mọi người có thể đặt câu hỏi và kết nối với những người khác, những người đóng góp thông tin chi tiết độc đáo và câu trả lời chất lượng. Một thách thức quan trọng là loại bỏ những câu hỏi thiếu chân thành - những câu hỏi được đặt ra dựa trên những tiền đề sai lầm hoặc có ý định đưa ra một tuyên bố hơn là tìm kiếm những câu trả lời hữu ích.\n\nBài toán đặt ra là phân loại câu hỏi trên quora xem đâu là chân thành hay thiếu chân thành.\n- Input: Câu hỏi dưới dạng văn bản\n- Output: 0/1 (Yes/No)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"markdown","source":"# Nội dung bài báo cáo\n\n1. Khảo sát dữ liệu\n2. Xử lý dữ liệu\n3. Chuẩn bị mô hình huấn luyện\n4. Huấn luyện và dự đoán\n5. Thử nghiệm và cải thiện\n6. Submit test","metadata":{}},{"cell_type":"markdown","source":"**Import các module cần thiết**","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\nimport gc\nimport re\nimport spacy\n\nfrom wordcloud import WordCloud, STOPWORDS, ImageColorGenerator\n\nfrom nltk.stem import PorterStemmer, SnowballStemmer\nfrom nltk.stem.lancaster import LancasterStemmer\n\nfrom keras.preprocessing.text import Tokenizer\nfrom keras.preprocessing.sequence import pad_sequences\nfrom keras import backend as K\nfrom keras.layers import *\nfrom keras.models import *\nfrom keras.initializers import Constant\nfrom keras.utils import plot_model\nfrom keras.optimizers import Adam\n\nfrom sklearn import metrics\nfrom sklearn.model_selection import train_test_split, KFold, StratifiedKFold\nfrom sklearn.datasets import make_classification\n\nfrom tqdm.notebook import tqdm\nfrom IPython.core.display import display, HTML\ntqdm().pandas()\n\npd_ctx = pd.option_context('display.max_colwidth', 100)\npd.set_option('display.float_format', lambda x: '%.3f' % x)","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:21:16.183408Z","iopub.execute_input":"2021-06-10T15:21:16.184027Z","iopub.status.idle":"2021-06-10T15:21:24.80951Z","shell.execute_reply.started":"2021-06-10T15:21:16.183923Z","shell.execute_reply":"2021-06-10T15:21:24.808593Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 1. Khảo sát dữ liệu","metadata":{}},{"cell_type":"code","source":"# đọc file dữ liệu để train\nTRAIN_FILE = '/kaggle/input/quora-insincere-questions-classification/train.csv'\nTEST_FILE = '/kaggle/input/quora-insincere-questions-classification/test.csv'\ndf = pd.read_csv(TRAIN_FILE)\ndf.info()\n\ntest_df = pd.read_csv(TEST_FILE)\nwith pd_ctx:\n    print(\"Sincere question\")\n    display(df[df['target'] == 0].head())\n    print(\"Insincere question\")\n    display(df[df['target'] == 1].head())","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:21:24.810873Z","iopub.execute_input":"2021-06-10T15:21:24.811254Z","iopub.status.idle":"2021-06-10T15:21:31.405004Z","shell.execute_reply.started":"2021-06-10T15:21:24.811225Z","shell.execute_reply":"2021-06-10T15:21:31.403938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Kích thước train.csv:**\n* Số dòng: 1.31 millions\n* Số cột: 3\n\n**Data field**\n+ `qid`: mã số của câu hỏi (question identifier)\n+ `quesntion_text`: nội dung của câu hỏi cần phân loại (type: text)\n+ `target`: nhãn của câu hỏi, câu chứa nội dung toxic có nhãn là 1, ngược lại là 0 (type: int)\n\nKhông có dữ liệu nào bất thường (missing, null)","metadata":{}},{"cell_type":"code","source":"df['word_count']= df.question_text.progress_apply(lambda x: len(x.split()))\ndata_neg = df[df['target']==0]\ndata_pos = df[df['target']==1]\nstatistic = pd.merge(\n    data_neg[['word_count']].describe(percentiles=[.8, .9999]), \n    data_pos[['word_count']].describe(percentiles=[.8, .9999]), \n    left_index=True, right_index=True, suffixes=('_sincere', '_insincere')\n)\ncolLabels = statistic.columns\ncellText = statistic.round(2).values\nrowLabels = statistic.index\n\nfig, axes = plt.subplots(nrows=1, ncols=2)\naxes[0] = fig.add_axes([0,0,1,1])\naxes[0].bar(['sincere question', 'insincere question'], df.target.value_counts())\nfor p in axes[0].patches:\n    width = p.get_width()\n    height = p.get_height()\n    percent = height / len(df)\n    x, y = p.get_xy() \n    axes[0].annotate(f'{percent:.2%}', (x + width/2, y + height + 0.01*len(df)), ha='center')\naxes[1].axis('off')\nmpl_table = axes[1].table(cellText = cellText, colLabels=colLabels, rowLabels = rowLabels, bbox=[2, 0, 2, 1.5], )\nmpl_table.auto_set_font_size(False)\nmpl_table.set_fontsize(14)","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:21:31.406669Z","iopub.execute_input":"2021-06-10T15:21:31.407012Z","iopub.status.idle":"2021-06-10T15:21:36.312633Z","shell.execute_reply.started":"2021-06-10T15:21:31.406978Z","shell.execute_reply":"2021-06-10T15:21:36.311647Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Nhận xét về phân lớp dữ liệu**\n\nDựa vào biểu đồ trên, ta nhận thấy dữ liệu được chia thành 2 class: 0 (sincere question) và 1 (insincere question)\n\n- class 0 : 1225312 dữ liệu chiếm 93.81%\n- class 1 : 80810 dữ liệu chiếm 6.19%\n\n=> Bộ dữ liệu để đào tạo bị mất cân bằng (kết quả negative gấp 15 lần positive)\n\nTỉ lệ dữ liệu 15:1 thường sẽ dẫn đến ngộ nhận chất lượng mô hình. Khi đó thước đo đánh giá mô hình là độ chính xác (accuracy) có thể đạt được rất cao mà không cần tới mô hình. Ví dụ, một dự báo ngẫu nhiên đưa ra tất cả đều là nhóm đa số thì độ chính xác đã đạt được là 93%. Do đó không nên lựa chọn độ chính xác làm chỉ số đánh giá mô hình để tránh lạc quan sai lầm về chất lượng.\n\n=> Trong phần báo cáo này, mình sẽ sử dụng chỉ số `F1_score` để đánh giá mô hình.\n\n**Nói qua về [F1 score](https://en.wikipedia.org/wiki/F-score):**\n\n`F1_score` là trung bình điều hòa giữa `precision` (độ chính xác) và `recall` (độ bao phủ)\n\nPrecision: trong tập tìm được thì bao nhiêu cái (phân loại) đúng.\n\nRecall: trong số các tồn tại, tìm ra được bao nhiêu cái (phân loại).\n\n\n\n\n**Nhận xét độ dài của các câu trong bộ dữ liệu**\n\n- Câu chân thành\n        Độ dài chung bình khoảng 12,5 từ. Câu dài nhất là 134 từ.\n        80% số câu có ít hơn hoặc bằng 15 từ.\n        Hầu như đều có dưới 53 từ.\n- Câu không chân thành \n        Độ dài trung bình là 17.3 từ. Câu dài nhát là 64 từ.\n        80% số câu ít hơn hoặc bằng 25 từ.\n        Hầu như đều có dưới 54 từ.\n\n=> Câu không chân thành có xu hướng dài hơn câu chân thành. Và độ dài của các câu chủ yếu nhỏ hơn 60 ký tự (giá trị này sẽ được dùng sau này)","metadata":{}},{"cell_type":"markdown","source":"### Khảo sát các từ xuất hiện nhiều trong từ phân lớp","metadata":{}},{"cell_type":"code","source":"def cloud(docs, title):\n    wordcloud = WordCloud(width=800, height=400, collocations=False, background_color=\"white\").generate(\" \".join(docs))\n    fig = plt.figure(figsize=(10,7), facecolor='w')\n    plt.imshow(wordcloud)\n    plt.axis('off')\n    plt.title(title, fontsize=25,color='k')\n    plt.tight_layout(pad=0)\n    plt.show()\ncloud(data_neg.question_text, \"Sincere question\")\ncloud(data_pos.question_text, \"Insincere question\")","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:21:36.314437Z","iopub.execute_input":"2021-06-10T15:21:36.315022Z","iopub.status.idle":"2021-06-10T15:22:03.894582Z","shell.execute_reply.started":"2021-06-10T15:21:36.314975Z","shell.execute_reply":"2021-06-10T15:22:03.893745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Nhận xét**\n\n- Word Cloud là một kỹ thuật trực quan hóa dữ liệu được sử dụng để biểu diễn dữ liệu văn bản, trong đó kích thước của mỗi từ cho biết tần suất hoặc tầm quan trọng của nó.\n- 2 word cloud khá tương tự nhau (khi so sánh về các từ nổi bật)\n- Các danh từ riêng xuất hiện nhiều hơn ở câu không chân thành\n","metadata":{}},{"cell_type":"markdown","source":"**Thống kê**","metadata":{}},{"cell_type":"code","source":"def statistic(df):\n    stats = pd.DataFrame();\n    stats['question_text'] = df['question_text']\n    stats['sp_char_words'] = stats['question_text'].str.findall(r'[^a-zA-Z0-9 ]').str.len()\n    stats['num_capital'] = stats['question_text'].progress_map(lambda x: len([c for c in str(x) if c.isupper()]))\n    stats['num_numerics'] = stats['question_text'].progress_map(lambda x: sum(c.isdigit() for c in x))\n    stats['num_stopwords'] = stats['question_text'].progress_map(lambda x: len([c for c in str(x).lower().split() if c in STOPWORDS]))\n    return stats\n# df_stat = statistic(df)\n# df_stat[['sp_char_words','num_capital', 'num_numerics', 'num_stopwords']].describe()","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:22:03.895642Z","iopub.execute_input":"2021-06-10T15:22:03.896077Z","iopub.status.idle":"2021-06-10T15:22:03.90333Z","shell.execute_reply.started":"2021-06-10T15:22:03.896046Z","shell.execute_reply":"2021-06-10T15:22:03.902363Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Nhận xét: Nhìn chung, dữ liệu dạng text chứa khá nhiều yêu tố gây nhiễu (kí tự đặc biệt, kí tự số, chữ hoa chữ thường)\n\nVì vậy ta cần có bước xử lý các ký tự đặc biệt, stopword (nếu cần)\n\n","metadata":{}},{"cell_type":"markdown","source":"# 2. Xử lý dữ liệu","metadata":{}},{"cell_type":"markdown","source":"Sau khi đánh giá ta thấy dữ liệu còn khá phức tạp và nhiều nhiễu. Để đơn giản hoá dữ liệu ta có thể thực hiện một số bước sau:\n- Loại bỏ các công thức toán học, đường dẫn\n- Chuẩn hóa các từ viết tắt thành dạng đầy đủ của nó\n- Sửa lỗi một số từ đặc biệt, hoặc bị sai chính tả \n- Xóa bỏ các ký tự đặc biệt (chỉ giữ lại số và chữ)\n\nRiêng về stopword, em nhân thấy rằng sau khi bỏ thì khả năng phân loại của mô hình bị giảm xuống, nên phần xử lý dữ liệu em sẽ để nguyên stopword","metadata":{}},{"cell_type":"code","source":"# dữ liệu để huấn luyện\ntrain = df.sample(frac = 1,random_state=123).reset_index(drop=True) # shuffle dữ liệu\n\n# Để demo nhanh, ở đây mình lấy ra 100 mẫu dữ liệu sample\nsample = train.sample(n=100, random_state=123)\nwith pd_ctx:\n    display(sample)","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:22:03.904677Z","iopub.execute_input":"2021-06-10T15:22:03.905132Z","iopub.status.idle":"2021-06-10T15:22:04.874382Z","shell.execute_reply.started":"2021-06-10T15:22:03.905088Z","shell.execute_reply":"2021-06-10T15:22:04.873549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## a. Cleaning data","metadata":{}},{"cell_type":"markdown","source":"**`clean_tag()`:** hàm này sẽ loại bỏ các biểu thức toán học, thay thế chúng bằng 'MATH EQUATION' và thay thế các đường liên kết bằng 'URL'. Bởi vì các biểu thức toán học và các đường link thường không mang nhiều ý nghĩa, không những vậy nó còn có thể gây ra nhiễu.\n\n**`contraction_fix()`:** Chuyển những từ viết tắt thành hoàn chỉnh để tránh xảy ra sự hiểu lầm.\n\n**`misspell_fix()`:** Do dữ liệu được thu thập trên Qoura, nên không thể tránh được việc bị sai chính tả. Nên việc sửa các từ bị sai chính tả là cần thiết, mục đích cũng giống với sửa các từ viết tắt. Nhưng ta không thể biết được hết các khả năng sai chính tả được, nên mình sẽ chỉ sửa những từ sai chính tả thường gặp, hoặc thay thế một số từ tối nghĩa thành từ đồng nghĩa với nó.","metadata":{}},{"cell_type":"code","source":"# Làm sạch câu\ncontractions= {\"i'm\": 'i am',\"i'm'a\": 'i am about to',\"i'm'o\": 'i am going to',\"i've\": 'i have',\"i'll\": 'i will',\"i'll've\": 'i will have',\"i'd\": 'i would',\"i'd've\": 'i would have',\"Whatcha\": 'What are you',\"amn't\": 'am not',\"ain't\": 'are not',\"aren't\": 'are not',\"'cause\": 'because',\"can't\": 'can not',\"can't've\": 'can not have',\"could've\": 'could have',\"couldn't\": 'could not',\"couldn't've\": 'could not have',\"daren't\": 'dare not',\"daresn't\": 'dare not',\"dasn't\": 'dare not',\"didn't\": 'did not','didn’t': 'did not',\"don't\": 'do not','don’t': 'do not',\"doesn't\": 'does not',\"e'er\": 'ever',\"everyone's\": 'everyone is',\"finna\": 'fixing to',\"gimme\": 'give me',\"gon't\": 'go not',\"gonna\": 'going to',\"gotta\": 'got to',\"hadn't\": 'had not',\"hadn't've\": 'had not have',\"hasn't\": 'has not',\"haven't\": 'have not',\"he've\": 'he have',\"he's\": 'he is',\"he'll\": 'he will',\"he'll've\": 'he will have',\"he'd\": 'he would',\"he'd've\": 'he would have',\"here's\": 'here is',\"how're\": 'how are',\"how'd\": 'how did',\"how'd'y\": 'how do you',\"how's\": 'how is',\"how'll\": 'how will',\"isn't\": 'is not',\"it's\": 'it is',\"'tis\": 'it is',\"'twas\": 'it was',\"it'll\": 'it will',\"it'll've\": 'it will have',\"it'd\": 'it would',\"it'd've\": 'it would have',\"kinda\": 'kind of',\"let's\": 'let us',\"luv\": 'love',\"ma'am\": 'madam',\"may've\": 'may have',\"mayn't\": 'may not',\"might've\": 'might have',\"mightn't\": 'might not',\"mightn't've\": 'might not have',\"must've\": 'must have',\"mustn't\": 'must not',\"mustn't've\": 'must not have',\"needn't\": 'need not',\"needn't've\": 'need not have',\"ne'er\": 'never',\"o'\": 'of',\"o'clock\": 'of the clock',\"ol'\": 'old',\"oughtn't\": 'ought not',\"oughtn't've\": 'ought not have',\"o'er\": 'over',\"shan't\": 'shall not',\"sha'n't\": 'shall not',\"shalln't\": 'shall not',\"shan't've\": 'shall not have',\"she's\": 'she is',\"she'll\": 'she will',\"she'd\": 'she would',\"she'd've\": 'she would have',\"should've\": 'should have',\"shouldn't\": 'should not',\"shouldn't've\": 'should not have',\"so've\": 'so have',\"so's\": 'so is',\"somebody's\": 'somebody is',\"someone's\": 'someone is',\"something's\": 'something is',\"sux\": 'sucks',\"that're\": 'that are',\"that's\": 'that is',\"that'll\": 'that will',\"that'd\": 'that would',\"that'd've\": 'that would have',\"em\": 'them',\"there're\": 'there are',\"there's\": 'there is',\"there'll\": 'there will',\"there'd\": 'there would',\"there'd've\": 'there would have',\"these're\": 'these are',\"they're\": 'they are',\"they've\": 'they have',\"they'll\": 'they will',\"they'll've\": 'they will have',\"they'd\": 'they would',\"they'd've\": 'they would have',\"this's\": 'this is',\"those're\": 'those are',\"to've\": 'to have',\"wanna\": 'want to',\"wasn't\": 'was not',\"we're\": 'we are',\"we've\": 'we have',\"we'll\": 'we will',\"we'll've\": 'we will have',\"we'd\": 'we would',\"we'd've\": 'we would have',\"weren't\": 'were not',\"what're\": 'what are',\"what'd\": 'what did',\"what've\": 'what have',\"what's\": 'what is',\"what'll\": 'what will',\"what'll've\": 'what will have',\"when've\": 'when have',\"when's\": 'when is',\"where're\": 'where are',\"where'd\": 'where did',\"where've\": 'where have',\"where's\": 'where is',\"which's\": 'which is',\"who're\": 'who are',\"who've\": 'who have',\"who's\": 'who is',\"who'll\": 'who will',\"who'll've\": 'who will have',\"who'd\": 'who would',\"who'd've\": 'who would have',\"why're\": 'why are',\"why'd\": 'why did',\"why've\": 'why have',\"why's\": 'why is',\"will've\": 'will have',\"won't\": 'will not',\"won't've\": 'will not have',\"would've\": 'would have',\"wouldn't\": 'would not',\"wouldn't've\": 'would not have',\"y'all\": 'you all',\"y'all're\": 'you all are',\"y'all've\": 'you all have',\"y'all'd\": 'you all would',\"y'all'd've\": 'you all would have',\"you're\": 'you are',\"you've\": 'you have',\"you'll've\": 'you shall have',\"you'll\": 'you will',\"you'd\": 'you would',\"you'd've\": 'you would have','jan.': 'january','feb.': 'february','mar.': 'march','apr.': 'april','jun.': 'june','jul.': 'july','aug.': 'august','sep.': 'september','oct.': 'october','nov.': 'november','dec.': 'december','I’m': 'I am','I’m’a': 'I am about to','I’m’o': 'I am going to','I’ve': 'I have','I’ll': 'I will','I’ll’ve': 'I will have','I’d': 'I would','I’d’ve': 'I would have','amn’t': 'am not','ain’t': 'are not','aren’t': 'are not','’cause': 'because','can’t': 'can not','can’t’ve': 'can not have','could’ve': 'could have','couldn’t': 'could not','couldn’t’ve': 'could not have','daren’t': 'dare not','daresn’t': 'dare not','dasn’t': 'dare not','doesn’t': 'does not','e’er': 'ever','everyone’s': 'everyone is','gon’t': 'go not','hadn’t': 'had not','hadn’t’ve': 'had not have','hasn’t': 'has not','haven’t': 'have not','he’ve': 'he have','he’s': 'he is','he’ll': 'he will','he’ll’ve': 'he will have','he’d': 'he would','he’d’ve': 'he would have','here’s': 'here is','how’re': 'how are','how’d': 'how did','how’d’y': 'how do you','how’s': 'how is','how’ll': 'how will','isn’t': 'is not','it’s': 'it is','’tis': 'it is','’twas': 'it was','it’ll': 'it will','it’ll’ve': 'it will have','it’d': 'it would','it’d’ve': 'it would have','let’s': 'let us','ma’am': 'madam','may’ve': 'may have','mayn’t': 'may not','might’ve': 'might have','mightn’t': 'might not','mightn’t’ve': 'might not have','must’ve': 'must have','mustn’t': 'must not','mustn’t’ve': 'must not have','needn’t': 'need not','needn’t’ve': 'need not have','ne’er': 'never','o’': 'of','o’clock': 'of the clock','ol’': 'old','oughtn’t': 'ought not','oughtn’t’ve': 'ought not have','o’er': 'over','shan’t': 'shall not','sha’n’t': 'shall not','shalln’t': 'shall not','shan’t’ve': 'shall not have','she’s': 'she is','she’ll': 'she will','she’d': 'she would','she’d’ve': 'she would have','should’ve': 'should have','shouldn’t': 'should not','shouldn’t’ve': 'should not have','so’ve': 'so have','so’s': 'so is','somebody’s': 'somebody is','someone’s': 'someone is','something’s': 'something is','that’re': 'that are','that’s': 'that is','that’ll': 'that will','that’d': 'that would','that’d’ve': 'that would have','there’re': 'there are','there’s': 'there is','there’ll': 'there will','there’d': 'there would','there’d’ve': 'there would have','these’re': 'these are','they’re': 'they are','they’ve': 'they have','they’ll': 'they will','they’ll’ve': 'they will have','they’d': 'they would','they’d’ve': 'they would have','this’s': 'this is','those’re': 'those are','to’ve': 'to have','wasn’t': 'was not','we’re': 'we are','we’ve': 'we have','we’ll': 'we will','we’ll’ve': 'we will have','we’d': 'we would','we’d’ve': 'we would have','weren’t': 'were not','what’re': 'what are','what’d': 'what did','what’ve': 'what have','what’s': 'what is','what’ll': 'what will','what’ll’ve': 'what will have','when’ve': 'when have','when’s': 'when is','where’re': 'where are','where’d': 'where did','where’ve': 'where have','where’s': 'where is','which’s': 'which is','who’re': 'who are','who’ve': 'who have','who’s': 'who is','who’ll': 'who will','who’ll’ve': 'who will have','who’d': 'who would','who’d’ve': 'who would have','why’re': 'why are','why’d': 'why did','why’ve': 'why have','why’s': 'why is','will’ve': 'will have','won’t': 'will not','won’t’ve': 'will not have','would’ve': 'would have','wouldn’t': 'would not','wouldn’t’ve': 'would not have','y’all': 'you all','y’all’re': 'you all are','y’all’ve': 'you all have','y’all’d': 'you all would','y’all’d’ve': 'you all would have','you’re': 'you are','you’ve': 'you have','you’ll’ve': 'you shall have','you’ll': 'you will','you’d': 'you would','you’d’ve': 'you would have'}\nmissing_spell = {'colour': 'color', 'centre': 'center', 'favourite': 'favorite', 'travelling': 'traveling', 'counselling': 'counseling', 'theatre': 'theater', 'cancelled': 'canceled', 'labour': 'labor', 'organisation': 'organization', 'wwii': 'world war 2', 'citicise': 'criticize', 'youtu ': 'youtube ', 'Qoura': 'Quora', 'sallary': 'salary', 'Whta': 'What', 'narcisist': 'narcissist', 'howdo': 'how do', 'whatare': 'what are', 'howcan': 'how can', 'howmuch': 'how much', 'howmany': 'how many', 'whydo': 'why do', 'doI': 'do I', 'theBest': 'the best', 'howdoes': 'how does', 'mastrubation': 'masturbation', 'mastrubate': 'masturbate', \"mastrubating\": 'masturbating', 'pennis': 'penis', 'Etherium': 'bitcoin', 'narcissit': 'narcissist', 'bigdata': 'big data', '2k17': '2017', '2k18': '2018', 'qouta': 'quota', 'exboyfriend': 'ex boyfriend', 'airhostess': 'air hostess', \"whst\": 'what', 'watsapp': 'whatsapp', 'demonitisation': 'demonetization', 'demonitization': 'demonetization', 'demonetisation': 'demonetization','electroneum':'bitcoin','nanodegree':'degree','hotstar':'star','dream11':'dream','ftre':'fire','tensorflow':'framework','unocoin':'bitcoin','lnmiit':'limit','unacademy':'academy','altcoin':'bitcoin','altcoins':'bitcoin','litecoin':'bitcoin','coinbase':'bitcoin','cryptocurency':'cryptocurrency','simpliv':'simple','quoras':'quora','schizoids':'psychopath','remainers':'remainder','twinflame':'soulmate','quorans':'quora','brexit':'demonetized','iiest':'institute','dceu':'comics','pessat':'exam','uceed':'college','bhakts':'devotee','boruto':'anime','cryptocoin':'bitcoin','blockchains':'blockchain','fiancee':'fiance','redmi':'smartphone','oneplus':'smartphone','qoura':'quora','deepmind':'framework','ryzen':'cpu','whattsapp':'whatsapp','undertale':'adventure','zenfone':'smartphone','cryptocurencies':'cryptocurrencies','koinex':'bitcoin','zebpay':'bitcoin','binance':'bitcoin','whtsapp':'whatsapp','reactjs':'framework','bittrex':'bitcoin','bitconnect':'bitcoin','bitfinex':'bitcoin','yourquote':'your quote','whyis':'why is','jiophone':'smartphone','dogecoin':'bitcoin','onecoin':'bitcoin','poloniex':'bitcoin','7700k':'cpu','angular2':'framework','segwit2x':'bitcoin','hashflare':'bitcoin','940mx':'gpu','openai':'framework','hashflare':'bitcoin','1050ti':'gpu','nearbuy':'near buy','freebitco':'bitcoin','antminer':'bitcoin','filecoin':'bitcoin','whatapp':'whatsapp','empowr':'empower','1080ti':'gpu','crytocurrency':'cryptocurrency','8700k':'cpu','whatsaap':'whatsapp','g4560':'cpu','payymoney':'pay money','fuckboys':'fuck boys','intenship':'internship','zcash':'bitcoin','demonatisation':'demonetization','narcicist':'narcissist','mastuburation':'masturbation','trignometric':'trigonometric','cryptocurreny':'cryptocurrency','howdid':'how did','crytocurrencies':'cryptocurrencies','phycopath':'psychopath','bytecoin':'bitcoin','possesiveness':'possessiveness','scollege':'college','humanties':'humanities','altacoin':'bitcoin','demonitised':'demonetized','brasília':'brazilia','accolite':'accolyte','econimics':'economics','varrier':'warrier','quroa':'quora','statergy':'strategy','langague':'language','splatoon':'game','7600k':'cpu','gate2018':'gate 2018','in2018':'in 2018','narcassist':'narcissist','jiocoin':'bitcoin','hnlu':'hulu','7300hq':'cpu','weatern':'western','interledger':'blockchain','deplation':'deflation', 'cryptocurrencies':'cryptocurrency', 'bitcoin':'blockchain cryptocurrency'}\n\ndef clean_tag(x):\n    if '[math]' in x:\n        x = re.sub('\\[math\\].*?math\\]', 'math equation', x) #replacing with [MATH EQUATION]\n    if 'http' in x or 'www' in x:\n        x = re.sub('(?:(?:https?|ftp):\\/\\/)?[\\w/\\-?=%.]+\\.[\\w/\\-?=%.]+', 'url', x) #replacing with [url]\n    return x\n\ndef contraction_fix(word):\n    try:\n        a=contractions[word]\n    except KeyError:\n        a=word\n    return a\n\ndef misspell_fix(word):\n    try:\n        a=missing_spell[word]\n    except KeyError:\n        a=word\n    return a\n\n\ndef clean_text(text):\n    text = clean_tag(text) # thay thế các tag thành từ cố định\n    text = \" \".join([contraction_fix(w) for w in text.split()]) # sửa từ viết tắt\n    text = \" \".join([misspell_fix(w) for w in text.split()]) # sửa từ viết sai chính tả\n    text = re.sub(r'[^a-zA-Z0-9]', ' ', text) # Loại bỏ các ký tự không phải chữ và số\n#     text = text.lower()\n    return text\n\ndef apply_clean_text(question_text):\n    tmp = pd.DataFrame()\n    tmp['question_text'] = question_text;\n    tmp['clean'] = tmp.question_text.progress_map(clean_text)\n    with pd_ctx:\n        display(tmp)\n    return tmp['clean']\n        \nsample['clean'] = apply_clean_text(sample.question_text)","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:22:04.875604Z","iopub.execute_input":"2021-06-10T15:22:04.876001Z","iopub.status.idle":"2021-06-10T15:22:04.981626Z","shell.execute_reply.started":"2021-06-10T15:22:04.875972Z","shell.execute_reply":"2021-06-10T15:22:04.980611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## b. Mã hóa cột văn bản và chuyển đổi chúng thành vectơ","metadata":{}},{"cell_type":"markdown","source":"Do trường `question_text` là dạng văn bản, nên để dễ huấn luyện ta cần mã hóa để chuyển thành vecto của các số nguyên.\n\nTokenize là quá trình chia nhỏ văn bản thành các phần nhỏ hơn được gọi là token. Mỗi token sẽ biểu diễn 1 từ trong câu.\n\nModule `keras.Tokenizer` sẽ giúp ta thực hiện viêc tokenize.\n\nBản chất nó sẽ duyệt qua các từ trong toàn bộ văn bản đê xây dựng lên 1 bộ từ điển. Sau đó sẽ sắp xếp các từ theo tần xuất xuất hiện của nó. Từ xuất hiện càng nhiều thì có index càng thấp. Sau đó sẽ sử dụng từ điển này để transform từng câu ở dạng text sang dạng sequence của số.","metadata":{}},{"cell_type":"markdown","source":"### Tạo từ điển","metadata":{}},{"cell_type":"markdown","source":"**`create_tokenizer()`:** sẽ tạo ra một từ điển từ tập văn bản truyền vào.\n\n`OOV_TOKEN`: là token cho các từ mà không xuất hiện trong tập từ điển.\n\n`word_index` là `dict` chứa ánh xạ của 1 từ sang index của nó\n\nindex càng nhỏ => tần suất xuất hiện càng nhiều","metadata":{}},{"cell_type":"code","source":"OOV_TOKEN = '<OOV>' # out of vocab token: thay thế các từ không có trong từ điển thành từ mà ta chọn\ndef create_tokenizer(docs):\n    tokenizer = Tokenizer(oov_token=OOV_TOKEN)\n    tokenizer.fit_on_texts(list(docs))\n    print(\"Size of vocabulary: \", len(tokenizer.word_index))\n    return tokenizer\ntokenizer = create_tokenizer(sample['clean'])\nprint(\"20 từ đầu tiên trong từ điển:\")\nlist(tokenizer.word_index.items())[:20]","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:22:04.984045Z","iopub.execute_input":"2021-06-10T15:22:04.98435Z","iopub.status.idle":"2021-06-10T15:22:04.999012Z","shell.execute_reply.started":"2021-06-10T15:22:04.98432Z","shell.execute_reply":"2021-06-10T15:22:04.99777Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Sử dụng từ điển chuyển text thành sequence","metadata":{}},{"cell_type":"markdown","source":"Như đã nói ở bên trên, phần này sẽ chuyển các câu text thành các chuỗi số. Mục đích là để cho máy có thể hiểu và dễ dàng học được thôi.","metadata":{}},{"cell_type":"code","source":"word_sequences = tokenizer.texts_to_sequences(sample['clean'])\n# Độ dài của mỗi chuỗi\nprint(\"Length of 20 first word_sequences:\")\nprint(list(map(lambda x: len(x) ,word_sequences[:20])))\n\nprint(\"\\n20 first word_sequences:\")\nfor sequence in word_sequences[:20]:\n    print(sequence)","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:22:05.00485Z","iopub.execute_input":"2021-06-10T15:22:05.00527Z","iopub.status.idle":"2021-06-10T15:22:05.018816Z","shell.execute_reply.started":"2021-06-10T15:22:05.005215Z","shell.execute_reply":"2021-06-10T15:22:05.017414Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Dễ dàng thấy độ dài của mỗi chuỗi không bằng nhau (chuỗi dài, chuỗi ngắn) => sẽ gây khó khắn cho quá trình huấn luyện mô hình.\n\nTa chuẩn hóa tất cả các input về cùng một độ dài cố định bằng ký thuật padding và truncating \n\n- `padding`: nếu chuỗi bị ngắn thì thực hiện padding bằng các thêm 0 vào đăng sau chuỗi.\n    \n- `truncating`: nếu chuỗi bị dài thì ta làm ngắn bằng cách bỏ đi phần dư ra ở cuối chuỗi.\n\nVề phần padding và truncating ta sẽ làm các chuỗi sẽ có cùng một độ dài cố đinh, nhưng bao nhiêu thì hợp lý ?\n\nNhớ lại phần thống kê bên trên, ta thấy rằng có 99,99% dữ liệu có dưới 54 từ. (0.01% còn lại tương ứng với khoảng 100 bản ghi)\n\nĐể an toàn thì mình sẽ chọn chiều dài tối đa là 60 => đảm bảo không ảnh hưởng đến quá trình trainning.\n\n","metadata":{}},{"cell_type":"code","source":"MAX_SENTENCE_LENGTH = 60 # Độ dài tối đa của chuỗi\nPADDING_TYPE = 'post' # kiểu padding, post = cuối chuỗi\nTRUNCATE_TYPE = 'post'# kiểu truncating, post = cuối chuỗi\ndef create_sequence(tokenizer, docs):\n    word_sequeces = tokenizer.texts_to_sequences(docs)\n    padded_word_sequences = pad_sequences(word_sequeces, maxlen=MAX_SENTENCE_LENGTH, padding=PADDING_TYPE, truncating=TRUNCATE_TYPE)\n    return padded_word_sequences\npadded_sequences = create_sequence(tokenizer, sample['clean'])\n\n    \n# Độ dài của mỗi chuỗi\nprint(\"Kích thước mảng:\",padded_sequences.shape)\n\nprint(\"Length of 20 first word_sequences:\")\nprint(list(map(lambda x: len(x) ,padded_sequences[:20])))\n\nprint(\"\\n10 first word_sequences:\")\nfor sequence in padded_sequences[:10]:\n    print(sequence)\n","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:22:05.020469Z","iopub.execute_input":"2021-06-10T15:22:05.020912Z","iopub.status.idle":"2021-06-10T15:22:05.04226Z","shell.execute_reply.started":"2021-06-10T15:22:05.020867Z","shell.execute_reply":"2021-06-10T15:22:05.041295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Sau bước này, độ dài của tất cả các chuỗi đều bằng nhau (len = 60)\nVề cơ bản thì phần tiền xứ lý dữ liệu đã xong.","metadata":{}},{"cell_type":"markdown","source":"**Áp dụng phần tiền xử lý cho dữ liệu**","metadata":{}},{"cell_type":"code","source":"# Thực hiện làm sạch cho dữ liêu huấn luyện và dữ liêu test để chuẩn bị qua quá trình train\ntrainY = train.target\n\nprint(\"Clean train question\")\ntrainX_text = apply_clean_text(train.question_text)\nprint(\"Clean test question\")\ntestX_text = apply_clean_text(test_df.question_text)","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:22:05.043697Z","iopub.execute_input":"2021-06-10T15:22:05.044058Z","iopub.status.idle":"2021-06-10T15:22:56.725065Z","shell.execute_reply.started":"2021-06-10T15:22:05.044026Z","shell.execute_reply":"2021-06-10T15:22:56.724052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Chia thành dữ liệu thành 2 tập train và valid","metadata":{}},{"cell_type":"markdown","source":"Chia dữ liêu train thành 2 tập có tỉ lệ 2 class bằng với ban đầu.\n- 80% để huấn luyện\n- 20% để xác thực ","metadata":{}},{"cell_type":"code","source":"# Chia thành tập train và validate\nX_train, X_val, y_train, y_val = train_test_split(trainX_text, trainY, test_size=0.2, random_state=123)","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:22:56.726377Z","iopub.execute_input":"2021-06-10T15:22:56.726655Z","iopub.status.idle":"2021-06-10T15:22:57.008756Z","shell.execute_reply.started":"2021-06-10T15:22:56.726628Z","shell.execute_reply":"2021-06-10T15:22:57.007675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. Chuẩn bị mô hình huấn luyện\n\n## Đầu tiên mình sẽ tìm hiểu một số khái niệm:\n\n`One-hot vector`: Đây là kỹ thuật biểu diễn từ bằng vector có số chiều bằng số từ vựng. Vector này có duy nhất một chiều có giá trị bằng 1 ứng với từ đang biểu diễn, các vị trí khác có giá trị 0. Ví dụ [1,0,0,0…0]. Biểu diễn này giải quyết được mẫu thuẫn tiềm năng của biểu diễn bằng số. Tuy nhiên, nhược điểm của phương pháp này là số chiều vector rất lớn, ảnh hưởng đến quá trình xử lý cũng như lưu trữ.\n\n`Embedding`: Do số lượng đặc trưng (từ trong từ điển) là khá lớn (nhược điểm của one-hot vector), nên người ta sinh ra kỹ thuật Embedding để giảm số chiều của không gian đặc trưng. Cụ thể là mỗi từ sẽ được biểu diễn bằng một vecto có số chiều xác định.\n\nCó 2 cách để biểu diễn embedding:\n- Sử dụng vector ngẫu nhiên: Với cách này, mỗi từ được biểu thị bằng một vector có giá trị của các chiều là ngẫu nhiên. Do đó, số lượng chiều chúng ta cần sử dụng ít hơn nhiều so với sử dụng one-hot. Ví dụ: nếu bạn có 1 triệu từ, bạn có thể biểu thị tất cả các từ đó trong không gian 3D, mỗi từ là một điểm trong không gian 3 chiều.\n- Sử dụng Word embedding: Đây được coi là cách tốt nhất để thể hiện các từ trong văn bản. Kỹ thuật này cũng gán mỗi từ với một vector, nhưng ưu việt hơn kỹ thuật vector ngẫu nhiên vì các vector này được tính toán để biểu diễn quan hệ tương đồng giữa các từ\n\n`SpatialDropout1D`: mỗi bước khi train model thì ngẫu nhiên (1-p%) các node bị loại bỏ nên model không thể phụ thuộc vào bất kì node nào của layer trước mà thay vào đó có xu hướng trải đều weight. Do đó mô hình sẽ có thể gây ra những đột biết, có thể thoát ra các lỗi mòn để đột phá. Dó đó có thể hạn chế được sự overfitting.\n\n`RNN` `(Mạng nơ ron truy hồi)`: ý tưởng chính là sử dụng một bộ nhớ để lưu lại thông tin từ từ những bước tính toán xử lý trước để dựa vào nó có thể đưa ra dự đoán chính xác nhất cho bước dự đoán hiện tại, Tuy nhiên nhược điểm là nó không xử lí hiệu quả được các thông tin dài hạn (vanishing gradient)\n\nĐể đối phó với vấn đề của mạng`RNN` truyền thống, người ta sử dụng Gated Recurrent Unit (GRU) và Long short term memory (LSTM)\n\n`LSTM/GRU`: LSTM không khác mô hình truyền thống của RNN,nhưng chúng sử dụng hàm tính toán khác ở các trạng thái ẩn. GRU là một phiên bản ít phức tạp hơn LSTM.\n\n## Để giải quyết bài toán hiện tại, mình sẽ kết hợp các layer trên thành một mô hình như sau:\n\n![model.png](attachment:12c8c1ee-6ef2-4993-a6fd-2e701c3fa3e3.png)","metadata":{},"attachments":{"12c8c1ee-6ef2-4993-a6fd-2e701c3fa3e3.png":{"image/png":"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"}}},{"cell_type":"code","source":"EMBEDDING_DIM = 300\nlearning_rate = 0.001\n\ndef createModel_bidirectional_LSTM_GRU(features,embedding_matrix = None):\n    output_bias = Constant(np.log([len(data_pos)/len(data_neg)])) # Khởi tạo gia trị đầu cho bias\n    \n    x_input = Input(shape=(MAX_SENTENCE_LENGTH))\n    if not(embedding_matrix is None):\n        embedding = Embedding(features, EMBEDDING_DIM, input_length=MAX_SENTENCE_LENGTH, weights=[embedding_matrix], trainable=False)(x_input)\n    else:\n        embedding = Embedding(features, EMBEDDING_DIM, input_length=MAX_SENTENCE_LENGTH)(x_input)\n    x = SpatialDropout1D(0.2)(embedding)\n    \n    lstm = Bidirectional(LSTM(256, return_sequences=True))(x)\n    gru = Bidirectional(GRU(128, return_sequences=True))(lstm)\n    \n    x = Concatenate()([lstm, gru])\n    x = GlobalAveragePooling1D()(x)\n    \n    x_output = Dense(1, activation='sigmoid', bias_initializer=output_bias)(x)\n    \n    model = Model(inputs=x_input, outputs=x_output)\n    opt = Adam(lr=learning_rate)\n    model.compile(loss='binary_crossentropy', optimizer= opt, metrics=[f1_m])\n    return model\n\n\n# Sử dụng hàm này để tính f1_score trong khi train model\n# không biết vì sao e dùng metrics.f1_score lại bị lỗi :(\ndef f1_m(y_true, y_pred):\n    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))\n    possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))\n    predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))\n    \n    recall = true_positives / (possible_positives + K.epsilon())\n    precision = true_positives / (predicted_positives + K.epsilon())\n    \n    return 2*((precision*recall)/(precision+recall+K.epsilon()))","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:27:34.672111Z","iopub.execute_input":"2021-06-10T15:27:34.67246Z","iopub.status.idle":"2021-06-10T15:27:34.685651Z","shell.execute_reply.started":"2021-06-10T15:27:34.67243Z","shell.execute_reply":"2021-06-10T15:27:34.684459Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Threshold\n\nBình thường, đối với phân lớp nhị phân kết quả dự đoán sẽ thuộc (0,1), threshold = 0.5 .\n\nNếu threshold < 0.5 thì phân lớp là negative, ngược lại thì là positive\n\nNhưng trong một số trường hợp, giá trị 0.5 này có thể chưa phải là tốt nhất. \n\nDo đó, ta thử điều chỉnh giá trị threshold này để tìm ra giá trị nào mà cho f1_score là tốt nhất => best_threshold","metadata":{}},{"cell_type":"code","source":"def best_threshold(y_train,train_preds):\n    tmp = [0,0,0] # idx, cur, max\n    delta = 0\n    for tmp[0] in tqdm(np.arange(0.1, 0.9, 0.01)):\n        tmp[1] = metrics.f1_score(y_train, np.array(train_preds)>tmp[0])\n        if tmp[1] > tmp[2]:\n            delta = tmp[0]\n            tmp[2] = tmp[1]\n    return delta, tmp[2] # threshold, f1_score","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:25:26.719931Z","iopub.execute_input":"2021-06-10T15:25:26.720374Z","iopub.status.idle":"2021-06-10T15:25:26.72765Z","shell.execute_reply.started":"2021-06-10T15:25:26.720334Z","shell.execute_reply":"2021-06-10T15:25:26.726492Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 4. Huấn luyện và dự đoán\n\n","metadata":{}},{"cell_type":"markdown","source":"Tận dụng TPU của kaggle để giảm thời gian huấn luyện.","metadata":{}},{"cell_type":"code","source":"# khởi tạo strategy sử dụng TPU để train model => tăng tốc độ train\nstrategy = None\ntry:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect() # TPU detection\n    strategy = tf.distribute.TPUStrategy(tpu)\n    print('Use TPU')\nexcept ValueError:\n    if len(tf.config.list_physical_devices('GPU')) > 0:\n        strategy = tf.distribute.MirroredStrategy()\n        print('Use GPU')\n    else:\n        strategy = tf.distribute.get_strategy()\n        print('Use CPU')","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:25:29.019692Z","iopub.execute_input":"2021-06-10T15:25:29.020246Z","iopub.status.idle":"2021-06-10T15:25:36.87321Z","shell.execute_reply.started":"2021-06-10T15:25:29.020199Z","shell.execute_reply":"2021-06-10T15:25:36.872169Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"`class_weight`: Nhận thấy tỉ lệ dữ liệu class 0: class 1 = 15:1 (dữ liệu bị lệch), để giảm thiểu ảnh hưởng thì mình sử dụng class_weight để cân bằng trọng số cho hàm mất mát trong khi huấn luyện. \nSau khi thử nghiệm với nhiều class_weight khác nhau, e thấy chọn tỉ lệ 1:3 mang lại hiệu quả ổn nhất.\n\n**Early Stop Callback:**\n\nNói một cách ngắn gọn là Early Stop Callback dùng để dừng quá trình train sớm, sau khi mà thông số chúng ta quan sát (có thể là validation accuracy hay validaiton loss) không “khá lên” sau một vài epochs.\n\n![early-stopping.png](attachment:2b38866d-87c3-44a1-84b3-8cfee66059ce.png)\n\nĐây cũng là một kỹ thuật hay được dùng để tránh overfit. Không phải cứ train với nhiều epochs là tốt, chúng ta train nhiều quá mà không thấy val_loss giảm nữa hoặc val_acc tăng nữa mà vẫn tiếp tục train thì sẽ dẫn đến có khả năng overfit.\n\n**Reduce Learning rate:**\n\nKhi bắt đầu training, em sẽ chọn learning rate lớn một xíu để tăng tốc quá trình train. Sau đó sẽ giảm tốc độ học đi nếu sau một số epochs, độ lỗi trên tập validation không giảm","metadata":{},"attachments":{"2b38866d-87c3-44a1-84b3-8cfee66059ce.png":{"image/png":"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"}}},{"cell_type":"code","source":"class_weight = {\n    0: 1,\n    1: 3,\n}\nbatch_size = 1024\nn_epochs = 30\n\nearly_stopping=tf.keras.callbacks.EarlyStopping(\n                                                monitor=\"val_loss\",\n                                                patience=3,\n                                                mode=\"min\",\n                                                restore_best_weights=True\n                                              )\n### Giảm learning rate khi model không được cải thiên (càng học càng ngu)\nreduce_lr=tf.keras.callbacks.ReduceLROnPlateau(\n                                                monitor=\"val_loss\",\n                                                factor=0.2,\n                                                patience=2,\n                                                verbose=1,\n                                                mode=\"auto\"\n                                            )\n\nmy_callbacks=[early_stopping,reduce_lr]\ndef train_model_and_predict(X_train, y_train, X_val, y_val, X_test, embedding_vec=None):\n    # tokenize and convert to sequence\n    print(\"Create vocab...\")\n    tokenizer = create_tokenizer(X_train)\n    print(\"Create sequences...\")\n    X_train_seq = create_sequence(tokenizer, X_train)\n    X_val_seq = create_sequence(tokenizer, X_val)\n    X_test_seq = create_sequence(tokenizer, X_test)\n    embedding_matrix = None\n    if not(embedding_vec is None):\n        embedding_matrix = load_embedding(embedding_vec, tokenizer.word_index)\n    \n    # build model and training\n    model = createModel_bidirectional_LSTM_GRU(len(tokenizer.word_index)+1, embedding_matrix)\n    model.fit(X_train_seq, y_train, batch_size=batch_size, epochs=n_epochs, validation_data=(X_val_seq, y_val), class_weight=class_weight, callbacks=my_callbacks)\n    \n    # get f1_score, threshold\n    val_pred = model.predict(X_val_seq, verbose=1, batch_size=256)\n    threshold, f1_score = best_threshold(y_val, val_pred)\n    \n    test_pred = model.predict(X_test_seq, verbose=1, batch_size=256)\n    \n    return threshold, f1_score, val_pred, test_pred","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:25:36.874629Z","iopub.execute_input":"2021-06-10T15:25:36.875128Z","iopub.status.idle":"2021-06-10T15:25:36.886401Z","shell.execute_reply.started":"2021-06-10T15:25:36.875094Z","shell.execute_reply":"2021-06-10T15:25:36.88541Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5. Thử nghiệm và cải thiện","metadata":{}},{"cell_type":"markdown","source":"## Train model without Pretrained Embeddings\nThử nghiệm với mô hình với lớp embedding sẽ không sử dụng bất kì pretrain word embeddings nào (mô hình học lại từ đầu)\n\nKhi đó phần trọng số của layer embedding sẽ được khởi tạo ngẫu nhiên, sau đó được cải thiện từ từ trong quá trình huấn luyện","metadata":{}},{"cell_type":"code","source":"# train\nwith strategy.scope():\n    threshold, f1_score, val_pred, test_pred = train_model_and_predict(X_train, y_train, X_val, y_val, testX_text)\nprint(metrics.classification_report(y_val,(val_pred>threshold).astype(int)))","metadata":{"execution":{"iopub.status.busy":"2021-06-10T15:27:46.376226Z","iopub.execute_input":"2021-06-10T15:27:46.376613Z","iopub.status.idle":"2021-06-10T15:35:56.837186Z","shell.execute_reply.started":"2021-06-10T15:27:46.37658Z","shell.execute_reply":"2021-06-10T15:35:56.836007Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Mô hình đã nhận diện được hầu hết các câu negative.\n\nTuy nhiên đối với các câu positive thì độ chính xác chưa được cao lắm, đồng thời cũng không thực sự nhạy (recall ~ 0.7). Dẫn đến F1 score chỉ được 0.65","metadata":{}},{"cell_type":"markdown","source":"## Train model with Pretrained Embeddings\nThử nghiệm với mô hình kết hợp các word embeddings được pretained\n\nTa xẽ xem xét các tập trọng số của embedding được trainning sẵn có cải thiện mô hình không.\n\nPhần này ta sẽ thử qua các embedding sau:\n- GloVe embedding\n- Paragram embedding\n- Wiki-news embedding","metadata":{}},{"cell_type":"markdown","source":"### Đọc file embeddings\n\nCác file embedding có dạng text, mỗi dòng chứa 1 word và kèm sau đó là 1 vector tương ứng\n\nTa cần lấy các word có trong từ điển kèm với vecto tương ứng để tạo thành 1 dict để có thể tra cứu nhanh các vecto tương ứng với các từ\n\n","metadata":{}},{"cell_type":"code","source":"# tách từ và vecto tương ứng với nó\ndef get_coefs(word, *arr): \n    return word, np.asarray(arr, dtype='float32')\n# lấy số dòng của file embeddings \ndef get_lines_count(file_name): \n    return sum(1 for _ in open(file_name, encoding=\"utf8\", errors='ignore'))\n# chuyển file embeddigns thành dict\ndef load_vec(file_name): \n    return dict(\n        get_coefs(*o.split(\" \")) \n            for o in tqdm(open(\n                file_name, encoding=\"utf8\", errors='ignore'), \n                total=get_lines_count(file_name)\n            ) if len(o) > 100\n    )","metadata":{"execution":{"iopub.status.busy":"2021-06-10T12:55:46.958289Z","iopub.execute_input":"2021-06-10T12:55:46.958754Z","iopub.status.idle":"2021-06-10T12:55:46.967056Z","shell.execute_reply.started":"2021-06-10T12:55:46.958709Z","shell.execute_reply":"2021-06-10T12:55:46.965431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Ta cần tạo một mảng chưa weight của các từ tương ứng với `tokenizer.word_index`\n\nNhận thấy các từ trong từ điển có khả năng không dó trong word embeddings. \n\n=> Để hiệu quả nhất thì với mỗi từ mà ta không tìm thấy trong word embeddings thì ta sẽ thử biến đổi từ sao cho tìm được vecto gần nó nhất. Bởi vì như vậy chắc chắn sẽ tốt hơn là không có thông tin gì\n\nĐể biến đổi từ thì ta sẽ sử dụng một số ký thuật sau:\n- Chuyển thành chữ viết hoa\n- Chuyển thành chữ thường\n- Chuyển thành chữ hoa\n- Sử dụng các thư viện để stem từ (cắt đi một phần kí tự ở cuối từ)\n\nChiến thuật là tìm được càng nhiều từ càng tốt.","metadata":{}},{"cell_type":"code","source":"EMBEDDING_DIM = 300 # chọn số chiều của vecto embedding là 300\n\nps = PorterStemmer()\nlc = LancasterStemmer()\nsb = SnowballStemmer('english')\n\ndef load_embedding(word2vec, word2index):\n    oov_count = 0 # Số lượng từ không tìm thấy vecto embeddings\n    vocab_count = 0 # Số lượng từ có vecto embeddings\n    vocab_size = len(word2index)\n    \n    embedding_weights = np.zeros((vocab_size+1, EMBEDDING_DIM)) # khởi tạo trọng số weight = 0\n    unknown_vector = np.zeros((EMBEDDING_DIM,), dtype=np.float32) - 1\n    unknown_words = []\n\n    # Tìm kiếm từng từ trong embeddings, nếu không thấy thì lần lượt thực hiện các kỹ thuật biến đổi từ để tìm ra từ gần nghĩa.\n    # => hi vọng embeddings cho trước phủ được càng nhiều từ càng tốt.\n    for key, i in tqdm(word2index.items()):\n        word = key\n        if word in word2vec:\n            embedding_weights[i] = word2vec[word]\n            continue\n\n        word = key.capitalize()       \n        if word in word2vec:\n            embedding_weights[i] = word2vec[word]\n            continue\n        \n        word = key.upper()       \n        if word in word2vec:\n            embedding_weights[i] = word2vec[word]\n            continue\n        \n        word = key.lower()       \n        if word in word2vec:\n            embedding_weights[i] = word2vec[word]\n            continue\n        \n        # PorterStemmer (\"python\",\"pythoner\",\"pythoning\",\"pythoned\" => \"python\")\n        word = ps.stem(key)        \n        if word in word2vec:\n            embedding_weights[i] = word2vec[word]\n            continue\n        \n        # LancasterStemmer\n        word = lc.stem(key)        \n        if word in word2vec:\n            embedding_weights[i] = word2vec[word]\n            continue\n            \n        # SnowballStemmer (connection, connections, connective, connected, and connecting => connect)\n        word = sb.stem(key)        \n        if word in word2vec:\n            embedding_weights[i] = word2vec[word]\n            continue\n            \n        unknown_words.append(key)\n            \n        embedding_weights[i] = unknown_vector\n\n    print('Top 10 Null word embeddings: ')\n    print(unknown_words[:10])\n#      % np.sum(np.sum(embedding_weights, axis=1) == -1 * EMBEDDING_DIM)\n    print('\\nNull word embeddings: %d' % len(unknown_words))\n    print(\"There are {:.2f}% word out of embedding file\".format(100*len(unknown_words)/vocab_size))\n    return embedding_weights","metadata":{"execution":{"iopub.status.busy":"2021-06-10T12:55:46.968942Z","iopub.execute_input":"2021-06-10T12:55:46.969389Z","iopub.status.idle":"2021-06-10T12:55:46.989258Z","shell.execute_reply.started":"2021-06-10T12:55:46.969342Z","shell.execute_reply":"2021-06-10T12:55:46.987848Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**1. GloVe embeddings**","metadata":{}},{"cell_type":"markdown","source":"GloVe là viết tắt của global vectors, một dự án mã nguồn mở của Stanford nhằm tạo ra các véc tơ biểu diễn cho các từ. ","metadata":{}},{"cell_type":"code","source":"GLOVE_FILE = 'glove.840B.300d/glove.840B.300d.txt'\n!unzip -n /kaggle/input/quora-insincere-questions-classification/embeddings.zip {GLOVE_FILE} -d .\nprint('loading glove_vec')\nglove_vec = load_vec(GLOVE_FILE)","metadata":{"execution":{"iopub.status.busy":"2021-06-10T12:55:46.990688Z","iopub.execute_input":"2021-06-10T12:55:46.991103Z","iopub.status.idle":"2021-06-10T13:01:31.240327Z","shell.execute_reply.started":"2021-06-10T12:55:46.991073Z","shell.execute_reply":"2021-06-10T13:01:31.231987Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    glove_threshold, glove_f1_score, glove_val_pred, glove_test_pred = train_model_and_predict(X_train, y_train, X_val, y_val, testX_text, glove_vec)\nprint(metrics.classification_report(y_val,(glove_val_pred>glove_threshold).astype(int)))","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:01:31.246721Z","iopub.execute_input":"2021-06-10T13:01:31.247245Z","iopub.status.idle":"2021-06-10T13:10:11.04845Z","shell.execute_reply.started":"2021-06-10T13:01:31.247186Z","shell.execute_reply":"2021-06-10T13:10:11.047193Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Sử dụng GloVe embedding đã cải thiện được hiệu quả của model, F1_score tăng rõ rệt (từ 0.65 lên 0.69) so với khi không sử dụng.\n\nHiệu năng được cải thiện không nằm ngoài dự đoán do việc sử dụng trọng số từ file embedding nó giúp các từ gần nghĩa với nhau sẽ có biểu diễn tương tự nhau => tăng khả năng đọc hiểu của model.\n","metadata":{}},{"cell_type":"code","source":"# Xóa để giải phóng bộ nhớ\ndel glove_vec\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:10:11.050007Z","iopub.execute_input":"2021-06-10T13:10:11.0503Z","iopub.status.idle":"2021-06-10T13:10:13.002804Z","shell.execute_reply.started":"2021-06-10T13:10:11.050272Z","shell.execute_reply":"2021-06-10T13:10:13.00187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**2. Paragram embeddings**\n\nTiếp tục thử nghiệm với một embedding khác","metadata":{}},{"cell_type":"code","source":"PARA_FILE = 'paragram_300_sl999/paragram_300_sl999.txt'\n!unzip -n /kaggle/input/quora-insincere-questions-classification/embeddings.zip {PARA_FILE} -d .\nprint('loading para_vec')\npara_vec = load_vec(PARA_FILE)","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:10:13.015951Z","iopub.execute_input":"2021-06-10T13:10:13.016729Z","iopub.status.idle":"2021-06-10T13:15:30.466528Z","shell.execute_reply.started":"2021-06-10T13:10:13.016679Z","shell.execute_reply":"2021-06-10T13:15:30.462882Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    para_threshold, para_f1_score, para_val_pred, para_test_pred = train_model_and_predict(X_train, y_train, X_val, y_val, testX_text, para_vec)\nprint(metrics.classification_report(y_val,(para_val_pred>para_threshold).astype(int)))","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:15:30.486012Z","iopub.execute_input":"2021-06-10T13:15:30.486424Z","iopub.status.idle":"2021-06-10T13:21:23.833356Z","shell.execute_reply.started":"2021-06-10T13:15:30.486386Z","shell.execute_reply":"2021-06-10T13:21:23.832053Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Với paragram embedding, ta thấy nó bao phủ được nhiều từ vựng hơn so với GloVe (GloVe ~ 81%, paragram ~ 83%)\n\nTuy nhiên F1_score lại bị giảm so với GloVe, nhưng vẫn hiệu quả hơn so với khi không sử dụng pretrain.","metadata":{}},{"cell_type":"code","source":"# Xóa để giải phóng bộ nhớ\ndel para_vec\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:21:23.834954Z","iopub.execute_input":"2021-06-10T13:21:23.835281Z","iopub.status.idle":"2021-06-10T13:21:26.189536Z","shell.execute_reply.started":"2021-06-10T13:21:23.835249Z","shell.execute_reply":"2021-06-10T13:21:26.188554Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**3. Wiki-news embeddings**\n\nTiếp tục thử nghiệm với wiki-news","metadata":{}},{"cell_type":"code","source":"WIKI_FILE = 'wiki-news-300d-1M/wiki-news-300d-1M.vec'\n!unzip -n /kaggle/input/quora-insincere-questions-classification/embeddings.zip {WIKI_FILE} -d .\nprint('loading wiki_vec')\nwiki_vec = load_vec(WIKI_FILE)","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:21:26.191701Z","iopub.execute_input":"2021-06-10T13:21:26.192021Z","iopub.status.idle":"2021-06-10T13:23:53.033029Z","shell.execute_reply.started":"2021-06-10T13:21:26.191989Z","shell.execute_reply":"2021-06-10T13:23:53.026326Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    wiki_threshold, wiki_f1_score, wiki_val_pred, wiki_test_pred = train_model_and_predict(X_train, y_train, X_val, y_val, testX_text, wiki_vec)\nprint(metrics.classification_report(y_val,(wiki_val_pred>wiki_threshold).astype(int)))","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:23:53.034744Z","iopub.execute_input":"2021-06-10T13:23:53.035093Z","iopub.status.idle":"2021-06-10T13:33:14.9498Z","shell.execute_reply.started":"2021-06-10T13:23:53.035056Z","shell.execute_reply":"2021-06-10T13:33:14.948271Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":" Sử dụng wiki-news embeddings, ta thấy số lượng từ không năm trong file này tăng nhiều hơn so với GloVe, nhưng bất hiệu năng của mô hình vẫn xấp xỉ với GloVe (F1_score ~ 0.69)","metadata":{}},{"cell_type":"code","source":"# Xóa để giải phóng bộ nhớ\ndel wiki_vec\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:33:14.951807Z","iopub.execute_input":"2021-06-10T13:33:14.952255Z","iopub.status.idle":"2021-06-10T13:33:17.244955Z","shell.execute_reply.started":"2021-06-10T13:33:14.952207Z","shell.execute_reply":"2021-06-10T13:33:17.243974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Stack Models Prediction\n\nTổng kết lại thì có thể thấy được rằng hiệu năng của model với các ma trận embeddings Glove, Paragram và Wiki-news khá tương đồng với nhau, cả về độ phủ, cả về f1_score và những yếu tố khác.\n\nTuy nhiên tại sao chúng ta không kết hợp lại các kết quả của từ mô hình bên trên, rồi đưa ra kết quả cuối cùng.\n\nTa sẽ lấy kết quả trung bình của 3 lần huấn luyện bên trên.","metadata":{}},{"cell_type":"code","source":"val_prod = np.zeros((len(X_val),), dtype=np.float32)\n\nval_prod += 1/3 * np.squeeze(glove_val_pred)\nval_prod += 1/3 * np.squeeze(para_val_pred)\nval_prod += 1/3 *np.squeeze(wiki_val_pred)\nthreshold_global, f1_global = best_threshold(y_val, val_prod)\nprint(metrics.classification_report(y_val,(val_prod>threshold_global).astype(int)))","metadata":{"execution":{"iopub.status.busy":"2021-06-10T14:02:46.196567Z","iopub.execute_input":"2021-06-10T14:02:46.196943Z","iopub.status.idle":"2021-06-10T14:02:53.003545Z","shell.execute_reply.started":"2021-06-10T14:02:46.196912Z","shell.execute_reply":"2021-06-10T14:02:53.002221Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Kết quả được cải thiện nhẹ, F1_score tăng lên gần 0.7","metadata":{}},{"cell_type":"markdown","source":"# 6. Submit test","metadata":{}},{"cell_type":"code","source":"pred_prob = np.zeros((len(testX_text),), dtype=np.float32)\npred_prob += 1/3 * np.squeeze(glove_test_pred)\npred_prob += 1/3 * np.squeeze(para_test_pred)\npred_prob += 1/3 * np.squeeze(wiki_test_pred)\ny_test_pre=((pred_prob>threshold_global).astype(int))\n\n## Creating the submission File\nsubmit = pd.DataFrame()\nsubmit[\"qid\"]=test_df.qid\nsubmit[\"prediction\"]=y_test_pre\nsubmit.to_csv(\"submission.csv\",index=False)","metadata":{"execution":{"iopub.status.busy":"2021-06-10T14:13:00.27246Z","iopub.execute_input":"2021-06-10T14:13:00.272939Z","iopub.status.idle":"2021-06-10T14:13:01.298477Z","shell.execute_reply.started":"2021-06-10T14:13:00.272895Z","shell.execute_reply":"2021-06-10T14:13:01.297313Z"},"trusted":true},"execution_count":null,"outputs":[]}]}