{"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":"**Họ tên**: Nguyễn Hữu Hưng\n\n**MSV**: 18020612\n\n","metadata":{}},{"cell_type":"markdown","source":"# 1. Mô tả bài toán\nQuora là một trang web hỏi đáp (Q&A) được cộng đồng người sử dụng tạo lập, trả lời, và biên tập. Quora tập hợp các câu hỏi và câu trả lời cho các chủ đề phát sinh trong cuộc sống hay công việc hàng ngày.\n\nMộ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\nTa cần phải xây dựng một mô hình phân loại được giữa những câu hỏi chân thành, mục đích tốt (Sincere) với những câu hỏi mang tính tiêu cực, không đúng đắn ấy (Insincere).\n\nInput: Câu hỏi trên Quora (dạng text)\n\nOutput: Gắn nhãn Insincere (1) or not (0)","metadata":{}},{"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":"2022-01-08T12:18:46.107548Z","iopub.execute_input":"2022-01-08T12:18:46.107963Z","iopub.status.idle":"2022-01-08T12:18:46.140364Z","shell.execute_reply.started":"2022-01-08T12:18:46.10786Z","shell.execute_reply":"2022-01-08T12:18:46.139491Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2. Phân tích và xử lý dữ liệu\nDữ liệu vào là các câu hỏi trên Quora. Nhiệm vụ phải làm là phân loại các câu hỏi ấy.\nMột câu hỏi bao gồm 3 thuộc tính:\n* qid : id duy nhất nhận diện câu hỏi.\n* question_text: câu hỏi dạng text.\n* target: nhãn của câu hỏi, bằng là 1 nếu là \"Insincere\", ngược lại thì bằng 0.\n\nTa sử dụng question_text là đầu vào X, target là label y\n","metadata":{}},{"cell_type":"code","source":"train_sample_sub = pd.read_csv('/kaggle/input/quora-insincere-questions-classification/sample_submission.csv')\ntrain_data = pd.read_csv(\"/kaggle/input/quora-insincere-questions-classification/train.csv\")\ntest_data = pd.read_csv(\"/kaggle/input/quora-insincere-questions-classification/test.csv\")\n\ntrain_data","metadata":{"execution":{"iopub.status.busy":"2022-01-08T12:18:46.14185Z","iopub.execute_input":"2022-01-08T12:18:46.142615Z","iopub.status.idle":"2022-01-08T12:18:53.111346Z","shell.execute_reply.started":"2022-01-08T12:18:46.142569Z","shell.execute_reply":"2022-01-08T12:18:53.109712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Lấy ra tập câu hỏi Insincere có nhãn 1\ninsincere_data = train_data[train_data.target == 1]\n#Lấy ra tập câu hỏi Sincere có nhãn 0\nsincere_data = train_data[train_data.target == 0]","metadata":{"execution":{"iopub.status.busy":"2022-01-08T12:18:53.112659Z","iopub.execute_input":"2022-01-08T12:18:53.112866Z","iopub.status.idle":"2022-01-08T12:18:53.224834Z","shell.execute_reply.started":"2022-01-08T12:18:53.112839Z","shell.execute_reply":"2022-01-08T12:18:53.224218Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Infor của tập train\ninsincere_data.info()","metadata":{"execution":{"iopub.status.busy":"2022-01-08T12:18:53.226914Z","iopub.execute_input":"2022-01-08T12:18:53.227452Z","iopub.status.idle":"2022-01-08T12:18:53.269673Z","shell.execute_reply.started":"2022-01-08T12:18:53.227409Z","shell.execute_reply":"2022-01-08T12:18:53.268709Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data.target.value_counts()","metadata":{"execution":{"iopub.status.busy":"2022-01-08T12:18:53.271442Z","iopub.execute_input":"2022-01-08T12:18:53.271753Z","iopub.status.idle":"2022-01-08T12:18:53.28775Z","shell.execute_reply.started":"2022-01-08T12:18:53.271693Z","shell.execute_reply":"2022-01-08T12:18:53.28678Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Ta thấy có 1225312 câu hỏi có gán nhãn 0 (Sincere) lớn hơn rất nhiều so với 80810 câu hỏi có nhãn 1 (Insincere)\n\nTa xem xét tỉ lệ này kỹ hơn ở biểu đồ bên dưới:","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport pandas as pd\n\ntemp = train_data['target'].value_counts(normalize=True).reset_index()\n\ncolors = ['#9f32ff', '#5fff30']\nexplode = (0.05, 0.05)\n \nplt.pie(temp['target'], explode=explode, labels=temp['index'], colors=colors,\n         autopct='%1.1f%%', shadow=True, startangle=0)\n \nfig = plt.gcf()\nfig.set_size_inches(10, 5)\nplt.axis('equal')\nplt.show()\nprint( \"Câu hỏi Sincere chiếm:\", sincere_data.shape[0] / train_data.shape[0] * 100)\nprint( \"Câu hỏi Insincere chiếm:\", insincere_data.shape[0] / train_data.shape[0] * 100)","metadata":{"execution":{"iopub.status.busy":"2022-01-08T12:18:53.289666Z","iopub.execute_input":"2022-01-08T12:18:53.289981Z","iopub.status.idle":"2022-01-08T12:18:53.461699Z","shell.execute_reply.started":"2022-01-08T12:18:53.289942Z","shell.execute_reply":"2022-01-08T12:18:53.460748Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Phân tích các từ xuất hiện nhiều nhất bằng n-gram** : là tần suất xuất hiện của n kí tự ( hoặc từ ) liên tiếp nhau có trong dữ liệu của corpus.\n* Unigram, mô hình với n=1, tức là ta sẽ tính tần suất xuất hiện của một kí tự (từ), như: “k”, “a”,…\n* bigrams với n=2, mô hình được sử dụng nhiều trong việc phân tích các hình thái cho ngôn ngữ, ví dụ với các chữ cái tiếng Anh, ‘th’,’he’,’in’,’an’,’er’ là các cặp kí tự hay xuất hiện nhất.\n* trigrams với n=3.","metadata":{}},{"cell_type":"code","source":"from wordcloud import STOPWORDS\nfrom collections import defaultdict\nimport seaborn as sns\nimport nltk\n\ndef ngram_extractor(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# Lấy max_row các từ dạng n_gram xuất hiện nhiều nhất trong dữ liệu\ndef generate_ngrams(df, col, n_gram, max_row):\n    temp_dict = defaultdict(int)\n    for question in df[col]:\n        for word in ngram_extractor(question, n_gram):\n            temp_dict[word] += 1\n    temp_df = pd.DataFrame(sorted(temp_dict.items(), key=lambda x: x[1])[::-1]).head(max_row)\n    temp_df.columns = [\"word\", \"wordcount\"]\n    return temp_df\n\ndef comparison_plot(df_1,df_2,col_1,col_2):\n    fig, ax = plt.subplots(1, 2, figsize=(20,10))\n    \n    sns.barplot(x=col_2, y=col_1, data=df_1, ax=ax[0])\n    sns.barplot(x=col_2, y=col_1, data=df_2, ax=ax[1])\n\n    ax[0].set_xlabel('Word count', size=12)\n    ax[0].set_ylabel('Words', size=12)\n    ax[0].set_title('Top words in sincere questions', size=16)\n\n    ax[1].set_xlabel('Word count', size=12)\n    ax[1].set_ylabel('Words', size=12)\n    ax[1].set_title('Top words in insincere questions', size=16)\n\n    fig.subplots_adjust(wspace=0.25)\n    \n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-08T12:21:47.886358Z","iopub.execute_input":"2022-01-08T12:21:47.886931Z","iopub.status.idle":"2022-01-08T12:21:48.571498Z","shell.execute_reply.started":"2022-01-08T12:21:47.886895Z","shell.execute_reply":"2022-01-08T12:21:48.570689Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Lấy ra 20 từ dạng unigram xuất hiện nhiều nhất trong 2 loại tập câu hỏi\nsincere_1gram = generate_ngrams(sincere_data, 'question_text', 1, 20)\ninsincere_1gram = generate_ngrams(insincere_data, 'question_text', 1, 20)\n\ncomparison_plot(sincere_1gram,insincere_1gram,'word','wordcount')","metadata":{"execution":{"iopub.status.busy":"2022-01-08T12:18:54.571021Z","iopub.execute_input":"2022-01-08T12:18:54.571611Z","iopub.status.idle":"2022-01-08T12:19:04.172886Z","shell.execute_reply.started":"2022-01-08T12:18:54.571568Z","shell.execute_reply":"2022-01-08T12:19:04.172078Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Lấy ra 20 từ dạng bigram xuất hiện nhiều nhất trong 2 loại tập câu hỏi\nsincere_2gram = generate_ngrams(sincere_data, 'question_text', 2, 20)\ninsincere_2gram = generate_ngrams(insincere_data, 'question_text', 2, 20)\n\ncomparison_plot(sincere_1gram,insincere_1gram,'word','wordcount')","metadata":{"execution":{"iopub.status.busy":"2022-01-08T12:19:04.174477Z","iopub.execute_input":"2022-01-08T12:19:04.174806Z","iopub.status.idle":"2022-01-08T12:19:19.475677Z","shell.execute_reply.started":"2022-01-08T12:19:04.174767Z","shell.execute_reply":"2022-01-08T12:19:19.474631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Lấy ra 20 từ dạng trigram xuất hiện nhiều nhất trong 2 loại tập câu hỏi\nsincere_3gram = generate_ngrams(sincere_data, 'question_text', 3, 20)\ninsincere_3gram = generate_ngrams(insincere_data, 'question_text', 3, 20)\n\ncomparison_plot(sincere_1gram,insincere_1gram,'word','wordcount')","metadata":{"execution":{"iopub.status.busy":"2022-01-08T12:19:19.478133Z","iopub.execute_input":"2022-01-08T12:19:19.478502Z","iopub.status.idle":"2022-01-08T12:19:34.500415Z","shell.execute_reply.started":"2022-01-08T12:19:19.478464Z","shell.execute_reply":"2022-01-08T12:19:34.499335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Đánh giá dữ liệu**\n\nTừ các biểu đồ trên ta có thể đưa ra những đánh giá về dữ liệu:\n* Số câu hỏi Sincere chiếm tới 93,8% cao hơn rất nhiều so với 6,2% các câu hỏi Insincere\n* Các câu hỏi Insincere chủ yếu bao gồm các từ như trump, women, white, men, indian, muslims, black, americans, girls, indians, sex, india\n* 3 câu hỏi Insincere bigram nhiều nhất là \"Donald Trump\", \"White People\", \"Black People\" => Liên quan đến chủng tộc.\n\n**Kết luận**\n* Các câu hỏi Insincere xoay quanh các tình huống giả định, tuổi tác, chủng tộc, v.v.\n* Các câu hỏi Sincere liên quan đến các tips, lời khuyên, gợi ý, sự thật, ...","metadata":{}},{"cell_type":"markdown","source":"**Xử lý dữ liệu đầu vào**\n\n\n\n***Ta cần xử lý những vấn đề sau:***\n* Chuyển về dạng unicode.\n* Chuyển về chữ in thường (lowercase).\n* Bỏ dấu, link, chữ số (Remove punctuation, link, number)\n* Phân tách một câu thành các từ, cụm từ,... có nghĩa (Tokenization).\n* Chuyển đổi, rút gọn các từ về từ gốc (Stemming hoặc Lemmazation).\n* Loại bỏ các stopword như (Remove stopword) như a, an, or, of, the, ... \n\nĐể xử lý dữ liệu vào, ta sử dụng Natural Language Toolkit(NLTK) - là bộ công cụ ngôn ngữ tự nhiên, là một thư viện được viết bằng Python hỗ trợ xử lý ngôn ngữ tự nhiên. Bằng cách cung cấp các cơ chế và kỹ thuật xử lý ngôn ngữ phổ biến, nó giúp cho việc xử lý ngôn ngữ tự nhiên trở lên dễ dàng, nhanh chóng hơn và có tác dụng làm sạch dữ liệu, xử lý dữ liệu đầu vào cho các thuật toán Machine Learning.\n\nNgoài ra còn giúp xử lý các stopwords - là các từ có tần số xuất hiện nhiều như the, to... các từ này thường mang ít giá trị ý nghĩa và không khác nhau nhiều trong các văn bản khác nhau. Ví dụ từ \"the\" hay \"to\" thì ở văn bản nào nó cũng không bị thay đổi về ý nghĩa. \nVí dụ: i, the, my, me, ...","metadata":{}},{"cell_type":"code","source":"import re\nimport nltk\nimport string\nfrom unidecode import unidecode\nfrom nltk.tokenize import word_tokenize\nfrom nltk.corpus import stopwords\nfrom nltk.stem import PorterStemmer, WordNetLemmatizer\nfrom wordcloud import STOPWORDS\n\nmispell_dict = {\"aren't\" : \"are not\",\n\"can't\" : \"cannot\",\n\"couldn't\" : \"could not\",\n\"didn't\" : \"did not\",\n\"doesn't\" : \"does not\",\n\"don't\" : \"do not\",\n\"hadn't\" : \"had not\",\n\"hasn't\" : \"has not\",\n\"haven't\" : \"have not\",\n\"he'd\" : \"he would\",\n\"he'll\" : \"he will\",\n\"he's\" : \"he is\",\n\"i'd\" : \"I would\",\n\"i'd\" : \"I had\",\n\"i'll\" : \"I will\",\n\"i'm\" : \"I am\",\n\"isn't\" : \"is not\",\n\"it's\" : \"it is\",\n\"it'll\":\"it will\",\n\"i've\" : \"I have\",\n\"let's\" : \"let us\",\n\"mightn't\" : \"might not\",\n\"mustn't\" : \"must not\",\n\"shan't\" : \"shall not\",\n\"she'd\" : \"she would\",\n\"she'll\" : \"she will\",\n\"she's\" : \"she is\",\n\"shouldn't\" : \"should not\",\n\"that's\" : \"that is\",\n\"there's\" : \"there is\",\n\"they'd\" : \"they would\",\n\"they'll\" : \"they will\",\n\"they're\" : \"they are\",\n\"they've\" : \"they have\",\n\"we'd\" : \"we would\",\n\"we're\" : \"we are\",\n\"weren't\" : \"were not\",\n\"we've\" : \"we have\",\n\"what'll\" : \"what will\",\n\"what're\" : \"what are\",\n\"what's\" : \"what is\",\n\"what've\" : \"what have\",\n\"where's\" : \"where is\",\n\"who'd\" : \"who would\",\n\"who'll\" : \"who will\",\n\"who're\" : \"who are\",\n\"who's\" : \"who is\",\n\"who've\" : \"who have\",\n\"won't\" : \"will not\",\n\"wouldn't\" : \"would not\",\n\"you'd\" : \"you would\",\n\"you'll\" : \"you will\",\n\"you're\" : \"you are\",\n\"you've\" : \"you have\",\n\"'re\": \" are\",\n\"wasn't\": \"was not\",\n\"we'll\":\" will\",\n\"didn't\": \"did not\"}\n\nstemmer = PorterStemmer()\nlemmatizer = WordNetLemmatizer()\n\ndef clean(text):        \n    # Convert to unicode \n    text = unidecode(text).encode(\"ascii\")\n    text = str(text, \"ascii\")\n\n    # chuyển về chữ thường, bỏ các link, kí tự đặc biệt, chữ số.\n    text = text.lower()\n    text = re.sub('https?://\\S+|www\\.\\S+', '', text)\n    text = re.sub('<.*?>+', '', text)\n    text = re.sub('[%s]' % re.escape(string.punctuation), '', text)  \n    text = re.sub('\\n', '', text)\n    text = re.sub('[’“”…]', ' ', text)  \n    text = ''.join(i for i in text if not i.isdigit())\n\n    # Chuyển các từ viết tắt trong từ điển về dạng thường\n    tokens = word_tokenize(text)\n    tokens = [mispell_dict.get(token) if (mispell_dict.get(token) != None) else token for token in tokens]\n    text = \" \".join(tokens)\n\n    # Remove stop-words   \n    tokens = word_tokenize(text)\n    tokens_without_sw = [word for word in tokens if not word in STOPWORDS]\n\n    # Chuyển biến thể ngữ pháp của từ về từ gốc\n    text = [lemmatizer.lemmatize(word) for word in tokens_without_sw ] \n    text = \" \".join(text)\n\n    return text","metadata":{"execution":{"iopub.status.busy":"2022-01-08T12:19:34.601802Z","iopub.status.idle":"2022-01-08T12:19:34.602157Z","shell.execute_reply.started":"2022-01-08T12:19:34.601961Z","shell.execute_reply":"2022-01-08T12:19:34.601978Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Insert cột các câu hỏi đã clean vào tập train\ntrain_data['clean_questions'] = train_data['question_text'].apply(clean)\ntrain_data","metadata":{"execution":{"iopub.status.busy":"2022-01-08T12:19:34.603407Z","iopub.status.idle":"2022-01-08T12:19:34.603701Z","shell.execute_reply.started":"2022-01-08T12:19:34.603544Z","shell.execute_reply":"2022-01-08T12:19:34.60356Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Convert dữ liệu**\n\nÁp dụng CountVectorizre, convert dữ liệu text về dạng vector của số lần xuất hiện của các token. Bag-of-Words là kỹ thuật cốt lõi cho vấn đề này, các phương pháp bao gồm:\n* Tách dữ liệu thành các token\n* Xác định trọng số cho mỗi token ứng với số lần xuất hiện của nó.","metadata":{}},{"cell_type":"code","source":"from sklearn.feature_extraction.text import CountVectorizer\nfrom sklearn.model_selection import train_test_split\n\nX = train_data['clean_questions']\nY = train_data['target']\n\ncount_vectorizer = CountVectorizer(analyzer=\"word\", ngram_range=(1,3))\nX_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = 0.2, random_state = 1)\n\ncount_train = count_vectorizer.fit(X)\n\nX_vec_train = count_train.transform(X_train)\nX_vec_test = count_train.transform(X_test)","metadata":{"execution":{"iopub.status.busy":"2022-01-08T12:19:34.604927Z","iopub.status.idle":"2022-01-08T12:19:34.605237Z","shell.execute_reply.started":"2022-01-08T12:19:34.605092Z","shell.execute_reply":"2022-01-08T12:19:34.605106Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. Training với mô hình hồi quy Logistic\n* Với **input** tập câu hỏi sau khi clean và convert X_train_vec $\\in$ $R^d$, **output** là nhãn Y_train $\\in \\{0, 1\\}$.\n* Mô hình: $Y|X=x \\sim Ber(y|\\sigma(f(x))$ với $f(x) = w^Tx+w_0$\n* Cho $f(x)$ đi qua hàm sigmoid: $\\sigma(z) = \\frac 1 {1+e^{-z}}$\n* Huấn luyện bộ tham số của mô hình $\\theta = (w, w_0)$: Tính Likelihood => Tính hàm lỗi Negative Loglikelihood (NLL) => Xuống đồi bằng đạo hàm cập nhật bộ tham số.\n\nChi tiết mô hình: https://excessive-source-1c9.notion.site/16-09-2021-H-i-quy-Logistics-cdcc911147e5458ba9203b58e6bd0099#dd32774a49cc44ac81c61578b831ad47","metadata":{}},{"cell_type":"code","source":"from sklearn.linear_model import LogisticRegression\nfrom sklearn.metrics import accuracy_score, recall_score ,f1_score\nfrom sklearn.metrics import classification_report\n\nmod = LogisticRegression(n_jobs=10, solver='saga',class_weight = 'balanced', C=0.1, verbose=1)\nmod.fit(X_vec_train, Y_train)\nY_pred = mod.predict(X_vec_test)","metadata":{"execution":{"iopub.status.busy":"2022-01-08T12:19:34.606458Z","iopub.status.idle":"2022-01-08T12:19:34.606959Z","shell.execute_reply.started":"2022-01-08T12:19:34.60678Z","shell.execute_reply":"2022-01-08T12:19:34.6068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Sự dụng F1-score làm metric**\n* Trung bình điều hòa giữa precision (độ chính xác) và recall (độ bao phủ). $\\frac {2}{F_1} = \\frac {1}{Precision} + \\frac {1}{Recall}$\n* Precision: đánh giá bao nhiêu % kết luận của model là chính xác-True. $Precision = \\frac{TP}{TP+FP}$\n* Recall: đánh giá bao nhiêu % positive samples mà model nhận được. $Recall = \\frac{TP}{TP+FN}$","metadata":{}},{"cell_type":"code","source":"print('Recall: ', recall_score(Y_pred, Y_test))\nprint('F1 score :', f1_score(Y_pred, Y_test), '\\n')\nprint(classification_report(Y_test, Y_pred))","metadata":{"execution":{"iopub.status.busy":"2022-01-08T12:19:34.607944Z","iopub.status.idle":"2022-01-08T12:19:34.60829Z","shell.execute_reply.started":"2022-01-08T12:19:34.608136Z","shell.execute_reply":"2022-01-08T12:19:34.608153Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Đánh giá mô hình:**\n* Đây là một mô hình khá đơn giản với kết quả nhận được đều ở mức trung bình.\n* Tuy mô hình không yêu cầu dữ liêu là linearly separable, nhưng đường phân chia giữa 2 class vẫn là đường tuyến tính, nên cơ bản, bộ dữ liệu cũng phải rất gần với linearly separable, trong bài toán này, theo em mô hình sẽ hoạt động không tốt do dữ liệu là các từ mà đôi khi rất thường xuất hiện ở cả 2 class hữu ích và độc hại nên rất khó để mô hình có thể dự đoán.\n* Mô hình còn yêu cầu các điểm dữ liệu là độc lập với nhau nhưng trong bài toán này rất khó sảy ra, vì các từ cùng xuất hiện đôi khi ảnh hưởng lẫn nhau **=> Điều này dẫn đến việc áp dụng mạng neural thông thường với đầu vào và đầu ra độc lập với nhau không phù hợp với dữ liệu dạng này**.\n* Thuật toán cũng chạy chậm hơn so với NB vì mỗi lần cập nhật trọng số ta lại phải tính lại đạo hàm của Loss funcion với từng biến.<br>\nTa có thể giảm thời gian training của mô hình bằng cách sử dụng các mini batch nhưng ở mô hình này em sẽ không đề cập đến nó do em đang hướng đến một mô hình có kết quả tốt hơn.","metadata":{}},{"cell_type":"markdown","source":"# 4. Submission","metadata":{}},{"cell_type":"code","source":"test_data['clean_questions'] = test_data['question_text'].apply(clean)\nX_test_vec = count_vectorizer.transform(test_data['clean_questions'])\npredictions = mod.predict(X_test_vec)\nsubmission = pd.DataFrame({'qid': test_data['qid'].values})\nsubmission['prediction'] = predictions\nsubmission.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2022-01-08T12:19:34.609375Z","iopub.status.idle":"2022-01-08T12:19:34.609949Z","shell.execute_reply.started":"2022-01-08T12:19:34.609768Z","shell.execute_reply":"2022-01-08T12:19:34.609789Z"},"trusted":true},"execution_count":null,"outputs":[]}]}