{"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":"# Work Flow\n1. <a href=\"#1.-Problem-Description\">Problem Description </a>\n2. <a href=\"#2.-Data-Processing\">Data Processing </a>\n   * <a href=\"#Cleaning-Data\">Cleaning Data</a>\n   * <a href=\"#Vectorization\">Vectorization</a><br>\n3. <a href=\"#3.-Training\">Data Processing </a>\n   * <a href=\"#Naive-Bayes\">Naive Bayes</a>\n   * <a href=\"#LogisticRegression\">LogisticRegression</a>$$$$\n<a href=\"#Submission\">Submission </a>\n","metadata":{}},{"cell_type":"markdown","source":"# 1. Problem Description\n  Một vấn đề tồn tại đối với bất kỳ trang web lớn nào hiện nay là làm thế nào để xử lý nội dung độc hại và gây chia rẽ. Quora muốn giải quyết vấn đề này trực tiếp để giữ cho nền tảng của họ trở thành một nơi mà người dùng có thể cảm thấy an toàn khi chia sẻ kiến thức của họ với thế giới.$$$$\n  Yêu cầu của bài toán là phân loại câu hỏi có phải là câu hỏi toxic hay không\n       => **đây là bài toán classifier**\n* Dữ liệu đầu vào sẽ là các câu hỏi (dữ liệu dạng text)\n* Đầu ra là 0:1\n\n>**Để đánh giá bài toán, ở đây ta dùng f1_score**\n![](https://www.digital-mr.com/media/cache/5e/b4/5eb4dbc50024c306e5f707736fd79c1e.png) \n$$$$**Precision** được định nghĩa là tỉ lệ số điểm Positive mô hình dự đoán đúng trên tổng số điểm mô hình dự đoán là Positive\n$$precision=\\frac{TP}{TP + FP}$$\n**Recall** được định nghĩa là tỉ lệ số điểm Positive mô hình dự đoán đúng trên tổng số điểm thật sự là Positive (hay tổng số điểm được gán nhãn là Positive ban đầu)\n$$recall=\\frac{TP}{TP + FN}$$\n**F1-score**<br>\nTuy nhiên, chỉ có Precision hay chỉ có Recall thì không đánh giá được chất lượng mô hình.\n>* Chỉ dùng Precision, mô hình chỉ đưa ra dự đoán cho một điểm mà nó chắc chắn nhất. Khi đó Precision = 1, tuy nhiên ta không thể nói là mô hình này tốt.\n>* Chỉ dùng Recall, nếu mô hình dự đoán tất cả các điểm đều là positive. Khi đó Recall = 1, tuy nhiên ta cũng không thể nói đây là mô hình tốt.<br>\nKhi đó F1-score được sử dụng. F1-score là trung bình điều hòa (harmonic mean) của precision và recall (giả sử hai đại lượng này khác 0). F1-score được tinh theo công thức:\n$$\\frac{1}{\\frac{1}{precision} + \\frac{1}{recall}}$$","metadata":{}},{"cell_type":"markdown","source":"**Thêm một số thư viện cần thiết**","metadata":{}},{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib.pyplot as plt\nimport seaborn as sns","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-01-05T02:22:58.998218Z","iopub.execute_input":"2022-01-05T02:22:58.998625Z","iopub.status.idle":"2022-01-05T02:22:59.862516Z","shell.execute_reply.started":"2022-01-05T02:22:58.998543Z","shell.execute_reply":"2022-01-05T02:22:59.861473Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Load dữ liệu vào data frame**","metadata":{}},{"cell_type":"code","source":"# Load dũ liệu vào dataframe\ntrain_df = pd.read_csv('/kaggle/input/quora-insincere-questions-classification/train.csv')\ntest_df = pd.read_csv('/kaggle/input/quora-insincere-questions-classification/test.csv')","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:22:59.865060Z","iopub.execute_input":"2022-01-05T02:22:59.865378Z","iopub.status.idle":"2022-01-05T02:23:06.393220Z","shell.execute_reply.started":"2022-01-05T02:22:59.865348Z","shell.execute_reply":"2022-01-05T02:23:06.392264Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.info()","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:06.395530Z","iopub.execute_input":"2022-01-05T02:23:06.395965Z","iopub.status.idle":"2022-01-05T02:23:06.688833Z","shell.execute_reply.started":"2022-01-05T02:23:06.395920Z","shell.execute_reply":"2022-01-05T02:23:06.687638Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Dữ liệu:**\n* Tập dữ liệu train gồm 13006122 hàng x 3 cột\n* 3 cột gồm 2 cột dữ liệu văn bản và 1 cột dữ liệu số\n* Cột pid chứa id của câu hỏi\n* Cột questions_text chứa nội dung câu hỏi\n* Cột target có 2 giá trị (0 nếu là câu hỏi insincere, 1 nếu là câu hỏi sincere) ","metadata":{}},{"cell_type":"code","source":"print('5 hàng dữ liệu đầu tiên của tập train')\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:06.690398Z","iopub.execute_input":"2022-01-05T02:23:06.690687Z","iopub.status.idle":"2022-01-05T02:23:06.711367Z","shell.execute_reply.started":"2022-01-05T02:23:06.690660Z","shell.execute_reply":"2022-01-05T02:23:06.710199Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('5 hàng dữ liệu đầu tiên của tập test')\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:06.712678Z","iopub.execute_input":"2022-01-05T02:23:06.712999Z","iopub.status.idle":"2022-01-05T02:23:06.725316Z","shell.execute_reply.started":"2022-01-05T02:23:06.712968Z","shell.execute_reply":"2022-01-05T02:23:06.724216Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Nhận xét:** Ta thấy các câu hỏi trong cột question_text giữa tập train và tập test là khá tương đồng","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(10,9))\nsns.countplot(x='target', data=train_df)\nprint('Sincere questions: ', train_df[train_df['target'] == 0].shape[0])\nprint('Insincere questions: ', train_df[train_df['target'] == 1].shape[0])\nprint('Total questions: ', train_df.shape[0])","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:06.726830Z","iopub.execute_input":"2022-01-05T02:23:06.727226Z","iopub.status.idle":"2022-01-05T02:23:07.147501Z","shell.execute_reply.started":"2022-01-05T02:23:06.727193Z","shell.execute_reply":"2022-01-05T02:23:07.146338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('Phần trăm số câu hỏi hữu ích: {}%'.format(100 - round(train_df['target'].mean()*100, 2)))\nprint('\\nPhần trăm số câu hỏi độc hại: {}%'.format(round(train_df['target'].mean()*100, 2)))","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:07.148863Z","iopub.execute_input":"2022-01-05T02:23:07.149189Z","iopub.status.idle":"2022-01-05T02:23:07.160765Z","shell.execute_reply.started":"2022-01-05T02:23:07.149158Z","shell.execute_reply":"2022-01-05T02:23:07.159702Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"  **Nhận xét:**\n* Số lượng câu hỏi sincere chiếm 93,81% lớn hơn rất nhiều so với số lượng câu hỏi insincere \n* Dữ liệu đang bị mất cân bằng nghiêm trọng\n> Sử dụng thước đo đánh giá mô hình là độ chính xác (accuracy) sẽ không phù hợp. <br>\nViệc tập dữ liệu bị mất cân bằng nghiêm trọng có thể dẫn tới sự dự báo kém chính xác của nhóm thiểu số (insincere question) \n\n \n **Hướng giải quyết:**\n* Chia lại tập dữ liệu theo tỉ lệ 4:1","metadata":{}},{"cell_type":"markdown","source":"# Phân tích dữ liệu bằng Word Cloud\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ó","metadata":{}},{"cell_type":"code","source":"from wordcloud import WordCloud\nprint(\"Word cloud thể  hiện các câu hỏi sincere: \")\nsincere_wordcloud = WordCloud(width=700, height=500, background_color='black', min_font_size=10).generate(str(train_df[train_df[\"target\"] == 0][\"question_text\"]))\nplt.figure(figsize=(10,9), facecolor=None)\nplt.imshow(sincere_wordcloud)\nplt.axis(\"off\")\nplt.tight_layout(pad=0)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:07.164348Z","iopub.execute_input":"2022-01-05T02:23:07.164816Z","iopub.status.idle":"2022-01-05T02:23:07.985009Z","shell.execute_reply.started":"2022-01-05T02:23:07.164772Z","shell.execute_reply":"2022-01-05T02:23:07.983740Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Word cloud thể  hiện các câu hỏi insincere: \")\ninsincere_wordcloud = WordCloud(width=700, height=500, background_color='black', min_font_size=10).generate(str(train_df[train_df[\"target\"] == 1][\"question_text\"]))\nplt.figure(figsize=(10,9), facecolor=None)\nplt.imshow(insincere_wordcloud)\nplt.axis(\"off\")\nplt.tight_layout(pad=0)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:07.987184Z","iopub.execute_input":"2022-01-05T02:23:07.987787Z","iopub.status.idle":"2022-01-05T02:23:08.672916Z","shell.execute_reply.started":"2022-01-05T02:23:07.987740Z","shell.execute_reply":"2022-01-05T02:23:08.672093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2. Data Processing","metadata":{}},{"cell_type":"markdown","source":"* Như ta đã phân tích ở phần trước, tập dữ liệu đang bị mất cân bằng. Ta cần phải chia lại tập train sao cho cân bằng hơn\n* Ở đây ta chia lại theo tỉ lệ 4:1 (4 hữu ích : 1 toxic)","metadata":{}},{"cell_type":"code","source":"from sklearn.utils import resample\n# Chia lại tập dữ liệu\nsincere = train_df[train_df.target == 0]\ninsincere = train_df[train_df.target == 1]\ndf_train_sampled = pd.concat([resample(sincere,replace = True,n_samples = len(insincere)*4), insincere])\n","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:08.673996Z","iopub.execute_input":"2022-01-05T02:23:08.674436Z","iopub.status.idle":"2022-01-05T02:23:09.100757Z","shell.execute_reply.started":"2022-01-05T02:23:08.674404Z","shell.execute_reply":"2022-01-05T02:23:09.099872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Cleaning Data","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* Chuyển các từ in hoa thành in thường\n* Chuyển các từ rút gọn về dạng hoàn chỉnh\n* Các từ dừng (a, an, the...) xuất hiện rất nhiều trong câu hỏi nhưng không liên quan đến nội dung câu hỏi nên cần được loại bỏ\n* Các số và ký tự đặc biệt cũng tương tự như từ dừng không ảnh hưởng đến ý nghĩa câu hỏi\n* Chuyển các từ về dạng từ gốc","metadata":{}},{"cell_type":"code","source":"import re\nimport nltk\nfrom nltk.stem import SnowballStemmer\nfrom nltk.tokenize.toktok import ToktokTokenizer\nfrom nltk.tokenize import word_tokenize\nfrom nltk.corpus import stopwords\nfrom nltk.stem import WordNetLemmatizer\nfrom nltk.stem import PorterStemmer\n\nwordnet_lemmatizer = WordNetLemmatizer()\nimport re, string\ntokenizer = ToktokTokenizer()\nstemmer = SnowballStemmer('english')\nstopword_list = nltk.corpus.stopwords.words('english')\n","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:09.101824Z","iopub.execute_input":"2022-01-05T02:23:09.102310Z","iopub.status.idle":"2022-01-05T02:23:09.940763Z","shell.execute_reply.started":"2022-01-05T02:23:09.102274Z","shell.execute_reply":"2022-01-05T02:23:09.939777Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def clean_text(text):\n\n    # Xoá HTML Tags\n    text = re.sub(re.compile('<.*?>'), '', text)\n\n    # Xoá  [\\], ['], [\"]\n    text = re.sub(r'\\\\', '', text)\n    text = re.sub(r'\\\"', '', text)\n    text = re.sub(r'\\'', '', text)\n\n    # Xoá chữ số\n    text = re.sub('[0-9]{5,}','#####', text);\n    text = re.sub('[0-9]{4,}','####', text);\n    text = re.sub('[0-9]{3,}','###', text);\n    text = re.sub('[0-9]{2,}','##', text);\n\n    # Xoá ký tự la mã\n    roman = re.compile(r'^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$');\n    text = roman.sub(r'', text);\n\n    # Chuyển các ký tự về dạng in thường\n    text = text.strip().lower()\n\n    # Xoá các ký tự đặc biệt\n    filters = '!\"\\'#$%@&*()+_-;:<=>.?{}|`\\\\^\\t\\n'\n    translate_dict = dict((c, \" \") for c in filters)\n    translate_map = str.maketrans(translate_dict)\n    text = text.translate(translate_map)\n    \n    #token \n    #tokens = tokenizer.tokenize(text)\n    #tokens = [token.strip() for token in tokens]\n   # tokens = [token for token in tokens if token not in stop_words]\n   # tokens = [stemmer.stem(token) for token in tokens]\n    #tokens = [wordnet_lemmatizer.lemmatize(token) for token in tokens]\n    \n    return text","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:09.942514Z","iopub.execute_input":"2022-01-05T02:23:09.942983Z","iopub.status.idle":"2022-01-05T02:23:09.953486Z","shell.execute_reply.started":"2022-01-05T02:23:09.942939Z","shell.execute_reply":"2022-01-05T02:23:09.952332Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train_sampled['preprocessed_questions'] = df_train_sampled['question_text'].apply(clean_text)","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:09.955202Z","iopub.execute_input":"2022-01-05T02:23:09.955724Z","iopub.status.idle":"2022-01-05T02:23:24.125212Z","shell.execute_reply.started":"2022-01-05T02:23:09.955680Z","shell.execute_reply":"2022-01-05T02:23:24.124183Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"print('Cột preprocessed_ question chứa các câu hỏi đã được làm s')\ndf_train_sampled.head()","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:24.126432Z","iopub.execute_input":"2022-01-05T02:23:24.126887Z","iopub.status.idle":"2022-01-05T02:23:24.140424Z","shell.execute_reply.started":"2022-01-05T02:23:24.126851Z","shell.execute_reply":"2022-01-05T02:23:24.139273Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Vectorization","metadata":{}},{"cell_type":"markdown","source":"**Vectorization:** Trước khi đưa vào huấn luyện ta cần chuyển dữ liệu từ dạng vô hướng sang dạng vector<br>\n**Mô hình túi từ (bag-of-words)** Mô hình bag-of-words (BOW) là cách biểu diễn biến văn bản tùy ý thành các vectơ có độ dài cố định bằng cách đếm số lần mỗi từ xuất hiện, không quan tâm đến ngữ pháp và thậm chí trật tự từ nhưng vẫn giữ tính đa dạng.\n>Bước 1: Xác định túi từ vựng gồm: the, cat, sat, in, hat, with <br>\n      Bước 2: Đếm số lần xuất hiện cảu các từ\n![](https://miro.medium.com/max/1536/1*3IACMnNpwVlCl8kSTJocPA.png)  \n* Mô hình túi từ thường được sử dụng trong các phương pháp phân loại tài liệu trong đó sự xuất hiện (tần suất) của mỗi từ được sử dụng như một đặc trưng để đào tạo máy phân loại\n* **Ưu điểm:** Đơn giản, tính toán nhanh, dễ tính toán. Không quan tâm đến vị trí và ngữ cảnh<br>\n\n**CountVectorize:** \n* được sử dụng để chuyển đổi một bộ sưu tập các tài liệu văn bản thành một vectơ có số lượng thuật ngữ / mã thông báo. Nó cũng cho phép xử lý trước dữ liệu văn bản trước khi tạo biểu diễn vectơ. Chức năng này làm cho nó trở thành một mô-đun biểu diễn tính năng rất linh hoạt cho văn bản\n","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nfrom sklearn.feature_extraction.text import CountVectorizer\nfrom sklearn.metrics import accuracy_score, f1_score, confusion_matrix, classification_report\n\nX = df_train_sampled['preprocessed_questions']\ny = df_train_sampled.target\ntest = test_df['question_text']\nX_train, X_test, y_train, y_test = train_test_split(df_train_sampled['preprocessed_questions'], df_train_sampled['target'], test_size=0.3)","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:24.141956Z","iopub.execute_input":"2022-01-05T02:23:24.142373Z","iopub.status.idle":"2022-01-05T02:23:24.248488Z","shell.execute_reply.started":"2022-01-05T02:23:24.142339Z","shell.execute_reply":"2022-01-05T02:23:24.247312Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* Chia tập dữ liệu ra thành 2 phần train, test với test_size = 0.3","metadata":{}},{"cell_type":"code","source":"cnt_vectorizer = CountVectorizer()\n#Fitting count vectorizer to both training and test sets (semi-supervised learning)\ncnt_vectorizer.fit(list(X_train) + list(X_test))\nX_train = cnt_vectorizer.transform(X_train) \nX_test = cnt_vectorizer.transform(X_test)","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:24.249900Z","iopub.execute_input":"2022-01-05T02:23:24.250244Z","iopub.status.idle":"2022-01-05T02:23:41.592921Z","shell.execute_reply.started":"2022-01-05T02:23:24.250211Z","shell.execute_reply":"2022-01-05T02:23:41.591890Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train_sampled[\"preprocessed_questions\"].head()\n","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:41.594448Z","iopub.execute_input":"2022-01-05T02:23:41.594855Z","iopub.status.idle":"2022-01-05T02:23:41.603190Z","shell.execute_reply.started":"2022-01-05T02:23:41.594813Z","shell.execute_reply":"2022-01-05T02:23:41.602257Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. Trainning","metadata":{}},{"cell_type":"markdown","source":"# Naive Bayes\n* **Naive Bayes Classification** (NBC) là một thuật toán dựa trên định lý Bayes về lý thuyết xác suất  để đưa ra các phán đoán cũng như phân loại dữ liệu dựa trên các dữ liệu được quan sát và thống kê. Naive Bayes Classification là một trong những thuật toán được ứng dụng rất nhiều trong các lĩnh vực Machine learning dùng để đưa các dự đoán chính xác nhất dự trên một tập dữ liệu đã được thu thập, vì nó khá dễ hiểu và độ chính xác cao. Nó thuộc vào nhóm Supervised Machine Learning Algorithms (thuật toán học có hướng dẫn), tức là máy học từ các ví dụ từ các mẫu dữ liệu đã có.$$$$\n 1. Gọi D là tập dữ liệu huấn luyện, trong đó mỗi phần tử dữ liệu X được biểu diễn bằng một vector chứa n giá trị thuộc tính A1, A2,...,An = {x1,x2,...,xn}\n 2. Giả sử có m lớp C1, C2,..,Cm. Cho một phần tử dữ liệu X, bộ phân lớp sẽ gán nhãn cho X là lớp có xác suất hậu nghiệm lớn nhất. Cụ thể, bộ phân lớp Bayes sẽ dự đoán X thuộc vào lớp Ci nếu và chỉ nếu:\n$$P(Ci|X) > P(Cj|X) (1<= i, j <=m, i != j)$$\n 3. Giá trị này sẽ tính dựa trên định lý Bayes.\nĐể tìm xác suất lớn nhất, ta nhận thấy các giá trị P(X) là giống nhau với mọi lớp nên không cần tính. Do đó ta chỉ cần tìm giá trị lớn nhất của P(X|Ci) * P(Ci). Chú ý rằng P(Ci) được ước lượng bằng |Di|/|D|, trong đó Di là tập các phần tử dữ liệu thuộc lớp Ci. Nếu xác suất tiền nghiệm P(Ci) cũng không xác định được thì ta coi chúng bằng nhau P(C1) = P(C2) = ... = P(Cm), khi đó ta chỉ cần tìm giá trị P(X|Ci) lớn nhất.<br>\n 4. Khi số lượng các thuộc tính mô tả dữ liệu là lớn thì chi phí tính toàn P(X|Ci) là rất lớn, dó đó có thể giảm độ phức tạp của thuật toán Naive Bayes giả thiết các thuộc tính độc lập nhau. Khi đó ta có thể tính:\n$$P(X|Ci) = P(x1|Ci)...P(xn|Ci)$$\n","metadata":{}},{"cell_type":"code","source":"import sklearn.metrics as metrics\nfrom sklearn.metrics import precision_score, recall_score, f1_score, accuracy_score","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:41.604751Z","iopub.execute_input":"2022-01-05T02:23:41.605416Z","iopub.status.idle":"2022-01-05T02:23:41.614631Z","shell.execute_reply.started":"2022-01-05T02:23:41.605375Z","shell.execute_reply":"2022-01-05T02:23:41.613663Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.naive_bayes import MultinomialNB\nMulNB = MultinomialNB()\nMulNB.fit(X_train,y_train)\ntest_predictions = MulNB.predict(X_test)\ntest_acc = accuracy_score(y_test, test_predictions) \ntest_f1 = f1_score(y_test, test_predictions)\nprint('Precision: %.3f' % precision_score(y_test, test_predictions))\nprint('Recall: %.3f' % recall_score(y_test,test_predictions))\nprint(f\"Testing accuracy:  {test_acc:.2%}, F1: {test_f1:.4f}\")\ny_pred_proba = MulNB.predict_proba(X_test)[::,1]\nfpr, tpr, _ = metrics.roc_curve(y_test,  y_pred_proba)\nauc = metrics.roc_auc_score(y_test, y_pred_proba)\nplt.plot(fpr,tpr,label=\"data 1, auc=\"+str(auc))\nplt.legend(loc=4)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:41.615972Z","iopub.execute_input":"2022-01-05T02:23:41.616562Z","iopub.status.idle":"2022-01-05T02:23:42.137115Z","shell.execute_reply.started":"2022-01-05T02:23:41.616520Z","shell.execute_reply":"2022-01-05T02:23:42.136079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Đánh giá:\n* Tốc độ chạy mô hình khá nhanh  do mô hình đơn giản\n* Điểm accuracy khá là cao do tập dữ liệu mất cân bằng\n* F1 score đạt được ở mức trung bình","metadata":{}},{"cell_type":"markdown","source":"# LogisticRegression","metadata":{}},{"cell_type":"markdown","source":"**Logistic Regression** là 1 thuật toán phân loại được dùng để gán các đối tượng cho 1 tập hợp giá trị rời rạc (như 0, 1, 2, ...). Một ví dụ điển hình là phân loại Email, gồm có email công việc, email gia đình, email spam, ...\n* Cũng giống như các thuật toán Linear (tìm và tối ưu w) với công thức chung: $$y = f(w^{T}x),(w \\in [w_{0}, w_{1},... w_{n}])$$\n* Đầu ra dự đoán của logistic regression thường được viết chung dưới dạng:$$y = \\theta (w^{T}x)$$\nTrong đó θ được gọi là logistic function.\n\n**Sigmoid function**<br>\n ![]( https://nickmccullum.com/images/python-deep-learning/deep-learning-activation-functions/sigmoid-function.png)\n\n* Như vậy sau khi tính được phần tuyến tính là $w^{T}x$, phần tuyến tính này sẽ được đưa vào hàm sigmoid($\\sigma()$). Hàm $\\sigma()$ sẽ trả về xác suất mà câu hỏi là hữu ích ($y = 0$) hay độc hại ($y = 1$) với: $$P(y_{1}|x_{i};w) = \\sigma(w^{T}x); P(y_{0}|x_{i};w) = 1 - \\sigma(w^{T}x)$$\n* Bài toán quay trở về với việc **tối ưu hàm mất mát L** với mục tiêu làm cho $P(y|x_{i}) = \\sigma(w^{T}x) = \\widehat{y}$ càng ngày càng lớn (tiến gần tới 1): $$L = -log(P(y|x_{i}))$$ $$<=> \\frac{\\partial L}{\\partial w} = (\\widehat{y} - y)x = (\\sigma(w^{T}x) - y)x$$ $$=> w = w + \\lambda(\\widehat{y} - y)x$$\n* Với $\\lambda$ là hệ học learning_rate (là một con số nhỏ thường nằm trong khoảng từ 0.01 đến 0.0001). <br>","metadata":{}},{"cell_type":"code","source":"from sklearn.linear_model import LogisticRegression\n# Fitting a simple Logistic Regression\nlogisticRegression = LogisticRegression(max_iter = 5000)\nlogisticRegression.fit(X_train,y_train)\ntest_predictions = logisticRegression.predict(X_test)\ntest_acc = accuracy_score(y_test, test_predictions) \ntest_f1 = f1_score(y_test, test_predictions) \nprint(f\"Testing accuracy:  {test_acc:.2%}, F1: {test_f1:.4f}\")\nprint('Precision: %.3f' % precision_score(y_test, test_predictions))\nprint('Recall: %.3f' % recall_score(y_test,test_predictions))\ny_pred_proba = logisticRegression.predict_proba(X_test)[::,1]\nfpr, tpr, _ = metrics.roc_curve(y_test,  y_pred_proba)\nauc = metrics.roc_auc_score(y_test, y_pred_proba)\nplt.plot(fpr,tpr,label=\"data 1, auc=\"+str(auc))\nplt.legend(loc=4)\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:23:42.138476Z","iopub.execute_input":"2022-01-05T02:23:42.138798Z","iopub.status.idle":"2022-01-05T02:24:46.281491Z","shell.execute_reply.started":"2022-01-05T02:23:42.138766Z","shell.execute_reply":"2022-01-05T02:24:46.280674Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Nhận xét:\n* Ở đây ta nhận được kết quả tốt hơn so với mô hình Naice Bayes\n* Thuật toán cũng chạy chậm hơn","metadata":{}},{"cell_type":"markdown","source":"# Submission","metadata":{}},{"cell_type":"code","source":"x_val = cnt_vectorizer.transform(test_df['question_text'])\nvalidation_predictions = logisticRegression.predict(x_val)\nsubmission = pd.DataFrame({'qid':test_df['qid'], 'prediction':validation_predictions })\nsubmission.to_csv('submission.csv', index=False)\nsubmission","metadata":{"execution":{"iopub.status.busy":"2022-01-05T02:24:46.282738Z","iopub.execute_input":"2022-01-05T02:24:46.283274Z","iopub.status.idle":"2022-01-05T02:24:54.618234Z","shell.execute_reply.started":"2022-01-05T02:24:46.283239Z","shell.execute_reply":"2022-01-05T02:24:54.617319Z"},"trusted":true},"execution_count":null,"outputs":[]}]}