├── test.txt ├── README.md ├── Text Classifier ├── data │ └── .gitignore ├── test.ipynb └── .ipynb_checkpoints │ └── test-checkpoint.ipynb ├── Text Summarization ├── model │ └── model ├── Text Summarization.ipynb └── .ipynb_checkpoints │ └── Text Summarization-checkpoint.ipynb ├── Topic Words ├── Untitled.ipynb └── .ipynb_checkpoints │ └── Untitled-checkpoint.ipynb └── Viblo Similarity Documents ├── .ipynb_checkpoints └── Similarity Documents-checkpoint.ipynb └── Similarity Documents.ipynb /test.txt: -------------------------------------------------------------------------------- 1 | aaaaasd abhsv 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Natual-Language-Processing 2 | -------------------------------------------------------------------------------- /Text Classifier/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | */ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /Text Summarization/model/model: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thanhhau097/Natual-Language-Processing/HEAD/Text Summarization/model/model -------------------------------------------------------------------------------- /Topic Words/Untitled.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "Code thực hiện bài báo: http://www.aclweb.org/anthology/C10-2069?fbclid=IwAR0EHm40BYzdpoZ9BfkMZeJJgKZ6drbp3_-TgCKtLGwbymcYmGGxZbwJvU8" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "# Preprocessing Data" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 3, 20 | "metadata": {}, 21 | "outputs": [], 22 | "source": [ 23 | "from pyvi import ViTokenizer, ViPosTagger\n", 24 | "from tqdm import tqdm\n", 25 | "import numpy as np\n", 26 | "import gensim\n", 27 | "import numpy as np" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "metadata": { 34 | "scrolled": true 35 | }, 36 | "outputs": [ 37 | { 38 | "name": "stderr", 39 | "output_type": "stream", 40 | "text": [ 41 | "\r", 42 | " 33%|███▎ | 1004/3080 [00:30<01:02, 33.46it/s]" 43 | ] 44 | } 45 | ], 46 | "source": [ 47 | "import os \n", 48 | "dir_path = os.path.dirname(os.path.realpath(os.getcwd()))\n", 49 | "dir_path = os.path.join(dir_path, 'Data')\n", 50 | "\n", 51 | "# Load data from dataset folder\n", 52 | "# VNTC-master/Data/10Topics/Ver1.1/Train_Full\n", 53 | "# VNTC-master/Data/10Topics/Ver1.1/Test_Full\n", 54 | "def get_data(folder_path):\n", 55 | " X = []\n", 56 | " y = []\n", 57 | " dirs = os.listdir(folder_path)\n", 58 | " for path in dirs:\n", 59 | " file_paths = os.listdir(os.path.join(folder_path, path))\n", 60 | " for file_path in tqdm(file_paths):\n", 61 | " with open(os.path.join(folder_path, path, file_path), 'r', encoding=\"utf-16\") as f:\n", 62 | " lines = f.readlines()\n", 63 | " lines = ' '.join(lines)\n", 64 | " lines = gensim.utils.simple_preprocess(lines)\n", 65 | " lines = ' '.join(lines)\n", 66 | " lines = ViTokenizer.tokenize(lines)\n", 67 | "\n", 68 | " X.append(lines)\n", 69 | " y.append(path)\n", 70 | "\n", 71 | " return X, y\n", 72 | "\n", 73 | "train_path = os.path.join(dir_path, 'VNTC-master/Data/10Topics/Ver1.1/Train_Full')\n", 74 | "X_data, y_data = get_data(train_path)" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": null, 80 | "metadata": {}, 81 | "outputs": [], 82 | "source": [ 83 | "import pickle\n", 84 | "\n", 85 | "pickle.dump(X_data, open('data/X_data.pkl', 'wb'))\n", 86 | "pickle.dump(y_data, open('data/y_data.pkl', 'wb'))" 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": 5, 92 | "metadata": { 93 | "scrolled": true 94 | }, 95 | "outputs": [], 96 | "source": [ 97 | "# test_path = os.path.join(dir_path, 'VNTC-master/Data/10Topics/Ver1.1/Test_Full')\n", 98 | "# X_test, y_test = get_data(test_path)" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": 6, 104 | "metadata": {}, 105 | "outputs": [], 106 | "source": [ 107 | "# pickle.dump(X_test, open('data/X_test.pkl', 'wb'))\n", 108 | "# pickle.dump(y_test, open('data/y_test.pkl', 'wb'))" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": 8, 114 | "metadata": {}, 115 | "outputs": [], 116 | "source": [ 117 | "#### Load data\n", 118 | "import pickle\n", 119 | "\n", 120 | "X_data = pickle.load(open('data/X_data.pkl', 'rb'))\n", 121 | "y_data = pickle.load(open('data/y_data.pkl', 'rb'))" 122 | ] 123 | }, 124 | { 125 | "cell_type": "markdown", 126 | "metadata": {}, 127 | "source": [ 128 | "## Bigram" 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "execution_count": 9, 134 | "metadata": {}, 135 | "outputs": [ 136 | { 137 | "data": { 138 | "text/plain": [ 139 | "'ông đồ cuối_cùng trên đảo vua tần cỡi cọp chơi tám cõi trời xanh kiếm quang sáng chói tiên_nhân cầm đuốc khói nhẹ_nhàng mắt say nhòa lệ theo cung đàn ngồi trên bãi biển lộng_gió ông đồ võ_hiển đạt bất_ngờ đọc cho tôi nghe bài tần vương ẩm_tửu của lý_hạ người được mệnh_danh là thi quỉ đời đường tiếng_tăm và tác_phẩm truyền lưu hậu_thế không thua_kém thi tiên lý bạch thi phật vương_duy thi thánh đỗ_phủ rồi ông tâm_sự tôi sinh ra nhằm lúc nho_học mạt_vận may_mắn được học dăm chữ thánh_hiền bây_giờ thỉnh_thoảng tôi chỉ còn dùng mớ chữ_nghĩa một thời vang bóng này khi có bạn tâm_giao hoặc ai đó nhờ viết câu_đối xưa men theo con đường bãi biển rợp bóng dừa xanh tôi về nhà ông thôn tây xã an vĩnh huyện đảo lý_sơn quảng_ngãi thời_gian như dừng lại trong ngôi nhà_cổ của ông đồ cuối_cùng hòn đảo này những bức hoành_phi câu_đối được viết bằng mực_tàu bút_lông nét chữ như rồng múa phượng bay treo từ hàng cột bờ hiên vào tận bàn_thờ tổ_tiên giữa gian nhà chính bộ sập gụ đã trải hơn trăm năm sáng bóng_nước thời_gian đó là nơi ông thường ngồi xếp_bằng để đọc sách và múa bút khi có người xin chữ trang_trọng nhất trong ngôi nhà_cổ là chiếc tủ bằng gỗ lim lúc_nào cũng ấm mùi nhang trầm phảng_phất trên hàng linh vị thờ các vị tổ_tiên bút tự của ông đồ đạt có khắp_nơi trên đảo lý_sơn vượt biển ra lý_sơn tôi tình_cờ biết ông đồ võ_hiển đạt khi được chứng_kiến một buổi an_táng theo nghi_lễ_mộ gió các ngư_dân bất_hạnh phải gửi xác dưới lòng đại_dương thi_hài trong quan_tài nhỏ chỉ là hình_nhân đất_sét nhưng lễ_nghi vẫn nghiêm linh với lời tụng kinh cờ phướn cầu_siêu những người đã ra đi mãi_mãi không về anh cán_bộ văn_phòng ủy_ban huyện cho biết gần nửa thế_kỷ qua đảo này chỉ có một thầy đồ duy_nhất và cũng có_lẽ là thầy đồ cuối_cùng không chỉ các đình chùa mà tất_cả chữ_nho trong bất_cứ ngôi nhà nào trên đảo đều do một tay ông viết ông kể hồi còn nhỏ vùng này chỉ có một trường tiểu_học dạy tiếng pháp ai muốn học cao hơn phải ra huế hoặc vào qui nhơn cụ thân_sinh của ông là một đồ nho ẩn_dật nhưng phóng_khoáng cho con đi học tiếng pháp nhưng vẫn khuyên ông nên dùi mài kinh_sử với nho_học đến bây_giờ ông vẫn nhớ lời cha dạy chữ pháp giúp con mở_mang văn_minh văn_hóa nhưng chữ_nho mới đủ thâm sâu để dạy con đạo làm người con_người sinh ra_đời không đem đến được gì và chết cũng chẳng mang theo được cái chi cuối_cùng chỉ có cái đạo làm người là lại nghe lời cha_ông theo cả nho_học lẫn pháp ngữ nhưng lấy chữ_nho làm trọng ông may_mắn có nhiều người thầy khả_kính uyên_thâm cả chữ_nho lẫn chữ pháp chín năm theo các thầy thêm mười năm tự học từ sách_vở đến năm_tuổi võ_hiển đạt đã trở_thành một người dạy chữ và cho chữ thánh_hiền đó cũng là lúc đất_nước giao_thời hầu_hết lớp trẻ đã chuyển sang dùi mài quốc_ngữ hoặc tiếng pháp chữ_nho dần_dần trở_thành linh tự trên các bàn_thờ đình_chùa và trong câu_đối của các bậc lớn_tuổi giáo huấn lớp hậu_sinh gìn_giữ đạo_đức gia phong đến giờ ông vẫn còn gìn_giữ nguyên_vẹn bộ tứ_thư được in từ năm và nhiều đầu_sách cổ khác ngôi nhà_cổ của ông đồ trong mùa thu_hoạch tỏi không gặp thời ông nối bước cha_lui về ẩn_dật hòn đảo nhỏ giữa biển ban_ngày vừa làm nghề cá vừa trồng rau khoai kiếm sống thanh_nhàn chiều_tối mở lớp gõ đầu_trẻ tuy_nhiên cho_dù kính_trọng chữ thánh_hiền nhưng nhiều gia_đình cũng không muốn con_em mình theo nho_học chỉ còn một thời vang bóng vừa khó học vừa không_thể xin được việc_làm thế là lớp_học của ông cứ vắng dần vắng dần cho đến lúc không_thể tồn_tại được nữa không gõ đầu_trẻ nữa nhưng ông trở_thành một người cho chữ thánh_hiền nổi_tiếng lý_sơn dù tuổi mới ngoài tam_thập chữ của ông trầm_mặc buồn âm linh tự nơi thờ_cúng đội lính hoàng sa_kiêu hùng thuở xưa và những người đã bỏ_mạng giữa biển khơi chữ của ông trang_nghiêm như lời gia huấn trên liễn thờ các bậc tiền hiền chữ của ông cũng huyền_ảo vi_diệu trên bàn_thờ nam hải tướng quân vị thần tôn_kính của ngư_dân quanh năm treo mạng trên đầu sóng ngọn gió người vui cũng tìm đến ông để xin mấy chữ mới treo trên bàn_thờ tổ_tiên trong ngày cưới_xin cất nhà mới người buồn cũng nài ông vài chữ cho trọn đạo_nghĩa trong lễ tang ma lúc_nào ông cũng vui_vẻ viết tặng khi có người đến xin chữ bởi theo ông đó không chỉ là bổn_phận mà còn là cái đạo của người theo nho_học chọn nhân_nghĩa để sống đời đã sắp đến hồi về với tổ_tiên_ông nói không còn gì phải hối_tiếc nhưng chỉ buồn một điều là chưa có một người học_trò chân_truyền nào để gửi_gắm lại cái chữ_cái đạo của thánh_hiền kể_cả con_cái con ông người bám đảo làm nghề biển người vào sài_gòn bươn_chải mưu_sinh nhiều lúc tôi đành ngẫm_nghĩ hình_như cái gì cũng có vận thịnh_suy của nó nho_học cũng vậy thôi ông trầm_ngâm tâm_sự rồi mài mực trải giấy khai_bút tặng tôi một chữ tâm làm hành_trang trở về với đất_liền theo ông đồ đạt người cho chữ thánh_hiền ngày_nay tuy không còn khắt_khe như xưa nữa nhưng vẫn có một_số điều cần tôn_trọng gìn_giữ để bút_lực có_thể đạt đến sự tinh_tế đến cái hồn sâu thẳm của từng nét chữ ông không viết khi mưa_gió ông cũng không cầm bút khi trời mây_âm hay lúc tịch dương ngả bóng ảm_đạm ông thường đề bút vào buổi sáng thời_điểm mặt_trời bắt_đầu tỏa nắng ấm sau khi thắp nén hương trầm lên bàn_thờ và cạn mấy tách trà ông mới chấm bút_lông vào mực và lúc nét bút bắt_đầu lướt trên giấy đỏ tâm người viết thanh_tịnh như mặt_nước hồ thu không vọng danh_lợi không sợ không khinh cũng không vui không buồn tất_cả chỉ còn có chữ và tâm người viết sẽ bộc_lộ trên cái thần cái hồn của nét chữ'" 140 | ] 141 | }, 142 | "execution_count": 9, 143 | "metadata": {}, 144 | "output_type": "execute_result" 145 | } 146 | ], 147 | "source": [ 148 | "X_data[0]" 149 | ] 150 | }, 151 | { 152 | "cell_type": "code", 153 | "execution_count": 24, 154 | "metadata": {}, 155 | "outputs": [], 156 | "source": [ 157 | "corpus = ''\n", 158 | "for X in X_data:\n", 159 | " corpus += X" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": 25, 165 | "metadata": {}, 166 | "outputs": [ 167 | { 168 | "data": { 169 | "text/plain": [ 170 | "69792128" 171 | ] 172 | }, 173 | "execution_count": 25, 174 | "metadata": {}, 175 | "output_type": "execute_result" 176 | } 177 | ], 178 | "source": [ 179 | "len(corpus)" 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": 26, 185 | "metadata": {}, 186 | "outputs": [], 187 | "source": [ 188 | "from nltk.collocations import *\n", 189 | "import nltk" 190 | ] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "execution_count": 29, 195 | "metadata": {}, 196 | "outputs": [], 197 | "source": [ 198 | "finder = BigramCollocationFinder.from_words(corpus.split(), window_size = 10)\n", 199 | "# số lần xuất hiện ít nhất của một từ, dùng để lọc những từ có số lượng ít hơn ngưỡng nhất định min_frequent,\n", 200 | "# nếu không muốn lọc thì để là 1\n", 201 | "min_frequent = 1\n", 202 | "finder.apply_freq_filter(min_frequent)\n", 203 | "\n", 204 | "# bigram - cặp gồm 2 từ\n", 205 | "bigram_measures = nltk.collocations.BigramAssocMeasures()" 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "execution_count": 33, 211 | "metadata": {}, 212 | "outputs": [], 213 | "source": [ 214 | "# xem số lần xuất hiện cùng nhau của từng cặp\n", 215 | "# for k,v in finder.ngram_fd.items():\n", 216 | "# print(k,v)" 217 | ] 218 | }, 219 | { 220 | "cell_type": "code", 221 | "execution_count": 34, 222 | "metadata": {}, 223 | "outputs": [], 224 | "source": [ 225 | "# điểm PMI của từng cặp\n", 226 | "pmi_results = finder.score_ngrams(bigram_measures.pmi)" 227 | ] 228 | }, 229 | { 230 | "cell_type": "code", 231 | "execution_count": 35, 232 | "metadata": {}, 233 | "outputs": [], 234 | "source": [ 235 | "# chuyển về dictionary để tìm kiếm\n", 236 | "pmi_results_dict = dict(pmi_results)" 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": 42, 242 | "metadata": {}, 243 | "outputs": [ 244 | { 245 | "data": { 246 | "text/plain": [ 247 | "6.852442811586141" 248 | ] 249 | }, 250 | "execution_count": 42, 251 | "metadata": {}, 252 | "output_type": "execute_result" 253 | } 254 | ], 255 | "source": [ 256 | "pmi_results_dict[('cứ', 'dần')]" 257 | ] 258 | }, 259 | { 260 | "cell_type": "markdown", 261 | "metadata": {}, 262 | "source": [ 263 | "# Điểm PMI cho một cặp từ\n", 264 | "\n", 265 | "$$ PMI(w_i, w_j) = \\log\\dfrac{P(w_i, w_j)}{P(w_i)P(w_j)} $$" 266 | ] 267 | }, 268 | { 269 | "cell_type": "code", 270 | "execution_count": 45, 271 | "metadata": {}, 272 | "outputs": [], 273 | "source": [ 274 | "# lấy điểm PMI cho cặp từ\n", 275 | "def get_pmi_of_pair(word1, word2):\n", 276 | " try:\n", 277 | " score = pmi_results_dict[(word1, word2)]\n", 278 | " except:\n", 279 | " score = 0\n", 280 | " finally:\n", 281 | " return score" 282 | ] 283 | }, 284 | { 285 | "cell_type": "code", 286 | "execution_count": 46, 287 | "metadata": {}, 288 | "outputs": [ 289 | { 290 | "data": { 291 | "text/plain": [ 292 | "1.4601253888073815" 293 | ] 294 | }, 295 | "execution_count": 46, 296 | "metadata": {}, 297 | "output_type": "execute_result" 298 | } 299 | ], 300 | "source": [ 301 | "get_pmi_of_pair('tôi', \"một\")" 302 | ] 303 | }, 304 | { 305 | "cell_type": "markdown", 306 | "metadata": {}, 307 | "source": [ 308 | "# Điểm PMI trung bình của một từ trong danh sách \n", 309 | "Danh sách ở trong bài báo là 10 từ, nên 1/9 có nghĩa là so sánh với 9 từ còn lại\n", 310 | "$$ avg-PMI(w_i) = \\dfrac{1}{9}\\sum_jPMI(wi, w_j) $$" 311 | ] 312 | }, 313 | { 314 | "cell_type": "code", 315 | "execution_count": 47, 316 | "metadata": {}, 317 | "outputs": [], 318 | "source": [ 319 | "# lấy điểm PMI của từ trong danh sách từ đưa ra\n", 320 | "def get_average_pmi_for_word(word, words_list): \n", 321 | " _sum = 0\n", 322 | " _count = len(words_list)\n", 323 | " for compared_word in words_list:\n", 324 | " _sum += get_pmi_of_pair(word, compared_word)\n", 325 | " \n", 326 | " return _sum/_count" 327 | ] 328 | }, 329 | { 330 | "cell_type": "code", 331 | "execution_count": 57, 332 | "metadata": {}, 333 | "outputs": [ 334 | { 335 | "data": { 336 | "text/plain": [ 337 | "0.06825178101438283" 338 | ] 339 | }, 340 | "execution_count": 57, 341 | "metadata": {}, 342 | "output_type": "execute_result" 343 | } 344 | ], 345 | "source": [ 346 | "get_average_pmi_for_word(\"một\", [\"một\", \"hai\", \"không\", \"có\", \"đứng\", \"ngồi\", \"nằm\", \"nhiều\", \"ít\", \"nhỏ\"])" 347 | ] 348 | }, 349 | { 350 | "cell_type": "markdown", 351 | "metadata": {}, 352 | "source": [ 353 | "# Tìm từ đại diện tốt nhất (topic word) trong danh sách các từ - words_list" 354 | ] 355 | }, 356 | { 357 | "cell_type": "code", 358 | "execution_count": 54, 359 | "metadata": {}, 360 | "outputs": [], 361 | "source": [ 362 | "# tìm từ đại diện tốt nhất (topic word) trong danh sách các từ - words_list\n", 363 | "def get_best_word(words_list):\n", 364 | " topic_word = words_list[0]\n", 365 | " max_score = 0\n", 366 | " for word in words_list[1:]:\n", 367 | " score = get_average_pmi_for_word(word, words_list)\n", 368 | " \n", 369 | " if score > max_score:\n", 370 | " max_score = score\n", 371 | " topic_word = word\n", 372 | " return topic_word" 373 | ] 374 | }, 375 | { 376 | "cell_type": "code", 377 | "execution_count": 56, 378 | "metadata": {}, 379 | "outputs": [ 380 | { 381 | "data": { 382 | "text/plain": [ 383 | "'không'" 384 | ] 385 | }, 386 | "execution_count": 56, 387 | "metadata": {}, 388 | "output_type": "execute_result" 389 | } 390 | ], 391 | "source": [ 392 | "get_best_word([\"một\", \"hai\", \"không\", \"có\", \"đứng\", \"ngồi\", \"nằm\", \"nhiều\", \"ít\", \"nhỏ\"])" 393 | ] 394 | }, 395 | { 396 | "cell_type": "markdown", 397 | "metadata": {}, 398 | "source": [ 399 | "## Kết luận: chỉ cần chạy code từ đầu đến cuối, rồi dùng hàm cuối cùng, truyền một danh sách các từ vào, nó sẽ tìm ra topic word.\n", 400 | "## Các công thức tính CP1, CP2 có vẻ không liên quan lắm, nên không cần tính ở đây. " 401 | ] 402 | }, 403 | { 404 | "cell_type": "code", 405 | "execution_count": null, 406 | "metadata": {}, 407 | "outputs": [], 408 | "source": [] 409 | }, 410 | { 411 | "cell_type": "code", 412 | "execution_count": null, 413 | "metadata": {}, 414 | "outputs": [], 415 | "source": [] 416 | }, 417 | { 418 | "cell_type": "code", 419 | "execution_count": null, 420 | "metadata": {}, 421 | "outputs": [], 422 | "source": [] 423 | } 424 | ], 425 | "metadata": { 426 | "kernelspec": { 427 | "display_name": "Python 3", 428 | "language": "python", 429 | "name": "python3" 430 | }, 431 | "language_info": { 432 | "codemirror_mode": { 433 | "name": "ipython", 434 | "version": 3 435 | }, 436 | "file_extension": ".py", 437 | "mimetype": "text/x-python", 438 | "name": "python", 439 | "nbconvert_exporter": "python", 440 | "pygments_lexer": "ipython3", 441 | "version": "3.6.5" 442 | } 443 | }, 444 | "nbformat": 4, 445 | "nbformat_minor": 2 446 | } 447 | -------------------------------------------------------------------------------- /Topic Words/.ipynb_checkpoints/Untitled-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "Code thực hiện bài báo: http://www.aclweb.org/anthology/C10-2069?fbclid=IwAR0EHm40BYzdpoZ9BfkMZeJJgKZ6drbp3_-TgCKtLGwbymcYmGGxZbwJvU8" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "# Preprocessing Data" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 3, 20 | "metadata": {}, 21 | "outputs": [], 22 | "source": [ 23 | "from pyvi import ViTokenizer, ViPosTagger\n", 24 | "from tqdm import tqdm\n", 25 | "import numpy as np\n", 26 | "import gensim\n", 27 | "import numpy as np" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "metadata": { 34 | "scrolled": true 35 | }, 36 | "outputs": [ 37 | { 38 | "name": "stderr", 39 | "output_type": "stream", 40 | "text": [ 41 | "\r", 42 | " 33%|███▎ | 1004/3080 [00:30<01:02, 33.46it/s]" 43 | ] 44 | } 45 | ], 46 | "source": [ 47 | "import os \n", 48 | "dir_path = os.path.dirname(os.path.realpath(os.getcwd()))\n", 49 | "dir_path = os.path.join(dir_path, 'Data')\n", 50 | "\n", 51 | "# Load data from dataset folder\n", 52 | "# VNTC-master/Data/10Topics/Ver1.1/Train_Full\n", 53 | "# VNTC-master/Data/10Topics/Ver1.1/Test_Full\n", 54 | "def get_data(folder_path):\n", 55 | " X = []\n", 56 | " y = []\n", 57 | " dirs = os.listdir(folder_path)\n", 58 | " for path in dirs:\n", 59 | " file_paths = os.listdir(os.path.join(folder_path, path))\n", 60 | " for file_path in tqdm(file_paths):\n", 61 | " with open(os.path.join(folder_path, path, file_path), 'r', encoding=\"utf-16\") as f:\n", 62 | " lines = f.readlines()\n", 63 | " lines = ' '.join(lines)\n", 64 | " lines = gensim.utils.simple_preprocess(lines)\n", 65 | " lines = ' '.join(lines)\n", 66 | " lines = ViTokenizer.tokenize(lines)\n", 67 | "\n", 68 | " X.append(lines)\n", 69 | " y.append(path)\n", 70 | "\n", 71 | " return X, y\n", 72 | "\n", 73 | "train_path = os.path.join(dir_path, 'VNTC-master/Data/10Topics/Ver1.1/Train_Full')\n", 74 | "X_data, y_data = get_data(train_path)" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": null, 80 | "metadata": {}, 81 | "outputs": [], 82 | "source": [ 83 | "import pickle\n", 84 | "\n", 85 | "pickle.dump(X_data, open('data/X_data.pkl', 'wb'))\n", 86 | "pickle.dump(y_data, open('data/y_data.pkl', 'wb'))" 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": 5, 92 | "metadata": { 93 | "scrolled": true 94 | }, 95 | "outputs": [], 96 | "source": [ 97 | "# test_path = os.path.join(dir_path, 'VNTC-master/Data/10Topics/Ver1.1/Test_Full')\n", 98 | "# X_test, y_test = get_data(test_path)" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": 6, 104 | "metadata": {}, 105 | "outputs": [], 106 | "source": [ 107 | "# pickle.dump(X_test, open('data/X_test.pkl', 'wb'))\n", 108 | "# pickle.dump(y_test, open('data/y_test.pkl', 'wb'))" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": 8, 114 | "metadata": {}, 115 | "outputs": [], 116 | "source": [ 117 | "#### Load data\n", 118 | "import pickle\n", 119 | "\n", 120 | "X_data = pickle.load(open('data/X_data.pkl', 'rb'))\n", 121 | "y_data = pickle.load(open('data/y_data.pkl', 'rb'))" 122 | ] 123 | }, 124 | { 125 | "cell_type": "markdown", 126 | "metadata": {}, 127 | "source": [ 128 | "## Bigram" 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "execution_count": 9, 134 | "metadata": {}, 135 | "outputs": [ 136 | { 137 | "data": { 138 | "text/plain": [ 139 | "'ông đồ cuối_cùng trên đảo vua tần cỡi cọp chơi tám cõi trời xanh kiếm quang sáng chói tiên_nhân cầm đuốc khói nhẹ_nhàng mắt say nhòa lệ theo cung đàn ngồi trên bãi biển lộng_gió ông đồ võ_hiển đạt bất_ngờ đọc cho tôi nghe bài tần vương ẩm_tửu của lý_hạ người được mệnh_danh là thi quỉ đời đường tiếng_tăm và tác_phẩm truyền lưu hậu_thế không thua_kém thi tiên lý bạch thi phật vương_duy thi thánh đỗ_phủ rồi ông tâm_sự tôi sinh ra nhằm lúc nho_học mạt_vận may_mắn được học dăm chữ thánh_hiền bây_giờ thỉnh_thoảng tôi chỉ còn dùng mớ chữ_nghĩa một thời vang bóng này khi có bạn tâm_giao hoặc ai đó nhờ viết câu_đối xưa men theo con đường bãi biển rợp bóng dừa xanh tôi về nhà ông thôn tây xã an vĩnh huyện đảo lý_sơn quảng_ngãi thời_gian như dừng lại trong ngôi nhà_cổ của ông đồ cuối_cùng hòn đảo này những bức hoành_phi câu_đối được viết bằng mực_tàu bút_lông nét chữ như rồng múa phượng bay treo từ hàng cột bờ hiên vào tận bàn_thờ tổ_tiên giữa gian nhà chính bộ sập gụ đã trải hơn trăm năm sáng bóng_nước thời_gian đó là nơi ông thường ngồi xếp_bằng để đọc sách và múa bút khi có người xin chữ trang_trọng nhất trong ngôi nhà_cổ là chiếc tủ bằng gỗ lim lúc_nào cũng ấm mùi nhang trầm phảng_phất trên hàng linh vị thờ các vị tổ_tiên bút tự của ông đồ đạt có khắp_nơi trên đảo lý_sơn vượt biển ra lý_sơn tôi tình_cờ biết ông đồ võ_hiển đạt khi được chứng_kiến một buổi an_táng theo nghi_lễ_mộ gió các ngư_dân bất_hạnh phải gửi xác dưới lòng đại_dương thi_hài trong quan_tài nhỏ chỉ là hình_nhân đất_sét nhưng lễ_nghi vẫn nghiêm linh với lời tụng kinh cờ phướn cầu_siêu những người đã ra đi mãi_mãi không về anh cán_bộ văn_phòng ủy_ban huyện cho biết gần nửa thế_kỷ qua đảo này chỉ có một thầy đồ duy_nhất và cũng có_lẽ là thầy đồ cuối_cùng không chỉ các đình chùa mà tất_cả chữ_nho trong bất_cứ ngôi nhà nào trên đảo đều do một tay ông viết ông kể hồi còn nhỏ vùng này chỉ có một trường tiểu_học dạy tiếng pháp ai muốn học cao hơn phải ra huế hoặc vào qui nhơn cụ thân_sinh của ông là một đồ nho ẩn_dật nhưng phóng_khoáng cho con đi học tiếng pháp nhưng vẫn khuyên ông nên dùi mài kinh_sử với nho_học đến bây_giờ ông vẫn nhớ lời cha dạy chữ pháp giúp con mở_mang văn_minh văn_hóa nhưng chữ_nho mới đủ thâm sâu để dạy con đạo làm người con_người sinh ra_đời không đem đến được gì và chết cũng chẳng mang theo được cái chi cuối_cùng chỉ có cái đạo làm người là lại nghe lời cha_ông theo cả nho_học lẫn pháp ngữ nhưng lấy chữ_nho làm trọng ông may_mắn có nhiều người thầy khả_kính uyên_thâm cả chữ_nho lẫn chữ pháp chín năm theo các thầy thêm mười năm tự học từ sách_vở đến năm_tuổi võ_hiển đạt đã trở_thành một người dạy chữ và cho chữ thánh_hiền đó cũng là lúc đất_nước giao_thời hầu_hết lớp trẻ đã chuyển sang dùi mài quốc_ngữ hoặc tiếng pháp chữ_nho dần_dần trở_thành linh tự trên các bàn_thờ đình_chùa và trong câu_đối của các bậc lớn_tuổi giáo huấn lớp hậu_sinh gìn_giữ đạo_đức gia phong đến giờ ông vẫn còn gìn_giữ nguyên_vẹn bộ tứ_thư được in từ năm và nhiều đầu_sách cổ khác ngôi nhà_cổ của ông đồ trong mùa thu_hoạch tỏi không gặp thời ông nối bước cha_lui về ẩn_dật hòn đảo nhỏ giữa biển ban_ngày vừa làm nghề cá vừa trồng rau khoai kiếm sống thanh_nhàn chiều_tối mở lớp gõ đầu_trẻ tuy_nhiên cho_dù kính_trọng chữ thánh_hiền nhưng nhiều gia_đình cũng không muốn con_em mình theo nho_học chỉ còn một thời vang bóng vừa khó học vừa không_thể xin được việc_làm thế là lớp_học của ông cứ vắng dần vắng dần cho đến lúc không_thể tồn_tại được nữa không gõ đầu_trẻ nữa nhưng ông trở_thành một người cho chữ thánh_hiền nổi_tiếng lý_sơn dù tuổi mới ngoài tam_thập chữ của ông trầm_mặc buồn âm linh tự nơi thờ_cúng đội lính hoàng sa_kiêu hùng thuở xưa và những người đã bỏ_mạng giữa biển khơi chữ của ông trang_nghiêm như lời gia huấn trên liễn thờ các bậc tiền hiền chữ của ông cũng huyền_ảo vi_diệu trên bàn_thờ nam hải tướng quân vị thần tôn_kính của ngư_dân quanh năm treo mạng trên đầu sóng ngọn gió người vui cũng tìm đến ông để xin mấy chữ mới treo trên bàn_thờ tổ_tiên trong ngày cưới_xin cất nhà mới người buồn cũng nài ông vài chữ cho trọn đạo_nghĩa trong lễ tang ma lúc_nào ông cũng vui_vẻ viết tặng khi có người đến xin chữ bởi theo ông đó không chỉ là bổn_phận mà còn là cái đạo của người theo nho_học chọn nhân_nghĩa để sống đời đã sắp đến hồi về với tổ_tiên_ông nói không còn gì phải hối_tiếc nhưng chỉ buồn một điều là chưa có một người học_trò chân_truyền nào để gửi_gắm lại cái chữ_cái đạo của thánh_hiền kể_cả con_cái con ông người bám đảo làm nghề biển người vào sài_gòn bươn_chải mưu_sinh nhiều lúc tôi đành ngẫm_nghĩ hình_như cái gì cũng có vận thịnh_suy của nó nho_học cũng vậy thôi ông trầm_ngâm tâm_sự rồi mài mực trải giấy khai_bút tặng tôi một chữ tâm làm hành_trang trở về với đất_liền theo ông đồ đạt người cho chữ thánh_hiền ngày_nay tuy không còn khắt_khe như xưa nữa nhưng vẫn có một_số điều cần tôn_trọng gìn_giữ để bút_lực có_thể đạt đến sự tinh_tế đến cái hồn sâu thẳm của từng nét chữ ông không viết khi mưa_gió ông cũng không cầm bút khi trời mây_âm hay lúc tịch dương ngả bóng ảm_đạm ông thường đề bút vào buổi sáng thời_điểm mặt_trời bắt_đầu tỏa nắng ấm sau khi thắp nén hương trầm lên bàn_thờ và cạn mấy tách trà ông mới chấm bút_lông vào mực và lúc nét bút bắt_đầu lướt trên giấy đỏ tâm người viết thanh_tịnh như mặt_nước hồ thu không vọng danh_lợi không sợ không khinh cũng không vui không buồn tất_cả chỉ còn có chữ và tâm người viết sẽ bộc_lộ trên cái thần cái hồn của nét chữ'" 140 | ] 141 | }, 142 | "execution_count": 9, 143 | "metadata": {}, 144 | "output_type": "execute_result" 145 | } 146 | ], 147 | "source": [ 148 | "X_data[0]" 149 | ] 150 | }, 151 | { 152 | "cell_type": "code", 153 | "execution_count": 24, 154 | "metadata": {}, 155 | "outputs": [], 156 | "source": [ 157 | "corpus = ''\n", 158 | "for X in X_data:\n", 159 | " corpus += X" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": 25, 165 | "metadata": {}, 166 | "outputs": [ 167 | { 168 | "data": { 169 | "text/plain": [ 170 | "69792128" 171 | ] 172 | }, 173 | "execution_count": 25, 174 | "metadata": {}, 175 | "output_type": "execute_result" 176 | } 177 | ], 178 | "source": [ 179 | "len(corpus)" 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": 26, 185 | "metadata": {}, 186 | "outputs": [], 187 | "source": [ 188 | "from nltk.collocations import *\n", 189 | "import nltk" 190 | ] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "execution_count": 29, 195 | "metadata": {}, 196 | "outputs": [], 197 | "source": [ 198 | "finder = BigramCollocationFinder.from_words(corpus.split(), window_size = 10)\n", 199 | "# số lần xuất hiện ít nhất của một từ, dùng để lọc những từ có số lượng ít hơn ngưỡng nhất định min_frequent,\n", 200 | "# nếu không muốn lọc thì để là 1\n", 201 | "min_frequent = 1\n", 202 | "finder.apply_freq_filter(min_frequent)\n", 203 | "\n", 204 | "# bigram - cặp gồm 2 từ\n", 205 | "bigram_measures = nltk.collocations.BigramAssocMeasures()" 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "execution_count": 33, 211 | "metadata": {}, 212 | "outputs": [], 213 | "source": [ 214 | "# xem số lần xuất hiện cùng nhau của từng cặp\n", 215 | "# for k,v in finder.ngram_fd.items():\n", 216 | "# print(k,v)" 217 | ] 218 | }, 219 | { 220 | "cell_type": "code", 221 | "execution_count": 34, 222 | "metadata": {}, 223 | "outputs": [], 224 | "source": [ 225 | "# điểm PMI của từng cặp\n", 226 | "pmi_results = finder.score_ngrams(bigram_measures.pmi)" 227 | ] 228 | }, 229 | { 230 | "cell_type": "code", 231 | "execution_count": 35, 232 | "metadata": {}, 233 | "outputs": [], 234 | "source": [ 235 | "# chuyển về dictionary để tìm kiếm\n", 236 | "pmi_results_dict = dict(pmi_results)" 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": 42, 242 | "metadata": {}, 243 | "outputs": [ 244 | { 245 | "data": { 246 | "text/plain": [ 247 | "6.852442811586141" 248 | ] 249 | }, 250 | "execution_count": 42, 251 | "metadata": {}, 252 | "output_type": "execute_result" 253 | } 254 | ], 255 | "source": [ 256 | "pmi_results_dict[('cứ', 'dần')]" 257 | ] 258 | }, 259 | { 260 | "cell_type": "markdown", 261 | "metadata": {}, 262 | "source": [ 263 | "# Điểm PMI cho một cặp từ\n", 264 | "\n", 265 | "$$ PMI(w_i, w_j) = \\log\\dfrac{P(w_i, w_j)}{P(w_i)P(w_j)} $$" 266 | ] 267 | }, 268 | { 269 | "cell_type": "code", 270 | "execution_count": 45, 271 | "metadata": {}, 272 | "outputs": [], 273 | "source": [ 274 | "# lấy điểm PMI cho cặp từ\n", 275 | "def get_pmi_of_pair(word1, word2):\n", 276 | " try:\n", 277 | " score = pmi_results_dict[(word1, word2)]\n", 278 | " except:\n", 279 | " score = 0\n", 280 | " finally:\n", 281 | " return score" 282 | ] 283 | }, 284 | { 285 | "cell_type": "code", 286 | "execution_count": 46, 287 | "metadata": {}, 288 | "outputs": [ 289 | { 290 | "data": { 291 | "text/plain": [ 292 | "1.4601253888073815" 293 | ] 294 | }, 295 | "execution_count": 46, 296 | "metadata": {}, 297 | "output_type": "execute_result" 298 | } 299 | ], 300 | "source": [ 301 | "get_pmi_of_pair('tôi', \"một\")" 302 | ] 303 | }, 304 | { 305 | "cell_type": "markdown", 306 | "metadata": {}, 307 | "source": [ 308 | "# Điểm PMI trung bình của một từ trong danh sách \n", 309 | "Danh sách ở trong bài báo là 10 từ, nên 1/9 có nghĩa là so sánh với 9 từ còn lại\n", 310 | "$$ avg-PMI(w_i) = \\dfrac{1}{9}\\sum_jPMI(wi, w_j) $$" 311 | ] 312 | }, 313 | { 314 | "cell_type": "code", 315 | "execution_count": 47, 316 | "metadata": {}, 317 | "outputs": [], 318 | "source": [ 319 | "# lấy điểm PMI của từ trong danh sách từ đưa ra\n", 320 | "def get_average_pmi_for_word(word, words_list): \n", 321 | " _sum = 0\n", 322 | " _count = len(words_list)\n", 323 | " for compared_word in words_list:\n", 324 | " _sum += get_pmi_of_pair(word, compared_word)\n", 325 | " \n", 326 | " return _sum/_count" 327 | ] 328 | }, 329 | { 330 | "cell_type": "code", 331 | "execution_count": 57, 332 | "metadata": {}, 333 | "outputs": [ 334 | { 335 | "data": { 336 | "text/plain": [ 337 | "0.06825178101438283" 338 | ] 339 | }, 340 | "execution_count": 57, 341 | "metadata": {}, 342 | "output_type": "execute_result" 343 | } 344 | ], 345 | "source": [ 346 | "get_average_pmi_for_word(\"một\", [\"một\", \"hai\", \"không\", \"có\", \"đứng\", \"ngồi\", \"nằm\", \"nhiều\", \"ít\", \"nhỏ\"])" 347 | ] 348 | }, 349 | { 350 | "cell_type": "markdown", 351 | "metadata": {}, 352 | "source": [ 353 | "# Tìm từ đại diện tốt nhất (topic word) trong danh sách các từ - words_list" 354 | ] 355 | }, 356 | { 357 | "cell_type": "code", 358 | "execution_count": 54, 359 | "metadata": {}, 360 | "outputs": [], 361 | "source": [ 362 | "# tìm từ đại diện tốt nhất (topic word) trong danh sách các từ - words_list\n", 363 | "def get_best_word(words_list):\n", 364 | " topic_word = words_list[0]\n", 365 | " max_score = 0\n", 366 | " for word in words_list[1:]:\n", 367 | " score = get_average_pmi_for_word(word, words_list)\n", 368 | " \n", 369 | " if score > max_score:\n", 370 | " max_score = score\n", 371 | " topic_word = word\n", 372 | " return topic_word" 373 | ] 374 | }, 375 | { 376 | "cell_type": "code", 377 | "execution_count": 56, 378 | "metadata": {}, 379 | "outputs": [ 380 | { 381 | "data": { 382 | "text/plain": [ 383 | "'không'" 384 | ] 385 | }, 386 | "execution_count": 56, 387 | "metadata": {}, 388 | "output_type": "execute_result" 389 | } 390 | ], 391 | "source": [ 392 | "get_best_word([\"một\", \"hai\", \"không\", \"có\", \"đứng\", \"ngồi\", \"nằm\", \"nhiều\", \"ít\", \"nhỏ\"])" 393 | ] 394 | }, 395 | { 396 | "cell_type": "markdown", 397 | "metadata": {}, 398 | "source": [ 399 | "## Kết luận: chỉ cần chạy code từ đầu đến cuối, rồi dùng hàm cuối cùng, truyền một danh sách các từ vào, nó sẽ tìm ra topic word.\n", 400 | "## Các công thức tính CP1, CP2 có vẻ không liên quan lắm, nên không cần tính ở đây. " 401 | ] 402 | }, 403 | { 404 | "cell_type": "code", 405 | "execution_count": null, 406 | "metadata": {}, 407 | "outputs": [], 408 | "source": [] 409 | }, 410 | { 411 | "cell_type": "code", 412 | "execution_count": null, 413 | "metadata": {}, 414 | "outputs": [], 415 | "source": [] 416 | }, 417 | { 418 | "cell_type": "code", 419 | "execution_count": null, 420 | "metadata": {}, 421 | "outputs": [], 422 | "source": [] 423 | } 424 | ], 425 | "metadata": { 426 | "kernelspec": { 427 | "display_name": "Python 3", 428 | "language": "python", 429 | "name": "python3" 430 | }, 431 | "language_info": { 432 | "codemirror_mode": { 433 | "name": "ipython", 434 | "version": 3 435 | }, 436 | "file_extension": ".py", 437 | "mimetype": "text/x-python", 438 | "name": "python", 439 | "nbconvert_exporter": "python", 440 | "pygments_lexer": "ipython3", 441 | "version": "3.6.5" 442 | } 443 | }, 444 | "nbformat": 4, 445 | "nbformat_minor": 2 446 | } 447 | -------------------------------------------------------------------------------- /Text Classifier/test.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Word2Vec" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 3, 13 | "metadata": {}, 14 | "outputs": [ 15 | { 16 | "name": "stderr", 17 | "output_type": "stream", 18 | "text": [ 19 | "/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:8: DeprecationWarning: Call to deprecated `wv` (Attribute will be removed in 4.0.0, use self instead).\n", 20 | " \n", 21 | "/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:9: DeprecationWarning: Call to deprecated `wv` (Attribute will be removed in 4.0.0, use self instead).\n", 22 | " if __name__ == '__main__':\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "\n", 28 | "import os\n", 29 | "from gensim.models import KeyedVectors \n", 30 | "dir_path = os.path.dirname(os.path.realpath(os.getcwd()))\n", 31 | "word2vec_model_path = os.path.join(dir_path, \"Data/vi/vi.vec\")\n", 32 | "\n", 33 | "w2v = KeyedVectors.load_word2vec_format(word2vec_model_path)\n", 34 | "vocab = w2v.wv.vocab\n", 35 | "wv = w2v.wv" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 6, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "def word_vector(word):\n", 45 | " return wv[word]" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 29, 51 | "metadata": {}, 52 | "outputs": [], 53 | "source": [ 54 | "topic = ['giao_thông', 'bóng_đá', 'tài_chính', 'thị_trường', 'sức_khoẻ', 'thế_giới', 'thể_thao', 'ẩm_thực']" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": 44, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "list_word = ['tai_nạn', 'đường_bộ', 'du_lịch', 'ông', 'đau']" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 45, 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [ 72 | "import numpy as np\n", 73 | "def get_best_topic(list_word, list_topic):\n", 74 | " best_score = 0\n", 75 | " \n", 76 | " for topic in list_topic:\n", 77 | " topic_score = 0\n", 78 | " for word in list_word:\n", 79 | " score = wv.similarity(word, topic)\n", 80 | " topic_score += score\n", 81 | " \n", 82 | " if topic_score > best_score:\n", 83 | " best_topic = topic\n", 84 | " best_score = topic_score\n", 85 | " \n", 86 | " return best_topic" 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": 46, 92 | "metadata": {}, 93 | "outputs": [ 94 | { 95 | "name": "stderr", 96 | "output_type": "stream", 97 | "text": [ 98 | "/anaconda3/lib/python3.6/site-packages/gensim/matutils.py:737: FutureWarning: Conversion of the second argument of issubdtype from `int` to `np.signedinteger` is deprecated. In future, it will be treated as `np.int64 == np.dtype(int).type`.\n", 99 | " if np.issubdtype(vec.dtype, np.int):\n" 100 | ] 101 | }, 102 | { 103 | "data": { 104 | "text/plain": [ 105 | "'giao_thông'" 106 | ] 107 | }, 108 | "execution_count": 46, 109 | "metadata": {}, 110 | "output_type": "execute_result" 111 | } 112 | ], 113 | "source": [ 114 | "get_best_topic(list_word, topic)" 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "metadata": {}, 120 | "source": [ 121 | "# Test Naive Bayes" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": 1, 127 | "metadata": {}, 128 | "outputs": [ 129 | { 130 | "name": "stderr", 131 | "output_type": "stream", 132 | "text": [ 133 | "/anaconda3/lib/python3.6/site-packages/sklearn/ensemble/weight_boosting.py:29: DeprecationWarning: numpy.core.umath_tests is an internal NumPy module and should not be imported. It will be removed in a future NumPy release.\n", 134 | " from numpy.core.umath_tests import inner1d\n", 135 | "/anaconda3/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n", 136 | " from ._conv import register_converters as _register_converters\n", 137 | "Using TensorFlow backend.\n" 138 | ] 139 | } 140 | ], 141 | "source": [ 142 | "from sklearn import model_selection, preprocessing, linear_model, naive_bayes, metrics, svm\n", 143 | "from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer\n", 144 | "from sklearn import decomposition, ensemble\n", 145 | "\n", 146 | "import pandas, xgboost, numpy, textblob, string\n", 147 | "from keras.preprocessing import text, sequence\n", 148 | "from keras import layers, models, optimizers\n", 149 | "from keras.layers import *" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": 2, 155 | "metadata": {}, 156 | "outputs": [], 157 | "source": [ 158 | "from pyvi import ViTokenizer, ViPosTagger\n", 159 | "from tqdm import tqdm\n", 160 | "import numpy as np\n", 161 | "import gensim\n", 162 | "import numpy as np" 163 | ] 164 | }, 165 | { 166 | "cell_type": "markdown", 167 | "metadata": {}, 168 | "source": [ 169 | "# Xử lý dữ liệu" 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": 3, 175 | "metadata": {}, 176 | "outputs": [], 177 | "source": [ 178 | "def preprocessing_doc(doc):\n", 179 | " lines = gensim.utils.simple_preprocess(doc)\n", 180 | " lines = ' '.join(lines)\n", 181 | " lines = ViTokenizer.tokenize(lines)\n", 182 | "\n", 183 | " return lines" 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": 5, 189 | "metadata": {}, 190 | "outputs": [], 191 | "source": [ 192 | "import pickle\n", 193 | "\n", 194 | "X_data = pickle.load(open('data/X_data.pkl', 'rb'))\n", 195 | "y_data = pickle.load(open('data/y_data.pkl', 'rb'))\n", 196 | "\n", 197 | "# X_test = pickle.load(open('data/X_test.pkl', 'rb'))\n", 198 | "# y_test = pickle.load(open('data/y_test.pkl', 'rb'))" 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": null, 204 | "metadata": {}, 205 | "outputs": [], 206 | "source": [ 207 | "# word level - we choose max number of words equal to 30000 except all words (100k+ words)\n", 208 | "tfidf_vect = TfidfVectorizer(analyzer='word', max_features=30000)\n", 209 | "tfidf_vect.fit(X_data) # learn vocabulary and idf from training set\n", 210 | "X_data_tfidf = tfidf_vect.transform(X_data)" 211 | ] 212 | }, 213 | { 214 | "cell_type": "code", 215 | "execution_count": 7, 216 | "metadata": {}, 217 | "outputs": [], 218 | "source": [ 219 | "from sklearn.decomposition import TruncatedSVD" 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": 8, 225 | "metadata": {}, 226 | "outputs": [ 227 | { 228 | "data": { 229 | "text/plain": [ 230 | "TruncatedSVD(algorithm='randomized', n_components=300, n_iter=5,\n", 231 | " random_state=42, tol=0.0)" 232 | ] 233 | }, 234 | "execution_count": 8, 235 | "metadata": {}, 236 | "output_type": "execute_result" 237 | } 238 | ], 239 | "source": [ 240 | "svd = TruncatedSVD(n_components=300, random_state=42)\n", 241 | "svd.fit(X_data_tfidf)" 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": 9, 247 | "metadata": {}, 248 | "outputs": [], 249 | "source": [ 250 | "X_data_tfidf_svd = svd.transform(X_data_tfidf)" 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": 37, 256 | "metadata": {}, 257 | "outputs": [], 258 | "source": [ 259 | "# from gensim.models import KeyedVectors \n", 260 | "# import os \n", 261 | "# dir_path = os.path.dirname(os.path.realpath(os.getcwd()))\n", 262 | "# word2vec_model_path = os.path.join(dir_path, \"Data/vi/vi.vec\")\n", 263 | "\n", 264 | "# w2v = KeyedVectors.load_word2vec_format(word2vec_model_path)\n", 265 | "# vocab = w2v.wv.vocab\n", 266 | "# wv = w2v.wv" 267 | ] 268 | }, 269 | { 270 | "cell_type": "code", 271 | "execution_count": 36, 272 | "metadata": {}, 273 | "outputs": [], 274 | "source": [ 275 | "# def get_word2vec_data(X):\n", 276 | "# word2vec_data = []\n", 277 | "# for x in X:\n", 278 | "# sentence = []\n", 279 | "# for word in x.split(\" \"):\n", 280 | "# if word in vocab:\n", 281 | "# # print(word)\n", 282 | "# sentence.append(wv[word])\n", 283 | "\n", 284 | "# word2vec_data.append(sentence)\n", 285 | "# # break\n", 286 | "# return word2vec_data\n", 287 | "\n", 288 | "# X_data_w2v = get_word2vec_data(X_data)\n", 289 | "# # X_test_w2v = get_word2vec_data(X_test)" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": 13, 295 | "metadata": {}, 296 | "outputs": [], 297 | "source": [ 298 | "encoder = preprocessing.LabelEncoder()\n", 299 | "y_data_n = encoder.fit_transform(y_data)" 300 | ] 301 | }, 302 | { 303 | "cell_type": "code", 304 | "execution_count": 14, 305 | "metadata": {}, 306 | "outputs": [ 307 | { 308 | "data": { 309 | "text/plain": [ 310 | "array(['Chinh tri Xa hoi', 'Doi song', 'Khoa hoc', 'Kinh doanh',\n", 311 | " 'Phap luat', 'Suc khoe', 'The gioi', 'The thao', 'Van hoa',\n", 312 | " 'Vi tinh'], dtype=' best_score:\n", 83 | " best_topic = topic\n", 84 | " best_score = topic_score\n", 85 | " \n", 86 | " return best_topic" 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": 46, 92 | "metadata": {}, 93 | "outputs": [ 94 | { 95 | "name": "stderr", 96 | "output_type": "stream", 97 | "text": [ 98 | "/anaconda3/lib/python3.6/site-packages/gensim/matutils.py:737: FutureWarning: Conversion of the second argument of issubdtype from `int` to `np.signedinteger` is deprecated. In future, it will be treated as `np.int64 == np.dtype(int).type`.\n", 99 | " if np.issubdtype(vec.dtype, np.int):\n" 100 | ] 101 | }, 102 | { 103 | "data": { 104 | "text/plain": [ 105 | "'giao_thông'" 106 | ] 107 | }, 108 | "execution_count": 46, 109 | "metadata": {}, 110 | "output_type": "execute_result" 111 | } 112 | ], 113 | "source": [ 114 | "get_best_topic(list_word, topic)" 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "metadata": {}, 120 | "source": [ 121 | "# Test Naive Bayes" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": 1, 127 | "metadata": {}, 128 | "outputs": [ 129 | { 130 | "name": "stderr", 131 | "output_type": "stream", 132 | "text": [ 133 | "/anaconda3/lib/python3.6/site-packages/sklearn/ensemble/weight_boosting.py:29: DeprecationWarning: numpy.core.umath_tests is an internal NumPy module and should not be imported. It will be removed in a future NumPy release.\n", 134 | " from numpy.core.umath_tests import inner1d\n", 135 | "/anaconda3/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n", 136 | " from ._conv import register_converters as _register_converters\n", 137 | "Using TensorFlow backend.\n" 138 | ] 139 | } 140 | ], 141 | "source": [ 142 | "from sklearn import model_selection, preprocessing, linear_model, naive_bayes, metrics, svm\n", 143 | "from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer\n", 144 | "from sklearn import decomposition, ensemble\n", 145 | "\n", 146 | "import pandas, xgboost, numpy, textblob, string\n", 147 | "from keras.preprocessing import text, sequence\n", 148 | "from keras import layers, models, optimizers\n", 149 | "from keras.layers import *" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": 2, 155 | "metadata": {}, 156 | "outputs": [], 157 | "source": [ 158 | "from pyvi import ViTokenizer, ViPosTagger\n", 159 | "from tqdm import tqdm\n", 160 | "import numpy as np\n", 161 | "import gensim\n", 162 | "import numpy as np" 163 | ] 164 | }, 165 | { 166 | "cell_type": "markdown", 167 | "metadata": {}, 168 | "source": [ 169 | "# Xử lý dữ liệu" 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": 3, 175 | "metadata": {}, 176 | "outputs": [], 177 | "source": [ 178 | "def preprocessing_doc(doc):\n", 179 | " lines = gensim.utils.simple_preprocess(doc)\n", 180 | " lines = ' '.join(lines)\n", 181 | " lines = ViTokenizer.tokenize(lines)\n", 182 | "\n", 183 | " return lines" 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": 5, 189 | "metadata": {}, 190 | "outputs": [], 191 | "source": [ 192 | "import pickle\n", 193 | "\n", 194 | "X_data = pickle.load(open('data/X_data.pkl', 'rb'))\n", 195 | "y_data = pickle.load(open('data/y_data.pkl', 'rb'))\n", 196 | "\n", 197 | "# X_test = pickle.load(open('data/X_test.pkl', 'rb'))\n", 198 | "# y_test = pickle.load(open('data/y_test.pkl', 'rb'))" 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": null, 204 | "metadata": {}, 205 | "outputs": [], 206 | "source": [ 207 | "# word level - we choose max number of words equal to 30000 except all words (100k+ words)\n", 208 | "tfidf_vect = TfidfVectorizer(analyzer='word', max_features=30000)\n", 209 | "tfidf_vect.fit(X_data) # learn vocabulary and idf from training set\n", 210 | "X_data_tfidf = tfidf_vect.transform(X_data)" 211 | ] 212 | }, 213 | { 214 | "cell_type": "code", 215 | "execution_count": 7, 216 | "metadata": {}, 217 | "outputs": [], 218 | "source": [ 219 | "from sklearn.decomposition import TruncatedSVD" 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": 8, 225 | "metadata": {}, 226 | "outputs": [ 227 | { 228 | "data": { 229 | "text/plain": [ 230 | "TruncatedSVD(algorithm='randomized', n_components=300, n_iter=5,\n", 231 | " random_state=42, tol=0.0)" 232 | ] 233 | }, 234 | "execution_count": 8, 235 | "metadata": {}, 236 | "output_type": "execute_result" 237 | } 238 | ], 239 | "source": [ 240 | "svd = TruncatedSVD(n_components=300, random_state=42)\n", 241 | "svd.fit(X_data_tfidf)" 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": 9, 247 | "metadata": {}, 248 | "outputs": [], 249 | "source": [ 250 | "X_data_tfidf_svd = svd.transform(X_data_tfidf)" 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": 37, 256 | "metadata": {}, 257 | "outputs": [], 258 | "source": [ 259 | "# from gensim.models import KeyedVectors \n", 260 | "# import os \n", 261 | "# dir_path = os.path.dirname(os.path.realpath(os.getcwd()))\n", 262 | "# word2vec_model_path = os.path.join(dir_path, \"Data/vi/vi.vec\")\n", 263 | "\n", 264 | "# w2v = KeyedVectors.load_word2vec_format(word2vec_model_path)\n", 265 | "# vocab = w2v.wv.vocab\n", 266 | "# wv = w2v.wv" 267 | ] 268 | }, 269 | { 270 | "cell_type": "code", 271 | "execution_count": 36, 272 | "metadata": {}, 273 | "outputs": [], 274 | "source": [ 275 | "# def get_word2vec_data(X):\n", 276 | "# word2vec_data = []\n", 277 | "# for x in X:\n", 278 | "# sentence = []\n", 279 | "# for word in x.split(\" \"):\n", 280 | "# if word in vocab:\n", 281 | "# # print(word)\n", 282 | "# sentence.append(wv[word])\n", 283 | "\n", 284 | "# word2vec_data.append(sentence)\n", 285 | "# # break\n", 286 | "# return word2vec_data\n", 287 | "\n", 288 | "# X_data_w2v = get_word2vec_data(X_data)\n", 289 | "# # X_test_w2v = get_word2vec_data(X_test)" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": 13, 295 | "metadata": {}, 296 | "outputs": [], 297 | "source": [ 298 | "encoder = preprocessing.LabelEncoder()\n", 299 | "y_data_n = encoder.fit_transform(y_data)" 300 | ] 301 | }, 302 | { 303 | "cell_type": "code", 304 | "execution_count": 14, 305 | "metadata": {}, 306 | "outputs": [ 307 | { 308 | "data": { 309 | "text/plain": [ 310 | "array(['Chinh tri Xa hoi', 'Doi song', 'Khoa hoc', 'Kinh doanh',\n", 311 | " 'Phap luat', 'Suc khoe', 'The gioi', 'The thao', 'Van hoa',\n", 312 | " 'Vi tinh'], dtype='\n", 79 | "14157\n" 80 | ] 81 | } 82 | ], 83 | "source": [ 84 | "print(type(content))\n", 85 | "print(len(content))" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": 40, 91 | "metadata": {}, 92 | "outputs": [ 93 | { 94 | "name": "stdout", 95 | "output_type": "stream", 96 | "text": [ 97 | "### Trong phần này tôi sẽ giúp các bạn mới học `React Native` hiểu qua phần cài đặt project đã tồn tại và cùng nhau tìm hiểu khái niệm cơ bản nhất của React Native.\n", 98 | "# I. Một số chia sẻ cá nhân\n", 99 | "\n", 100 | "## 1. Yêu cầu thứ 1\n", 101 | "Yêu cầu để thực hiện theo bài viết này, bạn hãy cài đặt môi trường theo bài viết dưới đây\n", 102 | "\n", 103 | "### [Học React Native từ cơ bản đến nâng cao - Phần 1 Hướng dẫn cài đặt và chạy \"Hello world\"](https://viblo.asia/p/hoc-react-native-tu-co-ban-den-nang-cao-phan-1-huong-dan-cai-dat-va-chay-hello-world-RQqKLYW0Z7z)\n", 104 | "\n", 105 | "## 2. Yêu cầu thứ 2\n", 106 | "Khi muốn code React Native bạn sẽ phải chọn cho mình 1 Editors phù hợp cho mình\n", 107 | "\n", 108 | "Bạn có thể tham khảo các Editors theo link dưới đây\n", 109 | "\n", 110 | "### [Top 10 Editors For React Native Mobile App Development](https://www.icicletech.com/blog/top-10-editors-for-react-native)\n", 111 | "\n", 112 | "Còn lựa chọn của tôi là [**`Visual Studio Code`**](https://code.visualstudio.com/) vì đơn giản là dùng khá nhẹ và tiện dụng\n", 113 | "\n", 114 | "![](https://i.imgur.com/ZfAI0VK.png)\n", 115 | "\n", 116 | "Nếu bạn cũng chọn **`Visual Studio Code`** như tôi thì tiếp tục cài các Extension theo bài viết dưới đây để giúp việc code React Native trở nên dễ dàng hơn\n", 117 | "\n", 118 | "### VSCode for React Native: \n", 119 | "[https://medium.com/react-native-training/vscode-for-react-native-526ec4a368ce](https://medium.com/react-native-training/vscode-for-react-native-526ec4a368ce)\n", 120 | "\n", 121 | "## 3. Yêu cầu thứ 3\n", 122 | "\n", 123 | "Kéo code ví dụ React Native về máy bạn:\n", 124 | "\n", 125 | "- Bạn mở terminal \n", 126 | "\n", 127 | " **`git clone https://github.com/oTranThanhNghia/LearnReactNative.git`**\n", 128 | "\n", 129 | "- Khi đã kéo code về xong vào trong folder `LearnReactNative` mà vừa kéo về\n", 130 | "\n", 131 | " gõ lệnh sau để cấu hình project: **`npm install react-native@0.55.4`**\n", 132 | "\n", 133 | "- Cấu hình lại Android SDK trong file `local.properties` trong folder của Android `LearnReactNative\\android` ở như sau: \n", 134 | "```\n", 135 | "sdk.dir=D\\:\\\\Android\\\\Sdk\n", 136 | "```\n", 137 | "- Chạy android gõ: `react-native run-android`\n", 138 | " Khi nào terminal hiển thị là bạn đã thành công. \n", 139 | " \n", 140 | "![](https://i.imgur.com/ianKmsQ.png)\n", 141 | "\n", 142 | "Nếu bạn gặp phải lỗi sau thì hãy kiểm tra lại `port 8081` có đang sử dụng không. Nếu có thì tắt nó đi và gõ lại lệnh `npm start` để khởi động lại Metro Bundler\n", 143 | "\n", 144 | "![](https://i.imgur.com/GjvmD4f.png)\n", 145 | "\n", 146 | "* Ngoài ra bạn hãy vào index.js để chọn example để chạy nhé:\n", 147 | "\n", 148 | "![](https://i.imgur.com/WSeVoA8.png)\n", 149 | "\n", 150 | "# II. Khái niệm cơ bản trong React Native\n", 151 | "## 1. Props\n", 152 | "Hầu hết các thành phần có thể custom được khi được tạo ra với các tham số khác nhau. Các tham số này được gọi là `props`\n", 153 | "Ví dụ về `Image` sẽ giúp bạn sử dụng prop `source` để hiển thị ảnh\n", 154 | "\n", 155 | "```javascript\n", 156 | "import React, {Component} from 'react';\n", 157 | "import {Image} from 'react-native';\n", 158 | "\n", 159 | "export default class Bananas extends Component {\n", 160 | " render() {\n", 161 | " let pic = {\n", 162 | " uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg'\n", 163 | " };\n", 164 | " return (\n", 165 | " \n", 166 | " );\n", 167 | " }\n", 168 | "}\n", 169 | "```\n", 170 | "\n", 171 | "\n", 172 | "![](https://i.imgur.com/BLVZLjk.png)\n", 173 | "\n", 174 | "Components bạn viết ra cũng có thể sử dụng `props`. Ví dụ dưới đây sẽ mô tả cách sử dụng `props` trong Component riêng biệt\n", 175 | "\n", 176 | "``` javascript\n", 177 | "import React, { Component } from 'react';\n", 178 | "import { Text, View } from 'react-native';\n", 179 | "\n", 180 | "class Greeting extends Component {\n", 181 | " render() {\n", 182 | " return (\n", 183 | " Hello {this.props.name}!\n", 184 | " );\n", 185 | " }\n", 186 | "}\n", 187 | "\n", 188 | "export default class LotsOfGreetings extends Component {\n", 189 | " render() {\n", 190 | " return (\n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " );\n", 197 | " }\n", 198 | "}\n", 199 | "```\n", 200 | "\n", 201 | "![](https://i.imgur.com/ThWUrYc.png)\n", 202 | "\n", 203 | "Sử dụng prop `name` giúp bạn có thể custom `Greeting` component 1 cách dễ dàng và giúp tái sử dụng lại component ở nhiều nơi\n", 204 | "\n", 205 | "## 2. State\n", 206 | "Trong khi `props` là không thể thay đổi thì `state` là kiểu dữ liệu có thể update được trong tương lai\n", 207 | "\n", 208 | "Nghe có vẻ khó hiểu nhưng bạn xem ví dụ dưới đây cho rõ ràng\n", 209 | "\n", 210 | "```javascript\n", 211 | "import React, { Component } from 'react';\n", 212 | "import { Text, View } from 'react-native';\n", 213 | "\n", 214 | "class Blink extends Component {\n", 215 | " constructor(props) {\n", 216 | " super(props);\n", 217 | " this.state = {isShowingText: true};\n", 218 | "\n", 219 | " // Toggle the state every second\n", 220 | " setInterval(() => {\n", 221 | " this.setState(previousState => {\n", 222 | " return { isShowingText: !previousState.isShowingText };\n", 223 | " });\n", 224 | " }, 1000);\n", 225 | " }\n", 226 | "\n", 227 | " render() {\n", 228 | " let display = this.state.isShowingText ? this.props.text : ' ';\n", 229 | " return (\n", 230 | " {display}\n", 231 | " );\n", 232 | " }\n", 233 | "}\n", 234 | "\n", 235 | "export default class BlinkApp extends Component {\n", 236 | " render() {\n", 237 | " return (\n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " );\n", 245 | " }\n", 246 | "}\n", 247 | "```\n", 248 | "\n", 249 | "![](https://i.imgur.com/fyuYkCx.gif)\n", 250 | "\n", 251 | "Trong demo ở trên là ví dụ về sau 1 giây sẽ nhấp nháy chữ.\n", 252 | "\n", 253 | "Trong đó:\n", 254 | " - `props`: `text` trong `Blink` component\n", 255 | " - `state`: `isShowingText` là cờ để hiển thị\n", 256 | "\n", 257 | "\n", 258 | "\n", 259 | "## 3. Style\n", 260 | " `Style` sẽ gợi nhắc các bạn nghĩ ngay đến style của Web. Tất cả cấu trúc, biến, giá trị hầu hết đều giống với CSS\n", 261 | " Bạn hãy xem ví dụ dưới đây \n", 262 | " \n", 263 | "```javascript\n", 264 | "import React, { Component } from 'react';\n", 265 | "import { StyleSheet, Text, View } from 'react-native';\n", 266 | "\n", 267 | "export default class LotsOfStyles extends Component {\n", 268 | " render() {\n", 269 | " return (\n", 270 | " \n", 271 | " just red\n", 272 | " just bigblue\n", 273 | " bigblue, then red\n", 274 | " red, then bigblue\n", 275 | " \n", 276 | " );\n", 277 | " }\n", 278 | "}\n", 279 | "\n", 280 | "const styles = StyleSheet.create({\n", 281 | " bigblue: {\n", 282 | " color: 'blue',\n", 283 | " fontWeight: 'bold',\n", 284 | " fontSize: 30,\n", 285 | " },\n", 286 | " red: {\n", 287 | " color: 'red',\n", 288 | " },\n", 289 | "});\n", 290 | "```\n", 291 | "\n", 292 | "Trong đó:\n", 293 | "- set 1 phần tử: `style={styles.red}` \n", 294 | "- set 2 phần tử trở lên sẽ phải để trong `[]` ví dụ như `style={[styles.red, styles.bigblue]}`\n", 295 | "\n", 296 | "## 4. Handling Touches\n", 297 | "\n", 298 | "Các phần trên là mới chỉ đáp ứng được việc hiển thị lên app. Còn trong phần này sẽ giúp cho User tương tác được với App. Đơn giản nhất là sự kiện click vào 1 nút\n", 299 | "\n", 300 | "Để dễ dàng nhất bạn hãy dùng cấu trúc như sau:\n", 301 | "\n", 302 | "```xml\n", 303 | "\n", 304 | "