{"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 môn Học máy\n\nGiảng viên: Trần Quốc Long\n\nLớp môn học: INT3405_1\n\nSinh viên: Đào Ngọc Việt Anh\n\nMSSV: 18020163","metadata":{}},{"cell_type":"markdown","source":"## 1. Mô tả bài toán\n* Hiện nay, xử lý những nội dung độc hại và gây chia rẽ là một thách thức đối với bất kỳ trang web nào.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 cộng đồng.\n\n* Vậy mục tiêu của bài toán này là xác định được những câu hỏi có nội dung nhạy cảm để có thể loại bỏ chúng. Đó là những câu hỏi không mang tính chất đóng góp, thiếu chân thành, thậm chí để đả kích một cá nhân, tập thể hay tổ chức nào đó.\n* Input: Câu hỏi từ Quora ở dạng text\n\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":"## 2. Phân tích dữ liệu","metadata":{}},{"cell_type":"markdown","source":"### Import những thư viện cần thiết\n","metadata":{}},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\")\nimport numpy as np \nimport pandas as pd \n\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n%matplotlib inline\nfrom nltk.tokenize import word_tokenize\nfrom nltk.corpus import stopwords\nfrom nltk.stem import PorterStemmer\n\nfrom string import punctuation \n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.pipeline import Pipeline\nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer\nfrom sklearn.metrics import f1_score, classification_report\nfrom xgboost import XGBClassifier\nimport lightgbm as lgb","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-01-06T13:32:15.911204Z","iopub.execute_input":"2022-01-06T13:32:15.911535Z","iopub.status.idle":"2022-01-06T13:32:19.722411Z","shell.execute_reply.started":"2022-01-06T13:32:15.91143Z","shell.execute_reply":"2022-01-06T13:32:19.721687Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = pd.read_csv(\"../input/quora-insincere-questions-classification/train.csv\")\ndf_test = pd.read_csv(\"../input/quora-insincere-questions-classification/test.csv\", index_col='qid')\ndf_train.tail()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T13:40:26.598154Z","iopub.execute_input":"2022-01-06T13:40:26.598427Z","iopub.status.idle":"2022-01-06T13:40:29.934255Z","shell.execute_reply.started":"2022-01-06T13:40:26.598398Z","shell.execute_reply":"2022-01-06T13:40:29.933408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Dữ liệu gồm 3 cột:\n\nqid: mã số câu hỏi\n\nquestion_text: câu hỏi\n\ntarget: nhãn dữ liệu (0 hoặc 1)","metadata":{}},{"cell_type":"code","source":"df_train.info()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T13:40:51.548586Z","iopub.execute_input":"2022-01-06T13:40:51.549217Z","iopub.status.idle":"2022-01-06T13:40:51.822922Z","shell.execute_reply.started":"2022-01-06T13:40:51.549179Z","shell.execute_reply":"2022-01-06T13:40:51.822097Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_test.info()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T13:41:19.488774Z","iopub.execute_input":"2022-01-06T13:41:19.489045Z","iopub.status.idle":"2022-01-06T13:41:19.538532Z","shell.execute_reply.started":"2022-01-06T13:41:19.489016Z","shell.execute_reply":"2022-01-06T13:41:19.537771Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Tập train gồm có 1306122 câu hỏi, tập test gồm có 375806 câu hỏi","metadata":{}},{"cell_type":"code","source":"#Ta biểu diễn đồ thị tỉ lệ số câu hỏi chân thành và số câu hỏi không chân thành trong tập train\nimport collections\n\nfig, ax = plt.subplots(1,1, figsize=(7,7))\nexplode=(0,0.1)\nlabels ='sincere','insincere'\ncolors = ['#00ff00', '#ff0000']\n\ncounts = list(dict(collections.Counter(list(df_train.target))).values()) \nax.pie(counts , explode=explode, labels=labels, colors=colors, autopct='%1.1f%%',shadow=True, startangle=90)","metadata":{"execution":{"iopub.status.busy":"2022-01-06T13:47:58.973699Z","iopub.execute_input":"2022-01-06T13:47:58.974099Z","iopub.status.idle":"2022-01-06T13:47:59.311866Z","shell.execute_reply.started":"2022-01-06T13:47:58.974062Z","shell.execute_reply":"2022-01-06T13:47:59.311145Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Nhận xét về dữ liệu\n\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.8% còn những câu hỏi không chân thành chỉ chiếm 6.12% \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,..\n ","metadata":{}},{"cell_type":"markdown","source":"### Khảo sát về tần suất các từ xuất hiện trong tập dữ liệu:\n\nWord clouds: Một từ càng xuất hiện nhiều trong văn bản thì từ đó càng lớn và đậm nét hơn trong Word clouds.","metadata":{}},{"cell_type":"code","source":"from wordcloud import WordCloud, STOPWORDS\nstopwords = set(STOPWORDS)","metadata":{"execution":{"iopub.status.busy":"2022-01-06T13:57:21.251263Z","iopub.execute_input":"2022-01-06T13:57:21.251563Z","iopub.status.idle":"2022-01-06T13:57:21.31646Z","shell.execute_reply.started":"2022-01-06T13:57:21.251527Z","shell.execute_reply":"2022-01-06T13:57:21.315784Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('Ảnh word cloud được tạo từ những câu hỏi chân thành:')\nsincere_wordcloud = WordCloud(width=600, height=400, background_color ='white', min_font_size = 10).generate(str(df_train[df_train[\"target\"] == 0][\"question_text\"]))\n#Positive Word cloud\nplt.figure(figsize=(15,6), facecolor=None)\nplt.imshow(sincere_wordcloud)\nplt.axis(\"off\")\nplt.tight_layout(pad=0)\nplt.show();","metadata":{"execution":{"iopub.status.busy":"2022-01-06T13:57:57.827215Z","iopub.execute_input":"2022-01-06T13:57:57.827466Z","iopub.status.idle":"2022-01-06T13:57:58.444632Z","shell.execute_reply.started":"2022-01-06T13:57:57.827438Z","shell.execute_reply":"2022-01-06T13:57:58.443945Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('Ảnh word cloud được tạo từ những câu hỏi thiếu chân thành:')\ninsincere_wordcloud = WordCloud(width=600, height=400, background_color ='white', min_font_size = 10).generate(str(df_train[df_train[\"target\"] == 1][\"question_text\"]))\n#Positive Word cloud\nplt.figure(figsize=(15,6), facecolor=None)\nplt.imshow(insincere_wordcloud)\nplt.axis(\"off\")\nplt.tight_layout(pad=0)\nplt.show();","metadata":{"execution":{"iopub.status.busy":"2022-01-06T13:58:49.183229Z","iopub.execute_input":"2022-01-06T13:58:49.183486Z","iopub.status.idle":"2022-01-06T13:58:49.755115Z","shell.execute_reply.started":"2022-01-06T13:58:49.183458Z","shell.execute_reply":"2022-01-06T13:58:49.7543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Thống kê những từ phổ biến trong các loại câu hỏi\n\nStop Words: Là những từ thường được sử dụng ( chẳng hạn như 'the', 'an', 'a',..). Để tránh những từ này chiếm dung lượng trong cơ sở dữ liệu hoặc mất thời gian xử lí, chúng ta nên loại bỏ chúng.","metadata":{}},{"cell_type":"code","source":"from nltk.corpus import stopwords\nstop_words = set(stopwords.words('english'))\nstop_words","metadata":{"execution":{"iopub.status.busy":"2022-01-06T14:03:10.504011Z","iopub.execute_input":"2022-01-06T14:03:10.504863Z","iopub.status.idle":"2022-01-06T14:03:10.524612Z","shell.execute_reply.started":"2022-01-06T14:03:10.504811Z","shell.execute_reply":"2022-01-06T14:03:10.523958Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Vocabulary(object):\n    \n    def __init__(self):\n        self.vocab = {}\n        self.STOPWORDS = set()\n        self.STOPWORDS = set(stopwords.words('english'))\n        \n    def build_vocab(self, lines):\n        for line in lines:\n            for word in line.split(' '):\n                word = word.lower()\n                if (word in self.STOPWORDS):\n                    continue\n                if (word not in self.vocab):\n                    self.vocab[word] = 0\n                self.vocab[word] +=1 \n    \n    def generate_ngrams(text, n_gram=1):\n        \"\"\"arg: text, n_gram\"\"\"\n        token = [token for token in text.lower().split(\" \") if token != \"\" if token not in STOPWORDS]\n        ngrams = zip(*[token[i:] for i in range(n_gram)])\n        return [\" \".join(ngram) for ngram in ngrams]\n    \n    def horizontal_bar_chart(df, color):\n        trace = go.Bar(\n            y=df[\"word\"].values[::-1],\n            x=df[\"wordcount\"].values[::-1],\n            showlegend=False,\n            orientation = 'h',\n            marker=dict(\n            color=color,\n            ),\n        )\n        return trace","metadata":{"execution":{"iopub.status.busy":"2022-01-06T14:07:43.793422Z","iopub.execute_input":"2022-01-06T14:07:43.794105Z","iopub.status.idle":"2022-01-06T14:07:43.804047Z","shell.execute_reply.started":"2022-01-06T14:07:43.794065Z","shell.execute_reply":"2022-01-06T14:07:43.803358Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sincere_vocab = Vocabulary()\nsincere_vocab.build_vocab(df_train[df_train['target'] == 0]['question_text'])\nsincere_vocabulary = sorted(sincere_vocab.vocab.items(), reverse=True, key=lambda kv: kv[1])\n    \ndf_sincere_vocab = pd.DataFrame(sincere_vocabulary, columns=['word_sincere', 'frequency'])\nsns.barplot(y='word_sincere', x='frequency', data=df_sincere_vocab[:20])","metadata":{"execution":{"iopub.status.busy":"2022-01-06T14:08:03.849142Z","iopub.execute_input":"2022-01-06T14:08:03.849428Z","iopub.status.idle":"2022-01-06T14:08:11.370271Z","shell.execute_reply.started":"2022-01-06T14:08:03.849399Z","shell.execute_reply":"2022-01-06T14:08:11.369622Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"insincere_vocab = Vocabulary()\ninsincere_vocab.build_vocab(df_train[df_train['target'] == 1]['question_text'])\ninsincere_vocabulary = sorted(insincere_vocab.vocab.items(), reverse=True, key=lambda kv: kv[1])\n\ndf_insincere_vocab = pd.DataFrame(insincere_vocabulary, columns=['word_insincere', 'frequency'])\nsns.barplot(y='word_insincere', x='frequency', data=df_insincere_vocab[:20])","metadata":{"execution":{"iopub.status.busy":"2022-01-06T14:08:17.305629Z","iopub.execute_input":"2022-01-06T14:08:17.305999Z","iopub.status.idle":"2022-01-06T14:08:18.282051Z","shell.execute_reply.started":"2022-01-06T14:08:17.305966Z","shell.execute_reply":"2022-01-06T14:08:18.281334Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Nhận xét\n\nNhư chúng ta có thể thấy rõ ràng có một số từ nhất định (chửi thề, từ ngữ phân biệt đối xử dựa trên chủng tộc, nhân vật chính trị, v.v.) xuất hiện rất nhiều trong các câu thiếu chân thành.","metadata":{}},{"cell_type":"markdown","source":"### Xử lý dữ liệu\n\nSau khi kiểm tra xong dữ liệu, ta có thể thấy dữ liệu đang khá phức tạp và nhiễu nên ta cần làm một số việc sau:\n* Chỉ giữ lại các ký tự chữ và số \n* Loại bỏ các stop word \n* Đưa các từ về đúng dạng gốc\n\n**Tokenization** : (tách từ) là một trong những bước quan trọng nhất trong quá trình tiền xử lý văn bản. Nói một cách đơn giản, tokenization là quá trình tách một cụm từ, câu, đoạn văn, một hoặc nhiều tài liệu văn bản thành các đơn vị nhỏ hơn. Mỗi đơn vị nhỏ hơn này được gọi là Tokens.\n\n**Stemming vs. lemmatization**: Với mục đích là giảm các dạng vô hướng của mỗi từ thành một cơ sở hoặc gốc chung.","metadata":{}},{"cell_type":"code","source":"df_train = df_train[['question_text', 'target']]\n\ndef text_processing(local_df):\n    \"\"\" return the dataframe with tokens stemmetized without numerical values & stopwords \"\"\"\n    stemmer = PorterStemmer()\n    # Perform preprocessing\n    local_df['txt_processed'] = local_df['question_text'].apply(lambda df: word_tokenize(df))\n    local_df['txt_processed'] = local_df['txt_processed'].apply(lambda x: [item for item in x if item.isalpha()])\n    local_df['txt_processed'] = local_df['txt_processed'].apply(lambda x: [item for item in x if item not in stop_words])\n    local_df['txt_processed'] = local_df['txt_processed'].apply(lambda x: [stemmer.stem(item) for item in x])\n    return local_df","metadata":{"execution":{"iopub.status.busy":"2022-01-06T14:19:03.496435Z","iopub.execute_input":"2022-01-06T14:19:03.497066Z","iopub.status.idle":"2022-01-06T14:19:03.529662Z","shell.execute_reply.started":"2022-01-06T14:19:03.497024Z","shell.execute_reply":"2022-01-06T14:19:03.528831Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = text_processing(df_train)\ndf_train.tail()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T14:30:05.681813Z","iopub.execute_input":"2022-01-06T14:30:05.682404Z","iopub.status.idle":"2022-01-06T14:38:25.930479Z","shell.execute_reply.started":"2022-01-06T14:30:05.682363Z","shell.execute_reply":"2022-01-06T14:38:25.929797Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 3. Training Model\n\n","metadata":{}},{"cell_type":"markdown","source":"Như đã nói ở trên, trong bài toán này ta không đánh giá độ chính xác của mô hình dựa trên Accuracy mà sẽ đánh giá dựa trên metric khác cụ thể là F1-score. ","metadata":{}},{"cell_type":"code","source":"def get_fscore_matrix(fitted_clf, model_name):\n    print(model_name, ' :')\n    \n    # get classes predictions for the classification report \n    y_train_pred, y_pred = fitted_clf.predict(X_train), fitted_clf.predict(X_test)\n    print(classification_report(y_test, y_pred), '\\n') # target_names=y\n    \n    # computes probabilities keep the ones for the positive outcome only      \n    print(f'F1-score = {f1_score(y_test, y_pred):.2f}')","metadata":{"execution":{"iopub.status.busy":"2022-01-06T15:08:14.938881Z","iopub.execute_input":"2022-01-06T15:08:14.939179Z","iopub.status.idle":"2022-01-06T15:08:14.944884Z","shell.execute_reply.started":"2022-01-06T15:08:14.939151Z","shell.execute_reply":"2022-01-06T15:08:14.944173Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Đối với bài toán này, ta sử dụng mô hình Logistic Regression Mô hình này giống với Linear Regression ở khía cạnh đầu ra là số thực, và giống với PLA ở việc đầu ra bị chặn (trong đoạn 0 -> 1). Mặc dù trong tên có chứa từ \"regression\", tuy vậy Logistic Regression thường được sử dụng nhiều cho các bài toán classification. Do vậy, em lựa chọn Logistic Regression cho bài toán này.","metadata":{}},{"cell_type":"code","source":"from sklearn.linear_model import LogisticRegression\nfrom sklearn.pipeline import Pipeline\nfrom sklearn.metrics import accuracy_score, f1_score\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.feature_extraction.text import CountVectorizer\n\ncount_vectorizer = CountVectorizer(analyzer=\"word\", ngram_range=(1,4), max_df=0.9)\nmodel = LogisticRegression(solver=\"saga\", class_weight=\"balanced\", C=0.5, max_iter=250, verbose=1, n_jobs=-1)\n\nvectorize_model_pipeline = Pipeline([\n    ('count_vectorizer', count_vectorizer),\n    ('model', model)\n])","metadata":{"execution":{"iopub.status.busy":"2022-01-06T15:19:26.886409Z","iopub.execute_input":"2022-01-06T15:19:26.88694Z","iopub.status.idle":"2022-01-06T15:19:26.893887Z","shell.execute_reply.started":"2022-01-06T15:19:26.886901Z","shell.execute_reply":"2022-01-06T15:19:26.893189Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Mặc dù đã xử lý dữ liệu ở phần phía trên, tuy vậy, dữ liệu đầu vào của ta vẫn là dạng Text (nó sạch hơn một chút thôi). Để sử dụng dữ liệu văn bản cho mô hình dự đoán, văn bản phải được phân tích cú pháp để loại bỏ một số từ nhất định - quá trình này được gọi là mã hóa . \n\nSau đó, những từ này cần được mã hóa dưới dạng số nguyên hoặc giá trị dấu phẩy động, để sử dụng làm đầu vào trong thuật toán học máy. Quá trình này được gọi là trích xuất đặc trưng (hoặc vectơ hóa).\n\n**CountVectorizer** đượ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\nHay nói ngắn gọn là sử dụng **CountVectorizer** để chuyển dữ liệu đầu vào từ Text sang Vectơ\n","metadata":{}},{"cell_type":"code","source":"# Convert a collection of text documents to string\ndf_train['str_processed'] = df_train['txt_processed'].apply(lambda x: \" \".join(x))\ndf_train.head(2)","metadata":{"execution":{"iopub.status.busy":"2022-01-06T15:19:31.500567Z","iopub.execute_input":"2022-01-06T15:19:31.500854Z","iopub.status.idle":"2022-01-06T15:19:32.349139Z","shell.execute_reply.started":"2022-01-06T15:19:31.500822Z","shell.execute_reply":"2022-01-06T15:19:32.348373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train, X_test, y_train, y_test = train_test_split(df_train['str_processed'], df_train['target'], test_size = 0.2, \n                                                    stratify = df_train.target.values)\n","metadata":{"execution":{"iopub.status.busy":"2022-01-06T15:19:35.145276Z","iopub.execute_input":"2022-01-06T15:19:35.145553Z","iopub.status.idle":"2022-01-06T15:19:36.095793Z","shell.execute_reply.started":"2022-01-06T15:19:35.145519Z","shell.execute_reply":"2022-01-06T15:19:36.095045Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pl_model = vectorize_model_pipeline.fit(X_train, y_train)\npl_model","metadata":{"execution":{"iopub.status.busy":"2022-01-06T15:19:37.703863Z","iopub.execute_input":"2022-01-06T15:19:37.704335Z","iopub.status.idle":"2022-01-06T15:28:37.621241Z","shell.execute_reply.started":"2022-01-06T15:19:37.704295Z","shell.execute_reply":"2022-01-06T15:28:37.620447Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"get_fscore_matrix(pl_model, 'Pipeline')","metadata":{"execution":{"iopub.status.busy":"2022-01-06T15:35:01.755566Z","iopub.execute_input":"2022-01-06T15:35:01.755844Z","iopub.status.idle":"2022-01-06T15:35:48.902999Z","shell.execute_reply.started":"2022-01-06T15:35:01.755814Z","shell.execute_reply":"2022-01-06T15:35:48.902174Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_test = text_processing(df_test)\ndf_test['str_processed'] = df_test['txt_processed'].apply(lambda x: \" \".join(x))\ndf_test.head(2)","metadata":{"execution":{"iopub.status.busy":"2022-01-06T15:40:18.846098Z","iopub.execute_input":"2022-01-06T15:40:18.846477Z","iopub.status.idle":"2022-01-06T15:42:44.501457Z","shell.execute_reply.started":"2022-01-06T15:40:18.846426Z","shell.execute_reply":"2022-01-06T15:42:44.50064Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_pred_final = pl_model.predict(df_test['str_processed'])\ny_pred_final","metadata":{"execution":{"iopub.status.busy":"2022-01-06T15:43:27.809929Z","iopub.execute_input":"2022-01-06T15:43:27.81087Z","iopub.status.idle":"2022-01-06T15:43:40.449424Z","shell.execute_reply.started":"2022-01-06T15:43:27.810817Z","shell.execute_reply":"2022-01-06T15:43:40.448538Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_submission = pd.DataFrame({\"qid\":df_test.index, \"prediction\":y_pred_final})\ndf_submission.head()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T15:43:44.416712Z","iopub.execute_input":"2022-01-06T15:43:44.417137Z","iopub.status.idle":"2022-01-06T15:43:44.433154Z","shell.execute_reply.started":"2022-01-06T15:43:44.417096Z","shell.execute_reply":"2022-01-06T15:43:44.432413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_submission.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2022-01-06T15:43:50.841336Z","iopub.execute_input":"2022-01-06T15:43:50.841934Z","iopub.status.idle":"2022-01-06T15:43:51.818828Z","shell.execute_reply.started":"2022-01-06T15:43:50.84189Z","shell.execute_reply":"2022-01-06T15:43:51.817541Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 4. Đánh giá mô hình Logistic Regression\n\nLogistic Regression là mô hình dễ sử dụng, và dễ hiểu, số điểm nó đạt được cũng tương đối cao:\n\nPrivate Score: 0.62545\n\nPublic Score: 0.61680\n\nLogistic Regression là một mô hình được sử dụng nhiều trong các bài toán Classification.\n\nMặc dù có tên là Regression, tức một mô hình cho fitting, Logistic Regression lại được sử dụng nhiều trong các bài toán Classification. Sau khi tìm được mô hình, việc xác định class y cho một điểm dữ liệu x được xác định bằng việc so sánh hai biểu thức xác suất: P(y = 1|x; w); P(y = 0|x; w) Nếu biểu thức thứ nhất lớn hơn thì ta kết luận điểm dữ liệu thuộc class 1, ngược lại thì nó thuộc class 0. Vì tổng hai biểu thức này luôn bằng 1 nên một cách gọn hơn, ta chỉ cần xác định xem P(y = 1|x; w) lớn hơn 0.5 hay không. Nếu có, class 1. Nếu không, class 0.\n\nLogistic Regression đạt được số điểm khá tốt","metadata":{}}]}