├── .gitignore ├── LICENSE ├── README.md ├── config ├── pytorch.yaml ├── sklearn.yaml └── tensorflow.yaml ├── data ├── input_vocab.txt └── target_vocab.txt ├── model ├── pytorch │ ├── cnn.py │ └── rnn.py ├── sklearn │ ├── bayes.py │ └── svm.py ├── tensorflow │ └── cnn.py └── tensorflow_v2 │ └── cnn2.py ├── requirements ├── req-base.txt └── req-tf1.txt ├── run ├── pytorch.py ├── sklearn.py └── tensorflow.py ├── script ├── prepare_data.sh └── tf1-env.sh ├── server ├── flask_app.py └── send_data.py └── util ├── batch_utils.py ├── conf_utils.py ├── data_utils.py └── output_utils.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | # pycharm 107 | .idea/ 108 | 109 | # project 110 | output/ 111 | data/THUCNews-5_2000 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 HaveTwoBrush 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # text-classification 2 | 3 | ## 1 简介 4 | 5 | `文本分类` 是 NLP 的基本任务之一,通过此任务的学习可以快速熟悉 NLP 的工作流程,同时了解 NLP 算法所能实现的效果。 6 | 7 | 本项目包含了 `tensorflow` `pytorch` `sklearn` 三个框架的各种不同实现,包括 `cnn` `rnn` 等。 8 | 除此之外,还提供了基本部署方法,可以使用 RESTful API 访问! 9 | 10 | ## 2 数据 11 | 12 | ### 2.1 THUCNews 数据集 13 | 14 | 我们选用了了开源的中文文本分类数据集`THUCNews`,介绍如下: 15 | 16 | > [THUCNews](http://thuctc.thunlp.org/) 是根据新浪新闻 RSS 订阅频道 2005~2011 年间的历史数据筛选过滤生成,包含 74 万篇新闻文档(2.19 GB),均为 UTF-8 纯文本格式。 17 | > 我们在原始新浪新闻分类体系的基础上,重新整合划分出 14 个候选分类类别:财经、彩票、房产、股票、家居、教育、科技、社会、时尚、时政、体育、星座、游戏、娱乐。 18 | 19 | | 序号 | 类别 | 数量 | 20 | | :-: | :-: | :-: | 21 | | 1 | 财经 | 37098 | 22 | | 2 | 彩票 | 7588 | 23 | | 3 | 房产 | 20050 | 24 | | 4 | 股票 | 154398 | 25 | | 5 | 家居 | 32586 | 26 | | 6 | 教育 | 41936 | 27 | | 7 | 科技 | 162929 | 28 | | 8 | 社会 | 50849 | 29 | | 9 | 时尚 | 13368 | 30 | | 10 | 时政 | 63086 | 31 | | 11 | 体育 | 131604 | 32 | | 12 | 星座 | 3578 | 33 | | 13 | 游戏 | 24373 | 34 | | 14 | 娱乐 | 92632 | 35 | 36 | ### 2.2 新数据集 1(THUCNews-5_2000,低配置) 37 | 38 | 由于原数据集较大,对硬件要求较高,因此我们先从中提取部分数据再使用。操作过程如下: 39 | 40 | 1. 我们从 THUCNews 数据集中选取类别名词词义相差比较大的 5 组数据,分别为: `体育, 房产, 股票, 时政, 游戏`。 41 | 2. 从每 1 组数据中随机取 2000 条放入的新的数据集中,最终得到 1 万条新闻数据。 42 | 3. 将新数据集按照 `8:2:2` 划分成训练集(train set)、验证集(validate set)、测试集(test set),保存在 `/data/THUCNews-5_2000/` 中。 43 | 44 | 数据集数量为: 45 | 46 | - train set: 1600 * 5 47 | - validate set: 200 * 5 48 | - test set: 200 * 5 49 | 50 | 获取数据方式见 `/script/prepare_data.sh`。 51 | 52 | ### 2.2 新数据集 2(THUCNews-14_10000,中配置) 53 | 54 | TODO 55 | 56 | ### 2.3 单个数据介绍 57 | 58 | 每个单独的文件是 1 条数据,文件名使用`-`切分后,前半部分是类别名称,后半部分是原 THUCNews 数据集中的 id 。 59 | 举例: 60 | ```bash 61 | 体育-76.txt 62 | ``` 63 | ## 3 结构 64 | 65 | ``` 66 | . 67 | ├── config # 配置 68 | ├── data # 数据 69 | │   └── THUCNews-5_2000 70 | │   ├── train 71 | │   ├── validate 72 | │   └── test 73 | ├── model # 模型 74 | │   ├── pytorch 75 | │   ├── tensorflow 76 | │   └── sklearn 77 | ├── output # 输出 78 | ├── run # 入口 79 | ├── script # 脚本 80 | ├── server # 部署 81 | └── util # 工具 82 | ``` 83 | 84 | ## 4 安装 85 | 86 | ```bash 87 | # 克隆代码 88 | git clone https://github.com/kinggreenhall/text-classification.git 89 | 90 | # 进入项目 91 | cd text-classification 92 | 93 | # 安装依赖 94 | bash script/tf1-env.sh 95 | 96 | # 准备数据 97 | bash script/prepare_data.sh 98 | 99 | # 开始训练 100 | python -m run.tensorflow -m cnn 101 | 102 | # 测试模型(需要替换 $train_date) 103 | python -m run.tensorflow -r test -d $train_date 104 | ``` 105 | 106 | ## 5 可视化 107 | 108 | ```bash 109 | # 使用 Tensorboard 进行可视化(需要替换 $train_date) 110 | tensorboard --logdir ./output/$train_date/log 111 | ``` 112 | 113 | > 当前仅 tensorflow 可用。 114 | 115 | ## 6 部署 116 | 117 | ```bash 118 | # 启动 flask 服务 119 | python -m server.flask_app 120 | # 发送 test 数据 121 | pythom -m server.send_data 122 | ``` 123 | 124 | > 当前仅 tensorflow 可用。 125 | 126 | ## 7 TODO 127 | 128 | - [x] tensorflow cnn 129 | - [ ] tensorflow rnn 130 | - [ ] tensorflow_v2 cnn 131 | - [ ] tensorflow_v2 rnn 132 | - [x] tensorflow flask server 133 | - [x] pytorch cnn 134 | - [x] pytorch rnn 135 | - [ ] pytorch flask server 136 | - [x] sklearn svm 137 | - [x] sklearn bayes 138 | 139 | ## 8 参考 140 | 141 | - [THUCTC: 一个高效的中文文本分类工具包](http://thuctc.thunlp.org/) 142 | - [text-classification-cnn-rnn](https://github.com/gaussic/text-classification-cnn-rnn) 143 | - [How to Fine-Tune BERT for Text Classification?](https://arxiv.org/pdf/1905.05583.pdf) 144 | 145 | ## 9 许可证 146 | 147 | [![](https://award.dovolopor.com?lt=License&rt=MIT&rbc=green)](./LICENSE) 148 | [![](https://award.dovolopor.com?lt=Ailln's&rt=idea&lbc=lightgray&rbc=red<c=red)](https://github.com/Ailln/award) 149 | -------------------------------------------------------------------------------- /config/pytorch.yaml: -------------------------------------------------------------------------------- 1 | data_path: "./data/" 2 | train_data_path: "./data/THUCNews-5_2000/train/" 3 | validate_data_path: "./data/THUCNews-5_2000/validate/" 4 | test_data_path: "./data/THUCNews-5_2000/test/" 5 | input_vocab_path: "./data/input_vocab.txt" 6 | target_vocab_path: "./data/target_vocab.txt" 7 | output_path: "./output/" 8 | 9 | frame_class: "pytorch" 10 | 11 | seq_length: 100 12 | num_classes: 5 13 | filter_size: 256 14 | kernel_size: 3 15 | vocab_size: 5000 16 | embedding_size: 50 17 | 18 | batch_size: 64 19 | epoch_size: 100 20 | num_save_epoch: 2 21 | learning_rate: 0.01 22 | dropout_keep_prob: 0.5 23 | 24 | # cnn 25 | opt_name: adam 26 | model_class: conv1d 27 | 28 | # rnn 29 | hidden_size: 1024 30 | num_layers: 1 -------------------------------------------------------------------------------- /config/sklearn.yaml: -------------------------------------------------------------------------------- 1 | data_path: "./data/" 2 | train_data_path: "./data/THUCNews-5_2000/train/" 3 | validate_data_path: "./data/THUCNews-5_2000/validate/" 4 | test_data_path: "./data/THUCNews-5_2000/test/" 5 | output_path: "./output/" 6 | 7 | frame_class: "sklearn" -------------------------------------------------------------------------------- /config/tensorflow.yaml: -------------------------------------------------------------------------------- 1 | data_path: "./data/" 2 | train_data_path: "./data/THUCNews-5_2000/train/" 3 | validate_data_path: "./data/THUCNews-5_2000/validate/" 4 | test_data_path: "./data/THUCNews-5_2000/test/" 5 | input_vocab_path: "./data/input_vocab.txt" 6 | target_vocab_path: "./data/target_vocab.txt" 7 | output_path: "./output/" 8 | 9 | frame_class: "tensorflow_v2" 10 | 11 | seq_length: 10 12 | num_classes: 5 13 | filter_size: 256 14 | kernel_size: 5 15 | vocab_size: 5000 16 | embedding_size: 50 17 | 18 | batch_size: 64 19 | epoch_size: 200 20 | num_save_epoch: 2 21 | learning_rate: 0.01 22 | dropout_keep_prob: 0.5 23 | 24 | opt_name: adam -------------------------------------------------------------------------------- /data/input_vocab.txt: -------------------------------------------------------------------------------- 1 | PAD 2 | UNK 3 | 。 4 | ? 5 | ! 6 | , 7 | 、 8 | ; 9 | : 10 | “ 11 | ” 12 | ‘ 13 | ’ 14 | … 15 | ( 16 | ) 17 | 《 18 | 》 19 | 〈 20 | 〉 21 | 【 22 | 】 23 | . 24 | , 25 | : 26 | ! 27 | ? 28 | _ 29 | " 30 | ' 31 | ( 32 | ) 33 | [ 34 | ] 35 | < 36 | > 37 | | 38 | & 39 | ~ 40 | ; 41 | + 42 | - 43 | * 44 | / 45 | = 46 | 0 47 | 1 48 | 2 49 | 3 50 | 4 51 | 5 52 | 6 53 | 7 54 | 8 55 | 9 56 | A 57 | B 58 | C 59 | D 60 | E 61 | F 62 | G 63 | H 64 | I 65 | J 66 | K 67 | L 68 | M 69 | N 70 | O 71 | P 72 | Q 73 | R 74 | S 75 | T 76 | U 77 | V 78 | W 79 | X 80 | Y 81 | Z 82 | a 83 | b 84 | c 85 | d 86 | e 87 | f 88 | g 89 | h 90 | i 91 | j 92 | k 93 | l 94 | m 95 | n 96 | o 97 | p 98 | q 99 | r 100 | s 101 | t 102 | u 103 | v 104 | w 105 | x 106 | y 107 | z 108 | 一 109 | 乙 110 | 二 111 | 十 112 | 丁 113 | 厂 114 | 七 115 | 卜 116 | 人 117 | 入 118 | 八 119 | 九 120 | 几 121 | 儿 122 | 了 123 | 力 124 | 乃 125 | 刀 126 | 又 127 | 三 128 | 于 129 | 干 130 | 亏 131 | 士 132 | 工 133 | 土 134 | 才 135 | 寸 136 | 下 137 | 大 138 | 丈 139 | 与 140 | 万 141 | 上 142 | 小 143 | 口 144 | 巾 145 | 山 146 | 千 147 | 乞 148 | 川 149 | 亿 150 | 个 151 | 勺 152 | 久 153 | 凡 154 | 及 155 | 夕 156 | 丸 157 | 么 158 | 广 159 | 亡 160 | 门 161 | 义 162 | 之 163 | 尸 164 | 弓 165 | 己 166 | 已 167 | 子 168 | 卫 169 | 也 170 | 女 171 | 飞 172 | 刃 173 | 习 174 | 叉 175 | 马 176 | 乡 177 | 丰 178 | 王 179 | 井 180 | 开 181 | 夫 182 | 天 183 | 无 184 | 元 185 | 专 186 | 云 187 | 扎 188 | 艺 189 | 木 190 | 五 191 | 支 192 | 厅 193 | 不 194 | 太 195 | 犬 196 | 区 197 | 历 198 | 尤 199 | 友 200 | 匹 201 | 车 202 | 巨 203 | 牙 204 | 屯 205 | 比 206 | 互 207 | 切 208 | 瓦 209 | 止 210 | 少 211 | 日 212 | 中 213 | 冈 214 | 贝 215 | 内 216 | 水 217 | 见 218 | 午 219 | 牛 220 | 手 221 | 毛 222 | 气 223 | 升 224 | 长 225 | 仁 226 | 什 227 | 片 228 | 仆 229 | 化 230 | 仇 231 | 币 232 | 仍 233 | 仅 234 | 斤 235 | 爪 236 | 反 237 | 介 238 | 父 239 | 从 240 | 今 241 | 凶 242 | 分 243 | 乏 244 | 公 245 | 仓 246 | 月 247 | 氏 248 | 勿 249 | 欠 250 | 风 251 | 丹 252 | 匀 253 | 乌 254 | 凤 255 | 勾 256 | 文 257 | 六 258 | 方 259 | 火 260 | 为 261 | 斗 262 | 忆 263 | 订 264 | 计 265 | 户 266 | 认 267 | 心 268 | 尺 269 | 引 270 | 丑 271 | 巴 272 | 孔 273 | 队 274 | 办 275 | 以 276 | 允 277 | 予 278 | 劝 279 | 双 280 | 书 281 | 幻 282 | 玉 283 | 刊 284 | 示 285 | 末 286 | 未 287 | 击 288 | 打 289 | 巧 290 | 正 291 | 扑 292 | 扒 293 | 功 294 | 扔 295 | 去 296 | 甘 297 | 世 298 | 古 299 | 节 300 | 本 301 | 术 302 | 可 303 | 丙 304 | 左 305 | 厉 306 | 右 307 | 石 308 | 布 309 | 龙 310 | 平 311 | 灭 312 | 轧 313 | 东 314 | 卡 315 | 北 316 | 占 317 | 业 318 | 旧 319 | 帅 320 | 归 321 | 且 322 | 旦 323 | 目 324 | 叶 325 | 甲 326 | 申 327 | 叮 328 | 电 329 | 号 330 | 田 331 | 由 332 | 史 333 | 只 334 | 央 335 | 兄 336 | 叼 337 | 叫 338 | 另 339 | 叨 340 | 叹 341 | 四 342 | 生 343 | 失 344 | 禾 345 | 丘 346 | 付 347 | 仗 348 | 代 349 | 仙 350 | 们 351 | 仪 352 | 白 353 | 仔 354 | 他 355 | 斥 356 | 瓜 357 | 乎 358 | 丛 359 | 令 360 | 用 361 | 甩 362 | 印 363 | 乐 364 | 句 365 | 匆 366 | 册 367 | 犯 368 | 外 369 | 处 370 | 冬 371 | 鸟 372 | 务 373 | 包 374 | 饥 375 | 主 376 | 市 377 | 立 378 | 闪 379 | 兰 380 | 半 381 | 汁 382 | 汇 383 | 头 384 | 汉 385 | 宁 386 | 穴 387 | 它 388 | 讨 389 | 写 390 | 让 391 | 礼 392 | 训 393 | 必 394 | 议 395 | 讯 396 | 记 397 | 永 398 | 司 399 | 尼 400 | 民 401 | 出 402 | 辽 403 | 奶 404 | 奴 405 | 加 406 | 召 407 | 皮 408 | 边 409 | 发 410 | 孕 411 | 圣 412 | 对 413 | 台 414 | 矛 415 | 纠 416 | 母 417 | 幼 418 | 丝 419 | 式 420 | 刑 421 | 动 422 | 扛 423 | 寺 424 | 吉 425 | 扣 426 | 考 427 | 托 428 | 老 429 | 执 430 | 巩 431 | 圾 432 | 扩 433 | 扫 434 | 地 435 | 扬 436 | 场 437 | 耳 438 | 共 439 | 芒 440 | 亚 441 | 芝 442 | 朽 443 | 朴 444 | 机 445 | 权 446 | 过 447 | 臣 448 | 再 449 | 协 450 | 西 451 | 压 452 | 厌 453 | 在 454 | 有 455 | 百 456 | 存 457 | 而 458 | 页 459 | 匠 460 | 夸 461 | 夺 462 | 灰 463 | 达 464 | 列 465 | 死 466 | 成 467 | 夹 468 | 轨 469 | 邪 470 | 划 471 | 迈 472 | 毕 473 | 至 474 | 此 475 | 贞 476 | 师 477 | 尘 478 | 尖 479 | 劣 480 | 光 481 | 当 482 | 早 483 | 吐 484 | 吓 485 | 虫 486 | 曲 487 | 团 488 | 同 489 | 吊 490 | 吃 491 | 因 492 | 吸 493 | 吗 494 | 屿 495 | 帆 496 | 岁 497 | 回 498 | 岂 499 | 刚 500 | 则 501 | 肉 502 | 网 503 | 年 504 | 朱 505 | 先 506 | 丢 507 | 舌 508 | 竹 509 | 迁 510 | 乔 511 | 伟 512 | 传 513 | 乒 514 | 乓 515 | 休 516 | 伍 517 | 伏 518 | 优 519 | 伐 520 | 延 521 | 件 522 | 任 523 | 伤 524 | 价 525 | 份 526 | 华 527 | 仰 528 | 仿 529 | 伙 530 | 伪 531 | 自 532 | 血 533 | 向 534 | 似 535 | 后 536 | 行 537 | 舟 538 | 全 539 | 会 540 | 杀 541 | 合 542 | 兆 543 | 企 544 | 众 545 | 爷 546 | 伞 547 | 创 548 | 肌 549 | 朵 550 | 杂 551 | 危 552 | 旬 553 | 旨 554 | 负 555 | 各 556 | 名 557 | 多 558 | 争 559 | 色 560 | 壮 561 | 冲 562 | 冰 563 | 庄 564 | 庆 565 | 亦 566 | 刘 567 | 齐 568 | 交 569 | 次 570 | 衣 571 | 产 572 | 决 573 | 充 574 | 妄 575 | 闭 576 | 问 577 | 闯 578 | 羊 579 | 并 580 | 关 581 | 米 582 | 灯 583 | 州 584 | 汗 585 | 污 586 | 江 587 | 池 588 | 汤 589 | 忙 590 | 兴 591 | 宇 592 | 守 593 | 宅 594 | 字 595 | 安 596 | 讲 597 | 军 598 | 许 599 | 论 600 | 农 601 | 讽 602 | 设 603 | 访 604 | 寻 605 | 那 606 | 迅 607 | 尽 608 | 导 609 | 异 610 | 孙 611 | 阵 612 | 阳 613 | 收 614 | 阶 615 | 阴 616 | 防 617 | 奸 618 | 如 619 | 妇 620 | 好 621 | 她 622 | 妈 623 | 戏 624 | 羽 625 | 观 626 | 欢 627 | 买 628 | 红 629 | 纤 630 | 级 631 | 约 632 | 纪 633 | 驰 634 | 巡 635 | 寿 636 | 弄 637 | 麦 638 | 形 639 | 进 640 | 戒 641 | 吞 642 | 远 643 | 违 644 | 运 645 | 扶 646 | 抚 647 | 坛 648 | 技 649 | 坏 650 | 扰 651 | 拒 652 | 找 653 | 批 654 | 扯 655 | 址 656 | 走 657 | 抄 658 | 坝 659 | 贡 660 | 攻 661 | 赤 662 | 折 663 | 抓 664 | 扮 665 | 抢 666 | 孝 667 | 均 668 | 抛 669 | 投 670 | 坟 671 | 抗 672 | 坑 673 | 坊 674 | 抖 675 | 护 676 | 壳 677 | 志 678 | 扭 679 | 块 680 | 声 681 | 把 682 | 报 683 | 却 684 | 劫 685 | 芽 686 | 花 687 | 芹 688 | 芬 689 | 苍 690 | 芳 691 | 严 692 | 芦 693 | 劳 694 | 克 695 | 苏 696 | 杆 697 | 杠 698 | 杜 699 | 材 700 | 村 701 | 杏 702 | 极 703 | 李 704 | 杨 705 | 求 706 | 更 707 | 束 708 | 豆 709 | 两 710 | 丽 711 | 医 712 | 辰 713 | 励 714 | 否 715 | 还 716 | 歼 717 | 来 718 | 连 719 | 步 720 | 坚 721 | 旱 722 | 盯 723 | 呈 724 | 时 725 | 吴 726 | 助 727 | 县 728 | 里 729 | 呆 730 | 园 731 | 旷 732 | 围 733 | 呀 734 | 吨 735 | 足 736 | 邮 737 | 男 738 | 困 739 | 吵 740 | 串 741 | 员 742 | 听 743 | 吩 744 | 吹 745 | 呜 746 | 吧 747 | 吼 748 | 别 749 | 岗 750 | 帐 751 | 财 752 | 针 753 | 钉 754 | 告 755 | 我 756 | 乱 757 | 利 758 | 秃 759 | 秀 760 | 私 761 | 每 762 | 兵 763 | 估 764 | 体 765 | 何 766 | 但 767 | 伸 768 | 作 769 | 伯 770 | 伶 771 | 佣 772 | 低 773 | 你 774 | 住 775 | 位 776 | 伴 777 | 身 778 | 皂 779 | 佛 780 | 近 781 | 彻 782 | 役 783 | 返 784 | 余 785 | 希 786 | 坐 787 | 谷 788 | 妥 789 | 含 790 | 邻 791 | 岔 792 | 肝 793 | 肚 794 | 肠 795 | 龟 796 | 免 797 | 狂 798 | 犹 799 | 角 800 | 删 801 | 条 802 | 卵 803 | 岛 804 | 迎 805 | 饭 806 | 饮 807 | 系 808 | 言 809 | 冻 810 | 状 811 | 亩 812 | 况 813 | 床 814 | 库 815 | 疗 816 | 应 817 | 冷 818 | 这 819 | 序 820 | 辛 821 | 弃 822 | 冶 823 | 忘 824 | 闲 825 | 间 826 | 闷 827 | 判 828 | 灶 829 | 灿 830 | 弟 831 | 汪 832 | 沙 833 | 汽 834 | 沃 835 | 泛 836 | 沟 837 | 没 838 | 沈 839 | 沉 840 | 怀 841 | 忧 842 | 快 843 | 完 844 | 宋 845 | 宏 846 | 牢 847 | 究 848 | 穷 849 | 灾 850 | 良 851 | 证 852 | 启 853 | 评 854 | 补 855 | 初 856 | 社 857 | 识 858 | 诉 859 | 诊 860 | 词 861 | 译 862 | 君 863 | 灵 864 | 即 865 | 层 866 | 尿 867 | 尾 868 | 迟 869 | 局 870 | 改 871 | 张 872 | 忌 873 | 际 874 | 陆 875 | 阿 876 | 陈 877 | 阻 878 | 附 879 | 妙 880 | 妖 881 | 妨 882 | 努 883 | 忍 884 | 劲 885 | 鸡 886 | 驱 887 | 纯 888 | 纱 889 | 纳 890 | 纲 891 | 驳 892 | 纵 893 | 纷 894 | 纸 895 | 纹 896 | 纺 897 | 驴 898 | 纽 899 | 奉 900 | 玩 901 | 环 902 | 武 903 | 青 904 | 责 905 | 现 906 | 表 907 | 规 908 | 抹 909 | 拢 910 | 拔 911 | 拣 912 | 担 913 | 坦 914 | 押 915 | 抽 916 | 拐 917 | 拖 918 | 拍 919 | 者 920 | 顶 921 | 拆 922 | 拥 923 | 抵 924 | 拘 925 | 势 926 | 抱 927 | 垃 928 | 拉 929 | 拦 930 | 拌 931 | 幸 932 | 招 933 | 坡 934 | 披 935 | 拨 936 | 择 937 | 抬 938 | 其 939 | 取 940 | 苦 941 | 若 942 | 茂 943 | 苹 944 | 苗 945 | 英 946 | 范 947 | 直 948 | 茄 949 | 茎 950 | 茅 951 | 林 952 | 枝 953 | 杯 954 | 柜 955 | 析 956 | 板 957 | 松 958 | 枪 959 | 构 960 | 杰 961 | 述 962 | 枕 963 | 丧 964 | 或 965 | 画 966 | 卧 967 | 事 968 | 刺 969 | 枣 970 | 雨 971 | 卖 972 | 矿 973 | 码 974 | 厕 975 | 奔 976 | 奇 977 | 奋 978 | 态 979 | 欧 980 | 垄 981 | 妻 982 | 轰 983 | 顷 984 | 转 985 | 斩 986 | 轮 987 | 软 988 | 到 989 | 非 990 | 叔 991 | 肯 992 | 齿 993 | 些 994 | 虎 995 | 虏 996 | 肾 997 | 贤 998 | 尚 999 | 旺 1000 | 具 1001 | 果 1002 | 味 1003 | 昆 1004 | 国 1005 | 昌 1006 | 畅 1007 | 明 1008 | 易 1009 | 昂 1010 | 典 1011 | 固 1012 | 忠 1013 | 咐 1014 | 呼 1015 | 鸣 1016 | 咏 1017 | 呢 1018 | 岸 1019 | 岩 1020 | 帖 1021 | 罗 1022 | 帜 1023 | 岭 1024 | 凯 1025 | 败 1026 | 贩 1027 | 购 1028 | 图 1029 | 钓 1030 | 制 1031 | 知 1032 | 垂 1033 | 牧 1034 | 物 1035 | 乖 1036 | 刮 1037 | 秆 1038 | 和 1039 | 季 1040 | 委 1041 | 佳 1042 | 侍 1043 | 供 1044 | 使 1045 | 例 1046 | 版 1047 | 侄 1048 | 侦 1049 | 侧 1050 | 凭 1051 | 侨 1052 | 佩 1053 | 货 1054 | 依 1055 | 的 1056 | 迫 1057 | 质 1058 | 欣 1059 | 征 1060 | 往 1061 | 爬 1062 | 彼 1063 | 径 1064 | 所 1065 | 舍 1066 | 金 1067 | 命 1068 | 斧 1069 | 爸 1070 | 采 1071 | 受 1072 | 乳 1073 | 贪 1074 | 念 1075 | 贫 1076 | 肤 1077 | 肺 1078 | 肢 1079 | 肿 1080 | 胀 1081 | 朋 1082 | 股 1083 | 肥 1084 | 服 1085 | 胁 1086 | 周 1087 | 昏 1088 | 鱼 1089 | 兔 1090 | 狐 1091 | 忽 1092 | 狗 1093 | 备 1094 | 饰 1095 | 饱 1096 | 饲 1097 | 变 1098 | 京 1099 | 享 1100 | 店 1101 | 夜 1102 | 庙 1103 | 府 1104 | 底 1105 | 剂 1106 | 郊 1107 | 废 1108 | 净 1109 | 盲 1110 | 放 1111 | 刻 1112 | 育 1113 | 闸 1114 | 闹 1115 | 郑 1116 | 券 1117 | 卷 1118 | 单 1119 | 炒 1120 | 炊 1121 | 炕 1122 | 炎 1123 | 炉 1124 | 沫 1125 | 浅 1126 | 法 1127 | 泄 1128 | 河 1129 | 沾 1130 | 泪 1131 | 油 1132 | 泊 1133 | 沿 1134 | 泡 1135 | 注 1136 | 泻 1137 | 泳 1138 | 泥 1139 | 沸 1140 | 波 1141 | 泼 1142 | 泽 1143 | 治 1144 | 怖 1145 | 性 1146 | 怕 1147 | 怜 1148 | 怪 1149 | 学 1150 | 宝 1151 | 宗 1152 | 定 1153 | 宜 1154 | 审 1155 | 宙 1156 | 官 1157 | 空 1158 | 帘 1159 | 实 1160 | 试 1161 | 郎 1162 | 诗 1163 | 肩 1164 | 房 1165 | 诚 1166 | 衬 1167 | 衫 1168 | 视 1169 | 话 1170 | 诞 1171 | 询 1172 | 该 1173 | 详 1174 | 建 1175 | 肃 1176 | 录 1177 | 隶 1178 | 居 1179 | 届 1180 | 刷 1181 | 屈 1182 | 弦 1183 | 承 1184 | 孟 1185 | 孤 1186 | 陕 1187 | 降 1188 | 限 1189 | 妹 1190 | 姑 1191 | 姐 1192 | 姓 1193 | 始 1194 | 驾 1195 | 参 1196 | 艰 1197 | 线 1198 | 练 1199 | 组 1200 | 细 1201 | 驶 1202 | 织 1203 | 终 1204 | 驻 1205 | 驼 1206 | 绍 1207 | 经 1208 | 贯 1209 | 奏 1210 | 春 1211 | 帮 1212 | 珍 1213 | 玻 1214 | 毒 1215 | 型 1216 | 挂 1217 | 封 1218 | 持 1219 | 项 1220 | 垮 1221 | 挎 1222 | 城 1223 | 挠 1224 | 政 1225 | 赴 1226 | 赵 1227 | 挡 1228 | 挺 1229 | 括 1230 | 拴 1231 | 拾 1232 | 挑 1233 | 指 1234 | 垫 1235 | 挣 1236 | 挤 1237 | 拼 1238 | 挖 1239 | 按 1240 | 挥 1241 | 挪 1242 | 某 1243 | 甚 1244 | 革 1245 | 荐 1246 | 巷 1247 | 带 1248 | 草 1249 | 茧 1250 | 茶 1251 | 荒 1252 | 茫 1253 | 荡 1254 | 荣 1255 | 故 1256 | 胡 1257 | 南 1258 | 药 1259 | 标 1260 | 枯 1261 | 柄 1262 | 栋 1263 | 相 1264 | 查 1265 | 柏 1266 | 柳 1267 | 柱 1268 | 柿 1269 | 栏 1270 | 树 1271 | 要 1272 | 咸 1273 | 威 1274 | 歪 1275 | 研 1276 | 砖 1277 | 厘 1278 | 厚 1279 | 砌 1280 | 砍 1281 | 面 1282 | 耐 1283 | 耍 1284 | 牵 1285 | 残 1286 | 殃 1287 | 轻 1288 | 鸦 1289 | 皆 1290 | 背 1291 | 战 1292 | 点 1293 | 临 1294 | 览 1295 | 竖 1296 | 省 1297 | 削 1298 | 尝 1299 | 是 1300 | 盼 1301 | 眨 1302 | 哄 1303 | 显 1304 | 哑 1305 | 冒 1306 | 映 1307 | 星 1308 | 昨 1309 | 畏 1310 | 趴 1311 | 胃 1312 | 贵 1313 | 界 1314 | 虹 1315 | 虾 1316 | 蚁 1317 | 思 1318 | 蚂 1319 | 虽 1320 | 品 1321 | 咽 1322 | 骂 1323 | 哗 1324 | 咱 1325 | 响 1326 | 哈 1327 | 咬 1328 | 咳 1329 | 哪 1330 | 炭 1331 | 峡 1332 | 罚 1333 | 贱 1334 | 贴 1335 | 骨 1336 | 钞 1337 | 钟 1338 | 钢 1339 | 钥 1340 | 钩 1341 | 卸 1342 | 缸 1343 | 拜 1344 | 看 1345 | 矩 1346 | 怎 1347 | 牲 1348 | 选 1349 | 适 1350 | 秒 1351 | 香 1352 | 种 1353 | 秋 1354 | 科 1355 | 重 1356 | 复 1357 | 竿 1358 | 段 1359 | 便 1360 | 俩 1361 | 贷 1362 | 顺 1363 | 修 1364 | 保 1365 | 促 1366 | 侮 1367 | 俭 1368 | 俗 1369 | 俘 1370 | 信 1371 | 皇 1372 | 泉 1373 | 鬼 1374 | 侵 1375 | 追 1376 | 俊 1377 | 盾 1378 | 待 1379 | 律 1380 | 很 1381 | 须 1382 | 叙 1383 | 剑 1384 | 逃 1385 | 食 1386 | 盆 1387 | 胆 1388 | 胜 1389 | 胞 1390 | 胖 1391 | 脉 1392 | 勉 1393 | 狭 1394 | 狮 1395 | 独 1396 | 狡 1397 | 狱 1398 | 狠 1399 | 贸 1400 | 怨 1401 | 急 1402 | 饶 1403 | 蚀 1404 | 饺 1405 | 饼 1406 | 弯 1407 | 将 1408 | 奖 1409 | 哀 1410 | 亭 1411 | 亮 1412 | 度 1413 | 迹 1414 | 庭 1415 | 疮 1416 | 疯 1417 | 疫 1418 | 疤 1419 | 姿 1420 | 亲 1421 | 音 1422 | 帝 1423 | 施 1424 | 闻 1425 | 阀 1426 | 阁 1427 | 差 1428 | 养 1429 | 美 1430 | 姜 1431 | 叛 1432 | 送 1433 | 类 1434 | 迷 1435 | 前 1436 | 首 1437 | 逆 1438 | 总 1439 | 炼 1440 | 炸 1441 | 炮 1442 | 烂 1443 | 剃 1444 | 洁 1445 | 洪 1446 | 洒 1447 | 浇 1448 | 浊 1449 | 洞 1450 | 测 1451 | 洗 1452 | 活 1453 | 派 1454 | 洽 1455 | 染 1456 | 济 1457 | 洋 1458 | 洲 1459 | 浑 1460 | 浓 1461 | 津 1462 | 恒 1463 | 恢 1464 | 恰 1465 | 恼 1466 | 恨 1467 | 举 1468 | 觉 1469 | 宣 1470 | 室 1471 | 宫 1472 | 宪 1473 | 突 1474 | 穿 1475 | 窃 1476 | 客 1477 | 冠 1478 | 语 1479 | 扁 1480 | 袄 1481 | 祖 1482 | 神 1483 | 祝 1484 | 误 1485 | 诱 1486 | 说 1487 | 诵 1488 | 垦 1489 | 退 1490 | 既 1491 | 屋 1492 | 昼 1493 | 费 1494 | 陡 1495 | 眉 1496 | 孩 1497 | 除 1498 | 险 1499 | 院 1500 | 娃 1501 | 姥 1502 | 姨 1503 | 姻 1504 | 娇 1505 | 怒 1506 | 架 1507 | 贺 1508 | 盈 1509 | 勇 1510 | 怠 1511 | 柔 1512 | 垒 1513 | 绑 1514 | 绒 1515 | 结 1516 | 绕 1517 | 骄 1518 | 绘 1519 | 给 1520 | 络 1521 | 骆 1522 | 绝 1523 | 绞 1524 | 统 1525 | 耕 1526 | 耗 1527 | 艳 1528 | 泰 1529 | 珠 1530 | 班 1531 | 素 1532 | 蚕 1533 | 顽 1534 | 盏 1535 | 匪 1536 | 捞 1537 | 栽 1538 | 捕 1539 | 振 1540 | 载 1541 | 赶 1542 | 起 1543 | 盐 1544 | 捎 1545 | 捏 1546 | 埋 1547 | 捉 1548 | 捆 1549 | 捐 1550 | 损 1551 | 都 1552 | 哲 1553 | 逝 1554 | 捡 1555 | 换 1556 | 挽 1557 | 热 1558 | 恐 1559 | 壶 1560 | 挨 1561 | 耻 1562 | 耽 1563 | 恭 1564 | 莲 1565 | 莫 1566 | 荷 1567 | 获 1568 | 晋 1569 | 恶 1570 | 真 1571 | 框 1572 | 桂 1573 | 档 1574 | 桐 1575 | 株 1576 | 桥 1577 | 桃 1578 | 格 1579 | 校 1580 | 核 1581 | 样 1582 | 根 1583 | 索 1584 | 哥 1585 | 速 1586 | 逗 1587 | 栗 1588 | 配 1589 | 翅 1590 | 辱 1591 | 唇 1592 | 夏 1593 | 础 1594 | 破 1595 | 原 1596 | 套 1597 | 逐 1598 | 烈 1599 | 殊 1600 | 顾 1601 | 轿 1602 | 较 1603 | 顿 1604 | 毙 1605 | 致 1606 | 柴 1607 | 桌 1608 | 虑 1609 | 监 1610 | 紧 1611 | 党 1612 | 晒 1613 | 眠 1614 | 晓 1615 | 鸭 1616 | 晃 1617 | 晌 1618 | 晕 1619 | 蚊 1620 | 哨 1621 | 哭 1622 | 恩 1623 | 唤 1624 | 啊 1625 | 唉 1626 | 罢 1627 | 峰 1628 | 圆 1629 | 贼 1630 | 贿 1631 | 钱 1632 | 钳 1633 | 钻 1634 | 铁 1635 | 铃 1636 | 铅 1637 | 缺 1638 | 氧 1639 | 特 1640 | 牺 1641 | 造 1642 | 乘 1643 | 敌 1644 | 秤 1645 | 租 1646 | 积 1647 | 秧 1648 | 秩 1649 | 称 1650 | 秘 1651 | 透 1652 | 笔 1653 | 笑 1654 | 笋 1655 | 债 1656 | 借 1657 | 值 1658 | 倚 1659 | 倾 1660 | 倒 1661 | 倘 1662 | 俱 1663 | 倡 1664 | 候 1665 | 俯 1666 | 倍 1667 | 倦 1668 | 健 1669 | 臭 1670 | 射 1671 | 躬 1672 | 息 1673 | 徒 1674 | 徐 1675 | 舰 1676 | 舱 1677 | 般 1678 | 航 1679 | 途 1680 | 拿 1681 | 爹 1682 | 爱 1683 | 颂 1684 | 翁 1685 | 脆 1686 | 脂 1687 | 胸 1688 | 胳 1689 | 脏 1690 | 胶 1691 | 脑 1692 | 狸 1693 | 狼 1694 | 逢 1695 | 留 1696 | 皱 1697 | 饿 1698 | 恋 1699 | 桨 1700 | 浆 1701 | 衰 1702 | 高 1703 | 席 1704 | 准 1705 | 座 1706 | 脊 1707 | 症 1708 | 病 1709 | 疾 1710 | 疼 1711 | 疲 1712 | 效 1713 | 离 1714 | 唐 1715 | 资 1716 | 凉 1717 | 站 1718 | 剖 1719 | 竞 1720 | 部 1721 | 旁 1722 | 旅 1723 | 畜 1724 | 阅 1725 | 羞 1726 | 瓶 1727 | 拳 1728 | 粉 1729 | 料 1730 | 益 1731 | 兼 1732 | 烤 1733 | 烘 1734 | 烦 1735 | 烧 1736 | 烛 1737 | 烟 1738 | 递 1739 | 涛 1740 | 浙 1741 | 涝 1742 | 酒 1743 | 涉 1744 | 消 1745 | 浩 1746 | 海 1747 | 涂 1748 | 浴 1749 | 浮 1750 | 流 1751 | 润 1752 | 浪 1753 | 浸 1754 | 涨 1755 | 烫 1756 | 涌 1757 | 悟 1758 | 悄 1759 | 悔 1760 | 悦 1761 | 害 1762 | 宽 1763 | 家 1764 | 宵 1765 | 宴 1766 | 宾 1767 | 窄 1768 | 容 1769 | 宰 1770 | 案 1771 | 请 1772 | 朗 1773 | 诸 1774 | 读 1775 | 扇 1776 | 袜 1777 | 袖 1778 | 袍 1779 | 被 1780 | 祥 1781 | 课 1782 | 谁 1783 | 调 1784 | 冤 1785 | 谅 1786 | 谈 1787 | 谊 1788 | 剥 1789 | 恳 1790 | 展 1791 | 剧 1792 | 屑 1793 | 弱 1794 | 陵 1795 | 陶 1796 | 陷 1797 | 陪 1798 | 娱 1799 | 娘 1800 | 通 1801 | 能 1802 | 难 1803 | 预 1804 | 桑 1805 | 绢 1806 | 绣 1807 | 验 1808 | 继 1809 | 球 1810 | 理 1811 | 捧 1812 | 堵 1813 | 描 1814 | 域 1815 | 掩 1816 | 捷 1817 | 排 1818 | 掉 1819 | 堆 1820 | 推 1821 | 掀 1822 | 授 1823 | 教 1824 | 掏 1825 | 掠 1826 | 培 1827 | 接 1828 | 控 1829 | 探 1830 | 据 1831 | 掘 1832 | 职 1833 | 基 1834 | 著 1835 | 勒 1836 | 黄 1837 | 萌 1838 | 萝 1839 | 菌 1840 | 菜 1841 | 萄 1842 | 菊 1843 | 萍 1844 | 菠 1845 | 营 1846 | 械 1847 | 梦 1848 | 梢 1849 | 梅 1850 | 检 1851 | 梳 1852 | 梯 1853 | 桶 1854 | 救 1855 | 副 1856 | 票 1857 | 戚 1858 | 爽 1859 | 聋 1860 | 袭 1861 | 盛 1862 | 雪 1863 | 辅 1864 | 辆 1865 | 虚 1866 | 雀 1867 | 堂 1868 | 常 1869 | 匙 1870 | 晨 1871 | 睁 1872 | 眯 1873 | 眼 1874 | 悬 1875 | 野 1876 | 啦 1877 | 晚 1878 | 啄 1879 | 距 1880 | 跃 1881 | 略 1882 | 蛇 1883 | 累 1884 | 唱 1885 | 患 1886 | 唯 1887 | 崖 1888 | 崭 1889 | 崇 1890 | 圈 1891 | 铜 1892 | 铲 1893 | 银 1894 | 甜 1895 | 梨 1896 | 犁 1897 | 移 1898 | 笨 1899 | 笼 1900 | 笛 1901 | 符 1902 | 第 1903 | 敏 1904 | 做 1905 | 袋 1906 | 悠 1907 | 偿 1908 | 偶 1909 | 偷 1910 | 您 1911 | 售 1912 | 停 1913 | 偏 1914 | 假 1915 | 得 1916 | 衔 1917 | 盘 1918 | 船 1919 | 斜 1920 | 盒 1921 | 鸽 1922 | 悉 1923 | 欲 1924 | 彩 1925 | 领 1926 | 脚 1927 | 脖 1928 | 脸 1929 | 脱 1930 | 象 1931 | 够 1932 | 猜 1933 | 猪 1934 | 猎 1935 | 猫 1936 | 猛 1937 | 馅 1938 | 馆 1939 | 凑 1940 | 减 1941 | 毫 1942 | 麻 1943 | 痒 1944 | 痕 1945 | 廊 1946 | 康 1947 | 庸 1948 | 鹿 1949 | 盗 1950 | 章 1951 | 竟 1952 | 商 1953 | 族 1954 | 旋 1955 | 望 1956 | 率 1957 | 着 1958 | 盖 1959 | 粘 1960 | 粗 1961 | 粒 1962 | 断 1963 | 剪 1964 | 兽 1965 | 清 1966 | 添 1967 | 淋 1968 | 淹 1969 | 渠 1970 | 渐 1971 | 混 1972 | 渔 1973 | 淘 1974 | 液 1975 | 淡 1976 | 深 1977 | 婆 1978 | 梁 1979 | 渗 1980 | 情 1981 | 惜 1982 | 惭 1983 | 悼 1984 | 惧 1985 | 惕 1986 | 惊 1987 | 惨 1988 | 惯 1989 | 寇 1990 | 寄 1991 | 宿 1992 | 窑 1993 | 密 1994 | 谋 1995 | 谎 1996 | 祸 1997 | 谜 1998 | 逮 1999 | 敢 2000 | 屠 2001 | 弹 2002 | 随 2003 | 蛋 2004 | 隆 2005 | 隐 2006 | 婚 2007 | 婶 2008 | 颈 2009 | 绩 2010 | 绪 2011 | 续 2012 | 骑 2013 | 绳 2014 | 维 2015 | 绵 2016 | 绸 2017 | 绿 2018 | 琴 2019 | 斑 2020 | 替 2021 | 款 2022 | 堪 2023 | 搭 2024 | 塔 2025 | 越 2026 | 趁 2027 | 趋 2028 | 超 2029 | 提 2030 | 堤 2031 | 博 2032 | 揭 2033 | 喜 2034 | 插 2035 | 揪 2036 | 搜 2037 | 煮 2038 | 援 2039 | 裁 2040 | 搁 2041 | 搂 2042 | 搅 2043 | 握 2044 | 揉 2045 | 斯 2046 | 期 2047 | 欺 2048 | 联 2049 | 散 2050 | 惹 2051 | 葬 2052 | 葛 2053 | 董 2054 | 葡 2055 | 敬 2056 | 葱 2057 | 落 2058 | 朝 2059 | 辜 2060 | 葵 2061 | 棒 2062 | 棋 2063 | 植 2064 | 森 2065 | 椅 2066 | 椒 2067 | 棵 2068 | 棍 2069 | 棉 2070 | 棚 2071 | 棕 2072 | 惠 2073 | 惑 2074 | 逼 2075 | 厨 2076 | 厦 2077 | 硬 2078 | 确 2079 | 雁 2080 | 殖 2081 | 裂 2082 | 雄 2083 | 暂 2084 | 雅 2085 | 辈 2086 | 悲 2087 | 紫 2088 | 辉 2089 | 敞 2090 | 赏 2091 | 掌 2092 | 晴 2093 | 暑 2094 | 最 2095 | 量 2096 | 喷 2097 | 晶 2098 | 喇 2099 | 遇 2100 | 喊 2101 | 景 2102 | 践 2103 | 跌 2104 | 跑 2105 | 遗 2106 | 蛙 2107 | 蛛 2108 | 蜓 2109 | 喝 2110 | 喂 2111 | 喘 2112 | 喉 2113 | 幅 2114 | 帽 2115 | 赌 2116 | 赔 2117 | 黑 2118 | 铸 2119 | 铺 2120 | 链 2121 | 销 2122 | 锁 2123 | 锄 2124 | 锅 2125 | 锈 2126 | 锋 2127 | 锐 2128 | 短 2129 | 智 2130 | 毯 2131 | 鹅 2132 | 剩 2133 | 稍 2134 | 程 2135 | 稀 2136 | 税 2137 | 筐 2138 | 等 2139 | 筑 2140 | 策 2141 | 筛 2142 | 筒 2143 | 答 2144 | 筋 2145 | 筝 2146 | 傲 2147 | 傅 2148 | 牌 2149 | 堡 2150 | 集 2151 | 焦 2152 | 傍 2153 | 储 2154 | 奥 2155 | 街 2156 | 惩 2157 | 御 2158 | 循 2159 | 艇 2160 | 舒 2161 | 番 2162 | 释 2163 | 禽 2164 | 腊 2165 | 脾 2166 | 腔 2167 | 鲁 2168 | 猾 2169 | 猴 2170 | 然 2171 | 馋 2172 | 装 2173 | 蛮 2174 | 就 2175 | 痛 2176 | 童 2177 | 阔 2178 | 善 2179 | 羡 2180 | 普 2181 | 粪 2182 | 尊 2183 | 道 2184 | 曾 2185 | 焰 2186 | 港 2187 | 湖 2188 | 渣 2189 | 湿 2190 | 温 2191 | 渴 2192 | 滑 2193 | 湾 2194 | 渡 2195 | 游 2196 | 滋 2197 | 溉 2198 | 愤 2199 | 慌 2200 | 惰 2201 | 愧 2202 | 愉 2203 | 慨 2204 | 割 2205 | 寒 2206 | 富 2207 | 窜 2208 | 窝 2209 | 窗 2210 | 遍 2211 | 裕 2212 | 裤 2213 | 裙 2214 | 谢 2215 | 谣 2216 | 谦 2217 | 属 2218 | 屡 2219 | 强 2220 | 粥 2221 | 疏 2222 | 隔 2223 | 隙 2224 | 絮 2225 | 嫂 2226 | 登 2227 | 缎 2228 | 缓 2229 | 编 2230 | 骗 2231 | 缘 2232 | 瑞 2233 | 魂 2234 | 肆 2235 | 摄 2236 | 摸 2237 | 填 2238 | 搏 2239 | 塌 2240 | 鼓 2241 | 摆 2242 | 携 2243 | 搬 2244 | 摇 2245 | 搞 2246 | 塘 2247 | 摊 2248 | 蒜 2249 | 勤 2250 | 鹊 2251 | 蓝 2252 | 墓 2253 | 幕 2254 | 蓬 2255 | 蓄 2256 | 蒙 2257 | 蒸 2258 | 献 2259 | 禁 2260 | 楚 2261 | 想 2262 | 槐 2263 | 榆 2264 | 楼 2265 | 概 2266 | 赖 2267 | 酬 2268 | 感 2269 | 碍 2270 | 碑 2271 | 碎 2272 | 碰 2273 | 碗 2274 | 碌 2275 | 雷 2276 | 零 2277 | 雾 2278 | 雹 2279 | 输 2280 | 督 2281 | 龄 2282 | 鉴 2283 | 睛 2284 | 睡 2285 | 睬 2286 | 鄙 2287 | 愚 2288 | 暖 2289 | 盟 2290 | 歇 2291 | 暗 2292 | 照 2293 | 跨 2294 | 跳 2295 | 跪 2296 | 路 2297 | 跟 2298 | 遣 2299 | 蛾 2300 | 蜂 2301 | 嗓 2302 | 置 2303 | 罪 2304 | 罩 2305 | 错 2306 | 锡 2307 | 锣 2308 | 锤 2309 | 锦 2310 | 键 2311 | 锯 2312 | 矮 2313 | 辞 2314 | 稠 2315 | 愁 2316 | 筹 2317 | 签 2318 | 简 2319 | 毁 2320 | 舅 2321 | 鼠 2322 | 催 2323 | 傻 2324 | 像 2325 | 躲 2326 | 微 2327 | 愈 2328 | 遥 2329 | 腰 2330 | 腥 2331 | 腹 2332 | 腾 2333 | 腿 2334 | 触 2335 | 解 2336 | 酱 2337 | 痰 2338 | 廉 2339 | 新 2340 | 韵 2341 | 意 2342 | 粮 2343 | 数 2344 | 煎 2345 | 塑 2346 | 慈 2347 | 煤 2348 | 煌 2349 | 满 2350 | 漠 2351 | 源 2352 | 滤 2353 | 滥 2354 | 滔 2355 | 溪 2356 | 溜 2357 | 滚 2358 | 滨 2359 | 粱 2360 | 滩 2361 | 慎 2362 | 誉 2363 | 塞 2364 | 谨 2365 | 福 2366 | 群 2367 | 殿 2368 | 辟 2369 | 障 2370 | 嫌 2371 | 嫁 2372 | 叠 2373 | 缝 2374 | 缠 2375 | 静 2376 | 碧 2377 | 璃 2378 | 墙 2379 | 撇 2380 | 嘉 2381 | 摧 2382 | 截 2383 | 誓 2384 | 境 2385 | 摘 2386 | 摔 2387 | 聚 2388 | 蔽 2389 | 慕 2390 | 暮 2391 | 蔑 2392 | 模 2393 | 榴 2394 | 榜 2395 | 榨 2396 | 歌 2397 | 遭 2398 | 酷 2399 | 酿 2400 | 酸 2401 | 磁 2402 | 愿 2403 | 需 2404 | 弊 2405 | 裳 2406 | 颗 2407 | 嗽 2408 | 蜻 2409 | 蜡 2410 | 蝇 2411 | 蜘 2412 | 赚 2413 | 锹 2414 | 锻 2415 | 舞 2416 | 稳 2417 | 算 2418 | 箩 2419 | 管 2420 | 僚 2421 | 鼻 2422 | 魄 2423 | 貌 2424 | 膜 2425 | 膊 2426 | 膀 2427 | 鲜 2428 | 疑 2429 | 馒 2430 | 裹 2431 | 敲 2432 | 豪 2433 | 膏 2434 | 遮 2435 | 腐 2436 | 瘦 2437 | 辣 2438 | 竭 2439 | 端 2440 | 旗 2441 | 精 2442 | 歉 2443 | 熄 2444 | 熔 2445 | 漆 2446 | 漂 2447 | 漫 2448 | 滴 2449 | 演 2450 | 漏 2451 | 慢 2452 | 寨 2453 | 赛 2454 | 察 2455 | 蜜 2456 | 谱 2457 | 嫩 2458 | 翠 2459 | 熊 2460 | 凳 2461 | 骡 2462 | 缩 2463 | 慧 2464 | 撕 2465 | 撒 2466 | 趣 2467 | 趟 2468 | 撑 2469 | 播 2470 | 撞 2471 | 撤 2472 | 增 2473 | 聪 2474 | 鞋 2475 | 蕉 2476 | 蔬 2477 | 横 2478 | 槽 2479 | 樱 2480 | 橡 2481 | 飘 2482 | 醋 2483 | 醉 2484 | 震 2485 | 霉 2486 | 瞒 2487 | 题 2488 | 暴 2489 | 瞎 2490 | 影 2491 | 踢 2492 | 踏 2493 | 踩 2494 | 踪 2495 | 蝶 2496 | 蝴 2497 | 嘱 2498 | 墨 2499 | 镇 2500 | 靠 2501 | 稻 2502 | 黎 2503 | 稿 2504 | 稼 2505 | 箱 2506 | 箭 2507 | 篇 2508 | 僵 2509 | 躺 2510 | 僻 2511 | 德 2512 | 艘 2513 | 膝 2514 | 膛 2515 | 熟 2516 | 摩 2517 | 颜 2518 | 毅 2519 | 糊 2520 | 遵 2521 | 潜 2522 | 潮 2523 | 懂 2524 | 额 2525 | 慰 2526 | 劈 2527 | 操 2528 | 燕 2529 | 薯 2530 | 薪 2531 | 薄 2532 | 颠 2533 | 橘 2534 | 整 2535 | 融 2536 | 醒 2537 | 餐 2538 | 嘴 2539 | 蹄 2540 | 器 2541 | 赠 2542 | 默 2543 | 镜 2544 | 赞 2545 | 篮 2546 | 邀 2547 | 衡 2548 | 膨 2549 | 雕 2550 | 磨 2551 | 凝 2552 | 辨 2553 | 辩 2554 | 糖 2555 | 糕 2556 | 燃 2557 | 澡 2558 | 激 2559 | 懒 2560 | 壁 2561 | 避 2562 | 缴 2563 | 戴 2564 | 擦 2565 | 鞠 2566 | 藏 2567 | 霜 2568 | 霞 2569 | 瞧 2570 | 蹈 2571 | 螺 2572 | 穗 2573 | 繁 2574 | 辫 2575 | 赢 2576 | 糟 2577 | 糠 2578 | 燥 2579 | 臂 2580 | 翼 2581 | 骤 2582 | 鞭 2583 | 覆 2584 | 蹦 2585 | 镰 2586 | 翻 2587 | 鹰 2588 | 警 2589 | 攀 2590 | 蹲 2591 | 颤 2592 | 瓣 2593 | 爆 2594 | 疆 2595 | 壤 2596 | 耀 2597 | 躁 2598 | 嚼 2599 | 嚷 2600 | 籍 2601 | 魔 2602 | 灌 2603 | 蠢 2604 | 霸 2605 | 露 2606 | 囊 2607 | 罐 2608 | 匕 2609 | 刁 2610 | 丐 2611 | 歹 2612 | 戈 2613 | 夭 2614 | 仑 2615 | 讥 2616 | 冗 2617 | 邓 2618 | 艾 2619 | 夯 2620 | 凸 2621 | 卢 2622 | 叭 2623 | 叽 2624 | 皿 2625 | 凹 2626 | 囚 2627 | 矢 2628 | 乍 2629 | 尔 2630 | 冯 2631 | 玄 2632 | 邦 2633 | 迂 2634 | 邢 2635 | 芋 2636 | 芍 2637 | 吏 2638 | 夷 2639 | 吁 2640 | 吕 2641 | 吆 2642 | 屹 2643 | 廷 2644 | 迄 2645 | 臼 2646 | 仲 2647 | 伦 2648 | 伊 2649 | 肋 2650 | 旭 2651 | 匈 2652 | 凫 2653 | 妆 2654 | 亥 2655 | 汛 2656 | 讳 2657 | 讶 2658 | 讹 2659 | 讼 2660 | 诀 2661 | 弛 2662 | 阱 2663 | 驮 2664 | 驯 2665 | 纫 2666 | 玖 2667 | 玛 2668 | 韧 2669 | 抠 2670 | 扼 2671 | 汞 2672 | 扳 2673 | 抡 2674 | 坎 2675 | 坞 2676 | 抑 2677 | 拟 2678 | 抒 2679 | 芙 2680 | 芜 2681 | 苇 2682 | 芥 2683 | 芯 2684 | 芭 2685 | 杖 2686 | 杉 2687 | 巫 2688 | 杈 2689 | 甫 2690 | 匣 2691 | 轩 2692 | 卤 2693 | 肖 2694 | 吱 2695 | 吠 2696 | 呕 2697 | 呐 2698 | 吟 2699 | 呛 2700 | 吻 2701 | 吭 2702 | 邑 2703 | 囤 2704 | 吮 2705 | 岖 2706 | 牡 2707 | 佑 2708 | 佃 2709 | 伺 2710 | 囱 2711 | 肛 2712 | 肘 2713 | 甸 2714 | 狈 2715 | 鸠 2716 | 彤 2717 | 灸 2718 | 刨 2719 | 庇 2720 | 吝 2721 | 庐 2722 | 闰 2723 | 兑 2724 | 灼 2725 | 沐 2726 | 沛 2727 | 汰 2728 | 沥 2729 | 沦 2730 | 汹 2731 | 沧 2732 | 沪 2733 | 忱 2734 | 诅 2735 | 诈 2736 | 罕 2737 | 屁 2738 | 坠 2739 | 妓 2740 | 姊 2741 | 妒 2742 | 纬 2743 | 玫 2744 | 卦 2745 | 坷 2746 | 坯 2747 | 拓 2748 | 坪 2749 | 坤 2750 | 拄 2751 | 拧 2752 | 拂 2753 | 拙 2754 | 拇 2755 | 拗 2756 | 茉 2757 | 昔 2758 | 苛 2759 | 苫 2760 | 苟 2761 | 苞 2762 | 茁 2763 | 苔 2764 | 枉 2765 | 枢 2766 | 枚 2767 | 枫 2768 | 杭 2769 | 郁 2770 | 矾 2771 | 奈 2772 | 奄 2773 | 殴 2774 | 歧 2775 | 卓 2776 | 昙 2777 | 哎 2778 | 咕 2779 | 呵 2780 | 咙 2781 | 呻 2782 | 咒 2783 | 咆 2784 | 咖 2785 | 帕 2786 | 账 2787 | 贬 2788 | 贮 2789 | 氛 2790 | 秉 2791 | 岳 2792 | 侠 2793 | 侥 2794 | 侣 2795 | 侈 2796 | 卑 2797 | 刽 2798 | 刹 2799 | 肴 2800 | 觅 2801 | 忿 2802 | 瓮 2803 | 肮 2804 | 肪 2805 | 狞 2806 | 庞 2807 | 疟 2808 | 疙 2809 | 疚 2810 | 卒 2811 | 氓 2812 | 炬 2813 | 沽 2814 | 沮 2815 | 泣 2816 | 泞 2817 | 泌 2818 | 沼 2819 | 怔 2820 | 怯 2821 | 宠 2822 | 宛 2823 | 衩 2824 | 祈 2825 | 诡 2826 | 帚 2827 | 屉 2828 | 弧 2829 | 弥 2830 | 陋 2831 | 陌 2832 | 函 2833 | 姆 2834 | 虱 2835 | 叁 2836 | 绅 2837 | 驹 2838 | 绊 2839 | 绎 2840 | 契 2841 | 贰 2842 | 玷 2843 | 玲 2844 | 珊 2845 | 拭 2846 | 拷 2847 | 拱 2848 | 挟 2849 | 垢 2850 | 垛 2851 | 拯 2852 | 荆 2853 | 茸 2854 | 茬 2855 | 荚 2856 | 茵 2857 | 茴 2858 | 荞 2859 | 荠 2860 | 荤 2861 | 荧 2862 | 荔 2863 | 栈 2864 | 柑 2865 | 栅 2866 | 柠 2867 | 枷 2868 | 勃 2869 | 柬 2870 | 砂 2871 | 泵 2872 | 砚 2873 | 鸥 2874 | 轴 2875 | 韭 2876 | 虐 2877 | 昧 2878 | 盹 2879 | 咧 2880 | 昵 2881 | 昭 2882 | 盅 2883 | 勋 2884 | 哆 2885 | 咪 2886 | 哟 2887 | 幽 2888 | 钙 2889 | 钝 2890 | 钠 2891 | 钦 2892 | 钧 2893 | 钮 2894 | 毡 2895 | 氢 2896 | 秕 2897 | 俏 2898 | 俄 2899 | 俐 2900 | 侯 2901 | 徊 2902 | 衍 2903 | 胚 2904 | 胧 2905 | 胎 2906 | 狰 2907 | 饵 2908 | 峦 2909 | 奕 2910 | 咨 2911 | 飒 2912 | 闺 2913 | 闽 2914 | 籽 2915 | 娄 2916 | 烁 2917 | 炫 2918 | 洼 2919 | 柒 2920 | 涎 2921 | 洛 2922 | 恃 2923 | 恍 2924 | 恬 2925 | 恤 2926 | 宦 2927 | 诫 2928 | 诬 2929 | 祠 2930 | 诲 2931 | 屏 2932 | 屎 2933 | 逊 2934 | 陨 2935 | 姚 2936 | 娜 2937 | 蚤 2938 | 骇 2939 | 耘 2940 | 耙 2941 | 秦 2942 | 匿 2943 | 埂 2944 | 捂 2945 | 捍 2946 | 袁 2947 | 捌 2948 | 挫 2949 | 挚 2950 | 捣 2951 | 捅 2952 | 埃 2953 | 耿 2954 | 聂 2955 | 荸 2956 | 莽 2957 | 莱 2958 | 莉 2959 | 莹 2960 | 莺 2961 | 梆 2962 | 栖 2963 | 桦 2964 | 栓 2965 | 桅 2966 | 桩 2967 | 贾 2968 | 酌 2969 | 砸 2970 | 砰 2971 | 砾 2972 | 殉 2973 | 逞 2974 | 哮 2975 | 唠 2976 | 哺 2977 | 剔 2978 | 蚌 2979 | 蚜 2980 | 畔 2981 | 蚣 2982 | 蚪 2983 | 蚓 2984 | 哩 2985 | 圃 2986 | 鸯 2987 | 唁 2988 | 哼 2989 | 唆 2990 | 峭 2991 | 唧 2992 | 峻 2993 | 赂 2994 | 赃 2995 | 钾 2996 | 铆 2997 | 氨 2998 | 秫 2999 | 笆 3000 | 俺 3001 | 赁 3002 | 倔 3003 | 殷 3004 | 耸 3005 | 舀 3006 | 豺 3007 | 豹 3008 | 颁 3009 | 胯 3010 | 胰 3011 | 脐 3012 | 脓 3013 | 逛 3014 | 卿 3015 | 鸵 3016 | 鸳 3017 | 馁 3018 | 凌 3019 | 凄 3020 | 衷 3021 | 郭 3022 | 斋 3023 | 疹 3024 | 紊 3025 | 瓷 3026 | 羔 3027 | 烙 3028 | 浦 3029 | 涡 3030 | 涣 3031 | 涤 3032 | 涧 3033 | 涕 3034 | 涩 3035 | 悍 3036 | 悯 3037 | 窍 3038 | 诺 3039 | 诽 3040 | 袒 3041 | 谆 3042 | 祟 3043 | 恕 3044 | 娩 3045 | 骏 3046 | 琐 3047 | 麸 3048 | 琉 3049 | 琅 3050 | 措 3051 | 捺 3052 | 捶 3053 | 赦 3054 | 埠 3055 | 捻 3056 | 掐 3057 | 掂 3058 | 掖 3059 | 掷 3060 | 掸 3061 | 掺 3062 | 勘 3063 | 聊 3064 | 娶 3065 | 菱 3066 | 菲 3067 | 萎 3068 | 菩 3069 | 萤 3070 | 乾 3071 | 萧 3072 | 萨 3073 | 菇 3074 | 彬 3075 | 梗 3076 | 梧 3077 | 梭 3078 | 曹 3079 | 酝 3080 | 酗 3081 | 厢 3082 | 硅 3083 | 硕 3084 | 奢 3085 | 盔 3086 | 匾 3087 | 颅 3088 | 彪 3089 | 眶 3090 | 晤 3091 | 曼 3092 | 晦 3093 | 冕 3094 | 啡 3095 | 畦 3096 | 趾 3097 | 啃 3098 | 蛆 3099 | 蚯 3100 | 蛉 3101 | 蛀 3102 | 唬 3103 | 啰 3104 | 唾 3105 | 啤 3106 | 啥 3107 | 啸 3108 | 崎 3109 | 逻 3110 | 崔 3111 | 崩 3112 | 婴 3113 | 赊 3114 | 铐 3115 | 铛 3116 | 铝 3117 | 铡 3118 | 铣 3119 | 铭 3120 | 矫 3121 | 秸 3122 | 秽 3123 | 笙 3124 | 笤 3125 | 偎 3126 | 傀 3127 | 躯 3128 | 兜 3129 | 衅 3130 | 徘 3131 | 徙 3132 | 舶 3133 | 舷 3134 | 舵 3135 | 敛 3136 | 翎 3137 | 脯 3138 | 逸 3139 | 凰 3140 | 猖 3141 | 祭 3142 | 烹 3143 | 庶 3144 | 庵 3145 | 痊 3146 | 阎 3147 | 阐 3148 | 眷 3149 | 焊 3150 | 焕 3151 | 鸿 3152 | 涯 3153 | 淑 3154 | 淌 3155 | 淮 3156 | 淆 3157 | 渊 3158 | 淫 3159 | 淳 3160 | 淤 3161 | 淀 3162 | 涮 3163 | 涵 3164 | 惦 3165 | 悴 3166 | 惋 3167 | 寂 3168 | 窒 3169 | 谍 3170 | 谐 3171 | 裆 3172 | 袱 3173 | 祷 3174 | 谒 3175 | 谓 3176 | 谚 3177 | 尉 3178 | 堕 3179 | 隅 3180 | 婉 3181 | 颇 3182 | 绰 3183 | 绷 3184 | 综 3185 | 绽 3186 | 缀 3187 | 巢 3188 | 琳 3189 | 琢 3190 | 琼 3191 | 揍 3192 | 堰 3193 | 揩 3194 | 揽 3195 | 揖 3196 | 彭 3197 | 揣 3198 | 搀 3199 | 搓 3200 | 壹 3201 | 搔 3202 | 葫 3203 | 募 3204 | 蒋 3205 | 蒂 3206 | 韩 3207 | 棱 3208 | 椰 3209 | 焚 3210 | 椎 3211 | 棺 3212 | 榔 3213 | 椭 3214 | 粟 3215 | 棘 3216 | 酣 3217 | 酥 3218 | 硝 3219 | 硫 3220 | 颊 3221 | 雳 3222 | 翘 3223 | 凿 3224 | 棠 3225 | 晰 3226 | 鼎 3227 | 喳 3228 | 遏 3229 | 晾 3230 | 畴 3231 | 跋 3232 | 跛 3233 | 蛔 3234 | 蜒 3235 | 蛤 3236 | 鹃 3237 | 喻 3238 | 啼 3239 | 喧 3240 | 嵌 3241 | 赋 3242 | 赎 3243 | 赐 3244 | 锉 3245 | 锌 3246 | 甥 3247 | 掰 3248 | 氮 3249 | 氯 3250 | 黍 3251 | 筏 3252 | 牍 3253 | 粤 3254 | 逾 3255 | 腌 3256 | 腋 3257 | 腕 3258 | 猩 3259 | 猬 3260 | 惫 3261 | 敦 3262 | 痘 3263 | 痢 3264 | 痪 3265 | 竣 3266 | 翔 3267 | 奠 3268 | 遂 3269 | 焙 3270 | 滞 3271 | 湘 3272 | 渤 3273 | 渺 3274 | 溃 3275 | 溅 3276 | 湃 3277 | 愕 3278 | 惶 3279 | 寓 3280 | 窖 3281 | 窘 3282 | 雇 3283 | 谤 3284 | 犀 3285 | 隘 3286 | 媒 3287 | 媚 3288 | 婿 3289 | 缅 3290 | 缆 3291 | 缔 3292 | 缕 3293 | 骚 3294 | 瑟 3295 | 鹉 3296 | 瑰 3297 | 搪 3298 | 聘 3299 | 斟 3300 | 靴 3301 | 靶 3302 | 蓖 3303 | 蒿 3304 | 蒲 3305 | 蓉 3306 | 楔 3307 | 椿 3308 | 楷 3309 | 榄 3310 | 楞 3311 | 楣 3312 | 酪 3313 | 碘 3314 | 硼 3315 | 碉 3316 | 辐 3317 | 辑 3318 | 频 3319 | 睹 3320 | 睦 3321 | 瞄 3322 | 嗜 3323 | 嗦 3324 | 暇 3325 | 畸 3326 | 跷 3327 | 跺 3328 | 蜈 3329 | 蜗 3330 | 蜕 3331 | 蛹 3332 | 嗅 3333 | 嗡 3334 | 嗤 3335 | 署 3336 | 蜀 3337 | 幌 3338 | 锚 3339 | 锥 3340 | 锨 3341 | 锭 3342 | 锰 3343 | 稚 3344 | 颓 3345 | 筷 3346 | 魁 3347 | 衙 3348 | 腻 3349 | 腮 3350 | 腺 3351 | 鹏 3352 | 肄 3353 | 猿 3354 | 颖 3355 | 煞 3356 | 雏 3357 | 馍 3358 | 馏 3359 | 禀 3360 | 痹 3361 | 廓 3362 | 痴 3363 | 靖 3364 | 誊 3365 | 漓 3366 | 溢 3367 | 溯 3368 | 溶 3369 | 滓 3370 | 溺 3371 | 寞 3372 | 窥 3373 | 窟 3374 | 寝 3375 | 褂 3376 | 裸 3377 | 谬 3378 | 媳 3379 | 嫉 3380 | 缚 3381 | 缤 3382 | 剿 3383 | 赘 3384 | 熬 3385 | 赫 3386 | 蔫 3387 | 摹 3388 | 蔓 3389 | 蔗 3390 | 蔼 3391 | 熙 3392 | 蔚 3393 | 兢 3394 | 榛 3395 | 榕 3396 | 酵 3397 | 碟 3398 | 碴 3399 | 碱 3400 | 碳 3401 | 辕 3402 | 辖 3403 | 雌 3404 | 墅 3405 | 嘁 3406 | 踊 3407 | 蝉 3408 | 嘀 3409 | 幔 3410 | 镀 3411 | 舔 3412 | 熏 3413 | 箍 3414 | 箕 3415 | 箫 3416 | 舆 3417 | 僧 3418 | 孵 3419 | 瘩 3420 | 瘟 3421 | 彰 3422 | 粹 3423 | 漱 3424 | 漩 3425 | 漾 3426 | 慷 3427 | 寡 3428 | 寥 3429 | 谭 3430 | 褐 3431 | 褪 3432 | 隧 3433 | 嫡 3434 | 缨 3435 | 撵 3436 | 撩 3437 | 撮 3438 | 撬 3439 | 擒 3440 | 墩 3441 | 撰 3442 | 鞍 3443 | 蕊 3444 | 蕴 3445 | 樊 3446 | 樟 3447 | 橄 3448 | 敷 3449 | 豌 3450 | 醇 3451 | 磕 3452 | 磅 3453 | 碾 3454 | 憋 3455 | 嘶 3456 | 嘲 3457 | 嘹 3458 | 蝠 3459 | 蝎 3460 | 蝌 3461 | 蝗 3462 | 蝙 3463 | 嘿 3464 | 幢 3465 | 镊 3466 | 镐 3467 | 稽 3468 | 篓 3469 | 膘 3470 | 鲤 3471 | 鲫 3472 | 褒 3473 | 瘪 3474 | 瘤 3475 | 瘫 3476 | 凛 3477 | 澎 3478 | 潭 3479 | 潦 3480 | 澳 3481 | 潘 3482 | 澈 3483 | 澜 3484 | 澄 3485 | 憔 3486 | 懊 3487 | 憎 3488 | 翩 3489 | 褥 3490 | 谴 3491 | 鹤 3492 | 憨 3493 | 履 3494 | 嬉 3495 | 豫 3496 | 缭 3497 | 撼 3498 | 擂 3499 | 擅 3500 | 蕾 3501 | 薛 3502 | 薇 3503 | 擎 3504 | 翰 3505 | 噩 3506 | 橱 3507 | 橙 3508 | 瓢 3509 | 蟥 3510 | 霍 3511 | 霎 3512 | 辙 3513 | 冀 3514 | 踱 3515 | 蹂 3516 | 蟆 3517 | 螃 3518 | 螟 3519 | 噪 3520 | 鹦 3521 | 黔 3522 | 穆 3523 | 篡 3524 | 篷 3525 | 篙 3526 | 篱 3527 | 儒 3528 | 膳 3529 | 鲸 3530 | 瘾 3531 | 瘸 3532 | 糙 3533 | 燎 3534 | 濒 3535 | 憾 3536 | 懈 3537 | 窿 3538 | 缰 3539 | 壕 3540 | 藐 3541 | 檬 3542 | 檐 3543 | 檩 3544 | 檀 3545 | 礁 3546 | 磷 3547 | 瞭 3548 | 瞬 3549 | 瞳 3550 | 瞪 3551 | 曙 3552 | 蹋 3553 | 蟋 3554 | 蟀 3555 | 嚎 3556 | 赡 3557 | 镣 3558 | 魏 3559 | 簇 3560 | 儡 3561 | 徽 3562 | 爵 3563 | 朦 3564 | 臊 3565 | 鳄 3566 | 糜 3567 | 癌 3568 | 懦 3569 | 豁 3570 | 臀 3571 | 藕 3572 | 藤 3573 | 瞻 3574 | 嚣 3575 | 鳍 3576 | 癞 3577 | 瀑 3578 | 襟 3579 | 璧 3580 | 戳 3581 | 攒 3582 | 孽 3583 | 蘑 3584 | 藻 3585 | 鳖 3586 | 蹭 3587 | 蹬 3588 | 簸 3589 | 簿 3590 | 蟹 3591 | 靡 3592 | 癣 3593 | 羹 3594 | 鬓 3595 | 攘 3596 | 蠕 3597 | 巍 3598 | 鳞 3599 | 糯 3600 | 譬 3601 | 霹 3602 | 躏 3603 | 髓 3604 | 蘸 3605 | 镶 3606 | 瓤 3607 | 矗 -------------------------------------------------------------------------------- /data/target_vocab.txt: -------------------------------------------------------------------------------- 1 | 体育 2 | 房产 3 | 时政 4 | 游戏 5 | 股票 -------------------------------------------------------------------------------- /model/pytorch/cnn.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | 3 | 4 | class Model(nn.Module): 5 | def __init__(self, config): 6 | super().__init__() 7 | self.seq_length = config["seq_length"] 8 | self.batch_size = config["batch_size"] 9 | self.embedding_size = config["embedding_size"] 10 | self.vocab_size = config["vocab_size"] 11 | self.num_classes = config["num_classes"] 12 | self.filter_size = config["filter_size"] 13 | self.kernel_size = config["kernel_size"] 14 | self.opt_name = config["opt_name"] 15 | self.lr = config["learning_rate"] 16 | self.dropout_keep_prob = config["dropout_keep_prob"] 17 | self.model_class = config["model_class"] 18 | 19 | self.embed = nn.Embedding(self.vocab_size, self.embedding_size) 20 | 21 | self.conv2d = nn.Conv2d(1, self.filter_size, (self.kernel_size, self.embedding_size), padding=(2, 0)) 22 | self.max_pool2d = nn.MaxPool2d((1, self.seq_length)) 23 | 24 | self.conv1d_and_max_pool = nn.Sequential( 25 | nn.Conv1d(self.embedding_size, self.filter_size, self.kernel_size, padding=1), 26 | nn.MaxPool1d(self.seq_length) 27 | ) 28 | self.fc_and_softmax = nn.Sequential( 29 | nn.Linear(self.filter_size, self.num_classes), 30 | nn.Softmax(1) 31 | ) 32 | 33 | def forward(self, input_data): 34 | out = self.embed(input_data) 35 | if self.model_class == "conv2d": 36 | out = self.conv2d(out).squeeze() 37 | out = self.max_pool2d(out).squeeze() 38 | elif self.model_class == "conv1d": 39 | out = out.permute(0, 2, 1) 40 | out = self.conv1d_and_max_pool(out).squeeze() 41 | else: 42 | raise ValueError("model class is wrong!") 43 | out = self.fc_and_softmax(out) 44 | return out 45 | -------------------------------------------------------------------------------- /model/pytorch/rnn.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from torch.autograd import Variable 4 | 5 | USE_CUDA = torch.cuda.is_available() 6 | 7 | 8 | class Model(nn.Module): 9 | def __init__(self, config): 10 | super().__init__() 11 | self.seq_length = config["seq_length"] 12 | self.hidden_size = config["hidden_size"] 13 | self.num_layers = config["num_layers"] 14 | self.batch_size = config["batch_size"] 15 | self.embedding_size = config["embedding_size"] 16 | self.vocab_size = config["vocab_size"] 17 | self.num_classes = config["num_classes"] 18 | 19 | self.embed = nn.Embedding(self.vocab_size, self.embedding_size) 20 | self.rnn = nn.LSTM( 21 | input_size=self.embedding_size, 22 | hidden_size=self.hidden_size, 23 | num_layers=self.num_layers, 24 | batch_first=True 25 | ) 26 | self.fc_and_softmax = nn.Sequential( 27 | nn.Linear(self.seq_length * self.hidden_size, self.num_classes), 28 | nn.Softmax(1) 29 | ) 30 | 31 | def forward(self, input_data): 32 | out = self.embed(input_data) 33 | out = out.permute(1, 0, 2) 34 | hidden = Variable(torch.zeros(self.num_layers, self.seq_length, self.hidden_size)) 35 | context = Variable(torch.zeros(self.num_layers, self.seq_length, self.hidden_size)) 36 | if USE_CUDA: 37 | hidden = hidden.cuda() 38 | context = context.cuda() 39 | 40 | out, _ = self.rnn(out, (hidden, context)) # seq, batch, hidden 41 | out = out.permute(1, 0, 2) 42 | 43 | out = out.reshape(self.batch_size, self.seq_length * self.hidden_size) 44 | out = self.fc_and_softmax(out) 45 | return out 46 | -------------------------------------------------------------------------------- /model/sklearn/bayes.py: -------------------------------------------------------------------------------- 1 | from sklearn import naive_bayes 2 | from sklearn.feature_extraction.text import TfidfVectorizer 3 | 4 | 5 | class Model(object): 6 | def __init__(self, vocab=None): 7 | self.vec = TfidfVectorizer(vocabulary=vocab) 8 | 9 | def get_tfidf(self, data, run_type): 10 | if run_type in ["train", "test"]: 11 | term_doc = self.vec.fit_transform(data) 12 | elif run_type in ["validate"]: 13 | term_doc = self.vec.transform(data) 14 | else: 15 | raise ValueError 16 | return term_doc 17 | 18 | @staticmethod 19 | def multi_nb(): 20 | nb = naive_bayes.MultinomialNB() 21 | return nb 22 | -------------------------------------------------------------------------------- /model/sklearn/svm.py: -------------------------------------------------------------------------------- 1 | from sklearn import svm 2 | from sklearn.feature_extraction.text import TfidfVectorizer 3 | 4 | 5 | class Model(object): 6 | def __init__(self, vocab=None): 7 | self.vec = TfidfVectorizer(vocabulary=vocab) 8 | 9 | def get_tfidf(self, data, run_type): 10 | if run_type in ["train", "test"]: 11 | term_doc = self.vec.fit_transform(data) 12 | elif run_type in ["validate"]: 13 | term_doc = self.vec.transform(data) 14 | else: 15 | raise ValueError 16 | return term_doc 17 | 18 | @staticmethod 19 | def lin_svm(): 20 | lin_svm = svm.LinearSVC() 21 | return lin_svm 22 | -------------------------------------------------------------------------------- /model/tensorflow/cnn.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | 3 | 4 | class Model(object): 5 | def __init__(self, config): 6 | self.seq_length = config["seq_length"] 7 | self.embedding_size = config["embedding_size"] 8 | self.vocab_size = config["vocab_size"] 9 | self.num_classes = config["num_classes"] 10 | self.filter_size = config["filter_size"] 11 | self.kernel_size = config["kernel_size"] 12 | self.opt_name = config["opt_name"] 13 | self.lr = config["learning_rate"] 14 | self.dropout_keep_prob = config["dropout_keep_prob"] 15 | self.input_holder = tf.placeholder(tf.int32, [None, self.seq_length], "input_data") 16 | self.target_holder = tf.placeholder(tf.int32, [None, self.num_classes], "target_data") 17 | 18 | def cnn(self): 19 | # Embedding layer 20 | with tf.device("/cpu:0"), tf.name_scope("embedding_layer"): 21 | embedding = tf.Variable( 22 | tf.random_uniform([self.vocab_size, self.embedding_size], -1.0, 1.0), 23 | name="embedding" 24 | ) 25 | embedding_inputs = tf.nn.embedding_lookup(embedding, self.input_holder) 26 | 27 | # conv1d: inputs, filters, kernel_size 28 | # conv: [batch_size, seq_length, filters] 29 | conv_output = tf.layers.conv1d(embedding_inputs, self.filter_size, self.kernel_size, name="conv1d") 30 | # gmp: [batch_size, filters] 31 | gmp = tf.reduce_max(conv_output, reduction_indices=[1], name='gmp') 32 | # logits: [batch_size, num_classes] 33 | logits = tf.layers.dense(gmp, self.num_classes, name="fc") 34 | 35 | # dropout layer 36 | # 防止过拟合 37 | with tf.name_scope("dropout_layer"): 38 | dropout_logits = tf.nn.dropout(logits, self.dropout_keep_prob) 39 | 40 | cross_entropy = tf.nn.softmax_cross_entropy_with_logits_v2(logits=dropout_logits, labels=self.target_holder) 41 | 42 | loss = tf.reduce_mean(cross_entropy) 43 | tf.summary.scalar('loss', loss) 44 | if self.opt_name == "adam": 45 | train_step = tf.train.AdamOptimizer(self.lr).minimize(loss) 46 | else: 47 | train_step = tf.train.AdagradOptimizer(self.lr).minimize(loss) 48 | 49 | pred = tf.argmax(tf.nn.softmax(logits), 1) 50 | return train_step, pred, loss -------------------------------------------------------------------------------- /model/tensorflow_v2/cnn2.py: -------------------------------------------------------------------------------- 1 | from tensorflow import keras 2 | from tensorflow.keras import layers 3 | 4 | 5 | class Model(object): 6 | def __init__(self, config): 7 | self.seq_length = config["seq_length"] 8 | self.embedding_size = config["embedding_size"] 9 | self.vocab_size = config["vocab_size"] 10 | self.num_classes = config["num_classes"] 11 | self.filter_size = config["filter_size"] 12 | self.kernel_size = config["kernel_size"] 13 | self.opt_name = config["opt_name"] 14 | self.lr = config["learning_rate"] 15 | self.dropout_keep_prob = config["dropout_keep_prob"] 16 | 17 | def build(self): 18 | model = keras.Sequential([ 19 | layers.Embedding(input_dim=self.vocab_size, output_dim=self.embedding_size, input_length=self.seq_length), 20 | layers.Conv1D(filters=50, kernel_size=5, strides=1, padding='valid'), 21 | layers.MaxPool1D(2, padding='valid'), 22 | layers.Flatten(), 23 | layers.Dense(5, activation='relu'), 24 | layers.Softmax(1) 25 | ]) 26 | model.compile(optimizer=keras.optimizers.Adam(1e-3), 27 | loss=keras.losses.CategoricalCrossentropy(), 28 | metrics=['accuracy']) 29 | 30 | return model 31 | 32 | -------------------------------------------------------------------------------- /requirements/req-base.txt: -------------------------------------------------------------------------------- 1 | torch>=0.4.0 2 | Flask>=1.0.2 3 | PyYAML>=3.12 4 | numpy>=1.15.0 5 | tensorflow>=2.2.0 6 | tensorflow-gpu>=2.2.0 7 | tensorboard>=2.2.0 8 | scikit-learn>=0.19.0 9 | joblib>=0.15.1 -------------------------------------------------------------------------------- /requirements/req-tf1.txt: -------------------------------------------------------------------------------- 1 | tensorflow-gpu>=1.15.3 2 | scikit-learn>=0.23.1 3 | PyYAML>=5.3.1 -------------------------------------------------------------------------------- /run/pytorch.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | import torch 4 | import torch.nn as nn 5 | import torch.optim as optim 6 | from torch.autograd import Variable 7 | import numpy as np 8 | from sklearn import metrics 9 | 10 | from model.pytorch import cnn 11 | from model.pytorch import rnn 12 | from util import conf_utils 13 | from util import data_utils 14 | from util import batch_utils 15 | from util import output_utils 16 | 17 | parser = argparse.ArgumentParser() 18 | parser.add_argument("-r", "--run", default="train", help="run type") 19 | parser.add_argument("-c", "--config", default="./config/pytorch.yaml", help="run config") 20 | parser.add_argument("-m", "--model", default="cnn", help="model name") 21 | parser.add_argument("-d", "--date", default="", help="date file name") 22 | parser.add_argument("-t", "--text", default="", help="infer text") 23 | args = parser.parse_args() 24 | 25 | # 判断是否有GPU加速 26 | use_gpu = torch.cuda.is_available() 27 | print(f">> use gpu: {use_gpu}") 28 | 29 | 30 | def train(config_path): 31 | config = conf_utils.init_train_config(config_path) 32 | 33 | batch_size = config["batch_size"] 34 | epoch_size = config["epoch_size"] 35 | model_class = config["model_class"] 36 | print(f"\n>> model class is {model_class}") 37 | 38 | train_input, train_target, val_input, val_target = data_utils.gen_train_data(config) 39 | if args.model == "cnn": 40 | model = cnn.Model(config) 41 | elif args.model == "rnn": 42 | model = rnn.Model(config) 43 | else: 44 | raise Exception(f"error model: {args.model}") 45 | 46 | if use_gpu: 47 | model = model.cuda() 48 | 49 | criterion = nn.CrossEntropyLoss() 50 | optimizer = optim.SGD(model.parameters(), lr=config["learning_rate"]) 51 | 52 | for epoch in range(epoch_size): 53 | epoch = epoch + 1 54 | train_batch_gen = batch_utils.make_batch(train_input, train_target, batch_size) 55 | val_batch_gen = batch_utils.make_batch(val_input, val_target, batch_size) 56 | 57 | train_acc = 0 58 | val_acc = 0 59 | for batch_num in range(len(train_input) // batch_size): 60 | train_input_batch, train_target_batch = train_batch_gen.__next__() 61 | 62 | if args.model == "cnn" and model_class == "conv2d": 63 | train_input_batch_v = Variable(torch.LongTensor(np.expand_dims(train_input_batch, 1))) 64 | else: 65 | train_input_batch_v = Variable(torch.LongTensor(train_input_batch)) 66 | 67 | train_target_batch_v = Variable(torch.LongTensor(np.argmax(train_target_batch, 1))) 68 | 69 | if use_gpu: 70 | train_input_batch_v = train_input_batch_v.cuda() 71 | train_target_batch_v = train_target_batch_v.cuda() 72 | 73 | out = model(train_input_batch_v) 74 | loss = criterion(out, train_target_batch_v) 75 | _, pred = torch.max(out, 1) 76 | train_acc = (pred == train_target_batch_v).float().mean() 77 | 78 | # 后向传播 79 | optimizer.zero_grad() 80 | loss.backward() 81 | optimizer.step() 82 | 83 | if not batch_num % 10: 84 | with torch.no_grad(): 85 | val_input_batch, val_target_batch = val_batch_gen.__next__() 86 | if args.model == "cnn" and model_class == "conv2d": 87 | val_input_batch_v = Variable(torch.LongTensor(np.expand_dims(val_input_batch, 1))) 88 | else: 89 | val_input_batch_v = Variable(torch.LongTensor(val_input_batch)) 90 | 91 | val_target_batch_v = Variable(torch.LongTensor(np.argmax(val_target_batch, 1))) 92 | if use_gpu: 93 | val_input_batch_v = val_input_batch_v.cuda() 94 | val_target_batch_v = val_target_batch_v.cuda() 95 | val_out = model(val_input_batch_v) 96 | _, val_pred = torch.max(val_out, 1) 97 | val_acc = (val_pred == val_target_batch_v).float().mean() 98 | 99 | print(f">> e:{epoch:3} s:{batch_num:2} loss:{loss:5.4} train-acc:{train_acc:.4f} val-acc:{val_acc:.4f}") 100 | 101 | if epoch > 10 and train_acc >= 0.9 and val_acc >= 0.9: 102 | torch.save({ 103 | "epoch": epoch, 104 | "optimizer": optimizer.state_dict(), 105 | "model": model.state_dict(), 106 | "train_acc": train_acc 107 | }, config["model_path"] + f"{args.model}.pt") 108 | 109 | 110 | def test(config_path): 111 | config = conf_utils.init_test_config(config_path) 112 | 113 | batch_size = config["batch_size"] 114 | model_class = config["model_class"] 115 | if args.model == "cnn": 116 | print(f"\n>> model class is {model_class}") 117 | 118 | test_data, test_target = data_utils.gen_test_data(config) 119 | 120 | model = cnn.Model(config) 121 | if use_gpu: 122 | model = model.cuda() 123 | 124 | model.load_state_dict(torch.load(config["model_path"] + "cnn.pt", map_location=torch.device('cpu'))["model"]) 125 | 126 | test_batch_gen = batch_utils.make_batch(test_data, test_target, batch_size) 127 | 128 | pred_list = [] 129 | target_list = [] 130 | for batch_num in range(len(test_data) // batch_size): 131 | test_input_batch, test_target_batch = test_batch_gen.__next__() 132 | 133 | if args.model == "cnn" and model_class == "conv2d": 134 | test_input_batch_v = Variable(torch.LongTensor(np.expand_dims(test_input_batch, 1))) 135 | else: 136 | test_input_batch_v = Variable(torch.LongTensor(test_input_batch)) 137 | 138 | if use_gpu: 139 | test_input_batch_v = test_input_batch_v.cuda() 140 | 141 | # 向前传播 142 | out = model(test_input_batch_v) 143 | _, pred = torch.max(out, 1) 144 | if use_gpu: 145 | pred = pred.cpu().numpy() 146 | pred_list.extend(pred) 147 | target_list.extend([np.argmax(target) for target in test_target_batch]) 148 | 149 | report = metrics.classification_report(target_list, pred_list) 150 | print(f"\n>> REPORT:\n{report}") 151 | output_utils.save_metrics(config, "report.txt", report) 152 | 153 | cm = metrics.confusion_matrix(target_list, pred_list) 154 | print(f"\n>> Confusion Matrix:\n{cm}") 155 | output_utils.save_metrics(config, "confusion_matrix.txt", str(cm)) 156 | 157 | 158 | def infer(text): 159 | config = conf_utils.init_test_config("20-07-15_05-08-14") 160 | model_class = config["model_class"] 161 | 162 | model = cnn.Model(config) 163 | if use_gpu: 164 | model = model.cuda() 165 | 166 | model.load_state_dict(torch.load(config["model_path"] + "cnn.pt", map_location=torch.device('cpu'))["model"]) 167 | 168 | infer_input_batch, target_vocab = data_utils.gen_infer_data(config, text) 169 | if args.model == "cnn" and model_class == "conv2d": 170 | infer_input_v = Variable(torch.LongTensor(np.expand_dims(infer_input_batch, 1))) 171 | else: 172 | infer_input_v = Variable(torch.LongTensor(infer_input_batch)) 173 | 174 | if use_gpu: 175 | infer_input_v = infer_input_v.cuda() 176 | 177 | # 向前传播 178 | out = model(infer_input_v) 179 | _, pred = torch.max(out, 1) 180 | 181 | target = target_vocab[pred[0]] 182 | print(f"\n\n>> {text}: {target}") 183 | return target 184 | 185 | 186 | if __name__ == '__main__': 187 | if args.run == "train": 188 | train(args.config) 189 | elif args.run == "test": 190 | if args.date == "": 191 | raise ValueError("test need -d arg") 192 | else: 193 | test(args.date) 194 | elif args.run == "infer": 195 | if args.text == "": 196 | raise ValueError("infer need -t arg") 197 | else: 198 | infer(args.text) 199 | else: 200 | raise ValueError("The first parameter is wrong, only support train or test!") 201 | -------------------------------------------------------------------------------- /run/sklearn.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | import joblib 4 | from sklearn import metrics 5 | 6 | from util import data_utils 7 | from util import conf_utils 8 | from util import output_utils 9 | from model.sklearn import svm 10 | from model.sklearn import bayes 11 | 12 | parser = argparse.ArgumentParser() 13 | parser.add_argument("-r", "--run", default="train", help="run type") 14 | parser.add_argument("-c", "--config", default="./config/sklearn.yaml", help="run config") 15 | parser.add_argument("-m", "--model", default="svm", help="model name") 16 | parser.add_argument("-d", "--date", default="", help="date file name") 17 | parser.add_argument("-t", "--text", default="", help="infer text") 18 | args = parser.parse_args() 19 | 20 | 21 | def train(config_path): 22 | config = conf_utils.init_train_config(config_path) 23 | 24 | train_input, train_target, validate_input, validate_target = data_utils.gen_train_data(config) 25 | 26 | if args.model == "bayes": 27 | model = bayes.Model() 28 | train_term_doc = model.get_tfidf(train_input, "train") 29 | validate_term_doc = model.get_tfidf(validate_input, "validate") 30 | m = model.multi_nb() 31 | m.fit(train_term_doc, train_target) 32 | elif args.model == "svm": 33 | model = svm.Model() 34 | train_term_doc = model.get_tfidf(train_input, "train") 35 | validate_term_doc = model.get_tfidf(validate_input, "validate") 36 | m = model.lin_svm() 37 | m.fit(train_term_doc, train_target) 38 | else: 39 | raise Exception(f"error model name: {args.model}") 40 | 41 | # save vocab 42 | vocab = model.vec.vocabulary_ 43 | joblib.dump(vocab, config["model_path"] + "vocab.json") 44 | 45 | # save model 46 | joblib.dump(m, config["model_path"] + f"{args.model}.m") 47 | 48 | # validate 49 | validate_preds = m.predict(validate_term_doc) 50 | 51 | report = metrics.classification_report(validate_target, validate_preds) 52 | print(f"\n>> REPORT:\n{report}") 53 | 54 | cm = metrics.confusion_matrix(validate_target, validate_preds) 55 | print(f"\n>> Confusion Matrix:\n{cm}") 56 | 57 | 58 | def test(time_str): 59 | config = conf_utils.init_test_config(time_str) 60 | 61 | test_input, test_target = data_utils.gen_test_data(config) 62 | 63 | vocab = joblib.load(config["model_path"] + "vocab.json") 64 | 65 | model = bayes.Model(vocab) 66 | test_term_doc = model.get_tfidf(test_input, "test") 67 | 68 | m = joblib.load(config["model_path"] + f"{args.model}.m") 69 | 70 | test_preds = m.predict(test_term_doc) 71 | 72 | report = metrics.classification_report(test_target, test_preds) 73 | print(f"\n>> REPORT:\n{report}") 74 | output_utils.save_metrics(config, "report.txt", report) 75 | 76 | cm = metrics.confusion_matrix(test_target, test_preds) 77 | print(f"\n>> Confusion Matrix:\n{cm}") 78 | output_utils.save_metrics(config, "confusion_matrix.txt", str(cm)) 79 | 80 | 81 | if __name__ == '__main__': 82 | if args.run == "train": 83 | train(args.config) 84 | elif args.run == "test": 85 | if args.date == "": 86 | raise ValueError("test need -d arg") 87 | else: 88 | test(args.date) 89 | else: 90 | raise ValueError("The first parameter is wrong, only support train or test!") 91 | -------------------------------------------------------------------------------- /run/tensorflow.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | import numpy as np 4 | import tensorflow as tf 5 | from sklearn import metrics 6 | 7 | from util import data_utils 8 | from util import batch_utils 9 | from util import conf_utils 10 | from util import output_utils 11 | from model.tensorflow import cnn 12 | from model.tensorflow_v2 import cnn2 13 | 14 | parser = argparse.ArgumentParser() 15 | parser.add_argument("-r", "--run", default="train", help="run type") 16 | parser.add_argument("-c", "--config", default="./config/pytorch.yaml", help="run config") 17 | parser.add_argument("-m", "--model", default="cnn", help="model name") 18 | parser.add_argument("-d", "--date", default="", help="date file name") 19 | parser.add_argument("-t", "--text", default="", help="infer text") 20 | args = parser.parse_args() 21 | 22 | 23 | def train(config_path): 24 | config = conf_utils.init_train_config(config_path) 25 | batch_size = config["batch_size"] 26 | epoch_size = config["epoch_size"] 27 | num_save_epoch = config["num_save_epoch"] 28 | 29 | train_input, train_target, validate_input, validate_target = data_utils.gen_train_data(config) 30 | 31 | validate_input_batch = validate_input[:batch_size] 32 | validate_target_batch = validate_target[:batch_size] 33 | 34 | print(">> build model...") 35 | model = cnn.Model(config) 36 | train_step, pred, cost = model.cnn() 37 | 38 | with tf.Session() as sess: 39 | init = tf.global_variables_initializer() 40 | sess.run(init) 41 | 42 | saver = tf.train.Saver() 43 | 44 | merged = tf.summary.merge_all() 45 | train_writer = tf.summary.FileWriter(config["log_train_path"], sess.graph) 46 | 47 | max_val_acc = 0 48 | max_key = 0 49 | for epoch in range(epoch_size): 50 | epoch = epoch + 1 51 | batch_gen = batch_utils.make_batch(train_input, train_target, batch_size) 52 | for batch_num in range(len(train_input)//batch_size): 53 | train_input_batch, train_target_batch = batch_gen.__next__() 54 | 55 | _, loss, train_pred, summary = sess.run([train_step, cost, pred, merged], feed_dict={ 56 | model.input_holder: train_input_batch, 57 | model.target_holder: train_target_batch 58 | }) 59 | train_writer.add_summary(summary) 60 | 61 | if not batch_num % 5: 62 | input_train_arr = np.argmax(train_target_batch, 1) 63 | target_train_arr = np.array(train_pred) 64 | acc_train = np.sum(input_train_arr == target_train_arr)*100/len(input_train_arr) 65 | 66 | validate_pred = sess.run([pred], feed_dict={ 67 | model.input_holder: validate_input_batch, 68 | model.target_holder: validate_target_batch 69 | }) 70 | input_validate_arr = np.argmax(validate_target_batch, 1) 71 | target_validate_arr = np.array(validate_pred) 72 | acc_val = np.sum(input_validate_arr == target_validate_arr)*100/len(input_validate_arr) 73 | print(f">> e:{epoch:3} s:{batch_num:2} loss:{loss:5.4} acc_t: {acc_train:3f} acc_v: {acc_val:3f}") 74 | 75 | if acc_val > max_val_acc: 76 | max_val_acc = acc_val 77 | max_key = 0 78 | else: 79 | max_key += 1 80 | 81 | if not epoch % num_save_epoch: 82 | saver.save(sess, config["model_path"]+"model", global_step=epoch) 83 | print(">> save model...") 84 | 85 | # 1000 batch val acc 没有增长,提前停止 86 | if max_key > 200: 87 | print(">> No optimization for a long time, auto stopping...") 88 | break 89 | 90 | time_str = config["time_now"] 91 | print(f">> use this command for test:\npython -m run.tensorflow -r test -d {time_str} ") 92 | 93 | 94 | def test(time_str): 95 | config = conf_utils.init_test_config(time_str) 96 | batch_size = config["batch_size"] 97 | 98 | test_input, test_target = data_utils.gen_test_data(config) 99 | target_vocab = data_utils.get_vocab(config["target_vocab_path"]) 100 | 101 | print(">> build model...") 102 | model = cnn.Model(config) 103 | _, pred, _ = model.cnn() 104 | 105 | with tf.Session() as sess: 106 | saver = tf.train.Saver() 107 | lastest_checkpoint_name = tf.train.latest_checkpoint(config["model_path"]) 108 | print(f">> last checkpoint: {lastest_checkpoint_name}") 109 | saver.restore(sess, lastest_checkpoint_name) 110 | 111 | batch_gen = batch_utils.make_batch(test_input, test_target, batch_size, False) 112 | input_target_list = [] 113 | pred_target_list = [] 114 | for batch_num in range(len(test_input)//batch_size): 115 | test_input_batch, test_target_batch = batch_gen.__next__() 116 | 117 | pred_target_arr = sess.run(pred, feed_dict={ 118 | model.input_holder: test_input_batch, 119 | model.target_holder: test_target_batch 120 | }) 121 | 122 | input_target_arr = np.argmax(test_target_batch, 1) 123 | input_target_list.extend(input_target_arr.tolist()) 124 | pred_target_list.extend(pred_target_arr.tolist()) 125 | 126 | input_target_list = [target_vocab[i_data] for i_data in input_target_list] 127 | pred_target_list = [target_vocab[p_data] for p_data in pred_target_list] 128 | report = metrics.classification_report(input_target_list, pred_target_list) 129 | print(f"\n>> REPORT:\n{report}") 130 | output_utils.save_metrics(config, "report.txt", report) 131 | 132 | cm = metrics.confusion_matrix(input_target_list, pred_target_list) 133 | print(f"\n>> Confusion Matrix:\n{cm}") 134 | output_utils.save_metrics(config, "confusion_matrix.txt", str(cm)) 135 | 136 | 137 | def get_server_sess(time_str): 138 | config = conf_utils.init_test_config(time_str) 139 | input_vocab = data_utils.get_vocab(config["input_vocab_path"]) 140 | target_vocab = data_utils.get_vocab(config["target_vocab_path"]) 141 | 142 | print(">> build model...") 143 | model = cnn.Model(config) 144 | _, pred, _ = model.cnn() 145 | 146 | sess = tf.InteractiveSession() 147 | saver = tf.train.Saver() 148 | lastest_checkpoint_name = tf.train.latest_checkpoint(config["model_path"]) 149 | print(f">> last checkpoint: {lastest_checkpoint_name}") 150 | saver.restore(sess, lastest_checkpoint_name) 151 | return sess, pred, target_vocab, input_vocab, model 152 | 153 | 154 | def train_v2(config_path): 155 | config = conf_utils.init_train_config(config_path) 156 | train_input, train_target, validate_input, validate_target = data_utils.gen_train_data(config) 157 | 158 | print(">> build model...") 159 | if args.model == "cnn": 160 | model = cnn2.Model(config).build() 161 | # elif args.model == "rnn": 162 | # model = rnn.Model(config).build() 163 | else: 164 | raise Exception(f"error model: {args.model}") 165 | 166 | model.summary() 167 | 168 | model.fit(train_input, train_target, batch_size=64, epochs=20, validation_data=(validate_input, validate_target)) 169 | 170 | config = conf_utils.init_test_config(config["time_now"]) 171 | test_input, test_target = data_utils.gen_test_data(config) 172 | model.evaluate(test_input, test_target, batch_size=64) 173 | 174 | 175 | if __name__ == '__main__': 176 | if args.run == "train": 177 | train(args.config) 178 | elif args.run == "test": 179 | if args.date == "": 180 | raise ValueError("test need -d arg") 181 | else: 182 | test(args.date) 183 | elif args.run == "infer": 184 | if args.text == "": 185 | raise ValueError("infer need -t arg") 186 | else: 187 | infer(args.text) 188 | else: 189 | raise ValueError("The first parameter is wrong, only support train or test!") 190 | -------------------------------------------------------------------------------- /script/prepare_data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo `date` 4 | echo -e "\n## Prepare data.\n" 5 | 6 | 7 | data_dir="./data/THUCNews-5_2000/" 8 | 9 | if [ ! -d ${data_dir} ]; then 10 | if [ ! -f "./data/THUCNews-5_2000.zip" ];then 11 | echo ">> 1 Download dataset..." 12 | wget -c https://cnlp.dovolopor.com/downloads/THUCNews-5_2000.zip -O ./data/THUCNews-5_2000.zip 13 | echo ">> 2 Unzip dataset..." 14 | unzip ./data/THUCNews-5_2000.zip -d ./data/ 15 | rm ./data/THUCNews-5_2000.zip 16 | else 17 | echo "!! file is exists." 18 | fi 19 | else 20 | echo -e "!! ${data_dir} dir is exists." 21 | fi 22 | 23 | train_dir=${data_dir}"train/" 24 | validate_dir=${data_dir}"validate/" 25 | test_dir=${data_dir}"test/" 26 | if [ ! -d ${train_dir} -a ! -d ${validate_dir} -a ! -d ${test_dir} ]; then 27 | echo -e "\n>> 3 split train validate and test data.\n" 28 | 29 | mkdir ${train_dir} 30 | mkdir ${validate_dir} 31 | mkdir ${test_dir} 32 | 33 | class_arr=(体育 房产 时政 游戏 股票) 34 | for class_name in ${class_arr[@]}; do 35 | echo ">> split "${class_name}"..." 36 | 37 | num=0 38 | tmp_arr=() 39 | for file in `ls ${data_dir}`; do 40 | if [ ${file:0:2} = ${class_name} ]; then 41 | tmp_arr[num]=${file} 42 | if [ ${num} -lt 1200 ]; then 43 | mv ${data_dir}${file} ${train_dir} 44 | elif [ ${num} -ge 1200 -a ${num} -lt 1600 ]; then 45 | mv ${data_dir}${file} ${validate_dir} 46 | else 47 | mv ${data_dir}${file} ${test_dir} 48 | fi 49 | let num++ 50 | fi 51 | done 52 | done 53 | else 54 | echo -e "!! ${train_dir} dir is exists." 55 | echo -e "!! ${validate_dir} dir is exists." 56 | echo -e "!! ${test_dir} dir is exists." 57 | fi 58 | 59 | echo -e "\n## Successful." -------------------------------------------------------------------------------- /script/tf1-env.sh: -------------------------------------------------------------------------------- 1 | conda create -n tf1 python=3.7.6 -v 2 | conda activate tf1 3 | pip install -r requirements/req-tf1.txt -------------------------------------------------------------------------------- /server/flask_app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request 2 | 3 | from run import tensorflow 4 | 5 | time_str = "18-08-14_23-58-25" 6 | sess, pred, target_vocab, input_vocab, model = tensorflow.get_server_sess(time_str) 7 | 8 | app = Flask(__name__) 9 | 10 | 11 | @app.route("/") 12 | def index(): 13 | return "Please use /text_classification." 14 | 15 | 16 | @app.route('/text_classification', methods=['GET', 'POST']) 17 | def text_classification(): 18 | if request.method == 'POST': 19 | text = request.form["text"] 20 | word_list = text[:1000] 21 | input_id_list = [] 22 | for word in word_list: 23 | if word in input_vocab: 24 | word_id = input_vocab.index(word) 25 | else: 26 | word_id = input_vocab.index("UNK") 27 | input_id_list.append(word_id) 28 | 29 | pred_target_arr = sess.run(pred, feed_dict={ 30 | model.input_holder: [input_id_list], 31 | model.target_holder: [[1, 0, 0, 0, 0]] 32 | }) 33 | 34 | class_name = target_vocab[pred_target_arr[0]] 35 | return class_name 36 | else: 37 | return "Please use POST method." 38 | 39 | 40 | if __name__ == "__main__": 41 | app.run(host='127.0.0.1', port=5000) 42 | -------------------------------------------------------------------------------- /server/send_data.py: -------------------------------------------------------------------------------- 1 | import http.client 2 | import urllib.parse 3 | 4 | with open("./data/THUCNews-5_2000/test/体育-76.txt", "r", encoding="utf-8") as f_file: 5 | input_data = "" 6 | for line in f_file: 7 | line = line.strip().replace(" ", "") 8 | input_data += line 9 | 10 | params = urllib.parse.urlencode({"text": input_data}) 11 | 12 | conn = http.client.HTTPConnection("127.0.0.1:5000") 13 | headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"} 14 | conn.request("POST", "/text_classification", body=params, headers=headers) 15 | response = conn.getresponse() 16 | print(response.read().decode("utf-8")) 17 | conn.close() 18 | -------------------------------------------------------------------------------- /util/batch_utils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def shuffle_batch(input_data, target_data): 5 | datas = [] 6 | for i_data, t_data in zip(input_data, target_data): 7 | datas.append([i_data, t_data]) 8 | 9 | np.random.shuffle(datas) 10 | 11 | input_data_shuffle = [] 12 | target_data_shuffle = [] 13 | for data in datas: 14 | input_data_shuffle.append(data[0]) 15 | target_data_shuffle.append(data[1]) 16 | 17 | return input_data_shuffle, target_data_shuffle 18 | 19 | 20 | def make_batch(input_data, target_data, batch_size, is_shuffle=True): 21 | if is_shuffle: 22 | input_data, target_data = shuffle_batch(input_data, target_data) 23 | 24 | for step in range(len(input_data) // batch_size): 25 | s = batch_size * step 26 | e = batch_size * (step + 1) 27 | 28 | input_data_batch = input_data[s:e] 29 | target_data_batch = target_data[s:e] 30 | 31 | yield input_data_batch, target_data_batch 32 | -------------------------------------------------------------------------------- /util/conf_utils.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from datetime import datetime 3 | import yaml 4 | 5 | from util import output_utils 6 | 7 | 8 | def read_config(config_path): 9 | with open(config_path, "r", encoding="utf-8") as f_config: 10 | config_data = yaml.load(f_config.read(), Loader=yaml.FullLoader) 11 | return config_data 12 | 13 | 14 | def init_train_config(config_path): 15 | time_now = datetime.now().strftime("%y-%m-%d_%H-%M-%S") 16 | print(f">> start time: {time_now}\n") 17 | 18 | config = read_config(config_path) 19 | config["config_path"] = config_path 20 | config["time_now"] = time_now 21 | config["output_path_with_time"] = config["output_path"] + config["time_now"] + "/" 22 | config["log_train_path"] = config["output_path_with_time"]+"log/" 23 | config["model_path"] = config["output_path_with_time"]+"model/" 24 | 25 | output_utils.check_path(config["log_train_path"]) 26 | output_utils.check_path(config["model_path"]) 27 | output_utils.cp_config(config) 28 | # output_utils.cp_data(config) 29 | return config 30 | 31 | 32 | def init_test_config(train_time_str): 33 | time_now = datetime.now().strftime("%y-%m-%d_%H-%M-%S") 34 | print(f">> start time: {time_now}\n") 35 | 36 | test_config_path = list(Path(f"./output/{train_time_str}/config/").glob("*.yaml"))[0] 37 | config = read_config(test_config_path) 38 | 39 | config["test_path_with_time"] = config["output_path_with_time"] + "test/" + time_now + "/" 40 | 41 | output_utils.cp_model(config) 42 | return config 43 | 44 | 45 | def init_server_config(train_time_str): 46 | time_now = datetime.now().strftime("%y-%m-%d_%H-%M-%S") 47 | print(f">> start time: {time_now}\n") 48 | 49 | test_config_path = list(Path(f"./output/{train_time_str}/config/").glob("*.yaml"))[0] 50 | config = read_config(test_config_path) 51 | return config 52 | -------------------------------------------------------------------------------- /util/data_utils.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | import yaml 4 | import numpy as np 5 | 6 | 7 | def get_vocab(vocab_path): 8 | with open(vocab_path, "r", encoding="utf-8") as f_vocab: 9 | vocab_list = [] 10 | for line in f_vocab: 11 | vocab_list.append(line.strip()) 12 | return vocab_list 13 | 14 | 15 | def read_data(input_data_path): 16 | path = Path(input_data_path) 17 | input_data_list = [] 18 | target_data_list = [] 19 | for input_path in path.glob("*.txt"): 20 | target_data = input_path.name.split("-")[0] 21 | with open(str(input_path), "r", encoding="utf-8") as f_file: 22 | input_data = "" 23 | for line in f_file: 24 | line = line.strip().replace(" ", "") 25 | input_data += line 26 | input_data_list.append(input_data) 27 | target_data_list.append(target_data) 28 | return input_data_list, target_data_list 29 | 30 | 31 | def word2id(input_vocab, input_word_list, seq_length): 32 | all_input_id_list = np.zeros([len(input_word_list), seq_length]) 33 | for i_input, word_item in enumerate(input_word_list): 34 | word_item_list = [word for word in word_item] 35 | word_item_len = len(word_item_list) 36 | 37 | if word_item_len >= seq_length: 38 | word_item_list = word_item_list[:seq_length] 39 | else: 40 | word_item_list = word_item_list + ["PAD"] * (seq_length-word_item_len) 41 | 42 | input_id_list = [] 43 | for word in word_item_list: 44 | if word in input_vocab: 45 | word_id = input_vocab.index(word) 46 | else: 47 | word_id = input_vocab.index("UNK") 48 | input_id_list.append(word_id) 49 | all_input_id_list[i_input] = np.array(input_id_list) 50 | 51 | read_percent = i_input/(len(input_word_list)/100) 52 | if not i_input % 10: 53 | print(f">> convert: {read_percent:3.1f}%", end="\r") 54 | 55 | return all_input_id_list 56 | 57 | 58 | def target2id(target_vocab, target_data): 59 | target_id_list = np.zeros([len(target_data), len(target_vocab)]) 60 | for i_target, target_item in enumerate(target_data): 61 | if target_item in target_vocab: 62 | target_id = target_vocab.index(target_item) 63 | target_id_list[i_target][target_id] = 1 64 | else: 65 | raise ValueError(target_item) 66 | return target_id_list 67 | 68 | 69 | def gen_train_data(config): 70 | print("\n>> start read train data...") 71 | train_input, train_target = read_data(config["train_data_path"]) 72 | 73 | if len(train_input) == 0: 74 | raise Exception("!! train data is None, please run `bash ./script/prepare_data.sh` first.") 75 | 76 | print(">> start read validate data...") 77 | validate_input, validate_target = read_data(config["validate_data_path"]) 78 | 79 | if config["frame_class"] == "sklearn": 80 | return train_input, train_target, validate_input, validate_target 81 | else: 82 | print("\n>> start read input vocab...") 83 | input_vocab = get_vocab(config["input_vocab_path"]) 84 | print(">> start read target vocab...") 85 | target_vocab = get_vocab(config["target_vocab_path"]) 86 | 87 | print("\n>> word to id: train...") 88 | train_input_list = word2id(input_vocab, train_input, config["seq_length"]) 89 | print(">> word to id: validate...") 90 | validate_input_list = word2id(input_vocab, validate_input, config["seq_length"]) 91 | 92 | print("\n>> target to id: train...") 93 | train_target_list = target2id(target_vocab, train_target) 94 | print(">> target to id: validate...") 95 | validate_target_list = target2id(target_vocab, validate_target) 96 | 97 | return train_input_list, train_target_list, validate_input_list, validate_target_list 98 | 99 | 100 | def gen_test_data(config): 101 | print("\n>> start read test data...") 102 | test_input, test_target = read_data(config["test_data_path"]) 103 | 104 | if config["frame_class"] == "sklearn": 105 | return test_input, test_target 106 | else: 107 | print(">> start read input vocab...") 108 | input_vocab = get_vocab(config["input_vocab_path"]) 109 | print(">> start read target vocab...") 110 | target_vocab = get_vocab(config["target_vocab_path"]) 111 | 112 | print("\n>> word to id: test...") 113 | test_input_list = word2id(input_vocab, test_input, config["seq_length"]) 114 | print("\n>> target to id: test...") 115 | test_target_list = target2id(target_vocab, test_target) 116 | 117 | return test_input_list, test_target_list 118 | 119 | 120 | def gen_infer_data(config, text): 121 | print(">> start read input vocab...") 122 | input_vocab = get_vocab(config["input_vocab_path"]) 123 | print(">> start read target vocab...") 124 | target_vocab = get_vocab(config["target_vocab_path"]) 125 | 126 | print("\n>> word to id: test...") 127 | infer_input_list = word2id(input_vocab, [text, text], config["seq_length"]) 128 | 129 | return infer_input_list, target_vocab 130 | -------------------------------------------------------------------------------- /util/output_utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | 4 | import yaml 5 | 6 | 7 | def check_path(path_name): 8 | if not os.path.exists(path_name): 9 | os.makedirs(path_name) 10 | print(f">> makedir {path_name}") 11 | 12 | 13 | def cp_config(config): 14 | target_path = config["output_path_with_time"] + "config/" 15 | check_path(target_path) 16 | 17 | save_path = target_path + config["config_path"].split("/")[-1] 18 | save_dump = yaml.dump(config, default_flow_style=False, allow_unicode=True, encoding=None) 19 | with open(save_path, "w", encoding="utf-8") as f_save: 20 | f_save.write(save_dump) 21 | 22 | 23 | def cp_data(config): 24 | target_path = config["output_path_with_time"] + "data/" 25 | shutil.copytree(config["data_path"], target_path) 26 | 27 | 28 | def cp_model(config): 29 | target_path = config["test_path_with_time"] + "model/" 30 | shutil.copytree(config["model_path"], target_path) 31 | 32 | 33 | def save_metrics(config, save_name, metrics_data): 34 | save_path = config["test_path_with_time"] + save_name 35 | with open(save_path, "w", encoding="utf-8") as f_save: 36 | f_save.write(metrics_data) 37 | --------------------------------------------------------------------------------