{"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":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-06-10T13:42:02.004276Z","iopub.execute_input":"2021-06-10T13:42:02.004540Z","iopub.status.idle":"2021-06-10T13:42:02.011708Z","shell.execute_reply.started":"2021-06-10T13:42:02.004517Z","shell.execute_reply":"2021-06-10T13:42:02.010870Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I. Phân tích bài toán:\n- Nhiệm vụ phải làm trong bài toán là **phân loại** các câu **insincere** và **sincere** có trên hệ thống của Quora\n- Tập đầu vào là tập các câu hỏi tiếng anh được cho dưới dạng *text* và đi kèm là *id* của từng câu cũng như *nhãn dán (label)* cho từng câu (**insincere** là 1 và **sincere** là 0) đầu ra là các giá trị 0 hoặc 1 là nhãn mà mô hình đoán\n- Với bài toán trên, ta cần chuyển dữ liệu từ dạng *text* sang ma trận đặc trưng dưới dạng *số* sau đó kết hợp với mô hình học máy (mô hình Logistic Regression) để huấn luyện và dự đoán kết quả đầu ra ","metadata":{}},{"cell_type":"code","source":"# Đọc dữ liệu từ bài toán: \ndf = pd.read_csv('../input/quora-insincere-questions-classification/train.csv')","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:42:02.023745Z","iopub.execute_input":"2021-06-10T13:42:02.025165Z","iopub.status.idle":"2021-06-10T13:42:06.587690Z","shell.execute_reply.started":"2021-06-10T13:42:02.025139Z","shell.execute_reply":"2021-06-10T13:42:06.586698Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Lấy ra 1 số các câu trong tập input\ndf.head(5)","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:42:06.588871Z","iopub.execute_input":"2021-06-10T13:42:06.589101Z","iopub.status.idle":"2021-06-10T13:42:06.617095Z","shell.execute_reply.started":"2021-06-10T13:42:06.589079Z","shell.execute_reply":"2021-06-10T13:42:06.615779Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"TỔNG QUÁT VỀ TẬP INPUT:\n- Tổng cộng 1306122 câu hỏi dưới dạng text được gán nhãn và không có giá trị null\n- Target (nhãn) là tập số nguyên gồm 2 giá trị 1 và 0\n- Tổng số câu **sincere** là 1225312 số câu **insincere** là 80810","metadata":{}},{"cell_type":"code","source":"# Thông tin về tập input:\ndf.info()","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:42:06.618621Z","iopub.execute_input":"2021-06-10T13:42:06.618875Z","iopub.status.idle":"2021-06-10T13:42:06.911926Z","shell.execute_reply.started":"2021-06-10T13:42:06.618850Z","shell.execute_reply":"2021-06-10T13:42:06.910120Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Mô phỏng về độ tương quan giữa các câu insincere và sincere dưới dạng biểu đồ:\n\nval = df.target.value_counts().values\nnames = ['Sincere', 'Insincere']\nplt.bar(names, val)\nplt.suptitle('Number of Sincere and Insincere Questions')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:42:06.913903Z","iopub.execute_input":"2021-06-10T13:42:06.914290Z","iopub.status.idle":"2021-06-10T13:42:07.073812Z","shell.execute_reply.started":"2021-06-10T13:42:06.914252Z","shell.execute_reply":"2021-06-10T13:42:07.072471Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"val","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:42:07.075258Z","iopub.execute_input":"2021-06-10T13:42:07.075688Z","iopub.status.idle":"2021-06-10T13:42:07.083146Z","shell.execute_reply.started":"2021-06-10T13:42:07.075645Z","shell.execute_reply":"2021-06-10T13:42:07.082276Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"II. Tiền xử lý cho dữ liệu đầu vào:\n- Với dữ liệu dạng text, ta cần chuyển sang số và biểu diễn thông qua các ma trận để huấn luyện mô hình học máy\n- Các bước tiền xử lý trong bài gồm có:\n    - Loại bỏ các dấu câu, và các từ stop_words có trong câu hỏi (các từ stop_words thường là những từ viết tắt và không mang nhiều ý nghĩa và có thể ảnh hưởng đến trọng số của những từ quan trọng trong câu)\n    - Loại bỏ các số có trong câu (cũng giống như stop_words các số thường không mang nhiều ý nghĩa trong việc phân loại câu nên cần loại bỏ)\n    - Sử dụng phương pháp **TF_IDF** hoặc đếm số lần xuất hiện của những từ đặc trưng trong câu để biểu diễn ma trận trọng số của những từ quan trọng trong câu hỏi (trong bài này ta sẽ kiểm tra cả 2 cách và so sánh kết quả giữa chúng)\n- Sau đó, ta sẽ chia tập input thành 2 phần: 1 phần để huấn luyện và 1 phần để kiểm tra độ chính xác của mô hình (tỉ lệ là 7:3)\n    \n    \n*** Phương pháp TF_IDF**:\n- Là phương pháp cơ bản trong việc xử lý dữ liệu văn bản trong xử lý ngôn ngữ tự nhiên.\n- Mục đích: Cân bằng mức độ quan trọng giữa các từ và loại bỏ 1 số những từ không cần thiết bằng cách tính trọng số TF (Term frequence) và IDF (Inverse document frequence)\n- TF (Term frequence) được tính như sau:\n    **TF(t, d) = ( số lần từ t xuất hiện trong văn bản d) / (tổng số từ trong văn bản d)** ========> Tần suất của từ t (trong khoảng [0,1])\n- IDF (Inverse document frequence) được tính như sau:\n    **IDF(t, D) = log_e( Tổng số văn bản trong tập mẫu D/ Số văn bản có chứa từ t )** ===========> Mức độ quan trọng của từ t\n- Trọng số TF_IDF của từ t là ***TF(t, d) * IDF(t, D)***\n","metadata":{}},{"cell_type":"code","source":"from string import punctuation, digits\nfrom nltk.corpus import stopwords\nfrom nltk.tokenize import word_tokenize\nfrom nltk.stem import WordNetLemmatizer\n\nwordnet_lemmatizer = WordNetLemmatizer()\n# Khai báo tập các dấu câu và tập các stop_words của tiếng Anh\npuncs = set(punctuation)\nstop_w = set(stopwords.words('english'))","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:42:07.085490Z","iopub.execute_input":"2021-06-10T13:42:07.085797Z","iopub.status.idle":"2021-06-10T13:42:08.851588Z","shell.execute_reply.started":"2021-06-10T13:42:07.085767Z","shell.execute_reply":"2021-06-10T13:42:08.850543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(puncs)\nprint(stop_w)","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:42:08.852836Z","iopub.execute_input":"2021-06-10T13:42:08.853224Z","iopub.status.idle":"2021-06-10T13:42:08.858106Z","shell.execute_reply.started":"2021-06-10T13:42:08.853153Z","shell.execute_reply":"2021-06-10T13:42:08.857056Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Tiền xử lý dữ liệu:\ndef lemSentence(sentence): # Xây dựng lại cấu trúc câu sau khi đã loại bỏ các ký tự và các từ không cần thiết\n    token_words = word_tokenize(sentence)\n    lem_sentence = []\n    for word in token_words:\n        lem_sentence.append(wordnet_lemmatizer.lemmatize(word, pos=\"v\"))\n        lem_sentence.append(\" \")\n    return \"\".join(lem_sentence)\n\ndef clean(text): # Loại bỏ các ký tự không cần thiết \n    # Loại bỏ các dấu câu\n    text = text.translate(str.maketrans('', '', punctuation))\n    # Loại bỏ các số\n    text = text.translate(str.maketrans('', '', digits))\n    # Loại bỏ các stop_words\n    text = [w for w in word_tokenize(text) if not w.lower() in stop_w]\n    text = ' '.join(text)\n    # Thiết lập lại cấu trúc của câu\n    text = lemSentence(text)\n    return text","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:42:08.860441Z","iopub.execute_input":"2021-06-10T13:42:08.860712Z","iopub.status.idle":"2021-06-10T13:42:08.874285Z","shell.execute_reply.started":"2021-06-10T13:42:08.860685Z","shell.execute_reply":"2021-06-10T13:42:08.873237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Lấy ra tập train và tập nhãn dán của dữ liệu\ntrain_quests = df.question_text\ntrain_labels = df.target","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:42:08.875608Z","iopub.execute_input":"2021-06-10T13:42:08.876020Z","iopub.status.idle":"2021-06-10T13:42:08.893012Z","shell.execute_reply.started":"2021-06-10T13:42:08.875994Z","shell.execute_reply":"2021-06-10T13:42:08.892028Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Thực hiện việc tiền xử lý với dữ liệu đầu vào và lưu kết quả vào 1 hàng mới có tên là \"question_text_cleaned\"\ndf['question_text_cleaned'] = df.question_text.apply(lambda x: clean(x))","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:42:09.272636Z","iopub.execute_input":"2021-06-10T13:42:09.273008Z","iopub.status.idle":"2021-06-10T13:47:44.789015Z","shell.execute_reply.started":"2021-06-10T13:42:09.272982Z","shell.execute_reply":"2021-06-10T13:47:44.788471Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Lấy ra 1 số câu sau khi đã thực hiện tiền xử lý\ndf.head(5)","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:47:44.790280Z","iopub.execute_input":"2021-06-10T13:47:44.790701Z","iopub.status.idle":"2021-06-10T13:47:44.801293Z","shell.execute_reply.started":"2021-06-10T13:47:44.790669Z","shell.execute_reply":"2021-06-10T13:47:44.800256Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer\nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.metrics import accuracy_score, f1_score, confusion_matrix, classification_report, plot_confusion_matrix\nfrom sklearn.model_selection import train_test_split","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:47:44.802861Z","iopub.execute_input":"2021-06-10T13:47:44.803232Z","iopub.status.idle":"2021-06-10T13:47:44.821229Z","shell.execute_reply.started":"2021-06-10T13:47:44.803170Z","shell.execute_reply":"2021-06-10T13:47:44.820165Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* Sau khi thực hiện việc loại bỏ các ký tự và các từ ngữ không cần thiết, ta sẽ thực hiện việc mã hóa TF_IDF cho tập từ vựng mới \n* Thư viện sklearn đã hỗ trợ việc tính toán cũng như chuyển đổi mà trận TF_IDF (tính toán trọng số và chuyển đổi từ dạng text sang ma trận trọng số) tương tự với cách đếm số từ quan trọng trong 1 câu hỏi\n*Link: https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html ----------------\n    https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html","metadata":{}},{"cell_type":"code","source":"# Khai báo hàm thực hiện tính trọng số\ncount_vectorizer = CountVectorizer()\ntf_idf_vectorizer = TfidfVectorizer()\n# Chia tập dữ liệu đầu vào thành 2 phần (tập train và test theo tỷ lệ (7:3))\nx_train, x_test, y_train, y_test = train_test_split(df['question_text_cleaned'], train_labels, test_size=0.3)\n# Tiến hành tính toán trọng số của các từ trong tập huấn luyện\ncount_vectorizer.fit(x_train)\ntf_idf_vectorizer.fit(x_train)\n# Biến đổi các câu trong tập train thành ma trận trọng số\nvt_count_train = count_vectorizer.transform(x_train)\nvt_count_test = count_vectorizer.transform(x_test)\n\ntfidf_vt_train = tf_idf_vectorizer.transform(x_train)\ntfidf_vt_test = tf_idf_vectorizer.transform(x_test)","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:47:44.823998Z","iopub.execute_input":"2021-06-10T13:47:44.824273Z","iopub.status.idle":"2021-06-10T13:48:45.916432Z","shell.execute_reply.started":"2021-06-10T13:47:44.824251Z","shell.execute_reply":"2021-06-10T13:48:45.915339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Ma trận trọng số của các câu hỏi sẽ là input cho mô hình và có shape là (914285, 176283)\n# trong đó: 914285 là số lượng các câu hỏi \n#           176283 là kích thước mà trận trọng số dại diện cho câu hỏi đó được xây dựng từ tập từ vựng của dữ liệu đầu vào \ntfidf_vt_train.shape","metadata":{"execution":{"iopub.status.busy":"2021-06-10T13:48:45.917712Z","iopub.execute_input":"2021-06-10T13:48:45.918092Z","iopub.status.idle":"2021-06-10T13:48:45.924217Z","shell.execute_reply.started":"2021-06-10T13:48:45.918058Z","shell.execute_reply":"2021-06-10T13:48:45.923215Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"III. Huấn luyện mô hình và báo cáo kết quả:\n* Sử dụng mô hình học máy Logistics Regression để thực thiện huấn luyện và kiểm tra độ chính xác","metadata":{}},{"cell_type":"code","source":"# Khái báo mô hình\nmodel_1 = LogisticRegression(n_jobs=10, solver='saga', C=0.1, verbose=1)\nmodel_2 = LogisticRegression(n_jobs=10, solver='sag', C=0.1, verbose=1)\n# Tiến hành huấn luyện trên tập dữ liệu đã được mã hóa bằng TF_IDF\nmodel_1.fit(vt_count_train, y_train)\nmodel_2.fit(tfidf_vt_train, y_train)","metadata":{"execution":{"iopub.status.busy":"2021-06-10T14:07:43.629867Z","iopub.execute_input":"2021-06-10T14:07:43.630709Z","iopub.status.idle":"2021-06-10T14:08:31.468123Z","shell.execute_reply.started":"2021-06-10T14:07:43.630662Z","shell.execute_reply":"2021-06-10T14:08:31.467635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Độ chính xác trên tập train\npreds = model_1.predict(vt_count_train)\naccuracy = accuracy_score(y_train, preds)\nprint(\"Accuracy in train set: \", accuracy)\n# Dự đoán bằng mô hình vừa huấn luyện\ny_preds = model_1.predict(vt_count_test)\n# Ma trận lỗi của mô hình\nprint(f\"Confusion matrix: \") \nprint(confusion_matrix(y_test, y_preds))","metadata":{"execution":{"iopub.status.busy":"2021-06-10T14:10:17.532862Z","iopub.execute_input":"2021-06-10T14:10:17.533263Z","iopub.status.idle":"2021-06-10T14:10:17.909754Z","shell.execute_reply.started":"2021-06-10T14:10:17.533229Z","shell.execute_reply":"2021-06-10T14:10:17.908716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Ma trận lỗi của mô hình:\nplot_confusion_matrix(model_1, vt_count_test, y_test)\nplot_confusion_matrix(model_2, tfidf_vt_test, y_test)\nplt.show()  ","metadata":{"execution":{"iopub.status.busy":"2021-06-10T14:18:09.924660Z","iopub.execute_input":"2021-06-10T14:18:09.924941Z","iopub.status.idle":"2021-06-10T14:18:10.774702Z","shell.execute_reply.started":"2021-06-10T14:18:09.924918Z","shell.execute_reply":"2021-06-10T14:18:10.773557Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* Từ 2 ma trận lỗi trên, ta có thể thấy việc mã hóa dữ liệu đầu vào bằng cách đếm số lần xuất hiện của các từ trong câu cho độ chính xác cao hơn việc mã hóa bằng phương pháp TF_IDF","metadata":{}},{"cell_type":"code","source":"# Báo cáo kết quả thực hiện được \nprint(\"Classificaiton report:\\n\", classification_report(y_test, y_preds, target_names=[\"Sincere\", \"Insincere\"]))","metadata":{"execution":{"iopub.status.busy":"2021-06-10T14:12:23.296118Z","iopub.execute_input":"2021-06-10T14:12:23.296513Z","iopub.status.idle":"2021-06-10T14:12:23.782271Z","shell.execute_reply.started":"2021-06-10T14:12:23.296490Z","shell.execute_reply":"2021-06-10T14:12:23.781111Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}