{"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 BÀI TẬP LỚN HỌC MÁY CUỐI KỲ\n\nMã Lớp: INT3405_1\n\nHọ và tên: Nguyễn Trọng Hải\n\nMã số sinh viên: 18020447","metadata":{}},{"cell_type":"markdown","source":"## MÔ TẢ BÀI TOÁ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. \n\nMộ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\nTrong cuộc thi này, chúng ta sẽ phát triển các mô hình xác định và gắn cờ cho các câu hỏi không chân thành.\n\n* Input: Các câu hỏi trên Quora dưới dạng text\n* Output: giá trị 0 hoặc 1 (0: câu hỏi chân thành; 1: câu hỏi không chân thành)","metadata":{}},{"cell_type":"markdown","source":"## PHÂN TÍCH DỮ LIỆU\n","metadata":{}},{"cell_type":"markdown","source":"#### Import thư viện cần thiết","metadata":{}},{"cell_type":"code","source":"import re\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n%matplotlib inline\nimport seaborn as sns\nfrom tqdm import tqdm\ntqdm.pandas()\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn import metrics\nfrom sklearn.metrics import accuracy_score, f1_score\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras.preprocessing.text import Tokenizer\nfrom tensorflow.keras.preprocessing.sequence import pad_sequences\n\nfrom tensorflow.keras.optimizers import Adam\nimport tensorflow_addons as tfa\n\nfrom tensorflow.keras.layers import *\nfrom tensorflow.keras.models import *\nfrom tensorflow.keras import initializers, regularizers, constraints, optimizers, layers\nfrom tensorflow.keras.initializers import *\nfrom tensorflow.keras.optimizers import *\nimport tensorflow.keras.backend as K\nfrom tensorflow.keras.callbacks import *\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n\nimport os\nimport time\nimport gc\nimport re\nimport glob","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:44:41.559736Z","iopub.execute_input":"2022-01-08T03:44:41.559988Z","iopub.status.idle":"2022-01-08T03:44:46.775687Z","shell.execute_reply.started":"2022-01-08T03:44:41.559961Z","shell.execute_reply":"2022-01-08T03:44:46.774958Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Đọc dữ liệu","metadata":{}},{"cell_type":"code","source":"train = pd.read_csv('../input/quora-insincere-questions-classification/train.csv')\ntest = pd.read_csv('../input/quora-insincere-questions-classification/test.csv')","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:44:46.777319Z","iopub.execute_input":"2022-01-08T03:44:46.777555Z","iopub.status.idle":"2022-01-08T03:44:52.422385Z","shell.execute_reply.started":"2022-01-08T03:44:46.777524Z","shell.execute_reply":"2022-01-08T03:44:52.421626Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.info()","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:44:52.425719Z","iopub.execute_input":"2022-01-08T03:44:52.425937Z","iopub.status.idle":"2022-01-08T03:44:52.705771Z","shell.execute_reply.started":"2022-01-08T03:44:52.425913Z","shell.execute_reply":"2022-01-08T03:44:52.705073Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test.info()","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:44:52.707198Z","iopub.execute_input":"2022-01-08T03:44:52.707467Z","iopub.status.idle":"2022-01-08T03:44:52.790575Z","shell.execute_reply.started":"2022-01-08T03:44:52.707435Z","shell.execute_reply":"2022-01-08T03:44:52.789884Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"***Nhận xét***: Dữ liệu huấn luyện và kiểm thử không có giá trị null","metadata":{}},{"cell_type":"code","source":"ax, fig = plt.subplots(figsize=(10, 7))\nquestion_class = train[\"target\"].value_counts()\nquestion_class.plot(kind= 'bar', color= [\"blue\", \"orange\"])\nplt.title('Bar chart')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:44:52.793246Z","iopub.execute_input":"2022-01-08T03:44:52.793499Z","iopub.status.idle":"2022-01-08T03:44:52.991679Z","shell.execute_reply.started":"2022-01-08T03:44:52.793466Z","shell.execute_reply":"2022-01-08T03:44:52.991026Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Tỉ lệ phần trăm số câu hỏi Insincere là:\", (len(train.loc[train.target==1])) / (len(train.loc[train.target == 0])) * 100)","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:44:52.993067Z","iopub.execute_input":"2022-01-08T03:44:52.993541Z","iopub.status.idle":"2022-01-08T03:44:53.107726Z","shell.execute_reply.started":"2022-01-08T03:44:52.993504Z","shell.execute_reply":"2022-01-08T03:44:53.106883Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Nhận xét về dữ liệu\nDựa vào biểu đồ trên ta có thể thấy, số lượng câu hỏi gán nhãn chân thành chiếm phần lớn với tỷ lệ 93.4% còn những câu hỏi không chân thành chỉ chiếm 6.6%\n\n=> Tập dữ liệu bị mất cân bằng, vì thế nên khi đánh giá chất lượng mô hình ta không nên lựa chọn độ chính xác(accuracy) làm chỉ số đánh giá mô hình. Thay vào đó ta có thể sử dụng các metric thay thế như: F1_score, Recall,..","metadata":{}},{"cell_type":"markdown","source":"#### Phân tích từng câu hỏi","metadata":{}},{"cell_type":"markdown","source":"**Số lượng từ trong câu**","metadata":{}},{"cell_type":"code","source":"words = train['question_text'].apply(lambda x: len(x) - len(''.join(x.split())) + 1)\ntrain['words'] = words\nwords = train.loc[train['words']<200]['words']\nsns.distplot(words, color='g')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:44:53.109325Z","iopub.execute_input":"2022-01-08T03:44:53.109846Z","iopub.status.idle":"2022-01-08T03:44:59.808709Z","shell.execute_reply.started":"2022-01-08T03:44:53.109802Z","shell.execute_reply":"2022-01-08T03:44:59.808054Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('Số lượng từ trung bình của các câu hỏi trong dữ liệu huấn luyện là {0:.0f}.'.format(np.mean(train['question_text'].apply(lambda x: len(x.split())))))\nprint('Số lượng từ trung bình của các câu hỏi trong dữ liệu kiểm thử là {0:.0f}.'.format(np.mean(test['question_text'].apply(lambda x: len(x.split())))))","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:44:59.809918Z","iopub.execute_input":"2022-01-08T03:44:59.810786Z","iopub.status.idle":"2022-01-08T03:45:01.905104Z","shell.execute_reply.started":"2022-01-08T03:44:59.810747Z","shell.execute_reply":"2022-01-08T03:45:01.903576Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('Số lượng từ lớn nhất của các câu hỏi trong dữ liệu huấn luyện là {0:.0f}.'.format(np.max(train['question_text'].apply(lambda x: len(x.split())))))\nprint('Số lượng từ lớn nhất của các câu hỏi trong dữ liệu kiểm thử là {0:.0f}.'.format(np.max(test['question_text'].apply(lambda x: len(x.split())))))","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:45:01.906517Z","iopub.execute_input":"2022-01-08T03:45:01.906801Z","iopub.status.idle":"2022-01-08T03:45:04.012969Z","shell.execute_reply.started":"2022-01-08T03:45:01.906765Z","shell.execute_reply":"2022-01-08T03:45:04.012259Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('Số lượng ký tự trung bình của các câu hỏi trong dữ liệu huấn luyện là {0:.0f}.'.format(np.mean(train['question_text'].apply(lambda x: len(x)))))\nprint('Số lượng ký tự trung bình của các câu hỏi trong dữ liệu kiểm thử là {0:.0f}.'.format(np.mean(test['question_text'].apply(lambda x: len(x)))))","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:45:04.014259Z","iopub.execute_input":"2022-01-08T03:45:04.014582Z","iopub.status.idle":"2022-01-08T03:45:05.138840Z","shell.execute_reply.started":"2022-01-08T03:45:04.014543Z","shell.execute_reply":"2022-01-08T03:45:05.138184Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"***Nhận xét:*** Có thể thấy độ dài trung bình của các câu hỏi trong tập dữ liệu huấn luyện và kiểm thử tương tự nhau, tuy nhiên có những câu hỏi khá dài trong tập dữ liệu huấn luyện","metadata":{}},{"cell_type":"markdown","source":"### Xử LÝ DỮ LIỆU","metadata":{}},{"cell_type":"markdown","source":"#### CÁC BƯỚC TIỀN XỬ LÝ DỮ LIỆU:\n\n* Lowering\n* Xoá các số (do các số không có ý nghĩa trong việc phân lớp)\n* Xoá các kí tự đặc biệt\n* Mispelling (thay thế các từ viết tắt)","metadata":{}},{"cell_type":"markdown","source":"Như đã phân tích về dữ liệu ở trên, ta sẽ quy chuẩn số lượng từ trong một câu hỏi. Do ta sử dụng tập từ điển đã được huấn luyện sẵn là tập embeddings nên mỗi vector có độ dài là 300, và mỗi câu hỏi sẽ có tối đa 80 từ","metadata":{}},{"cell_type":"code","source":"embed_size = 300 #độ dài của vector\nmax_features = 120000 #số lượng từ xuất hiện nhiều nhất để huấn luyện\nmaxlen = 80 #số lượng từ trong câu ","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:45:05.142754Z","iopub.execute_input":"2022-01-08T03:45:05.143258Z","iopub.status.idle":"2022-01-08T03:45:05.150775Z","shell.execute_reply.started":"2022-01-08T03:45:05.143207Z","shell.execute_reply":"2022-01-08T03:45:05.150160Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Lowering**","metadata":{}},{"cell_type":"code","source":"train[\"question_text\"] = train[\"question_text\"].apply(lambda x: x.lower())\ntest[\"question_text\"] = test[\"question_text\"].apply(lambda x: x.lower())","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:45:05.154884Z","iopub.execute_input":"2022-01-08T03:45:05.157348Z","iopub.status.idle":"2022-01-08T03:45:05.913424Z","shell.execute_reply.started":"2022-01-08T03:45:05.157311Z","shell.execute_reply":"2022-01-08T03:45:05.912520Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Xoá các số**","metadata":{}},{"cell_type":"code","source":"def clean_numbers(x):\n    if bool(re.search(r'\\d', x)):\n        x = re.sub('[0-9]{5,}', '#####', x)\n        x = re.sub('[0-9]{4}', '####', x)\n        x = re.sub('[0-9]{3}', '###', x)\n        x = re.sub('[0-9]{2}', '##', x)\n    return x","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:45:05.914784Z","iopub.execute_input":"2022-01-08T03:45:05.915034Z","iopub.status.idle":"2022-01-08T03:45:05.921413Z","shell.execute_reply.started":"2022-01-08T03:45:05.915001Z","shell.execute_reply":"2022-01-08T03:45:05.920465Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"question_text\"] = train[\"question_text\"].progress_apply(lambda x: clean_numbers(x))\ntest[\"question_text\"] = test[\"question_text\"].apply(lambda x: clean_numbers(x))","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:45:05.925346Z","iopub.execute_input":"2022-01-08T03:45:05.925858Z","iopub.status.idle":"2022-01-08T03:45:14.216006Z","shell.execute_reply.started":"2022-01-08T03:45:05.925820Z","shell.execute_reply":"2022-01-08T03:45:14.215268Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Xoá ký tự đặc biệt**","metadata":{}},{"cell_type":"code","source":"puncts = [',', '.', '\"', ':', ')', '(', '-', '!', '?', '|', ';', \"'\", '$', '&', '/', '[', ']', '>', '%', '=', '#', '*', '+', '\\\\', '•',  '~', '@', '£', \n '·', '_', '{', '}', '©', '^', '®', '`',  '<', '→', '°', '€', '™', '›',  '♥', '←', '×', '§', '″', '′', 'Â', '█', '½', 'à', '…', \n '“', '★', '”', '–', '●', 'â', '►', '−', '¢', '²', '¬', '░', '¶', '↑', '±', '¿', '▾', '═', '¦', '║', '―', '¥', '▓', '—', '‹', '─', \n '▒', '：', '¼', '⊕', '▼', '▪', '†', '■', '’', '▀', '¨', '▄', '♫', '☆', 'é', '¯', '♦', '¤', '▲', 'è', '¸', '¾', 'Ã', '⋅', '‘', '∞', \n '∙', '）', '↓', '、', '│', '（', '»', '，', '♪', '╩', '╚', '³', '・', '╦', '╣', '╔', '╗', '▬', '❤', 'ï', 'Ø', '¹', '≤', '‡', '√', ]\n\ndef clean_text(x):\n    x = str(x)\n    for punct in puncts:\n        if punct in x:\n            x = x.replace(punct, f' {punct} ')\n    return x","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:45:14.217386Z","iopub.execute_input":"2022-01-08T03:45:14.217646Z","iopub.status.idle":"2022-01-08T03:45:14.228376Z","shell.execute_reply.started":"2022-01-08T03:45:14.217612Z","shell.execute_reply":"2022-01-08T03:45:14.227574Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"question_text\"] = train[\"question_text\"].progress_apply(lambda x: clean_text(x))\ntest[\"question_text\"] = test[\"question_text\"].apply(lambda x: clean_text(x))","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:45:14.229755Z","iopub.execute_input":"2022-01-08T03:45:14.230024Z","iopub.status.idle":"2022-01-08T03:45:28.786838Z","shell.execute_reply.started":"2022-01-08T03:45:14.229981Z","shell.execute_reply":"2022-01-08T03:45:28.786062Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Mispelling**","metadata":{}},{"cell_type":"code","source":"mispell_dict = {\"ain't\": \"is not\", \"aren't\": \"are not\",\"can't\": \"cannot\", \"'cause\": \"because\", \"could've\": \"could have\", \"couldn't\": \"could not\", \"didn't\": \"did not\",  \"doesn't\": \"does not\", \"don't\": \"do not\", \"hadn't\": \"had not\", \"hasn't\": \"has not\", \"haven't\": \"have not\", \"he'd\": \"he would\",\"he'll\": \"he will\", \"he's\": \"he is\", \"how'd\": \"how did\", \"how'd'y\": \"how do you\", \"how'll\": \"how will\", \"how's\": \"how is\",  \"I'd\": \"I would\", \"I'd've\": \"I would have\", \"I'll\": \"I will\", \"I'll've\": \"I will have\",\"I'm\": \"I am\", \"I've\": \"I have\", \"i'd\": \"i would\", \"i'd've\": \"i would have\", \"i'll\": \"i will\",  \"i'll've\": \"i will have\",\"i'm\": \"i am\", \"i've\": \"i have\", \"isn't\": \"is not\", \"it'd\": \"it would\", \"it'd've\": \"it would have\", \"it'll\": \"it will\", \"it'll've\": \"it will have\",\"it's\": \"it is\", \"let's\": \"let us\", \"ma'am\": \"madam\", \"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\",\"o'clock\": \"of the clock\", \"oughtn't\": \"ought not\", \"oughtn't've\": \"ought not have\", \"shan't\": \"shall not\", \"sha'n't\": \"shall not\", \"shan't've\": \"shall not have\", \"she'd\": \"she would\", \"she'd've\": \"she would have\", \"she'll\": \"she will\", \"she'll've\": \"she will have\", \"she's\": \"she is\", \"should've\": \"should have\", \"shouldn't\": \"should not\", \"shouldn't've\": \"should not have\", \"so've\": \"so have\",\"so's\": \"so as\", \"this's\": \"this is\",\"that'd\": \"that would\", \"that'd've\": \"that would have\", \"that's\": \"that is\", \"there'd\": \"there would\", \"there'd've\": \"there would have\", \"there's\": \"there is\", \"here's\": \"here is\",\"they'd\": \"they would\", \"they'd've\": \"they would have\", \"they'll\": \"they will\", \"they'll've\": \"they will have\", \"they're\": \"they are\", \"they've\": \"they have\", \"to've\": \"to have\", \"wasn't\": \"was not\", \"we'd\": \"we would\", \"we'd've\": \"we would have\", \"we'll\": \"we will\", \"we'll've\": \"we will have\", \"we're\": \"we are\", \"we've\": \"we have\", \"weren't\": \"were not\", \"what'll\": \"what will\", \"what'll've\": \"what will have\", \"what're\": \"what are\",  \"what's\": \"what is\", \"what've\": \"what have\", \"when's\": \"when is\", \"when've\": \"when have\", \"where'd\": \"where did\", \"where's\": \"where is\", \"where've\": \"where have\", \"who'll\": \"who will\", \"who'll've\": \"who will have\", \"who's\": \"who is\", \"who've\": \"who have\", \"why's\": \"why is\", \"why've\": \"why have\", \"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'd\": \"you all would\",\"y'all'd've\": \"you all would have\",\"y'all're\": \"you all are\",\"y'all've\": \"you all have\",\"you'd\": \"you would\", \"you'd've\": \"you would have\", \"you'll\": \"you will\", \"you'll've\": \"you will have\", \"you're\": \"you are\", \"you've\": \"you have\", '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': 'Ethereum', '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'}\n\ndef _get_mispell(mispell_dict):\n    mispell_re = re.compile('(%s)' % '|'.join(mispell_dict.keys()))\n    return mispell_dict, mispell_re\n\nmispellings, mispellings_re = _get_mispell(mispell_dict)\ndef replace_typical_misspell(text):\n    def replace(match):\n        return mispellings[match.group(0)]\n    return mispellings_re.sub(replace, text)","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:45:28.788496Z","iopub.execute_input":"2022-01-08T03:45:28.788768Z","iopub.status.idle":"2022-01-08T03:45:28.815976Z","shell.execute_reply.started":"2022-01-08T03:45:28.788733Z","shell.execute_reply":"2022-01-08T03:45:28.815237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"question_text\"] = train[\"question_text\"].progress_apply(lambda x: replace_typical_misspell(x))\ntest[\"question_text\"] = test[\"question_text\"].apply(lambda x: replace_typical_misspell(x))","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:45:28.817685Z","iopub.execute_input":"2022-01-08T03:45:28.818290Z","iopub.status.idle":"2022-01-08T03:46:25.552123Z","shell.execute_reply.started":"2022-01-08T03:45:28.818250Z","shell.execute_reply":"2022-01-08T03:46:25.551292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Chia dữ liệu để huấn luyện với tỉ lệ 90:10**","metadata":{}},{"cell_type":"code","source":"# split to train and val\ntrain, val = train_test_split(train, test_size=0.1, random_state=2018) ","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:46:25.553739Z","iopub.execute_input":"2022-01-08T03:46:25.554243Z","iopub.status.idle":"2022-01-08T03:46:26.132982Z","shell.execute_reply.started":"2022-01-08T03:46:25.554190Z","shell.execute_reply":"2022-01-08T03:46:26.132265Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# fill up the missing values\ntrain_X = train[\"question_text\"].fillna(\"_na_\").values\nval_X = val[\"question_text\"].fillna(\"_na_\").values\ntest_X = test[\"question_text\"].fillna(\"_##_\").values","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:46:26.134416Z","iopub.execute_input":"2022-01-08T03:46:26.134690Z","iopub.status.idle":"2022-01-08T03:46:26.436334Z","shell.execute_reply.started":"2022-01-08T03:46:26.134654Z","shell.execute_reply":"2022-01-08T03:46:26.435601Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get the target values\ntrain_y = train['target'].values\nval_y = val['target'].values ","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:46:26.437515Z","iopub.execute_input":"2022-01-08T03:46:26.437776Z","iopub.status.idle":"2022-01-08T03:46:26.442869Z","shell.execute_reply.started":"2022-01-08T03:46:26.437741Z","shell.execute_reply":"2022-01-08T03:46:26.442162Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Tokenize**\n\nTokenize các câu hỏi thành các token(các từ) sau đó gán chỉ số cho từng từ và thay từng từ thành chỉ số tương ứng của từ đó.","metadata":{}},{"cell_type":"code","source":"tokenizer = Tokenizer(num_words=max_features)\ntokenizer.fit_on_texts(list(train_X)) # gán chỉ số cho từng từ\nword_index = tokenizer.word_index # lấy chỉ số của các từ\ntrain_X = tokenizer.texts_to_sequences(train_X) # thay thế các từ bởi chỉ số tương ứng của từ đó\nval_X = tokenizer.texts_to_sequences(val_X)  # thay thế các từ bởi chỉ số tương ứng của từ đó\ntest_X = tokenizer.texts_to_sequences(test_X) # thay thế các từ bởi chỉ số tương ứng của từ đó","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:46:26.444029Z","iopub.execute_input":"2022-01-08T03:46:26.444885Z","iopub.status.idle":"2022-01-08T03:47:16.582087Z","shell.execute_reply.started":"2022-01-08T03:46:26.444847Z","shell.execute_reply":"2022-01-08T03:47:16.581221Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Pad chuỗi** - nếu số lượng từ trong câu hỏi lớn hơn 'max_len' thì chuyển thành 'max_len' hoặc nếu số từ trong văn bản ít hơn 'max_len' thì bổ sung thêm số 0 vào các giá trị còn lại","metadata":{}},{"cell_type":"code","source":"train_X = pad_sequences(train_X, maxlen=maxlen)\nval_X = pad_sequences(val_X, maxlen=maxlen)\ntest_X = pad_sequences(test_X, maxlen=maxlen)","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:47:16.583448Z","iopub.execute_input":"2022-01-08T03:47:16.583742Z","iopub.status.idle":"2022-01-08T03:47:29.763348Z","shell.execute_reply.started":"2022-01-08T03:47:16.583706Z","shell.execute_reply":"2022-01-08T03:47:29.762433Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Tráo dữ liệu**","metadata":{}},{"cell_type":"code","source":"#shuffling the data\nnp.random.seed(1203)\ntrn_idx = np.random.permutation(len(train_X))\nval_idx = np.random.permutation(len(val_X))\n\ntrain_X = train_X[trn_idx]\nval_X = val_X[val_idx]\ntrain_y = train_y[trn_idx]\nval_y = val_y[val_idx]   ","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:47:29.764536Z","iopub.execute_input":"2022-01-08T03:47:29.765578Z","iopub.status.idle":"2022-01-08T03:47:30.127040Z","shell.execute_reply.started":"2022-01-08T03:47:29.765539Z","shell.execute_reply":"2022-01-08T03:47:30.126292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Ở Bài toán này, để tăng hiệu quả phân lớp, ta sẽ sử dụng từ điển chứa trọng số của các từ đã được huấn luyện sẵn (Glove)","metadata":{}},{"cell_type":"code","source":"! unzip ../input/quora-insincere-questions-classification/embeddings.zip -d input/","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:47:30.130417Z","iopub.execute_input":"2022-01-08T03:47:30.131200Z","iopub.status.idle":"2022-01-08T03:51:04.212009Z","shell.execute_reply.started":"2022-01-08T03:47:30.131163Z","shell.execute_reply":"2022-01-08T03:51:04.211209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Ta sẽ tạo ma trận embedding chỉ chứa những từ trong ma trận word2vec mà có trong word_index","metadata":{}},{"cell_type":"code","source":"EMBEDDING_FILE = './input/glove.840B.300d/glove.840B.300d.txt'\ndef get_coefs(word,*arr): return word, np.asarray(arr, dtype='float32')\nembeddings_index = dict(get_coefs(*o.split(\" \")) for o in open(EMBEDDING_FILE)) # lấy hệ số của từng từ trong tập embedding\n\nall_embs = np.stack(embeddings_index.values()) \nemb_mean,emb_std = all_embs.mean(), all_embs.std()\nembed_size = all_embs.shape[1]\n\n# word_index = tokenizer.word_index\nnb_words = min(max_features, len(word_index))\nembedding_matrix = np.random.normal(emb_mean, emb_std, (nb_words, embed_size)) # tạo hệ số ma trận ngẫu nhiên \nfor word, i in word_index.items():\n    if i >= max_features: continue\n    embedding_vector = embeddings_index.get(word) \n    if embedding_vector is not None: embedding_matrix[i] = embedding_vector # thay các hệ số của những từ có trong tập embedding","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:51:04.213962Z","iopub.execute_input":"2022-01-08T03:51:04.214292Z","iopub.status.idle":"2022-01-08T03:55:47.773356Z","shell.execute_reply.started":"2022-01-08T03:51:04.214247Z","shell.execute_reply":"2022-01-08T03:55:47.772508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## HUẤN LUYỆN MÔ HÌNH","metadata":{}},{"cell_type":"markdown","source":"#### Định nghĩa F1-score\n\nDo dữ liệu bị mất cân bằng nên metric phù hợp nhất là F1 score","metadata":{}},{"cell_type":"code","source":"!pip install tensorflow-addons","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:55:47.803172Z","iopub.execute_input":"2022-01-08T03:55:47.803410Z","iopub.status.idle":"2022-01-08T03:55:57.042374Z","shell.execute_reply.started":"2022-01-08T03:55:47.803382Z","shell.execute_reply":"2022-01-08T03:55:57.041495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"f1 = tfa.metrics.F1Score(num_classes=1, threshold=0.5)\naccuracy = tf.keras.metrics.BinaryAccuracy(\n    name='binary_accuracy', dtype=None, threshold=0.5\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Định nghĩa hàm Learning rate và Early stopping để giúp hàm loss hội tụ hiệu quả hơn","metadata":{}},{"cell_type":"code","source":"reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=2, min_lr=0.0001, verbose=0)\nearlystopping = EarlyStopping(monitor='val_loss', min_delta=0.0001, patience=5, verbose=1, mode='auto', restore_best_weights=True)\ncallbacks = [reduce_lr, earlystopping]","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:55:59.705175Z","iopub.execute_input":"2022-01-08T03:55:59.705679Z","iopub.status.idle":"2022-01-08T03:55:59.711047Z","shell.execute_reply.started":"2022-01-08T03:55:59.705641Z","shell.execute_reply":"2022-01-08T03:55:59.710395Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Thiết lập model","metadata":{}},{"cell_type":"markdown","source":"Xây dựng mô hình huấn luyện bằng LSTM (Long Short-Term Memory Networks)\n\nTrước khi hiểu mô hình LSTM là gì thì ta cần hiểu qua về mạng RNN - recurrent neural network. RNN có thể mang thông tin từ các layer trước đến layer sau, nên nó có thể dùng để xử lý thông tin dạng chuỗi. Một ví dụ của RNN trong bài toán dự đoán video, RNN có thể mang thông tin của frame ảnh từ state trước tới state sau, tuy nhiên state ở trước đó càng xa thì càng bị vanishing gradient, nghĩa là thông tin chỉ mang được qua một lượng state nhất định hay nói cách khác là model chỉ học được từ các state gần nó - short term memory\n\nVì vậy, mô hình Long short term memory ra đời để giải quyết vấn đề khi ta cần các thông tin từ state ở trước đó rất xa và tránh được vanishing gradient. Nó vẫn giữ tư tưởng chính của RNN là sự sao chép kiến trúc theo dạng chuỗi nhưng có phần phức tạp hơn.","metadata":{}},{"cell_type":"code","source":"def model_lstm_atten(embedding_matrix):\n    inp = Input(shape=(maxlen,))\n    x = Embedding(max_features, embed_size, weights=[embedding_matrix], trainable=False)(inp)\n    x = Bidirectional(LSTM(128, return_sequences=True))(x)\n    x = Bidirectional(LSTM(64, return_sequences=True))(x)\n    x = GlobalMaxPool1D()(x)\n    x = Dense(64, activation=\"relu\")(x)\n    x = Dense(1, activation=\"sigmoid\")(x)\n    model = Model(inputs=inp, outputs=x)\n    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=[f1])\n    return model","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:55:59.712838Z","iopub.execute_input":"2022-01-08T03:55:59.713145Z","iopub.status.idle":"2022-01-08T03:55:59.722389Z","shell.execute_reply.started":"2022-01-08T03:55:59.713109Z","shell.execute_reply":"2022-01-08T03:55:59.721618Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Train model","metadata":{}},{"cell_type":"code","source":"model = model_lstm_atten(embedding_matrix)\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:55:59.723466Z","iopub.execute_input":"2022-01-08T03:55:59.723897Z","iopub.status.idle":"2022-01-08T03:56:01.090270Z","shell.execute_reply.started":"2022-01-08T03:55:59.723861Z","shell.execute_reply":"2022-01-08T03:56:01.089568Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.fit(train_X, train_y, batch_size=512, epochs=10, validation_data=(val_X, val_y), callbacks=callbacks)","metadata":{"execution":{"iopub.status.busy":"2022-01-08T03:56:01.091432Z","iopub.execute_input":"2022-01-08T03:56:01.091691Z","iopub.status.idle":"2022-01-08T04:16:12.683259Z","shell.execute_reply.started":"2022-01-08T03:56:01.091656Z","shell.execute_reply":"2022-01-08T04:16:12.682496Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Predict","metadata":{}},{"cell_type":"code","source":"pred_val_y = model.predict([val_X], batch_size=1024, verbose=0)\npred_test_y = model.predict([test_X], batch_size=1024, verbose=0)","metadata":{"execution":{"iopub.status.busy":"2022-01-08T04:16:12.684902Z","iopub.execute_input":"2022-01-08T04:16:12.685421Z","iopub.status.idle":"2022-01-08T04:16:55.383863Z","shell.execute_reply.started":"2022-01-08T04:16:12.685383Z","shell.execute_reply":"2022-01-08T04:16:55.383085Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Xác định threshold có F1 cao nhất với threshold trong khoảng từ 0.10 đến 0.50","metadata":{}},{"cell_type":"code","source":"def f1_smart(y_true, y_pred):\n    thresholds = []\n    for thresh in np.arange(0.1, 0.501, 0.01):\n        thresh = np.round(thresh, 2)\n        res = f1_score(y_true, (y_pred > thresh).astype(int))\n        thresholds.append([thresh, res])\n        print(\"F1 score at threshold {0} is {1}\".format(thresh, res))\n\n    thresholds.sort(key=lambda x: x[1], reverse=True)\n    best_thresh = thresholds[0][0]\n    best_f1 = thresholds[0][1]\n    print(\"Best threshold: \", best_thresh)\n    return  best_f1, best_thresh","metadata":{"execution":{"iopub.status.busy":"2022-01-08T04:16:55.385450Z","iopub.execute_input":"2022-01-08T04:16:55.385817Z","iopub.status.idle":"2022-01-08T04:16:55.392782Z","shell.execute_reply.started":"2022-01-08T04:16:55.385776Z","shell.execute_reply":"2022-01-08T04:16:55.391771Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"f1, threshold = f1_smart(val_y, pred_val_y)\nprint('Optimal F1: {} at threshold: {}'.format(f1, threshold))","metadata":{"execution":{"iopub.status.busy":"2022-01-08T04:16:55.394263Z","iopub.execute_input":"2022-01-08T04:16:55.394516Z","iopub.status.idle":"2022-01-08T04:16:56.683597Z","shell.execute_reply.started":"2022-01-08T04:16:55.394482Z","shell.execute_reply":"2022-01-08T04:16:56.682888Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## SUBMISSION","metadata":{}},{"cell_type":"code","source":"pred_test_y = (pred_test_y >threshold).astype(int)\nout_df = pd.DataFrame({\"qid\":test[\"qid\"].values})\nout_df['prediction'] = pred_test_y\nout_df.to_csv(\"submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2022-01-08T04:16:56.685099Z","iopub.execute_input":"2022-01-08T04:16:56.685547Z","iopub.status.idle":"2022-01-08T04:16:57.486230Z","shell.execute_reply.started":"2022-01-08T04:16:56.685507Z","shell.execute_reply":"2022-01-08T04:16:57.485436Z"},"trusted":true},"execution_count":null,"outputs":[]}]}