├── README.MD ├── bertsvr.sh ├── dat ├── alldat.txt ├── dev.tsv ├── test.tsv └── train.tsv ├── freeze_graph.py ├── images ├── cap00.png ├── cap01.png ├── cap02.png └── cap05.png ├── mobile_apisvr ├── api_service.py ├── static │ ├── css │ │ └── nlp.css │ ├── index.html │ └── js │ │ └── jquery-2.1.4.min.js └── templates │ └── index.html ├── mobile_svr └── bertsvr.sh ├── model ├── eval_results.txt └── label2id.pkl ├── modeling.py ├── optimization.py ├── requirements.txt ├── run_mobile.py └── tokenization.py /README.MD: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmxoxo/BERT-train2deploy/b03cb0a1b693e91fddab74eb7945c1de2b33a18f/README.MD -------------------------------------------------------------------------------- /bertsvr.sh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmxoxo/BERT-train2deploy/b03cb0a1b693e91fddab74eb7945c1de2b33a18f/bertsvr.sh -------------------------------------------------------------------------------- /dat/dev.tsv: -------------------------------------------------------------------------------- 1 | label txt 2 | -1 一个月都有点卡了, 3 | 1 手机很不错,玩游戏很流畅,快递小哥态度特别特别特别好,重要的事情说三遍? 4 | 1 初步用了一下,开始拿到手觉得真**大,玩了一会以后 真香!玩游戏很爽,双扬声器看片也很震撼~拍照的话现在还凑活看后期更新优化吧!这款手机比较适合影音娱乐用,一般人不建议用。 5 | -1 续航不行 玩吃鸡卡 6 | 1 物流配送速度很快,三天左右就到了,画面清晰,音质还挺好的,总之超喜欢的 7 | 0 着好看,都挺不错的。 但是京东的保价,双十一便宜100元,联系客服,说退100,这都10多天了,仍然没有解决。 8 | 1 手机是正品,质量很好,速度很快,价格不比别家便宜,还送膜、送耳机、送自拍神器。谢谢商家! 9 | 1 机很流畅,买的很好的一次,下次还要购买,一点都不卡。 10 | 0 不能再相信它了 11 | 1 比较了多款手机后,最后决定购买荣耀10,这是一款性价比不错的手机,配置比较高,功能也很强,外观非常漂亮,拍摄效果非常好!商家送的赠品也非常实惠,非常满意! 12 | -1 十号送到十一号就掉了一百还不能价保 13 | -1 赠送礼品实际上是没有,客服一直不处理,活动都是@的 14 | 1 心仪已久的一款手机,970处理器,运行速度非常快。之前用的MX6,现在转到荣耀阵营,希望带来非一般的体验 15 | 1 老婆买的,手机很好看,她很喜欢,爱不惜手呢。我也考虑入手一台了。哈 16 | 1 旧机是荣耀7,习惯了荣耀系统,新机反应速度很快,目前用着还不错 17 | -1 质量也不咋滴,卖的还比别家贵! 18 | -1 玩游戏不行,和描述不符 19 | 1 手机很小巧,五天到手里的总之还行 刚开始用 20 | -1 买不到一个月降价200。还保价不了! 21 | 1 在10月1买的,等了两天才发货,收货等了也两天发货......运行速度还蛮快的!玩吃鸡和王者也没有卡!人脸识别还挺快的!个人觉得还蛮不赖的!剩下的后续在追评吧! 22 | 1 用着挺好! 23 | 1 非常好的手机,速度快,屏幕清晰,拍照好,而且买来就是贴好膜的,很方便,再次选择荣耀是正确的!发货物流也都快! 24 | 1 宝贝拿到了,一直都想买的,今天到了,用了一下很喜欢,真的很好看啊啊啊,喜欢的快下手吧,支持国产手机,喔噢喜欢 25 | 1 好用,支持 26 | 1 不错好用 27 | -1 这款手机喜欢,外表轻盈,新颖,屏幕清晰,网速流畅,内存空间大,货真价实,京东诚实守信的平台,本来去实体店看了一圈,回后还是在京东买了,不错不错,喜欢喜欢。 28 | 1 不错,外观好,性能好,充电快。 29 | -1 充电充不进,客服留言没人回复 30 | 1 不错的商品质量也很好,很值这个价格,值得购买。 31 | 1 电话非常漂亮,家里老人很喜欢,下次还会在你家买电话的,给个超赞。 32 | 0 手机底部有一部分显示颜色跟别的地方有色差!左下角 33 | -1 电池不耐用,耗电快高,运行清完一个待机耗电50% 34 | -1 后面那个盖有裂缝 35 | 1 外观很漂亮,跟新一代的苹果比,一点都不逊色!变幻色彩的外观更吸引人! 36 | 1 手机很靓,操作很顺畅,功能很实用!值得拥有! 37 | 1 外观特别棒,幻影蓝的渐变色真的非常骚气,手机音效和 AI 拍摄真的非常棒! 38 | 1 手机不错,看上去挺漂亮的。用起来性能也很好。卖家送了不少东西都很实用。6g的内存速度已经很快了,没有卡顿的现象。建议128兆,相机的像素很高,随便拍点照,照片都有好几张。 39 | 1 手机不错,相信国产品牌,价格也很实惠,店家送了很多赠品 40 | 1 质量好,包装完好。 41 | 1 手机还不错 一点都不卡 42 | 0 手机的操控感觉不如苹果好用,也发热,指纹解锁一般凑活用用还可以。 43 | 1 屏幕的确很大,电池挺耐用的。 44 | 1 很好的一次购物哦 45 | 1 货已收到,不喜欢刘海屏,不过还好可以隐藏起来,这样挺好,已经在京东买第五台荣耀手机了,我爱荣耀,继续加油,棒棒的? 46 | 1 手机很好,质量不错,外观好看,值得拥有 47 | 1 手机收到!是正品。老公超爱的!棒棒哒! 48 | 1 手机很快,运行挺好,内存大,性价比高,指纹支付,不方便,总容易摁错 49 | 1 中间返回键确实不太灵敏,所以用起来不是很顺畅其他都还好吧。 50 | 1 用了一段时间,感觉很好,华为荣耀的手机不错,要不是用的荣耀6电池不行了,后盖也开裂,可能还不会换10 51 | 1 手机不错啊 感觉速度 快 手感很好 性能不错 现在华为的手机做得很好了 希望手机一直好用 52 | -1 破手机 耗电贼快 谁买谁知道 53 | 0 (?^?) 嫌弃你特意用了两天才来评价,这是对自己和大家的负责! 54 | -1 买几天又降了一百。。 55 | 1 比想像中的还要好,看视频几十k的速率也可以,听音乐音质很好,内存够大 56 | 1 机挺好的,就是颜色跟图片差别有点大啊。 57 | 1 手机到手,大小比较合适,屏幕色彩比较艳丽,感觉买的值 58 | 1 手机用了一下很漂亮手感很棒,发热也还可以能接受,送的东西很实用棒棒哒! 59 | 0 刚开始用,一般吧 60 | 1 这个屏幕的涮脸解锁老爸是最喜欢的一种,方便 相机的全景模式也方便使用,支持国产 61 | -1 荣耀现在拍照就没有一个正常的v10这样,10还是这样,我们不要求你有多完美,就是正常就好,拍出来的照片就跟p的一样! 62 | 0 电池一点不耐用 63 | 0 我买的灰色给我送个蓝色。。最多三星 64 | 1 还不错的一次购物经历,感觉不错哦。 65 | -1 手机发烫的厉害,尤其是用赠送的手机壳,特别热 66 | -1 耳机防爆膜支架都没有送 67 | -1 以前用的小米为发烧而生! 用了荣耀10才知道什么是真正的发热! 在他面前小米的发热不值一提! 华为送你一句话:荣耀 为发烫而生! 如果不发热 续航在给力点荣耀10会就是一部好手机! 68 | 1 虽然是双十一买的,但是卖家发货超级快,隔天就收到货啦!款式小巧轻便非常喜欢,下午收到货特地用了一下再来评论,目前没有发热现象,下载速度很快,内存也够大,拍照功能也试了一下,个人觉得拍照片一般,大概是我没调好,这个价位6G+128G还是蛮值得买的,喜欢的亲们可以下单。 69 | 1 满意,送人的! 70 | 0 怎么说呢,玩着刺激战场充着电手机电量不长反而掉,其他的我觉得这个手机还行 71 | 1 手机不错,比之前的荣耀v9要小,但是屏幕却大,用起来很流畅 72 | 1 第一次买荣耀 ,还没打开用了 ,机壳好看大气 特别是背面很耀眼 73 | 0 与我看到的圖差很多啊 74 | -1 东西不好,屏幕小 75 | 1 可以,就是偶尔点屏膜不灵敏,不知道是不是贴钢化膜的原因 76 | 0 手机用起来挺好的,本人不打游戏11月5号买的券后1999,双11变成券后1899询问客服,应该是本产品参与秒杀,不支持价格保护了大家以后在京东买东西注意这个了 77 | 1 不错,大小操控刚好,比8稍微小一点,手感不错,拍的照片也不错,总之荣耀系列从来就没让我失望过 78 | 1 挺好用,触屏反应也挺快的,指纹和面部解锁也够给力,内存也够大 79 | 1 拿到手机,用起杠杠的 速度很快,用着很科学 80 | 1 颜色很#,你值得拥有 81 | 1 东西很好看,速度也很快。 82 | -1 指纹解锁太磨叽,还没有我之前的一加手机快 83 | -1 价太快,没什么好说的,22919189 84 | 1 很漂亮的手机,有些功能还没搞懂,愉快的购物,。 85 | 1 还没完全装好APP,外观尺寸显得长。里面预装了微博等,自己安装APP,还是很快的。拍照超清晰。 86 | 1 手机很满意,另外礼品更好。外包装很好,用了防撞袋。 87 | 1 到货好几天了,真心不错。一是物流超快,一天到货,赞一个。二是手机运行速度快,128G真的不一般,就是一个爽字。三是充电快,华为良心产品,品质就是不一样。支持国货、支持华为! 88 | -1 真差劲,就问怎么看后台运用,半天不回答 89 | 0 货速度很快,次日就到了,用的感觉也还不错,但是画质。己看。 90 | 0 刚到手,期待更多的使用时间,才可详细评价 91 | 0 网速不快还说是6G 92 | -1 感觉被骗了,像素差到不行,店家也不给解决,只说让我拿到店里去检修,伤心!伤心!气愤!气愤!差评! 93 | 1 买了还没用,还要琢磨一下,用了再追评 94 | 1 手机质量不错 抗摔,防水,防火,防被盗。打游戏顺畅无比,续航强。总之就是强 95 | -1 不耐温,,质量不行 96 | 1 手机那是相当不错,反应很快,尤其人脸识别,手感也很好,很喜欢。 97 | 1 手机不错,配送的速度很快。 98 | 1 手机很好,正品,中等用机一天一充4G内存对于不怎么玩大游戏的够用了,性价比高,而且该有的功能都有了,好评! 99 | 1 手机收到了,颜色很漂亮,会变色更潮美。运行很快,华为手机质量很好。 100 | 1 容易发热,我不玩游戏,就玩玩微信,看看新闻,听听歌都会发热,续航不行,一天两充,不过充电速度很给力,其他方面都不错,还有618最后时刻降价2599都能买个128g的了,后悔买早了 101 | 1 充电速度非常满意拍照很清晰,像素也是很舒 服音质不错,听音乐很舒服信号很好很强大, 玩几个小时游戏无压力手机性价比很高,系统 运行很流畅,玩游戏手感很好,屏幕占比还不 错,视觉效果好,看着比较高大上。 102 | 1 不错屏很大。电池耐用玩游游戏看电影超爽。华为加油 103 | 1 手机挺好用的,也非常好看! 104 | 1 确实不错,物流很快,值得购买,真的性价比很高,我是一如既往的花粉。自2012年以来,我的手机全部都是华为的。 105 | -1 就提前了一个小时买。不能保价也不能赔赠品京东真假 106 | 1 刚到手,用着不错。 107 | 1 非常好用商家良心 108 | 1 刚到手,手机外观设计好看,拿在手里很舒服,拍照效果不错,在官网验证是正品,具体性能测试还要玩几天后再看。 109 | -1 6G运存还不如我荣耀84g运存运存呢,玩个刺激战场一卡一卡的 110 | 1 手机没得说,非常棒,下次还会来 111 | 1 机拿到手用了下,性能很高,玩游戏很流畅,拍照很清晰,手机自带的HIFI功能听起来很震撼,个人感觉这台手机性价比很高,推荐! 112 | 1 外观非常漂亮。手感也不错,非常喜欢 113 | 0 发货速度很慢,服务态度一般 114 | 1 用了几天才来评价的,感觉很棒,也很流畅。吃鸡爽爽的。物流给力。服务很好。 115 | 1 自营没有黑色,在这家买,机子很好,价格还更优惠一些。 116 | 1 买给儿子用,他喜欢,还不错吧! 117 | 0 塞的一批. 118 | 1 手机收到了 质量杠杠的包装很细心没有破损值得购买 119 | 1 宝贝不错哦,快递哥哥服务好好哦 120 | 1 手机不错,用了两周才做出的评价 121 | 1 手机确实漂亮,渐变色很好看!面部解锁抬手就解锁,方便!店家送的耳机,手机壳,充电宝!祝生意兴隆 122 | 0 各方面都很好,NFC功能也很全面,比Apple Pay好,就是电池太不抗用了,和用了一年的vivo一个水平 123 | 1 手机很轻,功能强大。性价比很高 124 | 1 实惠好用。 虽然感觉写评语花掉了我大量的时间和精力! 所以在一段时间里,我总是不去评价或者随便写写! 但是,我又总是觉得好像有点对不住那些辛苦工作的卖家客服、仓管、老板。于是我写下了一小段话,给我觉得能拿到我五星好评的卖家的宝贝评价里面以示感谢和尊敬!宝贝性价比还是蛮高的。配送绝对是一流的,送货速度快,配送员服务态度好,希望卖家能再接再厉,做得更大更强,提供更多更好的东西给大家。 125 | 1 高大大气上档次,非常棒! 126 | -1 没有评价的那么好,玩游戏还是卡 127 | 1 质量很好,很顺畅。不卡 128 | 1 速度比原来的6快多了 129 | 1 超级快充很喜欢?很满意荣耀10超级喜欢 130 | 1 必须好评,我全家都是用的华为的,支持国货!已经推荐给同学了。手机很好看,反应也很快,不愧是华为。想买的朋友不用犹豫了! 131 | -1 新手机到货屏保贴的有问题,里边气泡和杂质 132 | -1 发热严重 不应该是发烫。 133 | 1 快递炒鸡快,物流小哥开车专送,手机也很漂亮,值得入手。 134 | 1 宝贝很好,到货很快,性价比很高,非常满意! 135 | 1 机没话说,毛病也没有网上说的多严重,反正我用到现在没啥让反感的地方,挺好的! 136 | 1 机外观很好看,电池也很经用,第一次买。得拥有。 137 | 1 质量非常好,与卖家描述的完全一致,非常满意,真的很喜欢,完全超出期望值,发货速度非常快,包装非常仔细、严实,物流公司服务态 138 | -1 手机边缘打游戏不灵敏 139 | 1 机很喜欢! 140 | 1 用起来不卡,照片质量很好哦⊙⊙! 141 | -1 十天就降价了体验极差 142 | 1 手机不错,运行速度快,拿在手里很舒服。是一款非常好的手机。 143 | 1 手机收到了,虽然有点曲折,但还是拿到了,很满意! 144 | 0 用了十八天左右更之前用起来完全不一样 145 | 1 外表还是很惊艳的,系统很流畅反应挺快,快充挺好,无线信号比我以前的三星还强。 146 | 1 手机拿到手感觉挺不错,运行速度也很流畅,手机也挺漂亮。客服很耐心的给解答,很愉快的一次购物。 147 | 1 好用的手机 148 | -1 就是懒得退货。天看着这质量问题,我就笑了。 149 | 1 续航正常水平 就是解锁经常分不清上下,用手指按刘海解锁 尴尬 150 | 1 颜色很好看,系统很流畅,电池应该够用,充电快,指纹识别快 151 | 1 不错,手机?很好用,还是特别是手感好,不大不小刚刚好! 152 | 1 东西收到了,挺好看的,试了一下,手感也还不错。只是送的手机壳不太好看,我用了原版手机壳。 153 | 0 拍照没怎么用过先不说,机身很漂亮灯光下渐变色。手感很舒服。屏幕刘海屏可以调,指纹解锁真的是无语的三次才能成功有时更多。人脸识别快,亮屏基本就解锁了。没玩游戏,日常运行流畅,再有就是续航方面了,轻度使用一天估计没问题,中度或重度使用者我就建议不要考虑了。一天估计要两充吧。还没有我的红米5电池耐用。这是刚入手两天的体验。还有就是后台开多了就会发热。估计吃鸡得烫手吧。以上纯属个人体验。总得来说颜值不错。系统有待提升。 154 | 0 用了这么久了,没有多少惊喜点~很规距,掉电快了点,ai拍照不错~ 155 | -1 手机没什么可说的就这么个东西 我选的纸质发票怎么没有! 156 | 1 拍人像的效果不错,运行速度也还可以。 157 | 1 28号晚上买的,31号到的,期待感被快递速度磨没了,手机到手后没有想象中满意。暂时用着没问题,用一段时间后再看看吧。 158 | 1 刚特意上官网查了一下,正品!特意用了一天才来评价,手感不错,吃鸡运行速度完全没问题,物流比预期的快了两天!卖家送的礼物也很实用 159 | 1 手机不错,屏幕也非常大! 160 | 1 刚洗完澡的狗子真厉害!血统很纯,给个好评! 161 | 1 手机很漂亮,分辨率很高,很清晰,拍照像素前后2400万,给点个赞? 162 | -1 12.11购买2099 12.12购买1899 相差一天200 连手机耳线都省了 手机性能还可以 163 | 0 帮老婆侄子买的 样子漂亮 一切都很好 只是没有小米性价比高 164 | 1 手机收到了了用了两天挺流畅的,很喜欢。机子性价比很高。 165 | -1 不玩游戏都好说 166 | 1 不错,服务态度也好。 167 | -1 给个不好无线网连接器卡了一逼 168 | 1 刚收到手机,非常漂亮,做工很好,手机还没用,进一步的体验还没有,一直在用华为手机,身边朋友也很多人在用,华为手机真的是进步很快,希望华为越做越好!更上层楼 169 | 1 不错比想象中的好指纹解锁非常快人脸识别也快 170 | 0 可以吧。。???。 171 | 1 不是很好,有点不喜欢,小了点信号又不好 172 | 0 还可以吧,支持下华为了 173 | 1 手机尺寸比我想象中要小,但是还是挺漂亮的 174 | 1 收到货用了天来评价,速度反应很快,拍照很棒。手机大小刚刚好。比较满意的一次购物。 175 | 1 幻影蓝炫酷背光,手感非常好! 176 | 1 不错,用着还可以,目前也没有卡顿现象 177 | 1 商品已经收到,外观很漂亮,用着也不卡顿,是一款值得购买的一款手机 178 | 1 送货速度较慢,手机用的还可以 179 | 1 手机不错,到手很快,手感舒适 180 | 0 用惯了水果机这款用起来感觉很违和 181 | 1 一直都用荣耀系列,很满意荣耀十 182 | 1 手机很好,开机按步骤操人脸识别很好用,指纹开机反应灵敏。还没试用,其他功能试用后在追评 183 | -1 一星评价送给快递包装 184 | 0 8G内存只开个微信就4G多了怕不是8G只是幌子拍照功能炒鸡强特别好拍照党的首选发热有很大改善外观也是炒鸡炫酷黑色超炫黑色超炫黑色超炫重要事情说三遍 185 | 1 手机收到了,超好用,京东快递也超快,这场购物超满意。 186 | 1 手机很好用,入手几周了。电池续航能力强,充电速度快。其他方面都挺好的,支持国产。 187 | -1 购买14天,屏幕磕一下就碎了。 188 | 0 你们卖翻新手机,我买到的不会是翻新手机吧! 189 | 1 手机用起来不错,外观真的很好看,适合女生,相机拍照像素很高,很满意 190 | 1 超漂亮的颜色,狂拽酷炫哪炸天!!!反应也很快,寄过来到收到就几天,很开心,赠品也特别多。 191 | 1 机很漂亮,性能还不错,华为荣耀就是好,。 192 | 1 用了一段时间,流畅性很好,暂未遇到异常,无论续航、系统都挺好,后面的只有时间来验证了,总的来说,华为荣耀的手机还是可以的,这是我用的第二部华为手机了!希望越做越好 193 | 1 手机非常棒,像素高,玩游戏一点都不卡,系统流畅。 194 | 1 华为荣耀手机高性价比。玩游戏流畅不卡顿。这次帮朋友买的。 195 | 1 手机收到了,很漂亮,反应很快,爱不释手! 196 | -1 单付款之后3天了,迟迟不发货。第一天,告诉我,会催催仓库,尽快发。第二天,继续说会催催仓库,尽快发。第三天,对我说没说,你可以取消订单。我说既然没货,为什么你们页面上直到现在还显示有货呢?店家不给解释。第四天,继续对我说,请你取消订单,迟迟不给发货。要求我取消订单,我拒绝了。第五天,显示已发货,实际是个空单号。显示的揽件人是虚拟的。。物流也没有任何进展。第六天,我申请京东客服介入,就发货了。总结一句:无聊,没有信用的商家。何必这样呢?以上绝无虚构,都有聊天截屏为证。店家要是觉得我诬陷或冤枉你们,欢迎来对质! 197 | 1 很不错,手感极佳,这是华为第二个在京东买了,用起来一切正常,很值得信赖的京东 198 | 1 手机收到了,屏显很高,反应速度快,拍照清晰,质量没得说,不过觉得电池消耗也挺快 199 | 0 买给妈妈用的,本来对老人家华为的拍照期待还比较高,但是说实话,整体的拍摄能力非常一般,特别是前置摄像头的调教,拍出来一片惨白,虽然现在流行美颜,但是也要给人选择的余地啊。完全没得调整的。 200 | 1 我的手机呢,我没拿手机,没怎么回答了呀 201 | 1 这款手机等了好久才到手,可能是发货慢,手机很漂亮,秒杀价,非常划算,性价比高。 202 | 1 手机真的很不错,很喜欢,用起来非常流畅。打王者荣耀再也不卡了! 203 | 1 电池的充电很快,手感,安全性考虑蛮好,支持国产,试用中,有体验后来追评吧! 204 | 1 运行速度比较好,个人很喜欢这个手机, 205 | 1 第一次用华为的手机,周六下单周日拿到手机。收到迫不及待的打开了包裹,果然没让我失望,握在手里手感超好,和5寸握感一样,手机屏幕很大满满的屏幕,最主要的是还有我喜欢的前置指纹解锁,还有nfc功能,以后不用特意带个甬城通卡了,哈哈(?)hiahiahia!打开相机,随手一拍,聚焦快,像素高。值得拥有! 206 | 1 用了一段时间,总体感觉还是不错的,支持华为。 207 | 1 物超所值,客服态度非常好,配送也快,有朋友想购买会介绍到这里买 208 | 1 非常的给力,物流第二天到,超快,手机也很好,不错。 209 | 1 手机好用,很清楚,照相更清楚哦赞 210 | 1 商品是正版,所以不用担心是不是自营的问题,等了3 天才拿到手机,上手手感很不错,荣耀颜值是我一直最喜欢的,至于游戏方面初次测试打吃鸡是全程无忧,没有一点卡顿,不过以后怎样还不知,毕竟安卓手机越用越卡嘛,后续就不评价了,给个4 星,一星扣在物流上! 211 | 1 宝贝已经收到,和店家描述的一样,快递非常给力,我质量非常满意,给店家评满五了,祝店家生意兴隆,财源滚滚。 212 | -1 第二天就降价,呵呵,耳机也没送。 213 | 0 耗电太大 214 | -1 卡路里我的天敌 215 | 1 手机可以,杂碎太多没一个好的,捆绑销售,送人都不好意思 216 | -1 新机就有这么多软件,严重怀疑是二手机, 217 | 1 收到机子感觉很炫啊,要是蓝色或紫色也许更增彩吧,我喜欢低调些,又不失大气,全屏清晰,拿在手上合适,不会太大增加手的负担。 218 | 1 太感谢啦,首先是商家态度很好,有什么问题都能及时回复。其次就是物流速度也很快。最后手机我很喜欢。赠品也很丰厚,颜色我也很喜欢! 219 | 1 手机运行流畅,拥有独特ai照相功能,比vivo手机的ai萌拍还要好 220 | 1 手机我就不用详细评价了,我看了好才买的。商家依靠京东发货,8月8号当天早上下单,当天傍晚就收到了,发货速度超快。这就是我要的。给商家点赞。 221 | 1 不错,蛮好的,很流畅,屏幕素质也很好 222 | 1 物流很快,拍照不错,系统速度也快。赠了很多实用的赠品。 223 | 1 背板是真的漂亮,手感也不错 224 | 1 大屏就是爽,呵呵看电视玩游戏杠杠滴!手机速度也快 225 | 1 好运行速度很快。反正我不玩游戏完全够用。五星好评。说好的的的的 226 | -1 以为我不评价,就欺负我,东西膜贴的都是烂的 227 | 0 *!买东西的时候,说的好好的,赠送跟官网一样!付钱后就不一样了,一拖再拖,硬是不发附属订单的货 228 | 1 手机到手了,系统非常流畅,支持 229 | 1 一直使用华为手机,每一次购买都没有失望过,拍出来的照片很漂亮,赠的原装耳机也很好,大赞? 230 | 1 5星好评,查了下,是真品,卖家发过来的连外包装都没有拆过,支持信誉卖家,给个赞?大家看图把 231 | 0 充电很快事真的,但是用起来更快。包装,有包装吗?就一个手机盒子啊 232 | 0 对于想买来吃鸡的朋友还是算了吧,体验为0,日常用用就好 233 | 0 我觉得性价比挺高,老婆觉得外观太丑,外观只有蓝色黑色可选 234 | 1 没毛病,挺流畅的,一点都不卡,现在就是用note10评价的 235 | 1 很不错的手机 HUAWEI大品牌值得信赖 做工优良值得购买 双十一价格实惠 很开心 236 | 0 续航一般,而且不玩游戏都发热 237 | 1 手机非常正宗,不发热,反应快,值得信赖,这是我非常完美的选择。 238 | 1 性价比很高的手机,买了好几个了,很好用 239 | 0 还不错,手机流畅,打游戏什么都没问题,是很不怎么样,日常刷刷qq微信轻度使用,也要一天一充。 240 | 1 东西是很好,服务也不错 241 | 0 朋友一起买的,他从**,我从京东,一样的价钱,人家送了很多东西,我这啥也没有, 242 | 1 手机刚使用,很喜欢,流畅稳定 243 | 1 手机机很漂亮,手机很大,送东西也挺多。值得购买。在用一段时间追评。 244 | 1 买来送给老公的,这款手机电池容量特别大,老公玩一天游戏电量也够用,而且散热还快屏幕大,正好赶上优惠,物超所值 245 | -1 开发票一不小心就成了电子发票,说了送耳机下完单就不认了。 246 | 1 天刚收到,大小合适,拿在手上手感不错,整体还可以,用一段时间再追评看 247 | 1 用了将近一个月了 感觉还是非常不错的 248 | 1 拿到黑色的,也很不错,电池不热,赖用。 249 | 1 外表颜值很高,运行特别流畅,目前没有发现什么不好的地方。挺好的一款机型 250 | 1 质量非常好,与卖家描述的完全一致, 真的很喜欢,完全超出期望值,发货速 度非常快,包装非常仔细、严实,京东公司服务态度很好,运送速度很快,很满意的一次购物店很好很好 251 | 1 手机外观 颜色 样式都非常漂亮 操作方便 使用流畅 显示清晰 拍照很强大 音质完美 赠送了多个礼品 店家服务很好 支持国产 支持华为荣耀 荣耀 252 | -1 这个手机最大的败笔,就是听歌不能同时充电,发热严重,视频效果也超级差,被好评忽悠了,***三十块钱的回扣,那些没良心的给好评 253 | 1 非常不错,很流畅,用的很爽 254 | 0 买的时候没说预售,想着快买了,谁知道又成预售! 255 | 1 手机用起来没问题。因为点别的事情出了点小插曲。经过与商家沟通后,事情圆满解决了。 256 | 1 手机很好用,特别清楚,信赖京东的东西 257 | 1 不错,好像有点费电 258 | 0 外观,手感都很好,只是信号接收不太好,在相同位置原来的旧手机都是满格信号,这款手机缺只有三四格,用流量上网也是时有时无 259 | 1 屏幕很大 电池续航能力也很好 260 | 1 挺满意的,性能不错。快递也很给力 261 | 1 用了几天来评价的,手机是正品,电池续航可以,相机拍照清晰,运行快,值得购买。 262 | 0 发热贼几把厉害 263 | 1 京东物流挺快的,荣耀产品很好 264 | 1 晚上拍照都特清晰,2400万像素果然不@! 265 | -1 不好用,很多时候返回键都不灵 266 | 1 非常满意这手机,手刚刚可以握住,瘦长身形。运行速度也非常快,玩游戏也不赖。唯一让我不满意的一点是续航不好,耗电非常快,一天一冲。 267 | 1 买回来后迫不及待就用了,各方面都非常流畅,很满意,当时唯一不习惯的就是指纹键在正面,两个星期下来就习惯了。 268 | 1 手机收到了,活动的时候买的,比平时便宜,手机也很好看。 269 | 0 拍照失真了。运行速度还行。 270 | 1 用了有一个月了。非常不错。吃鸡极限没压力。王者60帧 271 | 1 不得不说物流真的太快了,正品没得说,最喜欢的就是手机的外观,配置更是没得挑,太棒了! 272 | 1 一直以来都是用华为,这款是用起来感觉最好的,电池续航能力好,充电也快,手机速度也不错 273 | -1 手机刚开始不知道怎么超烫的,下了个安兔兔,一看49度吓死,过了会有点降温,但是耗电也超快,估计不是什么好货 274 | 1 手机屏幕大,手感好,物流快,好东西,看价格 275 | 1 常不错的一次购物,还赠送这么多礼品,超值!超赞。 276 | 1 非常不错 物流快 客服态度好 277 | 1 从两年之间使用华为荣耀8/荣耀9到荣耀10手机,感觉质量越来越好,功能越来越强大!这款荣耀10/128G存储量大,手感好!照相清晰度高!只是电量用得较快,约12个小时就得充电了。没有9待机时间长!商家送的赠品多! 278 | 1 还没使用,处出差,先给好评 279 | 1 质量好,服务好,物流快,好评! 280 | 0 电池耗电比较快 281 | 1 比其它店便宜很多,质量一样,还会继续支持。 282 | 1 手机用了两天才来评价的,首先外观非常漂亮,电池也耐用,4+128的配置对我来说完全够用,不玩游戏4G运存够用,喜欢拍照片128G内存也足够用,手机很好值得推荐。 283 | 0 刚到的时候,各种卡,用了一两天之后,还好 284 | 1 反应速度挺快的,音质也很好!感觉没买错,值了?其他的用段时间再给大家反应。 285 | 0 版本无法升级 286 | 0 耳机没有 钢化膜还没有 287 | -1 说好的送东西的,一个都没有,发票也没有,搞什么啊, 288 | -1 烂手机,~相机不能用,防爆膜没今天就翘起来了,人脸识别还没荣耀9快 289 | 1 非常不错的,很喜欢。 290 | 1 手机收到了,挺实用的,该有的功能都有,字体也大,老人用起来方便,电池还行,一天一充,好评 291 | 1 支持华为好手机 292 | 1 外观很漂亮,各方面都挺好的 293 | 0 为啥耗电这么快 294 | 1 不错,运行流畅,很喜欢,好评 295 | 1 非常好用,内存够大,无论是玩游戏还是看电影都不会卡。? 296 | -1 买了一天**旗舰店就降价了,运气好背 297 | -1 我感觉买到了假的,老自动关机 298 | -1 有想像的好,只想说一句呵 299 | 1 手机外观漂亮,性能稳定,电池耐用,非常喜欢! 300 | 1 东西正品是正品,用了一段时间,拍照还可以,玩游戏就有点力不从心了,卡顿发烫,玩游戏的话不推荐这款手机。 301 | 1 手机挺漂亮的,开机速度也挺快,其它的用过之后再来评价。 302 | 1 手机用了几天,运行速度快,很喜欢 303 | 1 东西还是比较满意的,双十一活动也没有延迟发货 304 | 0 电池太差,一天也没有玩游戏什么的,电就没有了 305 | 1 非常好用,你值得拥有。 306 | 1 东西外观不错,做工精致,拍照清晰。 307 | 0 拍照很清晰,通话声音也很大,运行新手机有时都会卡,手机发烫严重,玩了一会儿就很烫 308 | 1 nahui拿回来就用了,比较可以,先用着吧 309 | 1 像素不错,手感也刚刚好,物流也挺快。性能具体等用用再来补评。 310 | 1 很不错的手机,全新的,反应很快,比自营便宜一些。希望可以用久点时间。 311 | 1 手机很棒,很漂亮,运行也很流畅。 312 | 1 电池续航持久,屏幕色彩丰富,画面逼真,清晰度高 313 | 0 还中吧,一般 314 | 1 机拍照真的超级好看,而且店铺很棒,送的钢化膜,手机壳,耳机,都超级棒!欢的快入手,快入手!服也很好,有问必答,大赞?。物流更不用说,顺丰的,超级快。总之,很棒很棒! 315 | 0 一般了. 316 | 1 蓝色是我的幸运色,手机质量很好 317 | 1 运行很流畅 颜值非常高的手机 希望以后不会有问题 继续支持 318 | 1 手机收到了,看起来棒棒哒,挺漂亮的,很喜欢耶 319 | 1 非常好好性价比很高,比较小巧,口袋里面都没问题,看上去屏幕略窄 320 | -1 卡槽口有瑕疵,圈起来的漆没有喷到。 刚收到手机就是这样的,真实的评价。 321 | -1 用一段时间在评论 322 | 1 都买了两个了,老婆比较喜欢 323 | 1 可以,非常不错,还在使用过程中,感谢商家的好产品 324 | 1 用了几天才来评价,运行速度很快,完全满足我的使用,很满意。感谢卖家、感谢快递小哥辛苦了! 325 | 1 手机运行还不错,内存也可以,总体来说还是挺不错的 326 | 0 还行吧不是我理想那么好 327 | 1 试用了两天,手机外观很漂亮渐变色,速度也很流畅多任务操作感觉最好的就是充电快,电池能量大,消耗慢。性能好,功能全,而且不卡顿,摄像头也不错拍照效果很棒,总体很满意,性价比高。一如既往支持华为! 328 | 0 池掉电快,手机一般 329 | 1 送的东西我很喜欢,手机也不错,用了一天感觉还不错,电池也没有用多少电,主要是屏大呀,太过瘾了。 330 | 0 人的,朋友说不是很好用。 331 | 1 很好 。性价比非常高的手机,一直用荣耀,这次给老婆买的。 332 | 1 手机收到喽,物流太快了,领了卷比实体店便宜不少,满意 333 | 1 上海到到北京2天ok很快赠品质量不错?屏幕很大一天待机还有49的电量。 334 | 0 有时候感觉反应不够灵敏,点了还没反应,外观还不错,朋友都说好看 335 | 1 耀10真的不错,运行快,手感好,超赞! 336 | 1 手机屏幕大,很好(?▽?) 337 | 1 的是太好,特意用了几天才来评价的,好 338 | 1 外观非常漂亮 手感也很好 电池续航能力强 像素很高 339 | 1 用了一段时间手机不错,电池容量大,手机也不发热,数度也快。 340 | 1 刚收到手机。看了一下配置和网上一样的。赠送的物品也可以 341 | 1 一起买了俩个,老婆幻影紫,很喜欢,华为荣耀赞一个 342 | -1 无线网络卡顿,同等情况下,荣耀八无卡顿。 343 | 1 东西收到了:,质量杠杠的 344 | 1 用了两天感觉非常棒,官方正品,续航也狠给力,手机非常漂亮,在这里非常感谢京东小哥,下午下单第二天早上就到了,因为工作的原因我没在家,有帮我改派到我工作的地方!店家送的东西太多了狠实惠,耳机也是官方正品,充电宝不支持快充,很伤心!这是我第一次在京东购物,总体来说,还是很满意的,值得购买! 345 | 1 手机正品,包装很结实,谢谢卖家。 346 | 1 屏够大的,,很清楚的, 347 | -1 以前都在京东直营购买,这是唯一一次不在直营买,结果就出问题。荣耀10,第三周,手机故障严重,已无法使用。客服赶紧给我解释吧 348 | 0 电池一般 349 | 1 手机很好,之前还担心电量的问题,回来充好电后听了4个小时的歌掉了10格电,我觉得已经很好了? 350 | 1 手感不错,喜欢,物流服务态度好 351 | 1 挺不错的,东西已经使用了,电池可以用到一天不充电。屏幕大,感觉挺好的。 352 | 1 支持快充。支持人脸解锁功能,价格3199良心价。送的赠品很好精美! 353 | -1 机总自动关机。买了没多久就降价20 354 | 1 手机还可以,挺流畅的 355 | 1 一直在用荣耀 356 | 1 应该是正版,这款实用漂亮,幻影蓝挺好看的,各方面都很满意吧,,很愉快的一次网购 357 | -1 不想说啥,手机还好,其他就呵呵了 358 | -1 垃圾这个手机,连4G信号都没有,还不给退货,还说我的卡坏了,真有意思这商家!务差差差!货假货假货!万别买这家了! 359 | -1 刚买半月就降价价保也申请不了,不太满意 360 | 1 很好,发货速度很好,东西也很好! 361 | 1 价格适中,买的很合适,物有所值,替顾客想的很周到,还给配两个手机外套,我都动员身边亲朋好友使用手机就使用国产华为手机! 362 | 1 手机很好!华为值得信懒,京东专卖也是值得信懒的,别人肯定会说想得京豆就说好的,错!京东京豆我从来无用过,大钱花了还差那几个核桃俩枣吗 363 | -1 NIMA,外形满分,确实挺不错,挺漂亮的,游戏性能也不错,挺好的,吃鸡,王者都很流畅。摄像头只能用渣来形容,2400W?微信视频画质还不如以前800W的摄像头,模糊不清,好像打了马赛克一样,这NIMA的也算是2400W应该表现出来的样子?买这机器主要看中的就是拍照,结果拍照一塌糊涂,大失所望。本来后续换机准备支持一下华为,支持一下荣耀,但是就这吹出来的质量,实在让人无法有支持下去的动力。 364 | 1 质量非常好,运行非常快,一点都不卡,我非常喜欢这个手机 365 | 1 货收到了 手机很漂亮 显得高大上 手感不错 运行流畅 物超所值 强烈推荐? 366 | 1 电池续航问题方面有待提升,感觉好点挺快 367 | 0 发热严重,续航一般。一天两充最少。后置摄像头有点歪。3%开始充满1小时10分钟,挺快的。吃鸡玩了一把不卡。手机外观好看 很喜欢 小米mix2S从发布抢到现在,心很累。看到荣耀10很好看就买来试试了。感觉还可以吧。希望国产品牌越来越好。图没拍懒得弄了(▽`)ノ? 368 | 1 很不错的手机,非常满意 369 | -1 颜色不一样 370 | 0 午拿到之后,下午逛街看到实体店有,问了价格,2799,比实体店还贵. 371 | -1 发热特别严重,耗电也快,客服态度也不咋滴 372 | -1 和你想的不一样,手机也不怎么地 刚拿来玩游戏就卡,手机发热,烫手的那种 373 | -1 有意思,买了不到十天,就降价~ 374 | 1 很不错,收到第一时间就打开看看,确实很好看 375 | -1 王者荣耀打开直接卡死机 376 | 1 屏幕显示效果清晰通透看不出颗粒感,支持息屏显示,做工精细边框缝隙极微,背面竟然可以当镜子用?试了两把吃鸡相当不错,音质也不错 377 | 1 好手机很快… 378 | 1 东收到,但是由于是帮别人买,也没有使用的授权。只当收货了 379 | 1 屏幕很清晰,像素挺好,用的感觉挺好的,给个赞?。 380 | 1 手机还在慢慢体验中1但是手感很不错?很不错(*?╰╯`?)? 381 | 1 打游戏流畅,拍照像素也可以,总体来说还好。 382 | 1 错很好!全新正品! 383 | 1 用了几天后评价,比想象中的好,电池待机长,拍照效果超清晰 384 | 1 手机很好看,颜色很炫,性价比高,还有赠品,非常划算 385 | 1 用起来比较顺手,现在安卓系统比以前好用的多,手机速度比较不错,有的功能还没用,以后有问题再评价 386 | 1 出仓,快递挺快。送的手环比较鸡肋。 387 | 1 好的,性价比很高~ 388 | 0 外观可以 玩游戏** 卡 389 | 1 很漂亮的外表,上手很舒服 390 | -1 有点怀疑是假货,窗口小工具没有桌面天气。 391 | 1 拍照效果不错.玩游戏卡得# 392 | -1 价格变换太离谱了,18号到手,10.1就降价,申请价保还说没有,服务太差劲了! 393 | 1 手机不错,值得推荐,很喜欢! 394 | 1 卖家服务态度很好,是正品,国产机就是不错,还没开始用,希望用一阵以后还是如此? 395 | -1 快递可以说是没效率可言。拿到手机后都没心情去看手机质量怎么样了。如果在这个社会服务效率没有。一定会被这社会淘汰。 396 | 1 手机非常好,棒棒哒,愉快的购物,下次还来! 397 | 0 被这外观骗了 398 | 0 东西也还行吗,物流比较给力 399 | 1 期待很久的荣耀10,我们花粉家族引以为傲的一款手机,不管是外表还是内在运行都不会让人失望,不错 400 | 1 旗舰产品,性能优良,值得拥有 401 | 1 质量好,服务好,是正品,不错 402 | 1 运行很流畅,给儿子买的,抱着我腿说喜欢。 403 | 1 手机非常好,就是物流有一些慢,早知道发顺丰了,推荐买非常好 404 | 1 挺好的,性能很好,操作也很流畅,性价比很高 405 | -1 喇叭坏了 406 | 1 荣耀10总体来说是不错的,这个价格已经很好了 407 | 1 国产手机中的精品,外形很酷,性能强劲,电池耐用! 408 | 1 很实惠,颜色没有图片上的亮,也蛮好看的。性能蛮好的,很喜欢。 409 | 1 很不错,非常好的手机价格也是很好的。 410 | 1 收到宝贝了,快递非常给力,一天就到了,而且手机很好无损坏,外壳很好看,还赠送了许多东西,很满意 411 | 1 双十一下单,当天发货,物流挺快的。手机质量不错,商家信誉也不错!下次买手机再来! 412 | 1 手感不错,反应速度很快,打着王者好助手,很好。 413 | 1 手机贼好用,我用的第一部荣耀手机,小米和华为一直是我喜欢的品牌,希望越做做好。不过华为的拍照确实是国产巅峰了 414 | -1 *客服,退货都不可 415 | 1 京东商城各方面都还不错。非常不错,快递很给力,而且配送员的5很好,很好;关键是售后服务很到位,至少在中国,出现注重产品质量及服务细节的公司不是非常多,希望京东带动整个电商行业进行一次行业变革。 416 | -1 给我发这种颜色不喜欢 417 | -1 垃圾手机,什么都不想说,最好别在这间店买,一有问题就叫我去附近售后,兄弟姐妹们最好别在这买 418 | 1 手机很不错,拍照清晰,反应快,屏幕分辨率高! 419 | 1 手机收到了,高端大气,是我喜欢的大屏手机。使用一段时间再追评,感觉应该不错。 刚收到手机后我问客服新手机用再贴钢化膜吧,客服说用贴,等了两天我邮购到了钢化膜想让朋友帮我贴上,人家说手机带着膜呢,不用再贴了。 420 | 1 机挺好用,蛮好用的,现在身上带个x带个荣耀十一个用一个打游戏,美滋 421 | 1 手机的刘海非常喜欢,手机尺寸单手玩无压力,无论是玩游戏还是看视频都很好,处理器内存都是很不错的,下次补图吧 422 | -1 包裹被物流公司弄丢了 物流公司迟迟不给答复 423 | -1 @商铺,没有保价打什么11.11误导消费者购买,10.21购买2499到11.11就降到2275,此商家不诚信!购买需谨慎! 424 | 1 用了一段时间才过来评价,整体来说还是不错的 425 | 1 机挺好的,店老板也送了礼物,总之这是一个不错的商家,祝老板生意兴隆! 426 | 1 不错,好用,大屏 427 | 1 手机很好用,但是买完就降价几个鬼意思 428 | 1 手感不错,速度快,机身小巧,屏显示大,全屏,视频效果好 429 | 1 等了好久,终于到手了,速度快,声音好,拍照灵! 430 | 1 6月1号到货还可以吧,打开看了是正品,还送了手环,蓝牙音箱手机膜,店家服务态度很好,快递员也好,手机用了还比较满意 431 | 1 手机很好用,电池电量有点小,玩游戏耗电比较快,其余的比较完美 432 | -1 指纹不灵敏,老是没反应。 433 | -1 手机屏黑边大,wifi信号连接不稳定 434 | 1 用起来很流畅,很顺手,还非常漂亮 435 | 1 快递很快,服务很周到。现在购买还能有好多赠品。确实不错。 436 | 1 公幻影蓝,我幻影紫,绝配,很赞? 437 | 1 麒麟970很好,运行流畅,ai摄影强大,效果不错。吃鸡开高清也没压力,音质可以,快速充电确实很便利!很适合的一款手机,应该够用两年。出门别忘了带数据线 438 | 1 手机用这着不错,用了一星期了,感觉挺好用, 439 | 1 手机挺好用的 440 | 1 手机是正品,续航并不像其他评论说的那么渣,我玩#40分钟耗电5%,玩吃鸡大概40分钟耗电22%,感觉还不错;手机外观特别好看,拍照确实很强大。 441 | 1 手机非常好,屏幕大,像素也不错,主要还是长得好看 442 | 1 比想象的大 看电视 音质非常好 玩游戏也得劲 443 | 1 物流速度很快,手机手感很好,拍照效果不错 444 | -1 收的时候没看 赠品少了一个 445 | 1 就是物流发货慢了一点,手机质量不错! 446 | 1 这个必须点赞,轻巧不失靓丽,单手把控,运行速度,待机耗电也是没的说,很满意,其他功能等继续使用几天再说 447 | 1 荣耀10真的是很不错,运行非常流畅,店家赠送的小礼品也很好,值得购买 448 | 1 屏幕挺大的,适合眼睛不好的 449 | 1 手机感觉还不错,物流快。不知道耐不耐用 450 | 1 非常不错的手机,可以入手 451 | 0 不能插储存卡,刘海不好看,拍照还不错,我不喜欢 452 | 0 手机漂亮是真的,但是,手机耗电是真的快,还发热,重点是那个home键是一点也不灵敏,指纹得刷好几次,而且那个看后台应用划几次能成功一次就不错了,也许你会说可以用脸部识别,那不好意思,脸部识别讲真也不快。 453 | 0 帮同学买的,她已经看了很久了昨天晚上刚下单第二天早上就到了物流杠杠的,手机到手后玩了一天的刺激战没有什么问题速度很快~手机颜值也可以哦,不过手机壳要重新买好看的来哈哈啥 454 | 1 感觉很不错,还没用,应该很不错,价格合理,配件也齐全,值了。 455 | -1 这个颜色很奇怪,真的很奇怪,买到的手机颜色和自己选的时候看到的完全不一样 456 | 1 手机真是太好了,早就想买了, 457 | 0 只能说还行,现在手机旗舰机其实没看出来比千元机好在哪里。 458 | 1 手机是正品的,很好用,一点也不卡,屏幕清晰度很好.外观很好 459 | 1 手机很不错,是正品,物流的话还可以,因为我们这里较为偏远,所以总体很不错,满意的网购 460 | 0 手机出现在夜间面部解锁失效。 461 | 0 实话实说:1-电池不给力,体验很差,9电量,一会就到2,到2后正要切超级省电,直接关机,soc电量显示肯定有问题,电压衰减跳降?2-双卡,一个电信一个移动,移动卡收不到短信或严重滞后,卡换别的机器里都很正常,不知道找谁解决。手机小巧,漂亮,手握感觉不错,这是我最喜欢的。 462 | 1 确实很好用! 463 | 1 不错,很好。照相超级棒。一直用荣耀系列。卖家很好,赠品比自营的多。 464 | 1 手机的质量非常好,运行速度很快,打游戏也不卡,颜色非常漂亮,是正品,很棒,包装很仔细,严实,配件齐全,非常喜欢这款手机,非常满意的一次购物, 电池还可以,物有所值,值得购买。 465 | 1 屏幕大小合适 466 | 1 物流很赞,手机性能很好,用起来不会发烫 467 | -1 不要买了 服务 售后 和没有一样! 468 | 1 好好好好好。 469 | -1 太气人了 一星都不想给 买的时候都有赠品 但是去拿快递就一部手机 包装就一个塑料袋装着 赠品那去了 当时心情就不高兴了 然后联系客服 客服说你拍的没有赠品 难道说你那上面的赠品都是摆设吗 都是忽悠人的 如果你这一款没有赠品你干嘛还要在上面写赠品什么什么的 这不是在欺骗消费者的吗 470 | 0 用了10多天,说实话一般般吧,优点就是好看、通话声音大、拍照也不错、nfc也很灵敏。缺点:这两天按键经常失灵轻按一下就直接返回到桌面、非原配充电器充电很慢、玩王者拖影明显经常有特效拉一条在屏幕、王者掉帧严重、不支持微信指纹支付(所有华为手机都是)、手机不带套后壳容易花,总结来说日常用还可以,玩游戏不推荐用华为品牌的 471 | 1 手机挺好用的,颜色挺好看,,就是京东快递有点慢,买了4天从送到 472 | 0 宝贝收到,快递很给力,点赞!手机本身薄轻,手感不错,就是机身很容易发烫,号称游戏手机,可小朋友玩个弓箭射手都卡得要死,而且还时不时闪屏,无语! 473 | 1 直是华为的老用户,手机手感好,使用流畅外观也好看,支持华为。 474 | 1 荣耀8到10很容易上手,分辨率高了,照相效果上了台阶,推荐花粉购买。快递也很给力绝对正品! 475 | 1 懒得拍图了,手机无瑕疵完美 很满意。希望能用久一点。 476 | 1 好评,不错,手机很喜欢 477 | 0 整体感觉不错 到没注意到的是摄像头外置 严重影响美观 如果能够改进将会更满意吧 478 | 1 快发工资了,下定决心换个手机,咱还是很看好国产手机的,手机都有性价比的说法,虽说小米性价比不错,但自己更喜欢华为。 479 | -1 早上拿到手机,充电有声音其它还在测试 480 | 1 国庆购买,京东物流就是快,屏幕很好,荣耀商品值得信赖 481 | 0 手机性能都很不错,使着也很顺手。唯一的缺点真的像网上说的火麒麟,费电很快! 482 | 1 天刚到货 要下载的下载 开始试用 感觉很好 总之 给个好评吧 。 483 | 1 运行速度还可以,电量续航能力还没检测,等用用看,大屏非常满意。 484 | 1 用起来感觉很不错! 485 | 1 手机很好,与描述相符。支持国货 486 | 1 从下单到收货两天时间行程一千多千米,真快。手机收到原装,试用几天很好,反应快、相速好,值 487 | 1 手机很好看,运行速度快,卖家服务很好。 488 | 1 不错。还可以挺漂亮的! 489 | 1 从荣耀6到9,家人都在使用,我自己的荣耀7已用近三年了,对比几款手机后还是决定买了荣耀10,使用后总体还可以,就是电池续航时间没7长,小@也没有7的音质好。 490 | -1 买回来1个月了,手机屏幕开始失灵,建议大家不要买 491 | 1 东西很不错的,很喜欢!好用! 492 | -1 屏幕里面有好明显的黑点,百级无尘车间??真服了 493 | 0 手机就不说了。会员购物回馈京豆,1899元回馈949京豆? 不是该1899吗? 494 | 1 手机好用,屏幕大,配置高性价比高,家人很喜欢 495 | -1 别无脑吹国产,充电慢,耗电快,还卡, 496 | 1 给客服赞?!很耐心解答,另外手机棒棒哒!颜值很棒! 497 | 1 非常不错。 498 | 1 一直是华为的用户,这次也没让我失望。先说外观,很惊艳的机型,适合年轻人使用,屏幕小刘海是亮点。配置上对我来说足够用了,玩游戏和使用各种软件很流畅,不会发生卡顿,手机发热量也还可以接受。总之是一款值得购买的手机,支持国货! 499 | 1 收到宝贝了~看着很不错毛高大尚,送老婆的还没用先冲电,应该不错的一直用华为支持国货。用后再来评 500 | 1 满意的购物,专门试用了过后来评价的。希望能够后续有更好的使用体验,不过感觉按键不是太灵敏。 501 | 1 待机续航时间2天豪无压力,正常使用1天1夜,再长时间没试过。手机大小合适,一只手操作感觉舒服。 502 | 0 手机用了一段时间,频繁弹出其他应用,比如看着视频莫名其妙其他应用就弹出来了。问了手机售后没有用。只针产品不针对商家,以后不会再用华为任何产品了 503 | 1 手机好用,但感觉机器还是挺耗电的 504 | 1 手机是真品 太漂亮了 运行也非常快 我好喜欢 505 | 1 特别喜欢分辨率超高,物有所值,快递也很快,这次购物很满意 506 | 1 很好,送货及时,正在使用,很流畅,比原先的荣耀6plus要狭长一些。 507 | 1 荣耀10运行很快,外观,做工都很好,推荐购买 508 | 0 很好,非常满意 509 | 1 先东西送了好多!评!!然后手机性能很好,而且连接网络速度很快,绝大多数功能都比较齐全,打游戏尤其顺畅,我这是用手机两个星期左右了才来评价的,还有就是说一些小缺点,可能电池充电速度没那么快,要三四个小时才能满,还有就是一些功能上比如转屏感觉还不够灵敏,但是手机颜值还是阔以的! 510 | 1 仿佛是一件精品,店家服务态度很好呢 511 | 1 很好很喜欢 非常好 很棒 以后还会买 512 | 0 手机挺好用的,就去电量用的很快,不打游戏都这样 513 | 0 手机颜值高,上上网,聊聊Q,微微信,游游戏,运行流畅,拍照清晰,电池两天一充,指纹识别不灵敏是硬伤。 514 | 0 可能是地区的过,次日达很尴尬 515 | 0 电量掉的太快了其它的在用用再说 516 | -1 非常差的一次购物体验!第一次遇到这种情况!买手机的时候不给邮寄发票!联系以后给邮寄了一张没有盖发票章!现在又要折腾我一次!以后不是京东自营的东西我看是买不成了! 517 | 0 第二次使用荣耀手机,之前是荣耀8.之前手机因为内存32g太小,无奈换了这个荣耀10.荣耀10外观漂亮,全面屏,拍照多了一些好玩的功能,清晰度也比荣耀8好。安兔兔跑分没出现发热现象,看了评论中那么多说发热的,我这倒没有。荣耀10清晰度高点,但拍照效果一般。看视频时感觉色彩不是很好,还不如我之前的荣耀8.玩王者荣耀确实触屏手感不是很好,有时会出现误操作。喜欢看视频和玩游戏的朋友慎重选择。另外荣耀10出厂有原装膜和手机壳,所以卖家送的膜和壳基本用不到,送的耳机音效很差。现在的价格还是双十一的价格,还多送了指环架。看来这个手机确实保值率很低,掉价比较快。 518 | 1 手机收到了,目前还可以,没有什么问题,收到的赠品也很多 519 | -1 这就是照片中的幻影蓝 520 | -1 看个微信朋友圈都能卡,死机几分钟?那还买它做什么 521 | 1 给我小弟买了个手机,打开看了一下,还没有用,他还没回来,等回来了就说用一段时间再给你们追评,很好,下次还来光顾。 522 | 1 非常正点的手机,整个一小平板一样。商务气息十足。 523 | -1 拍照和视频极其模糊,所谓AI摄影技术完全没感觉出来 524 | 1 给孩子买的,机型,运行速度,孩子超喜欢! 525 | 1 超级喜欢,特效功能都不错。很喜欢! 526 | 1 刚使用了几天,各方面性能稳定,运行速度没得说。就是刚化膜有多送一个就好了,谢谢! 527 | 1 还行吧,看着还不错,用一段时间再追评。 528 | 1 手机很好,整体很流畅,拍照很美,玩起来爽 529 | 1 给老公买的,他说太好用了,非常满意的一次购物,物流快递安全送到家,服务态度好!全5分 530 | 1 手机挺好,反应速度挺快,游戏不卡顿,我也能上王者了 531 | 1 还不错哦,是正品哦,用起来很好 532 | 1 手机很流畅,这配置杠杠滴,一点都不会卡,拍照也清晰,还有超级快充和普通快充的功能,用原装充电器超级快充只要一个小时多就充满了,真的超级快的! 533 | 1 惊艳无比,系统流畅,拍摄清晰,非常棒 534 | 1 手机杠杠的,打游戏专用手机,吃鸡荣耀开顶配畅玩。 535 | -1 不怎么好跟预期差很多 536 | 1 很不错 不过用感觉有点卡 不知道是系统没更新还是怎么回事 反正很好看 用了几天感觉好多了 荣耀从没失望 支持国产 虽说有抄袭的地方 到也可以理解 537 | 0 色挺好看的,手机外壳很脆,才买了一周就裂纹了,更换需要20 538 | 0 扬声器有问题 539 | 1 屏幕很好,送的钢化膜一点用也没有,一摔就碎,稀碎稀碎的!非常好用!送的保护套也没什么用。手机掉地上很华丽的摔坏了! 540 | -1 说好送一年延保,送个鬼,@的,还不如在别家买! 541 | 1 还是京东买手机靠谱点 前几天我在**看见荣耀10是2599 比京东便宜200块 但是想了想还是在京东买好一点 所以多200块 最后还有优惠100就是2799-100=2699 反正我不差钱 这家店的手机真的挺好用的 服务态度也很好 542 | -1 了不到10天降价了也不给保价! 543 | 1 很不错啊 544 | 1 非常喜欢手感超棒有个性值得拥有 运行速度也值得点赞 545 | 1 蓝色很漂亮,验了一下,是真机,先玩玩再看吧,很流畅 546 | 1 手机真心不错,上网网速很快,值得拥有 547 | -1 手机用一下会发烫 548 | 1 手机收到了,质感好好哦?清楚度超高? 549 | -1 不得行,返回键失灵,客服 550 | 1 华为真的很不错 再买还会买华为的 551 | 0 我不知道手机是不是就是这样,人脸识别刚开机半天还算快,上王者总是技能发不出来,图片这个小程序,拖动很困难,玩吃鸡两小时没电,王者正常点,还是少在网上买了,刚收到没有点过头条里面就有6张头条图片。已经确定在京东买了两个问题手机了,这个感觉也不是很好 552 | 1 手机不错,还送了外壳,贴膜,送货及时,这是非常愉快的购物。 553 | 1 玩王者,吃鸡毫无压力,像素很好,张张照片都像大片的感觉 554 | 1 手机手感舒适,速度很快不卡段,照相非常清晰。 555 | 0 玩游戏也就死机几次,没我原来小米2新机的时候好,其他也还可以 556 | -1 微信拍摄***卡断 557 | 1 给亲娘的生日礼物?n专门买的这个炫酷颜色!美哭了!亲娘很满意!送的耳机和透明外壳很棒? 558 | 1 手机很好用,小巧精致。我不喜欢太大的,这个正好。赶上活动,也很实惠 559 | -1 拍照模糊,一般,特别是快递员态度恶劣,卖家售后推卸责任,真是瞎了眼选了他们这里购买 560 | 1 东西很好,很喜欢很好用。爱人很开心 561 | -1 了不到三天降400,请问可信度找谁保证?人民贬值了。 562 | 1 屏幕效果不错.手机很流畅。 563 | -1 不满意,才买10天就降价100元,还不支持价保 564 | 1 不错 官方机 565 | 1 手机很好,质感不错,使用非常棒,卖家发货也很快,手机性价比很高值得购买,非常棒的购物体验! 566 | 1 航还行 拍照很清晰 而且还有乐趣AR合拍? 567 | 1 我觉得这个手机就是个新鲜感,功能多,拍照赶不上OPPOr15,手感还不错! 568 | -1 打游戏发热超级严重,差评 569 | -1 电话经常性听不到对方说话或对方听不到己方说话 570 | 1 手机很漂亮,很流畅的,超级划算的呀! 571 | -1 机发热呀! 572 | 1 手机很好看,流畅不卡,前后2400万像素,高清拍照,? ? 573 | 1 屏幕颜色表现很棒,机器运行也快,但是很吃内存,6G的常规下剩下不到3G,可能也是Android的问题吧 574 | 0 电池啊 硬伤 其他都好 575 | -1 手机容易发热,打开相机10分钟会烫手。外观蛮漂亮。 576 | 1 手机不错,运行挺快,就是续航能力比较差 577 | 1 性价比超高,,好用手感 578 | 1 手机是正品,品质很好,很流畅。 579 | 1 东西收到了,很不错,就是送的东西质量一般 580 | 1 第二次在京东买东西,虽然说客服态度不是那么的好,物流也不是那么的快,六月二十四号买的,今天六月三十号才到,不过拿手机的那一刻还是很开心的,拆开看了也还满意,第一次用全面屏手机,感觉还不错吧,买不买看大家,手机还是不错的 581 | 1 机 还行 就是耗电有点快 就看后期使用怎么样了,前一把用的苹果手机 因为双卡双待所以换了,就是送的东西我不想吐槽了 一个手环寄了三个没一个可以用的 充不了电! 582 | -1 手机是挺好、不过京东贼坑、买之前问客服问好几次才回我、还不带耳机 583 | 1 直接上图,很满意,外观很漂亮,手感非常好。也很顺畅。很是满意,值得够买 584 | 1 外型漂亮,运行速度快,拍照棒极了 585 | 1 非常快的速度,过年呢,怕送不了货,没想到还是2天到达,完美 586 | 1 还需要六个字 587 | 0 总体来说不错。打王者的时候会发热。 588 | 1 很好,华为越来越棒 589 | 1 手机物流挺快的,显示送的东西也有送,不过确实那个原装的东西要好一点?总的来说还是不错的,对比了几家才买的,用户体验很nice,跟之前那个一模一样 590 | 1 是正品 非常好用 也不卡 物流也特别快 客服也非常有耐心。 591 | 0 耗电太快,不再相信华为 592 | 1 快递速度很快,手机也不错挺好的 593 | 0 这个手机网速好慢哦,我也不知道是什么原因 594 | 1 手机很不错,正品,很漂亮,酷炫。人脸解锁简直秒开啊。送的耳机也是正品,吃鸡神器已经被哥们拿走了。就是正常用着稍微有些发烫,电池用用再说。最好用手机上的膜就行了,贴的钢化膜在物理健的地方是个坑啊,边上还贴不严实。下单第三天就拿到手机了。这家店感觉不错,很实惠。 595 | -1 电池不怎么的,触摸也不是很灵活。 596 | 0 用不习惯,好多东西不会弄 597 | -1 刚买完就降100,还**不能报价 598 | 1 手机用起来还不错,游戏流畅,没的说。有一点儿遗憾的是~对华为不大友好,~游戏不可能录制视频,~新闻闪退频繁。 599 | 1 双11购买的,价格有优势,质量非常好,小巧玲珑,发货很快,滑动流畅,拍出照片清晰,优点多多。 600 | 1 东西很好哦,卖家态度也很好。 601 | 1 我哦懒得填写完整的评价内容但是我又看不得小红点通知 602 | 1 手机很好用。特别是充电速度很快。 603 | 0 可以家人很喜欢 604 | 1 拿到手,外观还不错。用起来手机反应还挺快的! 总体感觉挺好的。 605 | 1 新手机終于到货啦,内外包装都很严,这款产品外观漂亮,功能强大,让人很喜欢。 606 | 1 速度杠杠滴,手感很好 607 | 1 手机很好看 特别喜欢 而且送的东西也特别喜欢 608 | 1 手机无论外观还是性能都不错,是个很好的选择,我觉得不比苹果差,希望都支持国产 609 | 1 总体来说 很好 运行很快 610 | 0 感觉一般,心里没有什么太大的期盼。总之可以拥有 611 | 1 手机是正品,正在学习中,用着非常不错 612 | 1 相比朋友的荣耀V10!这款性价比更好点!拿在手里大小刚刚好!满意! 613 | 1 给儿子的,手机外观时尚漂亮,拍照清晰,使用流畅,好评。 614 | -1 东西一般,才买一周不到就削价100元,我这还没开始用呢?都说京东是可以保差价的,它家就是不同意,心中不爽就是不爽,以后买东西要瞅好了,物不美价不廉的千万别买,宝宝容易上当受骗。 615 | 1 这是家里买的第五个荣耀系列的手机了,必须给好评,手机操作反应速度很快,屏幕不刺眼,很满意5分好评! 616 | 1 看了很多款,还是觉得这款最好,机身漂亮,屏幕大,运行速度也很快,送给朋友,他说很喜欢! 617 | -1 不配叫做玩游戏手机,玩吃鸡开高帧率都卡 618 | 1 真的很漂亮,甩苹果?几十条街,我一直用魅族的,现在的魅族除了系统好以外都不行了,果断换华为,想入手p20的,但是看荣耀配置差不多,就荣耀了,黑色也很漂亮,手机轻,手感好 619 | 1 我终于来评论区了 玩了一个星期多 还可以 支持荣耀 620 | 1 屏幕非常清楚,电池正在使用中。已后再追评吧。总的来说不错。 621 | 1 手机收到了,东西还是挺好的,就是这个搞活动什么赠品都没有?。买的第二个了,幻影蓝还是挺好看的,手机也很顺滑,速度很快。棒棒哒。 622 | 1 物有所值,速度很快,用着很好,物流也快,客服很耐心,服务周到,必须五分好评。 623 | 1 外形美观大方,存储空间合理,尤其是拍摄效果非常好,很满意! 624 | -1 千万别买 625 | 1 还好 应该是正品 用的没什么问题 还是蛮好的 626 | -1 这个就是图片上的幻彩蓝,差距太大了 627 | 1 第一次买华为手机。挑选了好久。选了这家。手机很快就到了。很惊艳。确实很好看。赠品也很多。送了钢化膜。我不知道要不要贴上去。手机自带了一个膜。手机特色就是炫酷,全面屏。刚打开下载应用,准备吃鸡了。喜欢这款手机已经是gt版本。游戏加速。性价比高 628 | 1 第一次购买华为的手机,屏幕效果看着还不错,app的打开速度和流畅度都可以。 629 | -1 才买没几天就降价了 630 | 1 物有所值 631 | 0 该款产品尚可 632 | 1 手机便宜,质量非常好,是正品全网通,下次还会购买 633 | 0 产品收到了。很喜欢。就是有的时候在京东买东西售后很慢。特别是手机类别的产品。有的时候就特别快 634 | 0 玩游戏老是跳屏 635 | 1 用了三四天了,还不错哦,考虑了很久,果断下手了,荣耀10棒棒哒! 636 | 1 确实是一款不错的产品 ,拿到手的一刻很惊艳,很漂亮,想想当时就决定是它了,功能也很完全,质量也很可靠! 637 | -1 没有耳机,其他以后追评,没耳机真别扭! 638 | 1 绝对正品,荣耀还是很给力的,好评好评好评好评好评好评! 639 | 1 用了两天,还没发现什么问题。赠品挺多,刚好都用得上 640 | 1 送了自拍杆,还有充电宝,最棒的是运动耳机,很舒服运动起来不容易掉,一年了给亲戚朋友买了不少手机,次次有惊喜,逛京东,都成了碎片时间的首选了 641 | 1 实物与照片一致,物流也可以! 642 | 1 十分不错,手机给八分,物流给九分,快递员服务态度我可以给十分(刺激战场可以开到倒数第二个高清画质) 643 | 1 简单大方 很流畅。实用了一段时间才来评价 华为还是不错的 放心购买吧 644 | -1 以后不要买第三方的东西,三包期内换货难,服务没保障,服务体验差,网上本来就不能看真机,买错了还不能换,我是618买的,机子没开封,发现下错了单,店家不给换货,换货要按现在的价格去重新购买,网络本来就是虚拟的,很多东西都看不到,服务体验还跟不上,真叫人心寒 645 | 1 手机一直很想买,正好降价一键购入,是自己想要的,很好用! 646 | 1 手机挺好的哦,是原装手机!物流速度也快,服务态度也好,赞? 647 | 1 荣耀10不错,做工精细,像素很好,老婆很喜欢。 648 | 1 很好用,处理器970,128G内存,手机充电快耗电慢入手值了 649 | 1 先用几天再说 650 | 1 用了一个多月了!相当满意!运行速度,拍照质量,都无可挑剔!唯一有点儿累的就是大,沉,掉脸上很疼! 651 | 0 刚用一天,自己重启两次后续用用看吧 652 | 1 流很快,东西收到了,很好看具体性能用两天看 653 | 1 很不错呢,很愉快的一次购物 654 | 1 很好,用了蛮久了才来评 655 | 1 机拿到了。物流非常慢啊。21下的单25才拿到,目前正在使用,先用两天看 656 | 1 活动买的,价格优惠200!是使用一段时间来评价,是正品! 657 | 1 手机挺不错 658 | 1 手机质量杠杠的,用了一段时间了,很满意!卖家发货也快,包装也好,赞一个。 659 | 1 华为荣耀10看起来真的很漂亮,用起来也很流畅。缺点是有点发热,边框太大,希望出更好的作品。 660 | 0 单运行个微信,剩余的内存就还剩2个来G了?????慎买 661 | 0 京东物流迅速,双十二送货还那么及时,手机还可以。性价比比较高,用一段时间再来。 662 | 0 就那样。 663 | 1 绝对全新货,没问题,美的很!值得拥有 664 | 1 手机外观很漂亮,拿在手上也是正正好好的感觉。前摄后摄都是很高的配置,加上AI技术的运用,拍照的效果真是令人惊奇! 665 | 1 机很好看,手感用着也不错,非常喜欢这张手机! 666 | 1 手机壳很漂亮6G运行速度就是不一样 667 | 0 还行吧,不错,过两年再买新的呗, 668 | 1 电池用的有点快。别的都很好。 669 | -1 收到没到一个月就黑屏 开不了机 ? 670 | 1 第三部华为了 第一次用京东 物流特别快前天晚上下的单第二天上午就收到货了 用着非常不错 人脸解锁 特别方便 671 | 1 速度很快,内存也足够了,很不错啊 672 | -1 客服垃圾,耳机也没有发 673 | 1 感很好,运行很流畅,挺喜欢的,荣耀系列果然没有让我失望!持国产! 674 | 0 10分给6分吧! 675 | 1 手机收到了,挺满意的,外观颜色很喜欢,手感也不错,以后开启刷脸模式? 676 | 1 用了一段时间,手感速度都不错 ,看着也很美观,照相也很清晰 677 | 1 很满意,屏幕很大,也是我想要的款式 678 | 1 手机反应不错,拍摄效果好。特别是手持夜景。支持华为! 679 | 0 手机发热严重 特别容易发热 手机手感很好款式很好还行吧 680 | 1 妈非常喜欢,用着不错 681 | 1 感觉不错,运行快,外形也很好看,物流也不慢,用了2个月才评论,感觉很好。 682 | 1 刚收到手机,后续好用的话会跟进过来评价 683 | 1 手机大小、样式很满意。以前用努比亚,现在使用华为,功能方面还没有完全适应,不过会很快适应的。 684 | 1 非常不错 685 | 1 用的挺舒服,在华为官网验证为真 686 | 1 华为品质,值得信赖。中国的骄傲! 687 | 1 颜色比较喜欢,手机能用就行,这个对我来说已经配置超了,真的是喜欢才表预算买的 688 | 1 第一次在网上买手机,好多人都说网上买手机假货多,这次购物体验很棒,已经用了三天了,很棒,值得入手? 689 | 1 好用,手机速度也很快,店家包装得很好,不怕摔到 690 | 1 手机挺流畅的,买到钢化膜的前一天不小心掉地上了,换了次屏,幸亏有碎屏险。玻璃比较脆,还是得小心,客服还不错 691 | -1 原装手机胶套四周有毛边,拿着割肉,反馈也爱管不管的,到目前都没个满意的回复! 692 | 1 说其他你看看好不好,6到爆啊? 693 | -1 指纹更本用不了 694 | 1 对照相特别失望,还没有荣耀8拍的清晰,前置自拍,把美颜关了,都像极度美颜过的,拍不出清晰的照片,好像蒙了一层雾,老是看不清楚,后置好一点,但是也不清楚,老感觉照片失真,就是用专业照相的那个功能,也就普通相机的清晰度。其它性能还好,如果想要拍照好的,建议不要购买。 695 | 1 手机速度颜值还不错,电池不经用;电商后续冷淡,不咋滴。 696 | 1 不错,一直买的这个牌子,非常满意! 697 | 0 也就那样 一般了 698 | 1 手机一级棒,当时买了64g.隔天发现128的只此64的贵200,果断退货,买128.京东售后很好,无条件退货买128的,真心给个赞! 699 | 0 货盒明显被压过,还好手机没事 700 | 1 手机外观炫酷,功能强大,系统特别流畅,待机时间不错,商家靠谱,物流特别快 701 | 1 手机到了,拆开包裹一看,很漂亮,手感极佳,很美观,性能也很不错,好评。 702 | 1 一直是荣耀的忠实用户,荣耀10玩游戏流畅,拍照也很好,外观很酷炫,赞一个! 703 | 1 手机收到已用一段时间,感觉到很好,功能多,声音清:拍图淸析,内存较大,手写字体较靓,是一台非常合我理想的手机。就一台手机拍不了照片 704 | -1 机器来回在页面闪退,发热 705 | 1 使用正常,价格优惠,赠品也实用,客服响应也十分快捷周到! 706 | 0 说个问题,我们一宿舍在王者开黑,人家一千多的手机不卡,我这卡的# 707 | 1 外观很惊艳,照相很清晰,非常满意! 708 | 1 手机收到惊喜十分,颜色也是我喜欢的没有色差 售前老板人也好的回答我的问题 ,物流也挺快的贴心的送上门 709 | 1 非常棒手感好反应速度快,外观精致,渐变色很靓丽,屏幕分辨率高,色彩饱和度强,支持华为,支持国货,这家购买赠品也很给力哦!会继续关注! 710 | 1 感觉很不错,下次再继续买, 711 | -1 没耳机,扣一分!充电烫,扣一分!玩游戏烫,扣一分!系统和软件老旧,更新花了我一天时间,扣五分!下单第二天降价,扣五分!运行流畅,加五分!美观,加两分!极速充电加两分! 712 | 1 用了很久才来评价,非常好的一款手机,速度快,像素高,手感也好,总之,很满意 713 | 1 手机买回来用了几天,说下几点感受。首先像素很好,拍照也有很多功能,手机手感舒适,外观漂亮。运行游戏都很流畅,手机整体性价比比较高。电量不玩游戏的话还是炒鸡耐用的,充电特快。还有很多小功能还在探索中,给个好评! 714 | 1 手机是正品,刚拿到。目前很好用,赠品比较多,外观比较漂亮。 715 | 1 京东物流,速度快,次日达;手机不错,很漂亮,大小合适,单手使用方便。 716 | 1 手机很漂亮很喜欢 手感很好 大爱荣耀? 717 | 1 幕爽 ,行也很快 。游戏没压力,池也很耐用。嗯,满意的 。快递小哥也给力, 718 | 1 挺好用的!就是不知道后续有没有问题 719 | -1 不好用,自动截屏,速度慢,先差评,用用再说 720 | 1 目前用着挺好的,满意 721 | 1 特地用了几天评价,现阶段比较好用,国产手机也是很不错的,京东购物快递也可以,比较满意的一次购物 722 | 1 一直用荣耀的手机,品质还算挺好的。 723 | 1 部手机看了好久,手机反应快一点都不卡。和图片上一样只是耳机不怎么样,对这个手机卖家我还是顶你? 724 | 0 照相比较好 系统比较流畅 玩吃鸡游戏麦有杂音 滋滋响 725 | 1 质量不错,手感很棒,运行流畅,值得拥有! 726 | 1 手机颜值很高,运行也很流畅,尤其是拍摄功能非常强悍,完全满足了我的日常拍摄需求。 727 | 1 非常漂亮,分辨率也很高,用着很流畅! 728 | 1 这是商家送的赠品,刚到的全新手机,运行杠杠的,荣耀发热问题也处理得不错。可以入手比自营店的还要便宜。更划算。刚入手其他的方面待评价。 729 | 1 一直都是用华为的,真心不错? 730 | 1 价格合适,外观满意,大小握在手里刚好。分辨率高,特意玩了一把王者荣耀,很流畅,电池也不会发热。 731 | 1 东西很好 732 | 1 手机收到了,非常喜欢,像素音质都很好,机身手感也很棒,赞一个 733 | 1 很好的手机,全新的。拿来玩了一会,很流畅,速度很快 734 | 1 外观漂亮,质量很好,商家服务好 735 | 1 用了半天,还不错,界面慢慢熟悉中,后面用的可以再来追评,支持国产,送的套子不怎么样,机子运行比较流畅 736 | 1 手机很漂亮 也很流畅 737 | 0 质量还不错,用起来挺速度的,不卡顿,就是WiFi信号不是很好,老是断网,之前用的V8信号都比这个好,没有描述的那么好 738 | 1 用了两天,速度挺快,颜值高,双11搞活动还是很合算的。快递也快,总之很满意。好评。 739 | 1 屏幕好大 740 | 0 机使用感还行吧 还在慢慢适应中 真的不喜欢刘海. 741 | 1 很好用 物流太慢了 手机很好用 742 | 1 手机收到了 感觉很不错 毕竟是国产手机 支持 743 | 1 手机颜值爆表,非常喜欢。运行速度也很快。京东物流也是相当给力,中午就收到。? 744 | 1 物流很快,很不错的,冲胡歌买的 745 | -1 給差评别人才会看到,请客服讲解。手机很好,反应很快,可以确定的是指纹识别很灵敏,至于啊,那些说要20多次才能录入指纹的,该说你蠢呢还是,,,,,,手机的确会有发热的现象,相对已经很好了,毕竟现在快夏天了,拍照功能身为手机已经跟错了,本人是玩摄影的,在光线好的时候用专业模式采用raw格式保存,能和D750媲美了,当然啦,手机的镜头自配的都是广角,要求太多你就输了。目前体验就说到这,还有其它的以后再追评 746 | 1 蓝色的也不错,用起来还很流畅,速度不错。 747 | 1 荣耀10用的是第二代的超声波指纹方案,相比于上一代,第二代方案的识别速度和识别准确率@提升,湿手状况下也能识别的出来,喜欢 748 | -1 外观还行,内在性能就一般了 749 | 1 手机不错,就是物流慢了点 750 | -1 看了好多好评才买的,直接坑死了,直接差评,都在想是不是是不是水军在刷评论 751 | 1 手机收到了,大屏幕大电池巨霸气!!!游戏速度处理速度嗖嗖的!大赞。 752 | -1 发错货,买到海鸥灰发到蓝色 753 | -1 没过多久就有赠品,当时什么活动都没。 754 | 1 手机不错,挺好的非常满意 755 | 1 手机很漂亮,反应快,照相超清 756 | 1 颜值美观,握持感佳,运行起来也很流畅,拍照.音质都挺好!原装正品,服务贴心,赠品也多,京东好店,好评! 757 | 0 机是好手机,但是现在买手机都不带原装耳机的吗?道原装这个词并没有什么意义?不是附带在手机上面的? 758 | 1 手机是正品,还赠送手机壳,膜,耳机 759 | 0 还不错吧!感觉屏幕不灵敏,功能也比较少。拍照过的去!没什么大优势 760 | 1 包装结实,密封,机身流畅,速度可以的,?喜欢,很好 761 | 0 拍照很清晰,手机外观漂亮,打游戏发烫严重 762 | 1 快递非常快,快递员服务态度好,手机试用还可以 763 | 1 荣耀10很好看,很实用,性价比高。 764 | 1 用了几天 总体感觉挺不错 外观手感都挺好 挺上手 765 | 1 手机不错,原本预订V20的,一直没抢到手。直接下单荣耀10,顺丰给力,赠品丰富,手机流畅,128G容量大 766 | 1 手机是全新正品,很漂亮,要是有8十128就更好了。 767 | 0 外观非常好,经常卡顿,不是华为的风格啊 768 | 0 京东速度一如既往的快,手机目前没有什么问题,挺好的,待机时间不是很长,充电速度还可以吧,挺快的,比想象中差一点,卡针不知道在哪里,这个好无语 769 | 1 手机棒棒的,非常好 770 | 1 用几天了才来评论的 挺好的 信得过 771 | 1 发货很快,隔天就收到了,屏幕反应很灵敏,很好用,是正品 772 | 1 值得信赖,满意。 773 | 1 手机很不错? 774 | 0 套上送的保护壳就会沾在手机上形成一个一个印 775 | 1 给父亲买的。用的非常好 776 | 1 外观很漂亮、时尚,用着顺手,物超所值! 777 | 1 这款手机确实不错,拍照没的说,效果很好,充满电可以用一天,喜欢的亲放心购买 778 | -1 充电玩吃鸡直接没电关机 779 | 1 手机运行流畅,与照片相符,非标满意 780 | 1 入手第一感觉,漂亮棒棒的,喜欢大屏手机的,可以下手了,使用两天,系统流畅,续航超级给力, 781 | 0 一般,照片还是很好看 782 | 1 新手机很好用 不卡顿还很好看 783 | -1 格又降了400,客服不搭理人!评! 784 | 1 手机包装齐全,是正品原装手机,外观新颖,与实体店购买的手机一样,这款中老年人用还是可以的,京东网上价格实惠比其他的二手网上手机还要便宜,而且售后与实体店服务条款相同,值得购买, 785 | 1 不错吧,一直支持国产 786 | 1 挺漂亮的,也很流畅。续航没有网上说的那么恐怖,也可能是开了省电模式的原因,感觉还可以。拍照的话,感觉渲染的有些过分了,颜色过于艳丽,不知道会不会通过后期的更新改一下 787 | 1 手机可以 就是物流太慢了 十天才收到货 788 | 1 手机是正版,没有问题,用着很流畅,但是快递不是很快 789 | 1 手机很好。包装也不错。礼品也很多。顺丰快递很快就到了。客服人很好。支持。 790 | -1 手机信号弱,不晓得是不是双十一的原因,送的品牌耳机连个包装都没有,声音小的可怜,怎么查都是满耳朵电流声,要么不送东西,要么送点能用的,耳机买一个也才几十块,无力吐槽了 791 | 1 升级到了9.0,很好,流畅,不卡。 792 | 1 手机到了,很用心的用了空气泡沫进行隔离,商家用心了,电池消耗慢,可以用一天 793 | 1 查验过,是正品,同样的128G手机比别网店省300元,赠送的物品还多,同样价在别网店就是64G的。 794 | 1 手机很好,反应快,电池也好用 795 | 1 店家送的配件挺多的。这手机用了几天,手感不错。拍照也很清晰漂亮。 796 | 1 最爱华为家的手机了,特别是这款,今天上午到,性能没的说,电量完玩了一上午才用了百分之十,想想什么概念,商家服务态度也是极好,值得购买,还在犹豫的朋友赶紧下单吧! 797 | 1 指纹很不灵敏,比较郁闷。其他的都很好。运行速度也很快. 798 | 1 帮别人买的,手机已经使用,有许多功能,使用者用起来不太熟悉,还有待进一步了解,我还没有空见到手机,去详细去熟悉。好像没有送贴膜和保护套,这些也还得去买。基本功能先用着,有什么情况再做进一步评价。 799 | 1 手机挺好用的 就是看视频不能全屏了 分屏也不大好用 800 | -1 有点卡第一次用华为 801 | 1 试用了一个星期。很不错。特来请@, 802 | 1 很漂亮,很精美的一个手机,真心喜欢。 803 | 1 用了这么久才来评价,是因为要试用一下。手机外观漂亮,运行流畅,真的好用。支持国产。好评! 804 | 1 是真机,在官网上验过了,手机挺新的,很好 805 | 1 手机非常好 806 | 1 很好用的手机 807 | 0 总体还能接受,还在摸索中 808 | 0 已入手一周多,感觉系统反应时间比较满意,就不知一年后的效果能否保持,就知道多化几百增加的2G运行内存是否值得,电池持航一股没开游戏,基本一天一充!入手快了点在11。11入手的话可省150块 809 | 1 是正品,用起来挺好。就是手机与赠品分开发货却不通知,让人虚惊一场。 810 | 1 三天到货,手感好,书写流畅 811 | 1 下午才收到入手感觉不错,系统很流畅用,两年绝对没问题。 812 | 0 才用1天,三颗星是给之前p7的 813 | 1 确实是正品,性能很好,非常好用。 814 | 1 不错,像素好,内存大 815 | 1 很好很强大,充电很快,储存很大,因为是新手机,用起来也不卡,尤其是那个可以直接从短信上复制验证码的,省去了很大的麻烦,机身自带的一些应用也非常实用,省去了我自己下载的麻烦,感谢生产者制造者及发明者为我带来的方便 816 | 1 手机摸着挺舒服的 用惯了以前的手机有点不习惯 整体看还好就是后面用着不知咋样 先给个好评 后面有啥问题再追评 817 | 1 用了一个差不多有一个月了吧挺好用的然后玩游戏也也挺好的不卡,紫色的么紫色的那个挺好看 818 | 1 手机很不错,我说的这个东西我很喜欢。 819 | 0 还没用久用久了再说 820 | 1 机子真的不错,是正品,用着很舒服,比实体店送的东西多。值得推介 821 | 1 不错,可以拥有 822 | 1 手机很好,外观很赞。用起来很舒服 823 | 1 已收到很满意物流很快性能很好!不错 824 | -1 商家服务太差,价格定价随意 825 | 1 荣耀10真得是拍照功能很强大,2万4的像素,音乐效果也很好,值得拥有 826 | 1 手机?发货很快,第二天就到货了,用了几天感觉还行,礼品漏发和售后沟通一下就补发了,,这是我用的第三部华为手机了,确实能感受到很大的变化,人脸识别对於我我来说真的很好用,因为我的手老是季节性脱皮,指纹解锁有时都用不了。 827 | 0 手机外观很漂亮,很喜欢;速度也很快;但是玩游戏很容易发烫。 828 | 1 好像华为商城和京东自营都没有这款,据说这款是实体店才有卖的。手机感觉不错。 829 | 1 外观非常漂亮,是我喜欢的款式,新上手使用中。 830 | 1 手机收到了,物流很快,东西很好,很流畅,目前没有什么问题,用着看吧 831 | 0 一般般...说句实在话,拿到有点失望?,居然有时触屏不是很灵敏,以为是屏幕坏的但是试过几次好像又好了,不知道是不是卡顿现象,耗电有点快,不知道这么多人买有没有和我一样的,还有就是刚买的的手机里面有很多软件。。。。和之前的苹果6splus差不多流畅度级别吧(这个确实不吹不黑,和苹果7还有8系列就没比较过了,没钱买) 832 | 1 可以,目前为止没有什么不好的,屏幕够大, 833 | 0 拿到手第二天来评价,手机很惊艳,用起来不错,游戏优化不行,充电比较慢,快递很快, 834 | -1 6.15入手6.19降了120,30天的保价呢?屁话。 835 | 1 一直很喜欢华为的牌子,也习惯用这牌子的手机,网速也快,用着放心 836 | 1 商品很好,6+128G运行速度很快,拍照每张都很好,就像是大片,最喜欢的还是机身的颜色,蓝的好美,好喜欢,这次是愉快的购物,下次还来他家。 837 | 1 手机回来了,看起来不错后背很有感觉,手感不错挺重的,老婆很喜欢,回来就玩手机了,不给煮饭了现在8点了都不给煮饭了 838 | 1 外观很漂亮,机身颜色也好看,拍照效果不错,续航能力可以,总之满意。 839 | -1 池不行!!刚买的少了几百毫安! 840 | 1 常好看,系统也很流畅,拍照还不错,用起来挺顺手的。 841 | 1 机很漂亮店家很好物流超快@的好评! 842 | 1 很好的手机,运行很流畅,物流也很给力 843 | 1 感觉不错,多年ios抵不过国产诱惑虽然一下子不适应还是感觉手感不错,有待提高的是画质像素,显示风格。 844 | -1 刚买过就各种降价和送礼品,真是各种不爽(? ̄?^ ̄?) 嫌弃你 845 | 1 儿子这次非常高兴,自己作主,买到自己喜欢的手机,颜色非常漂亮,机子反应比较快,感谢厂家 846 | 1 给父亲买的,很满意,非常喜欢 。主要是喜欢小屏的,比较轻的。手感不错,背面很好看。性能就不说了,中端机中高端的配置。 847 | 1 非常漂亮的外观,性能也很好。性价比很高了。 848 | 1 用惯了小屏手机,换成这个很快就习惯了,手机运行速度很快,续航也很好一天下来随便玩游戏也不怕没电 849 | 1 不错买了两部了都没问题 850 | 1 快递很快,第二天就拿到手机了,第一次用华为手机,体验很不错好用,毕竟用的麒麟970的处理器,人脸识别很快,手机外观也很好看,手感不错,系统也很好用。 851 | -1 买了大概10天,降价700,购物体验极差 852 | 1 东西很好挺好看的下次还会来 853 | -1 手机里面的包装很脏,电池不满,都不知道被退过了几次,指纹解锁很垃圾,还能用吧,退回去还要邮费,算了!唉 854 | 1 很漂亮 很耐看。大爱华为 !大爱荣耀 !而且配置麒麟970处理器,还有指纹解锁?人脸识别!很棒,识别速度很快。另外能当万能遥控器,很好用 855 | -1 上个月买的到现在还没两个月,指纹键就坏了 856 | 1 手机用着很舒服,棒棒的 857 | 1 外观靓丽,新机速度运行都很快。 858 | 0 大牌包装 859 | -1 不知道好不好用。。。不过还是 860 | 0 手机还不如我用的vivox9呢!作性不如,也就华为喜欢吹牛忽悠人手机外放音质烂得#,耳机音质没法体验因为这是我第一次买手机耳机都不送的品牌了!前唯一觉得好的就是这手机是我喜欢的外观!星给京东快递的这速度我服! 861 | 1 手机手感贴别好,,反应快,一句话就是好,第二个华为手机了,值得购买信赖 862 | 1 手机突然就坏了,没手机可真是急死人,看了好多手机,还是喜欢小屏的,选了个配置满意的,荣耀10到手手感不错,很喜欢,后期追评 863 | 0 外观不错 性能也不错 home键触控不灵敏 864 | -1 手机发热,冬天能当暖宝使,夏天烫手。 865 | 1 货很快,第二天就到了,用了下也很不能,下次还来! 866 | 0 手机发烫,特别是玩吃鸡游戏的时候,其他的还算可以吧 867 | 1 手机太好看了(?)?用起来很方便速度很快,简直不要太爽 868 | 1 宝贝收到,颜值非常高的一款手机,运行速度完美,煲机中 869 | 1 外观漂亮,试用了一下很不错,拍照好看 870 | 1 性价比很高,用了感觉挺好的,速度杠杠的,很流畅。 871 | 0 综合来说,这款产品还是不错的。但一付款,后一天就降了60,货都还未到手就降了。客服也不给退差价。一开始发现也叫我不用拒收,先问一问供货商。收到后说不给退已经降下来的差价,让我退货。一来一回我自己亏个快递费,就为了那点差价又不值。中评。 872 | 1 客观评价一下,充电速度挺快的,但是充电玩游戏,充电速度还没放电速度快,不爱拍照,不评论,电量用的也挺快的,悲剧的是,后盖是玻璃材质的,才用一周,轻轻摔了一下,后盖玻璃碎了,不保修,心都碎了? 873 | 1 东西收到了/是正品行货/第一次在网上买手机不放心/收到后放心了/商家服务很好/给5星! 874 | 1 没有在京东的非自营上购过物。 下单后心里各种忐忑。,收到后,意外惊喜。不只正品包装精美,价格实在而且赠品多多。手感一流,大小适中。运行速度飞快。再也不怕应用装不下了。 875 | 0 之前买过这款手机,用的挺好的。现在买的这款,感觉像被人用过的,把电量用尽,第一次充了不短时间,感觉耗电特别快,不用一会耗好几个电 876 | 1 运作速度还是挺快的,整体不错,电池没发现异常,以前的机子内容小,这个不怕了,爱下什么都行,装什么也行 877 | 1 用了很久了很有手感推荐 878 | 1 用了好几天才来评价的,总体来说还是不错有优惠价购入很值。前置摄像像素很不错,拍起来很清晰,可以美美的自拍了 879 | 1 运行速度很快,电池也耐用,外观漂亮,适合自己使用 880 | -1 说给耳机的耳机没有送过来, 881 | 1 荣耀10Gt已用十天了,整机漂亮 拍照清晰 运行强悍 充电很快 用起来超爽 882 | 1 手机很好用 性价比高 好评! 883 | 0 没有耳机,其它等用用再说吧 884 | 1 包装整洁扎实,赠送的配件齐全,手机颜值高,其他还有待体验 885 | 1 一直用荣耀,从荣耀刚开始出,一直到荣耀10,一直相信京东,信赖京东!相信华为!国货当自强! 886 | 1 用了几天才来评价,手机用起来不卡,很快,我不打游戏完全满足我使用,以后再来追评! 887 | 1 物流发货速度很慢,从北京到北京3天才收到。并且拍的是极光色,发成了蓝色。因为急用就不换了。除此之外,一切都是很好的。ai拍摄可玩性极高。 888 | -1 就想问一下京东自营211限时达什么时候是隔天到货了?这还没过年呢, 889 | 0 第五人格发热严重 890 | 1 自带贴膜和手机壳可以的 891 | 1 机是正品 运行流畅!双11下的,快递慢了点?~ 店家还送了好多东西~省去了买配件的钱了 哈 892 | 1 手机的质量很好 是正品 ,屏幕很大 物流也好快 。 买东西一直很相信京东 。 用的好会推荐给朋友的。 893 | 1 宝贝收到了,颜色很标准,手感也很好,物流的速度特别快,特别棒的一次购物 894 | 0 谨慎购买无奈 895 | 1 手机很好看,大小合适,已升级GPU turbo,使用流畅,几个赠品也很不错,,送货也很快,推荐 896 | 1 东西好,价格也不是太贵,很适合,还会继续关注的 897 | 1 运行速度快,很喜欢,颜色也不错,性价比很高,第一次用华为,真心不错 898 | 1 很满意,不错 899 | 1 手机看起来高大上哦,颜色也是自己喜欢的,这几天用着感觉良好,屏幕很清晰,整体不错。 900 | 1 手机不错,赠品比较次 901 | -1 限量送耳机,我买的就不见有?还会员***连个耳机都不送。 902 | 1 宝贝收到了,和专卖店一样的,超级棒 903 | 0 怎么说呢,有点失望吧,尤其是店家态度,买之前很热情,之后爱答不理。服务态度很不好。手机也一般般。 904 | 1 东西挺好,唯一不好的就是竟然没有原装的耳机,华为真**坑,以后不买华为了,卖家挺好,挺有耐心,非常非常非常非常感谢 905 | 1 手机很好看,而且很流畅,适合各种人群使用,办公很方便,被华为吸粉了。 906 | 1 手机很好,快递特别快,卖家服务很好 907 | 0 还不错,有时候感觉触屏点击没反应 908 | 0 还可以吧,新机子有一点卡! 909 | 1 第一次在京东上买手机,老公说很好用,蛮好的 910 | 1 速度很快,照片也很清晰,比旧的好多了。双十一前买的,也有优惠。 911 | 0 玩一会就发热了 912 | -1 手机用着还可以,半个月降价200元,客服说不在保价周期内,华为手机贬值真快! 913 | 1 屏幕时而灵敏时而不是很灵敏,奇怪很的调校,希望华为多多优化系统,杜比音效是个亮点,看电影好爽,点赞 914 | 1 我是6.18购买的荣耀10幻影蓝全网通(6GB 128GB)官方标配手机,京东快递神速第二天就拿到了,这次荣耀10是一款颜值极高的全面屏旗舰。它正面采用了主流的刘海全面屏,一上手就能感觉到屏幕握持感极佳,机身下巴位置有一颗隐藏在玻璃下方的超声波指纹Home键。背面的变色极光曲面玻璃是这次荣耀10的亮点所在,上手感觉非常圆润。荣耀10的双曲面玻璃后盖通过变色极光镀膜工艺、纳米级波浪纹理和光程差原理,做出了流光溢彩的视觉效果,十分炫酷,荣耀10不仅有扎实的配置,更是有着刺激眼球的变色极光外观。作为一款旗舰机,保持着高性价比。表现优异,受到朋友们的赞叹。使用过多种品牌手机,购买荣耀10是我的最近这次更换手机的梦想。6.18购物优惠,女儿实现了我的愿望。京东物流速度也非常快,一到手,手感就非常舒服,不磕手很圆润,屏幕比华为mate8要小些,但操作非常流畅,比mate8和荣耀note8拍照效果要好很多,@声音也大多了,外放音效增强不少,手机发热比较快,最重要的信号问题还需要时间多测试才能下结论。一直在使用华为手机和其他产品,加上这部已经用过多部华为手机了。华为品牌一直在进步和成长,声誉越来越高 915 | 1 双十一便宜了400块,感觉亏了1个亿,用用还挺好的,也很好看 916 | 1 常棒!屏灵敏度快!一款值得买的手机。支持国货! 917 | 1 这家店手机真的非常好用,很流畅,画面感很棒,吃鸡的话把画面调到最高一点都不卡,必须得好评!? 918 | 1 手机很流畅,玩一般的游戏都没什么问题,正常使用一天半没问题。手机发热不大。综合来说,是一款不错的手机。而且颜值也挺高的。 919 | 1 机身很漂亮,颜色还不错,物流也很快 920 | 1 刚开始纠结米8和这个,最后选对了哈哈,玩游戏也很棒,电池也够用,而且真的很好看啊,紫色没选错 921 | 1 很好很喜欢! 922 | 0 不想说什么,什么售后,压根就是@的,再也不来了,线都这样子还说是正常,要是正常我寄给你用,你能用算我服 923 | 1 非常好!屏幕清。 924 | -1 才刚上手,因为运货运了五天,,发货太慢了。还不知道是不是翻新机? 925 | -1 拿到第一感觉很棒,做工很不错,商品本来可以给个好评就是告诉你们缺点而这些他们介绍里不会有的,第一:拍照只支持拉近一点,跟三星比起来差太多,如果近视眼想借助这个看远景基本作用不大了,第二:耗电快,我挂着很多微信跟其他软件非游戏,屏幕一直开着掉的速度比用了一年的手机还快,第三:耳朵不好的用这个手机也不行,听筒声音调到最大对方讲话声音依然很小。,手机系统,外观,自带功能都非常不错 926 | 1 非常好的购物体验!手机的运行和状态都很好,支持华为一波! 927 | 0 钢化膜不好,贴上去白边特别多 928 | 0 流是真的坑,星给客服, 929 | 1 货比三家之后发现还是这里的价格最优惠,好评也多多,果断下单,还送了不少赠品呢! 930 | 1 东值得信赖! 931 | -1 才买15天左右多天,降价两百 932 | 1 用了一个星期感觉还行 933 | 1 非常大的手机,一下子看中,爽 934 | 1 非常想入手的手机已经到手了,感觉美滋滋,舒服 935 | 1 东西挺好!原装未开封! 936 | 1 手机用了两天感觉还不错,一点都不卡,非常好用,没亏,赶紧买,坐等GPu turb技术出来 937 | 1 手机用起来很方便,超级快运行起来,而且荣耀10的设计很好看!十分满意! 938 | 1 很赞的宝贝,照相更方便好看!速度也很快。家人一直使用华为。 939 | 1 手感很好 940 | -1 买给妹妹的,手机很好,就是买了一天就降了一百,伤心 941 | 1 打王者可以,吃鸡还不行的,慢 942 | 1 很棒的手机,给小孩买的,顺畅。一个字赞 943 | 1 蛮喜欢的,挺好看的好看(?)?。比较流畅,充电也快。满意。 944 | -1 京东自营售后的政策比较好,肥的拖瘦,瘦的拖死。 945 | 1 价格优惠,性价比很高,正常使用两天,体验很好,电量待机表现很好。 946 | -1 电池不耐1天不到 947 | 1 手机很漂亮!非常喜欢!具体性能我用两天再来补评。 948 | 1 手机用着不错 949 | 1 手机很漂亮,速度也很快,用起来很爽!值得购买! 950 | 1 之前用过荣耀7,感觉还行,这次荣耀10外观还不错,容量也大,用起来也很流畅,个人挺满意的 951 | 1 外观漂亮,性能也不错,价钱适中 老公不喜欢大屏的 这个比较满意。隔天到,赞一个。 952 | 1 不错,机子很大,电池很耐用,用了两天感觉还可以,再用一段时间再评价 953 | 1 非常不错!每个手机都是京东买的,也放心,送货也快,也非常省心,信得过华为大品牌! 954 | 1 太快了,昨天晚上买的,今天下午就收到快递了,赞 955 | 1 超爱这款 超棒 颜值超高 956 | 1 反应速度快,比先前的vivoX6好用 957 | 1 必须全五星,真的很不错,比店里便宜,还送好多东西,运行速度也不错,唯一遗憾的是没有内存256的 958 | -1 啥手机#的商家谁买谁后悔。屏幕黑边说是游戏问题,说不懂游戏,只懂手机,还叫我去检测。快递还转运,运费还要我出。。一星都不想给你 959 | 1 好评,给五星。手机很满意。 960 | 1 宝贝拿到了,不太会玩,应该还不错的 961 | 1 屏幕极大,反应速度极快,电池耐用。 962 | 1 手感不错刚开封,开机,比我想象的小,屏大框小很喜欢很小巧 963 | 1 这手机拍照挺好用,是用过最好的手机,送赠品也是不少的,手感不大不小舒服 964 | 1 是正品,用起来很顺手,物有所值! 965 | 1 手机还不错,家里人用了 966 | 1 手机非常流畅,用起来很流畅,机身也非常炫酷。 967 | 1 好极,内存够大,屏幕够清晰,还能用两张电信卡,这个价格值了 968 | 1 颜色很漂亮 性价比很高 也很好用 商家还送了很多东西 969 | 1 看手机新闻啊微信啊比较多,一般每天睡觉的时候充一次,充的飞快的。屏幕很大,很清晰,不会和某疯撞款。最大的特点是信号超级无敌强的,住的楼层高,用的某疯和vivo通话都会断断续续,这款不会,就算进了电梯和地下车库一样信号很好通话清晰。 970 | 1 真的好惊艳的手机,运行速度真的非常快,老人上手也没压力 971 | 1 手机查了一下是正品 用起来手感很好 反应也快 挺满意的 972 | 1 很漂亮,我很喜欢, 973 | 0 触屏不怎么样其他的还可以吧 974 | 0 玩游戏和拍照都很好,但是我感觉没有苹果系统流畅 975 | -1 商家态度极差,欺骗客户,发票也不给,而且屏保险也不给,真的很生气,怎么会遇到这样的卖家,希望大家别上当了,换一家吧。 976 | 1 手机非常不错 小屏里的中端旗舰 之前用的荣耀8 系统啊 相机呀 各方面都提升不少 手小着用着非常得劲儿 977 | 0 手机速度挺快,颜值也不错,充点也很满意,最大问题是前置摄像头太假,关闭所有特效后还是假,搜了下网上评论也都是对前置摄像头吐槽,华为用了个什么劣质前置摄像头,对不起荣耀这个牌子 978 | 1 手机非常好用,流畅,屏幕大小比较适合我,赠送的东西也喜欢,都能用上,考虑再买一个给家人 979 | 1 给老弟买的手机,其很喜欢,外观漂亮,拍照清晰。 980 | 1 感好,速度快,刷脸快。然而这么好的功能,在~支付上只能用密码输入,我淘汰的那台指纹都能支持! 981 | 1 不好意思评价晚了!手机不错,商家不错,发货快,包装细心 982 | 1 说一下这几天的感受吧,概括一下,手机续航能力没得说,太给力了,玩游戏根本不在话下,全程不在卡顿的,一直保持60帧,音乐那叫一个棒,上下双喇叭,杜比音效很好,像素清晰可见,值得购买。 983 | 1 真的不错 984 | 1 手机不错,物流很快,系统流程,特别是颜色很喜欢! 985 | 1 手感很好,很喜欢,也很轻,用了一会,觉得很满意,值得购买 986 | 1 上网速度很快,颜色也很漂亮,性价比比较高还送了赠品。下次还会光顾 987 | 1 送了多个礼物非常满意,因为快递需要几天,我开始觉得时间太长就退了,去别人家买说是快,但是送礼物就一个,其余几个没有自己还要花钱单买,所以快也不值得了,又回来下单购买,所以送那多礼物少花钱等几天也觉得值了,好评五星愉快的网购,给店里人代买的~因为华为产品是我店里第八个产品了~质优价低~所以回购! 988 | 1 特意用了一段时间才来评价,外观非常靓丽,屏幕很细腻,拍照功能强大而且自带很多有趣的功能,没有卡顿过,没有死机,华为手机里性价比感觉很高,推荐购买! 989 | 1 原装正品,物流很快,电子发票已收到,开机很快,官网验证,新机啊! 990 | 0 心平气和的给你个评价先说手机,一切都可以忍,切换后台程序的下侧横划的操作方式,真想骂人。每次都得划几次才出来,很别扭!再说价格,京东早就宣传618活动,结果当天又降价211,我觉得这明显是商业欺诈,当然你们可以不这么认为,但是当手机还没到手或者刚拆封要回来评价,发现价格跌211,还是因为同一个理由618。不知道你自己怎么想。最后说服务,不说差劲。给个一般,没从人性额角度考虑,毫不顾及顾客感受,就告诉你拆了不能退,以购买时网页价格为准。不说别的希望有幸,你们也感受下。最后说一下,因为这个价格我觉得有欺骗的行为,所以三星。无脑同事还给我试新了,没辙。不退了 991 | 1 这是我的第二个荣耀10,真心不错,给个赞! 992 | 1 物流快,现在用的还不错,好评! 993 | -1 啥也不说了,刚买完就降价 994 | -1 真是一星都不想给,净忽悠人,说话一点也不负责任 995 | 0 用了一个月了 指纹解锁有问题 其他还行 996 | 0 三星不解释,外观没有于大嘴说的好看,价格也越来越高 997 | 1 特别中情荣耀系列,荣耀10外观手感都是我喜欢的,多种颜色,特别的亮哦 998 | 0 个手机一般 999 | 1 很好,非常满意 1000 | 1 机器很漂亮,运行速度快,比专卖店便宜好几百,送的东西也都用的上 1001 | 1 中度使用,待机一天没问题 1002 | 1 手机不错,很喜欢 1003 | 1 note10虽然没有红外,但是有大容量电池,有比荣耀其他系列更好的网络,有多功能nfc,有高音质双扬声器,再加上液冷散热。这些对我来说,就很不错了。再加上素质不错高于荣耀同系列的屏幕。所以我预购入手了。 1004 | 1 手机用这么久了,好用,是正品,就是赠品质量不怎么样 1005 | 1 帮朋友买的,一直都支持国产。 1006 | -1 价保形同虚设。 1007 | 0 买了一个星期屏幕就摔坏了,我也不知道要怎么评价,凉凉? 1008 | 1 物流不是很快,一直以来用华为,一如既往的好,跟老婆买的,拍照一流的。 1009 | -1 了十天,降价一百。是没谁了。 1010 | 1 一个6G运行内存的手机一#就死机,我就不明白了,还不如我以前3G运行内存的手机。我不知道是华为10就这样,还是我的机子有问题。 1011 | 1 手机很好 性价比高 华为手机好用,像素很好,特别是夜拍 1012 | 1 物流快,手机也不错,挺满意的 1013 | 1 手机好用,以前用的就是荣耀v8,中间用了一段别的手机,然后买了荣耀10,感觉华为真的非常好 1014 | 1 手机用的很舒服,屏幕看电视也很爽,好好好! 1015 | -1 手机花了600+修的还是有点弯曲 1016 | 1 手机收到了,跟我在实体店看的一样,价格却便宜很多,运行速度很快 ,屏幕手感很好,反应灵敏,非常喜欢 1017 | 1 综合性能非常棒的手机,外观绚丽,性能强劲,屏幕显示效果细腻,手感不错 1018 | -1 连个耳塞都不配, 1019 | 1 手机美到惊艳 华为一如既往的支持着很不错哦 还送碎屏险 真的是超值的手机美到惊艳 华为一如既往的支持着很不错哦 还送碎屏险 真的是超值的 1020 | -1 手机用了两三天充电发热严重,待机时间特别短,没怎么玩就没电了、客服说这属于正常,两千多买了个正常手机, 1021 | 1 机正品,赠品齐全,好评! 1022 | -1 运行速度快相机好服务好差 1023 | -1 手机可以,就是没有钢化膜! 1024 | 1 宝贝很好,刚入手,挺流畅 1025 | 1 整体来说很完美。我关注这款手机挺久的。好评 1026 | 1 货收到,打开包装就很喜欢,外表也很漂亮,关于其它用后再来追评。 1027 | 0 发货速度超快,手机手感很好,外观时尚漂亮,指纹解锁和人脸解锁都很快,非常满意,最后要吐槽一下手机配图错了,机身颜色选项和配图完全是反的,蓝色配紫色图,选的时候还觉得奇怪我,就这点非常不满意! 1028 | 1 东西很好,送了一些小礼品。物流还是一如既往的给力,下着大雨,快递小哥准时给我送货。 1029 | 1 完全符合预期,手持大小刚好,做工很不错,比v10要更好,整体性能是适合我的,尤其618活动非常给力。 1030 | 1 手机点耐用,大屏打游戏感觉超棒,手机不发烧,随便玩 1031 | 0 玩吃鸡卡成狗 1032 | 1 喜欢就买了,这是第二次买了! 1033 | 1 手机很好,网速特别快,信赖华为手机,为京东物流点赞,特别快 1034 | 1 双十一买的,到货速度快,刚收到,体验一下再评价 1035 | 1 特别好用,也好看 1036 | 1 外观好看,屏幕也很惊艳,拍照也没得说,玩游戏试了下也不怎么发热,机身比oppo r9s小一圈,屏幕荣耀10还大一圈,唯一不太满意的就是电池耗电太快了 1037 | -1 6.18页面显示送耳机的,却没收到 1038 | 0 还可以,价格还算合适送货速度快 1039 | 1 吃鸡不卡,手感舒适,是荣耀旗舰机的领航配置,这颜色很有趣,确实角度不同颜色不同,游戏方便比之前体验的小米8好太多,不卡不烫主要,很亮眼我不喜欢戴套,打游戏还不错吧,总之好评啦!客服不错 1040 | -1 充电特别慢,而且机身内存占的特别多,还说什么他们给的数据跟手机不一样,感觉被骗了 1041 | 1 手机速度很快,玩游戏画面清醒,好评 1042 | 0 刚下单两天,手机还没到手,发现居然降价了? 1043 | -1 态度不行 1044 | -1 不好 好关机 好卡屏 1045 | 1 华为荣耀10,这款产品值得入手。个人感觉还不错。手机中的战斗机。支持国产。 1046 | 1 手机很好,反应速度快,屏幕显示效果很好,拍照夜景不行。 1047 | 1 手机到两天了,总体感觉非常不错。荣耀10的激光镀膜工艺不是吹的,开箱那刻真的是惊艳到我了,颜值真的是没话说。更新GPU turbo之后,玩刺激战场HDR画质也能流畅运行,游戏体验很不错。续航也可以,充电那是真的快,一个多小时就能充满。2400万+1600万的像素,拍照清晰明亮。官方都说荣耀10是荣耀最全面的旗舰,果然找不出什么大缺点。还有店家很热心,服务态度很好,送的礼品我很喜欢。好评! 1048 | 1 很好用的手机一点也不卡,运行速度很快 1049 | 0 用了好几天了,后置摄像头很好。前摄有点迷,拍照没眼看。触屏手感emmm不太好。手机整体颜值是可以。 1050 | 1 非常喜欢,物流快,手机好看又流畅,值。 1051 | 0 我只能说,这事是假的荣耀10吗,刺激战场不行?要你何用 1052 | 1 手机特别好的,性能测试远超过预期目标,外观漂亮 1053 | 1 还可以吧 运输速度挺快的 比我想象中要快很多 包装也很周到 1054 | -1 说的是有200的优惠,实际没有 1055 | -1 跑完分很烫手 1056 | 1 手机下单后间隔一天就到了,很速度,比实体店还@子。给爸爸买的,很喜欢?相信京东, 1057 | 1 朋友介绍的店铺,手机发的顺丰,特别快,开机快,感觉蛮好,反应速度快,其他功能还没有摸索到 1058 | 1 宝贝收到,正品,喜欢 1059 | -1 对手机满意,对京东客服不满意 1060 | -1 问我的耳机在那里?买手机耳机都不送!!!太抠了!!!手机的质量确实很好,用着很舒服,支持华为手机,国产好手机。~家真的抠门,买手机耳机都不搭配一个,绝对差评。~ 1061 | 1 老公用的不错,正品!^_^ 1062 | -1 用了一段时间了 不知道是不是正品 看电视经常卡顿 发烫也严重 第一次买荣耀就这样子 1063 | 1 运行速度挺快。外形好看。整体给九分吧! 1064 | 0 手机没毛病,非常好。颜色一定要看好再买! 1065 | 1 运行速度还行,储存够大,EMUI9加持 用起来很可以 1066 | 1 收到宝贝了,先给个5星。 1067 | 1 太漂亮用起来非常好手感好颜值高,玩游戏无压力吃鸡王者荣耀随便玩,华为荣耀真的很棒,秒杀一切3000+手机 1068 | 1 比较了好多手机,最后选择这款性价比最高的,拿到手迫不及待的使用了,果然没让我失望,速度好快,大小正好一手掌握,超喜欢的 1069 | 1 手机很漂亮,适合手小的人,反应也挺快,像素很清楚,物流也不错。 1070 | 0 还行,电池一天两充这个确实是真的,人脸识别,用下巴都能打开, 1071 | 1 手机还可以,物流太慢 1072 | -1 货后贴膜迟迟未发! 1073 | 1 常好,手机好好看,老妈特别喜欢,赠品很多,价性价比高,下回继续来你家买 1074 | 1 手机还不错就是有些耗电和指纹解锁有时候难解开不过总体来说还是挺不错的 1075 | 1 朋友超级喜欢,不知道买了第几次了。好用? 1076 | 1 速度很流畅,分辨率很好,不错的机子 1077 | 1 物超所值,外观精美,颜色很漂亮,包装好!赞一个!推荐给朋友。 1078 | 1 给老公买的,挺喜欢的, 1079 | -1 手机用了一段时间了,电池没有说的那么耗电快,但是店家的服务质量问题需要改进,给一颗星不是手机的问题,是服务只有一颗星 1080 | -1 用了一个月回来降价400寒心! 1081 | 0 送货速度快,就像速度与激情那场电影,不过没有什么送。就一台手机 1082 | 1 用了将近两个月感觉很好打机看片也很满足 1083 | -1 手机没问题,就是商家太差劲,早上买的中午就降价了,找客服说是补偿差价, 1084 | 1 物流速度很快,但收到的手机是4月7日生产的手机,首发前生产的到现在才销售出去,值得怀疑~~~还有联系人右边字母排列触摸不灵敏~~~远不如之前的荣耀9 1085 | 1 屏幕颜色很好,手机颜色也很好,我很喜欢 1086 | 1 手机非常棒,很好看,用起来反应很快,不错。 1087 | -1 差,太差,售后态度一点都不好, 1088 | 1 手机很好,速度比原来的荣耀8快多了,容量大很多 1089 | 1 超帅的一款手机,物超所值,物流也快,打算给我妈买一台 1090 | 1 拍照效果不错 代机时间长适合长时间用手机的人 其中面部识别功能减少了输入密码时间一画开就能用很方便 开其他软件都不卡运行的满流畅的 买手机还送华为的蓝牙音响满不错的 总体来说我还满意 1091 | 1 颜值确实不错,手机比较迷你型,不喜欢大屏的可以入手。 1092 | 1 漂亮,速度还可以,很喜欢,支持国货。 1093 | 1 看着还不错,像素都挺高,颜色看着也漂亮的!现在用着还顺畅!华为手机应该不错的! 1094 | 1 很好,性价比很高的手机支持国产。双十一,价格很优惠,推荐。 1095 | -1 买没几天,沾了水,整个报销 1096 | 1 还好吧,我以为屏幕很大,刚刚好,合我心意。 1097 | 1 手机不错 很好 很好看 很好用 1098 | 1 昨天刚收到货 用了下感觉电量下的太快 续航能力不太给力 其他还好 用的时间短 以后在追评 1099 | 1 电池很给力,玩王者玩了5个小时还有电。 1100 | 1 好看,功能强大,看了好久,做了n多对比,最终决定买这款,果然没让我失望,运行很流畅,电池还够用,拍照效果很赞? 1101 | 1 手机收到了,物流很快。商家还送了赠品,手机反应很快,很满意。 1102 | -1 信号就跟坨斯一样,经常不知道对方在说什么,赠品送了不如不送没有什么乱用。 1103 | 1 正品,东西很快就收到了,发货非常快,东西也很好用,下次一直在这家买东西 1104 | 1 绝对的正品 用的很流畅的 商家太好了 1105 | 1 好,宝贝很棒,喜欢极了。么么么哒 1106 | -1 gt游戏机 哈哈哈哈 玩吃鸡都卡 下次换骁龙的 1107 | 1 手机很好用,用了一段时间才来评价的,所以我给五星好评,就是有一点不好,没有耳塞孔,其余的都蛮好 1108 | 1 小巧玲珑,握住很舒适,外观造型美观,性价比很高,~与~可以应用双开,喜欢? 1109 | 1 双十一买的,一个裸机价,全齐了。感谢老板。价格实惠,京东物流真叫快。 1110 | 1 了一个星期啦还可以! 1111 | 0 先用着在说 1112 | 1 机子手感很好,一手拿着很舒服,速度也很快,感觉用起来非常的。 1113 | 1 挺好的,物流也给力,昨天下单今天上午就收到了,查了一下,是正品,试了试手机,手机也挺流畅的,喜欢的可以来博海宇通公司买,在京东上就有博海宇通 1114 | 1 手机很满意,第一次用华为,以后都用华为了 1115 | 1 手机很不错 系统很流畅 很漂亮 就是中间物流出了一点小问题 商家给很好的解决了 好评 1116 | 1 荣耀10这款手机,可以,运行速度快,做工好! 1117 | -1 哈没什么好说的 拿完手机被车撞手机屏碎了然后骨折了自己换屏幕688哈荣耀10可以啊 差评是给配送员的如果他给我送楼上就没有那么多事了 拿手机7分钟被车撞 运气有点好 1118 | 1 荣耀10很棒,颜值高体验好,还是我胡代言 1119 | 1 相当的不错,手机很好,用的不错 1120 | 1 新手机很好,拍照很给力,用着也很流畅。顺便就给个好评吧。 1121 | 0 多任务真的# 1122 | 1 #会变色更潮美#手机到了,很帅,背面真的会变色,手感也特别好,手机很好用,是正品,很满意的一次购物。 1123 | 1 手机挺好的,不卡,上网快,我很喜欢,下次有机会还会买 1124 | 1 一个实体店买的.一个在这买的.对比了一下,一样,比店里买便宜,以后会继续关注 1125 | 1 手机性能和颜色都是很喜欢的,不错哟,一直用的苹果,买了荣耀觉得这款手机真心不错?,祝店家越做越好 1126 | 1 价格很优惠,原封未拆正品。荣耀10的指纹解锁并不像网上吐槽的那么差劲,挺快的。给妈买的,配置足够用了 1127 | 1 入手两个月,挺好的,特别是这大屏幕看片很爽! 1128 | 1 收到了,快递很快,手机外观很好看,内部运行内存也很棒,物有所值,超级喜欢。 1129 | 1 刚取回来就马上试用了一下 ?不错是我想要的机 1130 | 1 美丽 典雅 不失华为品质 大电池给力 1131 | 1 手机收到了,上手很快,支持华为荣耀10,增加的好多功能,拍照ai成像,图片清楚又美颜 1132 | 1 送女朋友的还没,试用后在评价 1133 | 1 可以!大小尺寸合适,比想象中好!运转快不卡,玩游戏看电影都爽。 1134 | 0 手机还不错,但是电确实耗的很快。而且打王者有时候摁不出来技能,闪现或者沈梦溪的技能,照相也还可以吧,后置很漂亮,前置凑活。前置没有Ai技术。马马虎虎吧,也就凑活。 1135 | 1 宝贝刚刚收到,拆开后觉得很漂亮。 1136 | 0 灰色好看,屏幕显示效果**,拍照颜色严重失真,运行还行 1137 | 1 手机外观漂亮,运行流畅,物流发货很快 1138 | 1 佳沪品牌店,非常专业,我拿到手机的速度,比线下店不慢。而且是首批,送了很多赠品,大爱这个店,如果能给六星一定给 1139 | 1 物流很快 手机很好看反应快 拍照清晰 客服很好 1140 | 1 华为手机无敌! 1141 | 1 手机很漂亮 感觉不错 支持国货 1142 | -1 刚收货就便宜120,还不能报价,我要退货 1143 | 1 手机不错哦,好评 1144 | 1 手机外观漂亮,系统好用,性价比很高超过预期。双十一活动,店铺价格很实在,比官网划算多了! 1145 | 1 手机还是不错的,价格也比实体店要便宜,赞一个 1146 | -1 我想问为什么吃鸡不是全面屏的 1147 | 0 玩一会摄像头区域发热很烫。 1148 | 1 超级快,无解好看,而且送的东西超级多,客服态度超级好。一句话nice 1149 | -1 怎么打都打不开这手机有毒 1150 | 0 手机一玩游戏就巨**烫,可以煎鸡蛋的那种? 1151 | 1 很好,送给朋友,他很满意 1152 | 1 的很好,很给力。 1153 | -1 正常浏览网页,手机上半部烫的厉害。 1154 | 1 拍照很清晰,看视频也很清晰,内存空间很大,平时也不玩游戏,满足日常使用需要,足够使用,机器小巧,方便携带。 1155 | 1 手机还可以一般般过得去 1156 | -1 电池发烫,耗电好快, 1157 | 1 用着挺好了,是正品 1158 | 1 用着还是不错的,相信华为~ 1159 | 1 还好 物流速度很快 北京到山东两天就到了 1160 | 1 手机不错,是原版华为荣耀10,手机外观很漂亮,没话说 1161 | -1 手机就那样,没什么稀奇的,反正我要求不高,能用就可以了。拿来点烟是不可能的。为了凑这字数我容易吗?够了吗?不够我再写几个字?这会儿估计是够了。 1162 | 1 手机很喜欢,比想象中理想很多,好评吧! 1163 | 1 物流挺快的,手机很不错啊 1164 | 1 手机挺好的,正品! 1165 | 1 运行速度很快,拍照效果相当不错。 1166 | -1 充电线用了不到一个月,就接触不好了 1167 | 0 屏幕颜色有点泛黄 触摸不灵敏 容易发热 拍照模糊 1168 | -1 *手机,天天降价,谁买谁亏!价格跌成 1169 | 1 反应很快,看着也不错,用了一次 1170 | -1 好后悔买了 发热好厉害? 1171 | -1 为什么手机后屏用手一捏就碎成这样了,很伤心,想问一下客服怎么解决这个问题。 1172 | 0 包装是真的简陋到了极点 1173 | -1 一句话,后悔, 1174 | 1 帮朋友买的,朋友说很棒,物超所值,荣耀确实性价比高。 1175 | 1 东西不错店主不错 1176 | 1 第一次用华为荣耀手机,感觉非常好 1177 | -1 机整体可以,但是供应商业务不熟练,我一再确定是否能装两张电信卡,告诉我可以。等我拿到手机,呵呵,确实可以装,但是这项技术电信还在测试调试阶段…后供应商告诉我说是运营商问题和她们无关。我勒个去… 1178 | -1 玩游戏卡 1179 | 1 物流快 手机也很好值得购买 1180 | -1 保护膜很多指甲扣过的印,进网许可证有撕过一样的气泡。充电头上又有很多汗印。最重要的居然没说明书。这手机居然不是全新的,这也太坑了。但到手开机了也没法说理了 哎**说明书都没有,希望全国联保一年不要出什么幺蛾子 1181 | 1 一直喜欢华为手机,这是第二部荣耀: 1182 | -1 明买的紫 给我发个蓝!!请问你们小学毕业了吗。机子还没 1183 | 1 荣耀10中6+128中最便宜的,很划算,用了快一个月了也没什么问题,绝对正版 1184 | 0 手机运行速度特快,也很漂亮,就是没有耳机 1185 | -1 这家店真的不行,发来的东西都是好旧的 1186 | 1 给老爸买的,先自己体验了下,屏幕,后背都很惊艳!自己用的米6,外观上荣耀10好看,比米6手机长一点,屏幕占比明显要高!重要的是湿手指纹可以识别,Ai摄影,麒麟970处理器,极光特效的外壳,保留3.5毫米的耳机接口,价格也很亲民!是一款颜值跟性能兼具的产品!不过个人觉得Mui还是好看一些 1187 | 1 续航挺长的,外观大气,挺好看的,超喜欢 1188 | -1 手机是不错,但是商家不带发票。对商家有点失望? 1189 | -1 颜色不相符合 1190 | 1 很快,一小时左右能充满,王者吃鸡基本都是满帧,相机也是不错,大小适中,一手好操作,好评 1191 | 1 以前用oppo r15梦境,除了充电慢用电快以外,别的都比oppo强的多,这手机颜值很高,不大,用起来正好 1192 | 1 安逸都没有人多的!晒太阳呢@网 1193 | -1 用了几天开始慢了,运行速度 1194 | 1 拿在手上温润如玉,手感非常好,而且乘着双十一前夕以优惠的价格拿下来了,颜色也不错,6+128g足够用了,电池续航和拍照都不错,特别是有了华为的Ai和游戏加速技术的加持,使日常生**验和游戏体验明显非常好?渐变色玻璃后壳给这手机颜值加分不少,指纹识别配合面部识别解锁更轻松自在。非常满意! 1195 | 1 没毛病,运行速度快,手感挺好,拍照也不错功能多,物流也给力 1196 | 1 大屏幕,手感好,速度特别快,感觉挺好!note 10名副其实!准备买多一部! 1197 | 0 一般般 处理器真的是让人大失所望诶!宁外看了拍照,简直有所夸大。菜! 1198 | 1 我觉得看起来很OK,虽然现在感觉不出效果如何。 1199 | 1 卖家发货速度很快,京东快递也给力,两天就收到了,手机很好用,正品行货。 1200 | 1 用了半个月再来评价!手机可以完美。电池很很很耐用,玩游戏很溜 1201 | 1 不错的,快充很好,就是续航能力不是很强 1202 | 1 手机蛮好,能满足我的使用要求!拍照还行,比我之前的8好,屏幕也还行,很好的购物体验。送的东西也不错,就是送的手机壳,我之前没和店家说下,送的HELLO KITTY,太女性化了用不了。 1203 | 1 手机不错,物流速度很快,非常完美。 1204 | 1 手机刚刚到,正在使用中,设计比较漂亮,像素高清,发货很快,服务好。好评! 1205 | 1 非常好用的一款手机 1206 | 1 送的手机膜很好用,滑溜溜的,触感很不错。整体性能满意,其他方面继续玩玩才知道 1207 | 1 音质:外观设计时尚大气,手机速度快,音质很好,画质很清晰,海报级自拍,每个人都是生活的主角,和家人一同定格美好的瞬间。充电十分快,待电很好,连续使用也不发烫。我的手比较小,拿在手里刚刚好。总体来说,性价比很高,值得购买! 好极了 很好 很棒 很快、使用流畅,国货当自强,真心赞,不要再花高价当冤大头了,送了一些赠品,但是分开发的货,有点想不通,快递不要钱吗? 1208 | -1 试用了一个月了,已经出现卡机死机情况,有一次吃鸡屏幕直接红屏,王者有时候开了直接死机,才用一个月。感觉像那种翻新机,建议大家考虑清楚再购买。 1209 | 1 质量很好,快递很给力 1210 | 0 拍照效果挺不错的,运行速度也可以,就是电池续航不怎么行! 1211 | -1 自营好还能不能信了? 1212 | -1 在京东最#的一次购物,来来@的折腾了半个月。我手机就是死机了,偏偏说没有问题。我的新手机都给搞成了二手货。赠品什么的质量也很次。看来买东西还得买自营的啊。 1213 | 1 王者不费电,手机还挺快指纹键应该赋予更多功能就完美了 1214 | 1 开机速度完美,手感不错,双十一也没有延误,好评 1215 | 1 手机收到一个周了,用了还不错,现在来补评价,挺喜欢的,就是加价购的智能手环用了几天就坏了,其他东西都不错, 1216 | 1 池续航目前不晓得啦,拍照效果杠杠的,宝贝真心不错啦,触感也是很好的,我拿着刚刚好,谢谢卖家! 1217 | 1 运行速度很不错,外观靓丽漂亮,颜色赞?,值得入手,店家送很多小东西哦 1218 | 0 !怎么说呢,自从不用苹果之后,就开始使用国产手机了,荣耀9荣耀10,两者的对比由大屏变全面屏了,荣耀9起来体验感还是不错的,买了两天了,发现全面屏的兼容性上差一点,电池续航是真的差,用了一年大半的荣耀九都比10强,除了上面两点别的都还可以,毕竟价格也不贵19 1219 | 1 华为老用户了,一直都是,支持国货,的确不比国外品牌差,好用。 1220 | 1 可以呀,用的挺舒服的。 1221 | -1 刚买两天,进京东有时候白屏,送的耳机也坏了,带了两次 1222 | 1 非常速度的发货,荣耀手机值得拥有! 1223 | 1 很好用和实体店铺买的没有区别。 1224 | 1 手机很漂亮 功能强大 1225 | -1 质量有问题,试过有时候自己重启 1226 | 1 目前用着不错,速度蛮快,照相很清晰,物流非常快! 1227 | -1 送货可以,手机不行,电不耐用,还发热 1228 | 1 快递已经收到,用可了还是可以的 1229 | 1 开始催了哈,物流很快,东西也不错,好评 1230 | 0 用了两天感觉都还不错,不过某平台同样的优惠,人家还送耳机自拍杆。这边我反正就只收到一个裸机哎! 1231 | 1 手机很好,手感也不错!是正品,物流也很快。在这我得感谢物流兄弟,送货上门了! 1232 | 1 我表弟买的,速度很快一如既往支持,运行也没什么问题,尺寸稍微选小了一点不过也还可以了哈 1233 | 0 用了一礼拜了,日常使用发热挺厉害的,而且续航也不给力,掉电挺快的,期望后期尽快优化。还有就是麒麟970的gpu性能确实比骁龙835差很多,可能跟游戏的调教和优化也有关系,原来835不卡的大型游戏970都挺卡的,建议爱玩游戏的小伙伴别选这个。其他方面都挺不错的,拍照也ok,总的来说还可以。 1234 | 1 我买的是荣耀10的6+128的。特意用过一段时间才来评价的。外观很养眼,弧形设计的也很不错。运行起来也相当的流畅。总的来说这款手机还是很不错的。以我个人而言,值得推荐。另,着重提一下,这次购物京东快递让我体验极差!!!10月21号晚接货,26号下午我才取到。特别是!显示从成都已出库到攀枝花转运站入库,运送了了近72小时!!!我也是醉了。火车都才14个小时就能跑到地方,作为以安全,快速作主打进入快递市场的京东快递愣是跑了近72小时,这无疑是很不合适的!!!而且,京东快递客服对此事没有做出任何有意义的答复,这让我心情很不好。恰逢当时我突有急事要离开攀枝花。最后无奈之下,我只能硬把我的火车票延迟了一天。扣了20左右的手续费,这也算是额外支出了? 1235 | 1 手机靓爆了 性能好 人脸识别 分量很轻 刚好一手的大小 老婆很喜欢 值得拥有 1236 | 1 手机非常不错,颜值高,速度快,续航时间长 1237 | -1 换了一个,还是坏的 1238 | 1 过年了,还在发货,速度也可以,比平时慢一天,不过也挺好的,手机颜值担当,速度也快!媳妇挺满意! 1239 | 1 手机不错,手感好 1240 | 1 手感好,屏幕尺寸合适,一个手操作方便。用起来很流畅,点软件秒开 1241 | 0 还行吧 不玩游戏仅看视频拍照内存足够了 1242 | 0 刚接触,感觉手感还是不错的,其它功能正在了解中 1243 | 1 手机还不错,是正品手机,华为的手机一直都很不错的的,值得购买的 1244 | 1 支持华为,很不错,玩游戏一点都不卡,外观好看,性能高. 1245 | 0 到手一个礼拜,死机一次,会再追评 1246 | 1 手机收到了,用了两天,非常满意,因为之前一部手机是荣耀八,所以新机上手很容易,还是熟悉的emui,970比荣耀8的950强大太多了,王者,吃鸡最高画质无压力,老板送了好多赠品,感谢! 1247 | 0 摸,指纹* 1248 | 1 华为(HUAWEI) 荣耀10游戏GT加速手机 幻影蓝 全网通6GB+128GB【1年碎屏险套装】但这个【1年碎屏险套装】很有疑问,问了客服说寄回店铺修。这个感觉有猫腻。 1249 | 1 手机很大,很流畅,还没怎么用,过几天再评价 1250 | 1 手机很好,妈妈很喜欢。 1251 | 0 收到里面就有应用软件,**京东***快手,是正品吗?头天晚上买的第二天就收到了,挺快的 1252 | 1 安卓还在适应中,性能挺好,玩游戏真心不错,就是屏小点,nfc功能挺实用,以前没用过,现在突然发现只带一个手机真的好便利 1253 | -1 电池不耐用,网络卡的要命,信号差,我估计买到假货了或者翻新机 1254 | 1 手机很好,就电池会发热 1255 | 1 不错 还算好用 也不是很宽的感觉 1256 | 1 现在小屏机越来越少了,这个是为数不多的选择,手感好,颜色漂亮。双11前抢的,优惠幅度大,大容量非常值得 1257 | 0 不知道究竟怎样,买来送人的,应该还行吧。 1258 | 1 收到手机好兴奋,手机很好用,上网速度与激情快,玩游戏一点也不卡,打农药,吃鸡手感过瘾,喜欢,好的不得了,照片晚上一样的清晰,支持华为,建议大家选购华为10或20,还有手机该有的套装全部齐全,一次到位。 1259 | 1 手感不错,外管也很好看,物流也快 1260 | 1 手机很满意,拍照功能能好,5.84屏幕我最满意的了 1261 | 1 华为手机太好用了,一直关注了很久,今天终于到手了。 1262 | 1 快没电的时候手机会卡 特别是玩游戏的时候 1263 | 1 手机挺不错的第一次用荣耀手机感觉挺不错的 1264 | 1 正在使用中,挺好,就是这颜色跟图片上的颜色一点也不一样,颜色适合男孩用,是蓝色的 1265 | 1 手机已收到各方面还行拍照也很清晰,手机外观很惊艳,还在研究试用中过后再评价。 1266 | 1 刚拿到,非常满意,谢谢店家送的小礼物 1267 | 1 挺好 挺顺畅的 1268 | 0 发热严重,AI拍照非常好 1269 | 1 手机拿到手两天了,全面屏很大,屏幕亮丽,外放声很大,比我的荣耀6好十陪 1270 | 1 美观漂亮,拍照清晰,图片真实好看。 1271 | 1 用了这么长时间才来评价,是一部好手机,电池板特好 1272 | 0 信我的,电池超不耐用,我喜欢荣耀10但是我不喜欢它的电池。 1273 | 1 还不错,给朋友买的,又便宜了点。 1274 | 1 用起来还不错,正在体验新新功能 1275 | 1 机身相对传统5.5屏的机小巧,和荣耀9差不多吧,但是屏幕更大,看着更爽,外观时尚漂亮,有970+6g运存加持系统比较流畅,玩刺激战场无压力,店家送了一个游戏摇杆玩王者农药和吃鸡都能用 1276 | 1 手机触屏流畅,充电迅速,就是耗电量太快,充满电不够用一天的 1277 | 1 帮老爸买的,他好像挺喜欢的,一直用的华为荣耀,因为我不在家,就不拍图片啦? 1278 | 1 京东物流就是快,赠品丰富,质量好,是个很好的购物平台,好评! 1279 | 1 送给妹妹的,说是很喜欢,外观大气漂亮,很好用,像素也不错! 1280 | 1 非常好(?▽?)漂亮完美 1281 | 1 差评,大家不要在他家买手机,发货超级慢,他们的客服态度特别不好!太#人了! 1282 | -1 啥都可以。就是贼耗电。唉。 1283 | 0 很一般吧 1284 | 1 手机已经使用了一个多星期,真的不错,网速快,很流畅呢,好漂亮! 1285 | 1 使用非常顺畅,游戏体验非常不错,不知道用几个月后会不会不行。 1286 | 1 爱机收到了 很好 很喜欢 照片就懒得拍了 老板服务不咋滴 物流也有点慢 1287 | 1 屏幕一个字:大,视觉效果好,音质好,拿到手就开始把玩,性能强大,系统运行流畅,照片相素很好 1288 | 1 非常不错的一次购物,还赠送这么多礼品,超值!超赞 1289 | 1 手机不错哦,样子很漂亮,华为的品牌还是值得信赖的,系统操作简单流畅,玩游戏一点也不卡 1290 | -1 上海新买的手机。卸载残留怎么有云南移动。重没装过云南移动app.解释哈 1291 | 0 火......麒麟。其他的都还好,就给个三星 1292 | 0 掉电非常快,没有想像的那么好,跟我原来用了3年旧的华为P8一样掉得快,早知道这样就不用买来换了,都想退了换了 1293 | 1 一如既往的满意,主要是快递快 1294 | 1 超级好用,性价比极高 1295 | 0 手机没怎么用 就剩下2G 1296 | 1 屏幕贼大 玩游戏贼爽 就是游戏加速要购买 1297 | 1 手机是买给妈妈用的,屏幕大 清晰 妈妈很是喜欢 不错? 1298 | -1 服务差,质量差 原件烂了不退换! 1299 | 1 刚拿到手,赶紧还不错 1300 | 1 手机不错,我们全家人用的手机都在京东买的,服务很好,物流很快。不错。 1301 | 0 很好,买给我老婆的,跟我现在用的V10没区别,这个还便宜。 1302 | 0 刚买到手就搞活动送耳机充电宝啊 1303 | 1 手机两天就到了,对手机质量很满意 1304 | 1 手机不错与描述相符,刚用,反应还挺快 1305 | -1 不靠谱了,双十一买的一周不发货来电话又说没货了,我买的时候没说没货啊,换成别的颜色别的颜色便宜100还不给补差价真的差劲头一次在京东遇到这种商家,失望! 1306 | 1 快递速度一流,昨天下单,今天就到了。入手很有沉重感,手机屏比我想像的还要大。看视频不错。赠送配件也非常多,物超所值。大容量电池值得期待。支持国产,支持华为。给华为点个赞,愿华为越做越好,多出精品。 1307 | 0 手机10号拿到的,用了几天,总体来说,拍照效果很好,像素够高,AI拍照也很不错,手机续航一般,这款荣耀10颜值很高,变色看起来很炫酷但一套上手机壳也就那样,手机应用软件下的差不多了,用鲁大师跑分也能跑20万多点,性能流畅度总体来说还行,就是手机发热让人头疼,也没有期待的那么给力和惊喜,我比较看重手机性能,麒麟970还是跟骁龙835有点差距的,第一次用华为荣耀系列的产品,这款手机还不错,就是没什么性价比,希望优化一下网络,给个中评,继续努力吧 1308 | 1 很满意,挺方便的,性价比挺高的,质量也很不错,很好的一次购物,东西还是挺好,京东快递很快 1309 | -1 质量越来越不行了 1310 | 1 新手机电池续航很好!外观也很炫,如过屏幕占比再高一点的话,那就完美了,不过这个价钱买这个手机,智能说划算。 1311 | 1 很好,值得购买的商品,超级棒的,京东就是好哦。 1312 | 1 手机非常好,反应也快物流也好快,用后N多天了才做评价,京东一直在身边,信赖京东商城 1313 | 1 非常清晰,手机电池耐用,手感也很好。 1314 | 1 机型漂亮|,炫彩紫的外壳高大上,运行速度快,128G内存容量大,赠品多,实惠。京东快递服务一流,一次愉快的购物。 1315 | 0 我怀疑我买到个@的荣耀。看一会快手就发热了 1316 | 1 手机非常的不错,厂家很细心,送了钢化膜,手机套等小配件! 1317 | -1 用了一个多月才来评价的.打字会自动跳来去.玩个鸡腿 1318 | 1 华为荣耀手机质量没的说,值得拥有。店家发货神速,京东快递神速 1319 | -1 刚买回来一天就降价,只能评价一星了 1320 | 1 还是很漂亮的,新机子运行速度肯定还是挺快的,使用一段时间会来追评 1321 | 1 非常好。便宜实惠。给老爸买的。老爸很喜欢。正品。支持国货 1322 | 1 使用起来还是不错的,流畅,空间又大,基本上一天是没啥问题的,使用着。值得! 1323 | 0 感觉二手机,新机出现卡顿,电量用得快,发热还可以。 1324 | 1 还不错这是第四部荣耀手机了 一直用的荣耀系列几年了 以后还会继续支持下去的 1325 | 1 真心不错,发货也快,赶上活动买的,值得推荐,还会再来赞一个 1326 | 1 用了几个月了,确实不错,最大的问题是屏幕亮度,在强光下真的看不清。 1327 | 1 手机样子小巧但是屏幕又大。拍照好看,送的东西也不错。 1328 | 1 刚开始用,手机拍照功能很强 1329 | 1 到货后特地用了几天才评!手机不错!响应快!不玩游戏 正常使用的话一天一充电!满意! 1330 | 1 荣耀十手机已经到货,外观很好,是正品,正在使用中下次还会回购。 1331 | 1 刚用了两天,好用,还没有发现有什么问题。 1332 | 1 服务五星,发货速度很快,手机刚开始不习惯,后来觉得也挺好,全五星好拼。 1333 | 1 一直想买的一款手机,手机好用拍照也些好。一个字好 1334 | 1 电池用一天没问题,充电很快。 1335 | 0 拍得蓝色,给我发了个黑的 1336 | -1 我是盲人不懂拍照。s 1337 | 1 总得来说华为荣耀10还是很不错的,虽然没有达到我心目中完美的地步,但是我还是愿意继续支持华为,支持麒麟芯,你们花在自主研发上的每一分钱 都是对祖国科技力量的提升,加油支持你们 1338 | -1 算了的,微信钱包锁都不能指纹,安装东西还要卡,还停止允许,也是醉了 1339 | 1 手机已经收到,很漂亮,目前还在使用中,初步体验很满意! 1340 | 1 手机收到了,还没有开始使用,看是满意的 1341 | 1 双11期间买的,价格比较优惠,用了一个月,没出现什么问题,运行流畅,妈妈用的蛮开心的。 1342 | 0 性价比一般边框宽,不玩游戏还可以,感觉拍照也好不到哪里去。 1343 | 0 运行速度不错,耗电太快了。 1344 | -1 换家店买手机壳 1345 | 1 手机很流畅,外壳也很好看 1346 | -1 耗电特别快,而且玩游戏手机发烫 1347 | 1 手机很漂亮,正品大爱,送货及时,期待赠品到达,好评。 1348 | -1 没有耳机手机一般亏了 1349 | 1 物超所值,值得购买,使用手机10天后宫才来评价,希望对你们有用,手机中的战斗机,电池耐用,不怎么发热,手机流畅 1350 | 1 全面屏就是用的特别舒服,一直用的荣耀系列,从荣耀6到10.没失望过,性价比特别高,而且这款手机充电特别快,颜值很高。特别值得买! 1351 | -1 怎么跑分才11万 1352 | 1 总得来说还不错吧送了一堆东西外壳太女性化了不适合我用不过那都是次要的手机很好很喜欢不大也不小刚刚好 1353 | 1 起来很方便!常的好! 1354 | -1 4G网信号特别不好 1355 | 1 手机手感很好,音质不错,电池应该也挺耐用 1356 | 1 手机质量好,超级喜欢,服务态度非常好,厂家非常细心,配送很多东西,我一直是华为的粉丝 1357 | 1 特别棒,相信华为荣耀,支持国产 1358 | -1 买个手机送个钢化膜能怎么滴 1359 | -1 好用虚有其表,上网下载慢的要死,卡成狗!幕不怎么灵敏,相机拍照效果不自然,色彩太过鲜艳不真实!池也不耐用!不是店家货不正就是这个品牌手机不好总之不建议大家购买!真是一次失败的购物! 1360 | 1 很实惠,价格合理,包装好,物流快,很满意. 1361 | 1 子是正品,,非常不错!望以后机子一切好,别出问题!递,简直是太快了!卖家很好,服务那真的没话说,一个字,好!宝贝也非常好,特意使用了几天才确认的!发的京东也非常给力!这次网上购物是我最满意的一次,推荐大家购买! 1362 | 1 刚到,外观还可以,上手也可 1363 | 1 手机特别棒、用了一段时间感觉良好,推荐购买 1364 | 1 还好,体验很不错?,拍照技术可以的? 1365 | 1 今天刚收到,具体体验追评 1366 | -1 电池不耐用,这里有点磕碰,客服不管,还说找快递,搞笑呢?外包装都没问题还找快递,想买的人想想吧,还是去官方买好。 1367 | 1 运行非常的快,大爱。 1368 | 0 手机很不错,但包装盒打包的很简单,就放了片泡棉。这样我很担心手机在过程中搞坏。希望下次不会了。 1369 | 1 手机挺好,外形,外观挺漂亮,挺好用,玩游戏一般,拍照挺好用,送的手机壳挺满意。 1370 | 1 想信哥,哥肯定不是个传说,绝对物超所值 1371 | 1 手机收到了运行非常快!拍照也清晰!电池待机时间也久!非常满意 1372 | 1 华为荣耀10很好用,屏膜大!运行速度快,上网一点都不卡!真好!物超所值啊! 1373 | 1 常不错,速度飞起。持华为,一样过两年用上20嘿嘿哥。 1374 | 1 期待了,好久,终于到了 1375 | 0 还算不错吧,挺喜欢 1376 | 1 老婆很满意,幻影蓝很漂亮,赠品要是好点就更好了,9.9包邮的东西真没用呀,全扔掉了,总之手机可以。 1377 | 1 手机挺棒,适合学生入手? 1378 | 1 包装的很好,手机用了一天没发现什么问题,就是耗电有点快。 1379 | 1 物流很快,手机系统不错,喜欢 1380 | 0 6g内存不知道其他4g去哪里 1381 | 1 手机很漂亮,功能比较全,性价比挺高,华为荣耀还是很值得推荐的,缺点是电池还是不给力。 1382 | -1 买手机没有耳机这是第一次? 1383 | 1 还可以,手机看起来漂亮,但不知使用起来怎么样,用一段时间在评论为什么不可以送个蓝牙耳机。 1384 | 1 给儿子买的,儿子特喜欢,手感非常好,满意给五个赞 1385 | 1 老婆↖(^^)↗说好就可以了。 1386 | 1 第一次在第三方卖家买手机,相当不错。价格也实惠。女友很喜欢 1387 | 1 手机很漂,运行速度很快,选择荣耀10不会错。 1388 | 1 快递邮到家好几天,一直没空。几天刚到家。看了挺好的。满意。就是没赠壳膜。 1389 | -1 太差劲了一点都不好用好卡反应迟钝 1390 | 1 还行吧!第一次要这个牌子的,感觉还可以 1391 | 0 外观设计好看,但是有阴阳屏,电量掉的也快 1392 | 1 手机拍照真的不错,夜间尽然照出白天的效果! 1393 | 1 华为手机特别好用,我一直用华为的,这次是帮别人买的,看到实手机?非常满意很心意!大屏高清!送的赠品也多 1394 | 1 手机挺好的,买给老爸的,他很喜欢。还送了很多小礼品,开心~ 1395 | 1 手感好,颜值很高,很不错,给儿子买的,他可喜欢! 1396 | 1 手机很好!物流很快! 1397 | 0 刚到手还没有 1398 | -1 前用着感觉还不错!释贼**不能解锁BL。。。就因为这个,我给1分! 1399 | 1 手机偏小,正好给老婆用。速度流畅,性能棒棒! 1400 | 1 荣耀10外观颜值高,特别变色的机身炫酷的很。昨天开机试玩下王者荣耀 高配无卡顿非常流畅 。性价比很高 双11优惠价格可以入手 1401 | 0 不知道为啥我的手机回来以后后玻璃缝隙挺大的 1402 | 1 收到几天了,用着还不错。很满意这机子, 1403 | -1 就一个裸机 耳机都没有 1404 | -1 很倒霉,看视频有声音没画面卡顿,然后申请退货被卖家拒收,拒收没有物流,也没有说明,拖延售后时长,手机退回3天物流给不出来,这种服务 真的是店的问题!!!! 服务真的不行 1405 | 0 手机很好,商家很渣,可惜了手机了,为手机点赞吧 1406 | 1 难得的小屏幕国货机,华为荣耀使用两天的体验各方面都很不错。支持国产,杠杠哒~ 1407 | 1 还不错,收到后老爸很喜欢,颜色很靓,系统也流畅,希望耐用! 1408 | 1 牌照效果绝佳,外观大气漂亮,送的东西也非常喜欢。唯一唯一的缺点就是送的膜,手机四周是曲面的,根本包不全会进灰的。其他都深得我意。 1409 | 1 可以。挺。很优 1410 | -1 小礼物都没有手机不行大家别买, 1411 | 1 运行速度快,拍照也很清晰,很喜欢这个颜色屏幕也很大,很喜欢。 1412 | 1 很不错的一款手机哦,就是发热有点大,整体来说拍照,性能,反应都很快,拍照也很清晰 1413 | 1 终于拿到手机了,折腾了半个小时把数据转移到新手机,无论是手感,反应还是系统感觉都不错,而且还送了一年碎屏宝,都说快递慢,可是我感觉挺快的,从上海到西安一天就到了,还在探索系统功能中,以后再评价 1414 | 1 比店里便宜很多,喜欢 1415 | 1 手机性能不错,很快,支持华为 1416 | -1 手机发烫,手机性能还行,这次是我买最不满意的了,手机有缝 1417 | 1 外观没的说,用的很开心,人脸解锁晚上没灯就不太好用了,必须在有光的地方,还有电池也有待提高 1418 | 0 货速度快,手机手感不错,使用下看性能怎么样。京东的包装是越来越简单了,就一个纸盒子包着,啥防护都没,包装给差评! 1419 | 0 手机刚开始使用,外观还不错,性能看看再说吧 1420 | 1 总得来说很满意,面部解锁方便,性价比很高,就是电池不太耐用。不过一直都用的华为荣耀,习以为常。快递很快,头天下单,隔天就到了。赠品蛮多 1421 | 1 首先,那我是真实本人评价,前些日子购买了这一台华为note10,外观,漂亮,性能也是很好的,用了这么些天,也没有什么毛病,总的来说,机子还是可以的,就是充电数据线,太褶皱了,,说难听点,就像二手的,她不像新的那种的表面光滑平滑的,卖家说正常,我保留我个人想法,不正常,只是外观,充电还是蛮快的,机子没啥毛病,很好 1422 | 1 货收到很满意,比线下少花钱!很好! 1423 | 1 性能和大小都很合适,上手感觉很棒 1424 | 1 很好!非常流畅,好评! 1425 | 1 手机还是非常棒的,性能、使用手感都不错,第一次用华为,唯一可能让我有些不习惯的是刘海屏,一开始我自己也觉得有点怪,不过用了一会之后感觉还挺自然的,再就是比起其他品牌的主打机,手机稍小,但其实相当够用了,其实这个大小应该是刚刚好。总的来说,荣耀10用起来挺舒服的,我很满意 1426 | 1 终于收到了,非常满意,比想的要好多了,画面很清楚,也不重,刚好,还送了好多赠品,满意的一次购物。 1427 | 1 货发的又快又好,华为手机质量不错,很好很满意 1428 | -1 机身是塑胶的,与宣传的金属机身不符 1429 | 1 手机运营很流畅,用了一天感觉很不错,国产手机还是得支持华为 1430 | -1 发热,难道我的是发烧版,关键300多公里发了7天 1431 | 1 所有一切都很好,我个人非常喜欢这台手机,快递12个小时内就送到了。 1432 | 1 本来还以为是假的,现在看来值得信赖,还送了很多东西,音响,耳机,拍照杆,钢化膜,总之,物美价廉。 1433 | 1 给家里买的,懒得拍照了,很喜欢这么大屏幕的,用着也没什么问题 1434 | 1 刚到货还在试用阶段,听说很不错,先用用看吧。 1435 | 1 京东速度就是快,1号发货2号上午就收到了,手机也很漂亮,可是老婆不喜欢这个颜色,不知道店家能不能给换个色 1436 | 1 都很好。~分身比较适用。 1437 | 1 款式漂亮 速度快 喜欢 超赞 1438 | 1 东西已经收到了,正品,正品,正品,价格也比较优惠,给个五星好评。手机很轻薄,照相效果特别好 1439 | 1 值得推荐 价格合理 包装也好 总的来说就是好 非常喜欢nice 1440 | 0 手机发烫好快,电感觉耗的好快,有可能是个人因素吧, 1441 | -1 买了一天又便宜100块。 1442 | 1 老婆很喜欢,非常好 1443 | 1 手机很好,最主要的价格便宜,用着很好,以后还会继续买的! 1444 | 0 售后服务太差,跟没有售后一样,发票要了一个多月。还是跟京东客服联系的,不然都不理你。 1445 | 1 用了一个月时间来评价,手机像素很好,但是手网络方面不是很好不知是营运商问题,还有蓝牙很多无法连接我的一个蓝牙耳机连不了,指纹识别完成不可以用,人脸识别没光线或与手机射光不能,店家服好,没耳机,华为的视频都是收费的 1446 | -1 拍照效果极差。什么AI摄影简直扯淡。苹果一年半转三星一年转华为三个月转三星。用起来也卡,虽然不玩游戏。充电很快,续航还行。 1447 | -1 先说优点吧,手感更好,外观好看,运行速度很快,虽然确实没有845流畅,不过也够用,~飞车最高画质,高帧,高清也不卡,拍照很清楚。缺点,跑电飞快,看一部1080的电影50的电没了,玩飞车开省电模式最多3个多小时。小插曲,买了两台一样的,一模一样的设置,屏幕成像居然不一样,一台明显发黄,刺眼,退了一台,还有一台朋友凑合用了。总之很不满意,估计荣耀的品控确实比华为差吧,很失望。 1448 | -1 一个别人买过的货 1449 | 1 到货慢啊,要了五天。心急的谨慎购买。感觉屏幕有点小,运行速度等都不错。 1450 | -1 买了没到一个月,又降价了,保价申请不了 1451 | -1 后摄像头拍照发黄 续航能力差 1452 | 1 第一次买华为的手机十分激动\\(≧▽≦)/,以前用过小米5_三星note8,但这次荣耀10发布让人眼前一亮刘海和下巴没有让我感到不搭,指纹录入和解锁也很快(录入的时候按照提示就行),荣耀10颜值真的高尤其是背面。 1453 | 1 运行速度很快,外观简单好看,功能很多,要求不高,完全够用了 1454 | 1 渐变色很漂亮,系统很流畅,反应灵敏,信号很好,声音效果没有宣传那么好。拍照效果也很好。送的东西也很多,耳机不错,其它礼品就一般般了,不过手机好就可以了。 1455 | -1 玩游戏屏幕触摸不灵敏,反应迟钝 1456 | 0 跟风买来试一试,不晓得用起来如何 1457 | 0 刚上手感觉拍照,系统等蛮好的,解锁速度快,用了一个多月出现屏幕死机,卡顿问题,初始用户体验不好,影响心情,后续跟客服沟通后申请返修,维修速度蛮快的,更换主板后暂时手机没什么问题,能正常使用,售后服务态度蛮好的,但感觉出厂品控把关可能要再细致些,使用一段时间再来追加评价。 1458 | 1 屏幕很清晰运行速度很快正常时间显示非常准孩子很喜欢 1459 | 1 收到手机了,颜色非常靓丽,送的手机壳也喜欢,给个好评 1460 | 1 产品收到了,外观手感都挺不错的。物流也很快。还没有使用。先好评。用后再追评! 1461 | 1 等了好久终于来啦!机子很新包装也挺好,不知道运行怎么样!使用后再来评价! 1462 | 1 给老爹买的,他说要个声音大的手机,就选了这个,还可以,很神奇的是这个A屏低亮度下频闪还好,没那么严重,拍照一般般,续航很好,但是电池太大导致充电不算特别快。 1463 | 1 期待的手机荣耀10,終于到了?,打开超出我的想像,很漂亮很轻,比我想像的要小,速度等待开机测试,一直支持华为,华为加油成为全球第一 1464 | 0 比官网贵了一百块,送了一大堆没用的东西。 1465 | 1 手机颜色很漂亮,像素美滋滋,物流也很快。 1466 | 1 物流超级快,下单不到10小时就到货了,手机用了两三天,感觉还可以。是正品,暂时没出现什么问题,比较满意的一次购物! 1467 | -1 昨天下的单,今早就到了不得不说物流很快。手机颜值特别高,大赞。另外,AI相机确实很赞,只是感觉前置不咋样。手机功能很赞,还支持抬手亮屏人脸解锁。唯一的缺点:手机发热太严重,打了一把吃鸡,手机上部分感觉太烫。给个一星吧,好评没人看,原谅我! 1468 | 1 今天手机刚到比我想象中还要好不错.荣耀10全网通版你值得拥有 1469 | 1 手机很好用,支持华为,脸部识别秒解锁,昨晚吃鸡连续一个多小时 不卡, 戴耳机音效没的说,充电很快,非常满意。 1470 | 1 用了一段时间,性能很不错,不愧为国产精品,支持华为,支持国货! 1471 | 1 手机不错,弟弟说颜值很高很喜欢~ 1472 | 1 拍照效果好,清晰度高,色彩真实,运行速度快。 1473 | 1 手机很漂亮,功能也很强大,手感也不错,我个人感觉唯一的缺点就是开静音时媒体声不一起跟着静音必须手动调整,我以前的手机不是这样的,开静音媒体声也跟着静音比较方便 1474 | 0 说?是?幻?影?紫?,全?店?的?人?都?认?为?是?蓝?色?的?,是?我?们?眼?神?有?问?题?吗? 1475 | 1 手机好用,屏幕清晰,系统快,老板还给了很多赠品 1476 | -1 带点不行,实际运存都不到一半 1477 | 0 手机不知为何老死机 1478 | 1 很好用 给店家好评 点赞 1479 | 0 好又不好,中等评价 1480 | 0 本来很喜欢荣耀系列的手机,从荣耀6,荣耀8,到荣耀10,一直很支持荣耀系列的牌子,荣耀10刚出就预订了,但是结果很失望,玩一局游戏就发热,卡屏,电量消耗快,后来买了荣耀其他款的手机,体验很好,荣耀系列都很好,就荣耀10差,不过我还是会一直支持荣耀,希望越做做好 1481 | 1 拍照效果杠杠滴,电池的话听歌聊天感觉还可以,充电速度超级快 1482 | 1 手机收到,快递给力,用了半个多月,很好,没发现缺点,全五星。 1483 | 1 第二天就到了,非常快,东西打开非常满意,物有所值! 1484 | 0 指纹解锁,电池,人脸解锁都没小米8好 1485 | 1 宝贝已收到,在京东买的第三部手机,很好,会继续信任京东,支持京东 1486 | 1 持国产产品!值高,速度快,喜欢! 1487 | 1 用了几天才来评价,总得来说很不错,我很喜欢,续航还可以,玩游戏的话要一天两充,拍照非常棒,外观好看 1488 | 1 手机很好用,孩子很喜欢,颜色很漂亮,赠品也很多,总之挺不错的。 1489 | 1 东西很好,质量也很棒,物流很快,客服态度也好,这个手机在太阳下转动,不一样的方向就会有不一样的颜色,有时候是紫色,有时候是蓝色,看起来特别好玩,而且它的功能也非常好,新手机用起来电池非常的持久,非常续航,感觉还是挺好的。可能扬声器的声音稍微小了一些,是手机自身的原因,跟其他的没有关系,也可以忽略不计,毕竟戴上耳机之后还是可以听到的,是一次挺满意的购物了 1490 | 1 这手机真的不错,可以入手,我用了两个星期,从运行内存,拍照等方面都是非常棒的,主要是不管你后台开了多少个软件,也不会影响正在用的这个,性价比高。 1491 | 1 功能非常强大,打游戏一点不卡顿,效果非常好。。拍照也很逼真。。而且颜色特别漂亮,很是喜欢,赞个 1492 | 1 质量非常的好哦,价格也很合适,非常好用,好评! 1493 | 1 自己看吧,性能确实牛# 1494 | 1 手机是正品,速度很快,很满意的一次购物 1495 | 1 屏幕显示清晰,运行流畅,非常棒 1496 | 1 手机是正品,非常不错,第二次购买了,赞一个,喜欢,老妈也喜欢 1497 | 0 Tel热areas大价钱一分货考虑 1498 | 0 还可以吧,希望好用,没有**送的赠品多 1499 | 1 很好。玩游戏看视频的神器。 1500 | -1 手机连耳机都没有 1501 | 1 期待已久的手机收到了,很满意的是正品的华为荣耀手机质量棒棒哒,好评的 1502 | 1 手机用着很爽,大屏看电影给力, 1503 | 1 用了一个月了,电池耐用,速度快信号也好价格实惠,非常满意 1504 | -1 服务态度极其恶劣,随手机赠送的壳缺少一个送话的开孔,导致安上壳以后打电话对方听不到声音,与客服沟通,客服的第一句话是没听到别人反应过这个问题,好像我在无理取闹,这是我在网络购物体验最差的一次,大家可以看看图片中对应送话孔的壳有没开孔,不推荐在他家买东西,没有良好的售后服务,东西没法买。 1505 | -1 第一次第三方买手机,真的很差,我还有一部荣耀play都升级了gt,荣耀play比荣耀10流畅无数倍,我也不知道是手机问题,还是荣耀10就这样,关键是触屏有问题,很多时候屏幕没反应,申请退货,说我撕掉了入网许可证,第一次退货,我也不懂,没办法,不能退,想换货,去检查确实没问题,不能换,只能说,第三方真的痛苦,唉,再也不会在第三方买了,手机问题太多 1506 | 1 是正品,不是假货,也不是翻新机,用的挺喜欢的 1507 | -1 同一天买了三台手机、两台寄到了、还有一台不知道要何年何月才能收到了 1508 | 0 东西一般,电池不耐用,没有想象中那么的好,用了几天来评价的!总之一般 1509 | 1 物流很快。手机也就这样毕竟安卓就这样 1510 | 1 宝贝很快就收到了,原装正品,非常满意,值得购买! 1511 | -1 手机买来,真心买错,开机没多久手机很烫,不是一般的烫,电池又不耐用!差 1512 | 1 手机配置很好,用起来运行很流畅,电量续航还行,拍照效果很好,很满意 1513 | 1 屏幕大,音效很棒,其他功能慢慢体验 1514 | -1 发烫手机,普通上网浏览网页都烫 1515 | 1 手机收到非常好,原装正品,运行速度非常流畅,值得入手。 1516 | 1 趁双十一买的,很划算,屏幕很大! 1517 | 1 帮朋友买的,她挺满意的。送给他老公的。现在手机都很成熟了 1518 | 1 第一眼看到这手机就是大,大屏,确实没有见过这么大的手机,外观设计好看,打王者,吃鸡不在话下,,大屏手机就是好。 1519 | 0 这手机还可以 1520 | 1 手机收到,快递很快,服务态度非常好,我不在家,快递跑了几趟,辛苦了。试了一下,手机反应很快,照像很清晰。开机电量显示剩余百分之三十了。店家服务态度很好,好多问题都一一解答。唯一缺点就是礼物太少,显得有点寒酸了 1521 | 1 挺不错的。很满意。质量方面也挺好的。很喜欢 1522 | 0 耳机坏了,要送就送些好的质量的,要不然真影响购物心情 1523 | -1 想说话。 1524 | 1 手机很棒,小巧,物流很快,预计三天,一天就到了,店家服务周到 1525 | 1 手机收到,是正品,这点大家可以放心购买,玩游戏很爽,很对得起这个价位,送的礼物也很实用呢? 1526 | 1 充电简直神速 人脸解锁非常快!指纹轻轻一碰到就解锁了 真的很惊艳 性价比可以说是很高了 而且卖家还送了好多东西?拍照也灰常清晰 色彩处理的很恰当 nice 1527 | 1 店家态度很消极 店家态度很消极 1528 | 0 耗电贼快,其他还好,基本没怎么玩,就刷一个半小时的手机,然后看下时间,从早到晚,电没了充电快,这是为了上膛快所以射的快? 1529 | 0 还行吧,对付用吧, 1530 | 1 前两天荣耀9不小心摔了,狠下心换了10,果然没让我失望,还是高颜值,手感还特好。 1531 | 1 这是买的第二个荣耀10了 很好用 华为的系统已经升级到安卓9.0。自己使用 支持华为超级快充。 1532 | 1 很好,下次还要来这儿买 1533 | 1 手机简约,系统操作干练,我用的很流畅,很不错 1534 | 1 东收到了,速度那是真快,掉价也 1535 | 1 手机挺不错的,颜值很高,手机运行很流畅,游戏体验感也蛮好,值得购买。 1536 | 1 拿到手机的那一刻真的给惊艳到了 华为果然是国产手机的老大!用下来体验很好!棒棒哒 1537 | 1 用了一段时间才来的,手机非常好,运行速度飞起来,吃鸡游戏也没有问题,商家还送了很多很实用的小物件,非常棒,拍照也杠杠的 1538 | -1 不好用,指纹太不灵了,还比别家的贵100圆。 1539 | 0 可以吧。 1540 | 1 手机收到啦~目前为止,确实很好用~很喜欢~ 1541 | 1 很喜欢这个机型和颜色,送的东西也不错,真不愧是我胡歌大佬代言的东西! 1542 | 1 手机挺好的,物流有点慢,home键也很好用呀,发热,夏天手机都会热,相信荣耀 1543 | 1 给孩子买的,孩子高兴就好。华为手机不错商家很给力。 1544 | 1 手机后屏很好看,好喜欢这个颜色,用起来也很流畅 1545 | 1 手感不错 整体都不错 1546 | 1 用了几天,确实不错,运行速度很快,拍出的照片非常棒,大小正合适,物流特快,一流的服务,很满意! 1547 | -1 想买的人我先说下,手机只谁便的刷一刷新闻,不开任何软件就会发热,而且手机掉电非常的快,上手特别失望 1548 | 1 特意用了几天才来评论,很好用,跟我想的一样,物流很快,晚上下单,第二天早上就到了! 1549 | 1 手机比我想象的还要大,看视频玩游戏是一绝 1550 | 1 还不错,挺喜欢的,第一次是使用大屏幕手机,一开始担心怕太大了,后面还是狠下心买了下来,入手了感觉刚刚好,其他的待后面感受。个人一直都挺支持华为的,不错,没让人失望。商家还送了这么多小礼物,赞。 1551 | 1 手机不错。电量很大。 1552 | 1 包装完好,手机很漂酿。赞?。等用段时间来追评 1553 | -1 四个字!不想说了! 1554 | 1 收到了还没用!使用后追评 1555 | 1 拍照效果很不错 续航能力也不错 关键这手机玩吃鸡和王者的时候屏幕不灵敏 我也不知道怎么回事? 1556 | 0 电池掉电太快了!也没玩游戏就看看新闻,不知道其他人的怎么样 1557 | 1 手机真的超级好看 手感挺好的 喜欢 1558 | 1 手机以收到一直没空评价,第一网购手机,还不错。物流提前一天,客服很棒。急急忙忙没功夫传照片了,下次吧 1559 | 1 手机很好容量大,非常喜欢。 1560 | 1 第二次买了这个同款,不是同一个店,希望一样好 1561 | 1 发货很快 是正品跟图片上的一模一样,手机的质量也非常的好,摄像也非常的清晰,店家还赠送了许多的礼品,礼品也很实用,值得购买。 1562 | -1 #手机,才买一个月经常失灵 1563 | 0 手机除了拍照录像都还可以吧。 1564 | 1 手机收到了,很实惠,颜色好看,物流也给力,喜欢哦! 1565 | 1 可以!价格相比比较便!~ 1566 | 1 手机质量不错,华为大品牌我信赖,运行速度快,手机很漂亮,支持华为大品牌 1567 | 1 手机手感很好,看着挺漂亮,玩王者不卡 1568 | 1 东西收到了,外观可以,用几天再说 1569 | 1 给孩子买的,还没用但外观比较漂亮,不过对华为手机还是很认可的。 1570 | 1 屏大流畅性好 1571 | 1 520送给老公的礼物,他很喜欢,物流发货也太快了,早上下单,下午就收到了,大爱,魅蓝,反应灵敏,拍照清晰,手感特好,且店家还送了许多配套礼物,如运动耳机,防爆膜,壳,原装耳机,还有背包。手机性能一点也不比苹果差,支持国货,感谢京东,感谢店家,好评,全5星。 1572 | 1 手机不错,速度快,拿着手感也好 1573 | 1 手机很好,而且很流畅,物流也很快。 1574 | 0 还可以,挺不错的 1575 | 1 贝等了好久终于拿到手,用了几天感觉不错,运行速度也很快,打游戏一点不都一卡,总体来说不错了! 1576 | 1 手机很好特别给力,感谢京东我会常来买东西的。 1577 | 0 耗电快一天两冲 1578 | 1 手机收到了,用着很顺溜,卖家送了小礼品,很不错哦,值得购买 1579 | -1 刚买一周就出问题了,大家别买了 1580 | 1 是正品没错,跑了20多万分,运行没有问题,流畅 1581 | 1 玩游戏真不是盖的,真的可以入手哈,快内存大,真的很给力 1582 | 1 非常好,玩着有手感 1583 | 1 机买来用了差不多一个多月了,就来说说用起来的体验吧一,刚收到手机的时候觉得这个手机好可爱啊,因为手机并不是很大,只是屏幕比较长,很小巧,女生用是不错的二,拍照方面还是蛮不错的,有时候拍风景的时候能识别场景然后自动加滤镜什么的,拍出来的照片很好看,还有自拍也不错,前置摄像头旁边好像还有闪光灯??总之自拍的时候光圈很大,光线可以很充足,觉得这个有点牛三,128G的内存可以说是充足的了,建议不玩游戏的朋友买64g就够了四,用了一个多月暂时没发现什么大型卡顿的现象,不过刚开始用的时候有卡过一两次,卡的时候开始怀疑人生然后想会不会是买了假手机不过后来基本用起来还是蛮流畅的。五,其实刚开始觉得手机下巴挺丑的,不过后来发现下巴用起来是很方便的,而且比后置指纹美观,不过微信不能指纹支付!这就很难受了!六,买的手机是黑色的,然后用过一阵子之后介绍给同学,同学也买了一个同款的,海鸥灰,海鸥灰真的好好看啊!比蓝色紫色都好看,当初以为灰色是最丑的,后来发现是最好看的?但是同学的用了几个星期就坏了,开始担心会不会我的也出现问题,总之希望不要给了好评之后手机就出现问题吧!然后能用上个几年! 1584 | 1 以啊 很好看的一步手机 值得入手 哈 1585 | 1 京东送货就是快,跟网上一样漂亮的手机及时收到,点赞 1586 | 1 电池续航能力良好很耐用 1587 | 1 第二个华为手机,这个比上一个轻,耳机的插口很影响玩游戏,屏幕没有上一个大,有点儿像苹果6 1588 | 1 外观非常漂亮,感觉不错,希望能耐用一点。 1589 | 1 手机漂亮大气,赠品多多,但不实用,好评! 1590 | 1 手感拿着很不错,性能也不错,快递也很快,客服态度好。颜色很漂亮 1591 | 1 池续航时间超长,手机外观也特别好看,快递也特别快,而且赠品多 1592 | 0 买错了,手感没有华为v9好。但是也能用吧 1593 | -1 配件都没配齐,耳机都没有 1594 | 1 手机收到了,非常好用。送货速度也及时,性价比高,满意。 1595 | 1 荣耀手机外观还不错,运行速度可以,好像手机电池不是很给力,电池容量不够大 1596 | 1 电话不错,很喜欢 1597 | 1 刚收到,外观不错,喜欢,帮朋友代买的 1598 | 1 和描述的一样,非常非常漂亮,高贵,配置很高,像素也可以,总体来说还不错,性价比很高。 1599 | 1 这款手机我觉得性价比真的很高,很不错,那个机子也速度也很快,其他的都还可以。 1600 | 1 手机很好,正品,自带手机膜,省了很多事。运行速度很快,拍照非常好 1601 | -1 说好有赠品的结果没有 1602 | 1 手机不错,和我在实体店看的一样,价格还比实体店低一点,就是送的东西不是太好,特别是膜,钢化膜有白边,还没有白边补充液,不过总体来说在这家店买还是很划算的。而且送货速度也很快,发的是顺丰快递,很有保障! 1603 | 1 棒哦,屏幕大,看片神器,你值得拥有么么哒哈 1604 | -1 解锁慢 碎屏 极易发热 游戏烫手 1605 | 1 屏幕清晰,相机的的拍照的清晰度也较真,手机运行也历害 1606 | 1 手机很好,反应好快,物流服务不错,快 1607 | 1 手感非常好,挺大气的 1608 | 0 首先这手机挺漂亮的,操作也挺流畅的,手感刚刚好,喜欢的朋友可以入手,但是不得不吐槽做工问题,华为的厂家究竟有没有质量检验机构,怎么这种机子都能放出来。想入手荣耀10的玩家还是先检查一下有没有质量问题,没有的话这机子的性价比还是挺高的~~扣的两分是质量问题 1609 | 1 感觉还不错,正在熟悉中,先把数据倒过来再说 1610 | 0 背面比正面好看,性能方面,吃鸡可以开HDR高清模式,续航一般,出厂自带保护膜和保护套还行, 还有就是多任务呼出方式还有待改善,经常误操作,这种呼出方式弄得原厂的膜都起了一个角了。 1611 | 1 运行速度可以 像素也很棒 1612 | 1 卖家发货及时,手机也是正品,价格实惠,赠品还多。第2个荣耀10了 这个手机性价比很高 推荐 1613 | 1 手机摸起来很舒服,用起来也很不错。电池也很经用,充电也非常快~ 1614 | -1 手机wifi无限掉,而且速度也超慢,我某米手机和果7下载速度都超快。真是无语了,以为华为的手机信号好。再用几天试试数据网络信号,。 1615 | -1 颜色完全不符图片 1616 | 1 这部手机很好看。note 10 处理器强大,就是我的工资啊!心痛。 1617 | -1 日**逼,买个修了的手机,还插了卡没网络,坑货。老子说假话出门撞死 1618 | -1 说好的耳机没有,没耳机没耳机! 1619 | 1 电池宇航能力不错,运行速度也是杠杠的,非常好用的一款手机,赞 1620 | 1 非常满意,性能不错外观也很棒,送的配件礼品也很好,给好评。 -------------------------------------------------------------------------------- /freeze_graph.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | #coding:utf-8 3 | 4 | __author__ = 'xmxoxo' 5 | 6 | ''' 7 | BERT模型文件 ckpt转pb 工具 8 | 9 | ''' 10 | 11 | #import contextlib 12 | import json 13 | import os 14 | from enum import Enum 15 | from termcolor import colored 16 | import sys 17 | import modeling 18 | import logging 19 | import tensorflow as tf 20 | import argparse 21 | import pickle 22 | 23 | 24 | def set_logger(context, verbose=False): 25 | if os.name == 'nt': # for Windows 26 | return NTLogger(context, verbose) 27 | 28 | logger = logging.getLogger(context) 29 | logger.setLevel(logging.DEBUG if verbose else logging.INFO) 30 | formatter = logging.Formatter( 31 | '%(levelname)-.1s:' + context + ':[%(filename).3s:%(funcName).3s:%(lineno)3d]:%(message)s', datefmt= 32 | '%m-%d %H:%M:%S') 33 | console_handler = logging.StreamHandler() 34 | console_handler.setLevel(logging.DEBUG if verbose else logging.INFO) 35 | console_handler.setFormatter(formatter) 36 | logger.handlers = [] 37 | logger.addHandler(console_handler) 38 | return logger 39 | 40 | 41 | class NTLogger: 42 | def __init__(self, context, verbose): 43 | self.context = context 44 | self.verbose = verbose 45 | 46 | def info(self, msg, **kwargs): 47 | print('I:%s:%s' % (self.context, msg), flush=True) 48 | 49 | def debug(self, msg, **kwargs): 50 | if self.verbose: 51 | print('D:%s:%s' % (self.context, msg), flush=True) 52 | 53 | def error(self, msg, **kwargs): 54 | print('E:%s:%s' % (self.context, msg), flush=True) 55 | 56 | def warning(self, msg, **kwargs): 57 | print('W:%s:%s' % (self.context, msg), flush=True) 58 | 59 | def create_classification_model(bert_config, is_training, input_ids, input_mask, segment_ids, labels, num_labels): 60 | """ 61 | 62 | :param bert_config: 63 | :param is_training: 64 | :param input_ids: 65 | :param input_mask: 66 | :param segment_ids: 67 | :param labels: 68 | :param num_labels: 69 | :param use_one_hot_embedding: 70 | :return: 71 | """ 72 | 73 | #import tensorflow as tf 74 | #import modeling 75 | 76 | # 通过传入的训练数据,进行representation 77 | model = modeling.BertModel( 78 | config=bert_config, 79 | is_training=is_training, 80 | input_ids=input_ids, 81 | input_mask=input_mask, 82 | token_type_ids=segment_ids, 83 | ) 84 | 85 | embedding_layer = model.get_sequence_output() 86 | output_layer = model.get_pooled_output() 87 | hidden_size = output_layer.shape[-1].value 88 | 89 | # predict = CNN_Classification(embedding_chars=embedding_layer, 90 | # labels=labels, 91 | # num_tags=num_labels, 92 | # sequence_length=FLAGS.max_seq_length, 93 | # embedding_dims=embedding_layer.shape[-1].value, 94 | # vocab_size=0, 95 | # filter_sizes=[3, 4, 5], 96 | # num_filters=3, 97 | # dropout_keep_prob=FLAGS.dropout_keep_prob, 98 | # l2_reg_lambda=0.001) 99 | # loss, predictions, probabilities = predict.add_cnn_layer() 100 | 101 | output_weights = tf.get_variable( 102 | "output_weights", [num_labels, hidden_size], 103 | initializer=tf.truncated_normal_initializer(stddev=0.02)) 104 | 105 | output_bias = tf.get_variable( 106 | "output_bias", [num_labels], initializer=tf.zeros_initializer()) 107 | 108 | with tf.variable_scope("loss"): 109 | if is_training: 110 | # I.e., 0.1 dropout 111 | output_layer = tf.nn.dropout(output_layer, keep_prob=0.9) 112 | 113 | logits = tf.matmul(output_layer, output_weights, transpose_b=True) 114 | logits = tf.nn.bias_add(logits, output_bias) 115 | probabilities = tf.nn.softmax(logits, axis=-1) 116 | log_probs = tf.nn.log_softmax(logits, axis=-1) 117 | 118 | if labels is not None: 119 | one_hot_labels = tf.one_hot(labels, depth=num_labels, dtype=tf.float32) 120 | 121 | per_example_loss = -tf.reduce_sum(one_hot_labels * log_probs, axis=-1) 122 | loss = tf.reduce_mean(per_example_loss) 123 | else: 124 | loss, per_example_loss = None, None 125 | return (loss, per_example_loss, logits, probabilities) 126 | 127 | 128 | def init_predict_var(path): 129 | num_labels = 2 130 | label2id = None 131 | id2label = None 132 | label2id_file = os.path.join(path, 'label2id.pkl') 133 | if os.path.exists(label2id_file): 134 | with open(label2id_file, 'rb') as rf: 135 | label2id = pickle.load(rf) 136 | id2label = {value: key for key, value in label2id.items()} 137 | num_labels = len(label2id.items()) 138 | print('num_labels:%d' % num_labels) 139 | else: 140 | print('Can\'t found %s' % label2id_file) 141 | return num_labels, label2id, id2label 142 | 143 | 144 | 145 | def optimize_class_model(args, logger=None): 146 | """ 147 | 加载中文分类模型 148 | :param args: 149 | :param num_labels: 150 | :param logger: 151 | :return: 152 | """ 153 | 154 | if not logger: 155 | logger = set_logger(colored('CLASSIFICATION_MODEL, Lodding...', 'cyan'), args.verbose) 156 | pass 157 | try: 158 | # 如果PB文件已经存在则,返回PB文件的路径,否则将模型转化为PB文件,并且返回存储PB文件的路径 159 | if args.model_pb_dir is None: 160 | tmp_dir = args.model_dir 161 | else: 162 | tmp_dir = args.model_pb_dir 163 | 164 | pb_file = os.path.join(tmp_dir, 'classification_model.pb') 165 | if os.path.exists(pb_file): 166 | print('pb_file exits', pb_file) 167 | return pb_file 168 | 169 | #增加 从label2id.pkl中读取num_labels, 这样也可以不用指定num_labels参数; 2019/4/17 170 | if not args.num_labels: 171 | num_labels, label2id, id2label = init_predict_var(tmp_dir) 172 | else: 173 | num_labels = args.num_labels 174 | #--- 175 | 176 | graph = tf.Graph() 177 | with graph.as_default(): 178 | with tf.Session() as sess: 179 | input_ids = tf.placeholder(tf.int32, (None, args.max_seq_len), 'input_ids') 180 | input_mask = tf.placeholder(tf.int32, (None, args.max_seq_len), 'input_mask') 181 | 182 | bert_config = modeling.BertConfig.from_json_file(os.path.join(args.bert_model_dir, 'bert_config.json')) 183 | 184 | loss, per_example_loss, logits, probabilities = create_classification_model(bert_config=bert_config, is_training=False, 185 | input_ids=input_ids, input_mask=input_mask, segment_ids=None, labels=None, num_labels=num_labels) 186 | 187 | # pred_ids = tf.argmax(probabilities, axis=-1, output_type=tf.int32, name='pred_ids') 188 | # pred_ids = tf.identity(pred_ids, 'pred_ids') 189 | 190 | probabilities = tf.identity(probabilities, 'pred_prob') 191 | saver = tf.train.Saver() 192 | 193 | with tf.Session() as sess: 194 | sess.run(tf.global_variables_initializer()) 195 | latest_checkpoint = tf.train.latest_checkpoint(args.model_dir) 196 | logger.info('loading... %s ' % latest_checkpoint ) 197 | saver.restore(sess,latest_checkpoint ) 198 | logger.info('freeze...') 199 | from tensorflow.python.framework import graph_util 200 | tmp_g = graph_util.convert_variables_to_constants(sess, graph.as_graph_def(), ['pred_prob']) 201 | logger.info('predict cut finished !!!') 202 | 203 | # 存储二进制模型到文件中 204 | logger.info('write graph to a tmp file: %s' % pb_file) 205 | with tf.gfile.GFile(pb_file, 'wb') as f: 206 | f.write(tmp_g.SerializeToString()) 207 | return pb_file 208 | except Exception as e: 209 | logger.error('fail to optimize the graph! %s' % e, exc_info=True) 210 | 211 | 212 | 213 | 214 | if __name__ == '__main__': 215 | pass 216 | 217 | """ 218 | bert_model_dir="/mnt/sda1/transdat/bert-demo/bert/chinese_L-12_H-768_A-12" 219 | model_dir="/mnt/sda1/transdat/bert-demo/bert/output/demo7" 220 | model_pb_dir=model_dir 221 | max_seq_len=128 222 | num_labels=2 223 | """ 224 | 225 | 226 | parser = argparse.ArgumentParser(description='Trans ckpt file to .pb file') 227 | parser.add_argument('-bert_model_dir', type=str, required=True, 228 | help='chinese google bert model path') 229 | parser.add_argument('-model_dir', type=str, required=True, 230 | help='directory of a pretrained BERT model') 231 | parser.add_argument('-model_pb_dir', type=str, default=None, 232 | help='directory of a pretrained BERT model,default = model_dir') 233 | parser.add_argument('-max_seq_len', type=int, default=128, 234 | help='maximum length of a sequence,default:128') 235 | parser.add_argument('-num_labels', type=int, default=None, 236 | help='length of all labels,default=2') 237 | parser.add_argument('-verbose', action='store_true', default=False, 238 | help='turn on tensorflow logging for debug') 239 | 240 | args = parser.parse_args() 241 | 242 | optimize_class_model(args, logger=None) 243 | 244 | -------------------------------------------------------------------------------- /images/cap00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmxoxo/BERT-train2deploy/b03cb0a1b693e91fddab74eb7945c1de2b33a18f/images/cap00.png -------------------------------------------------------------------------------- /images/cap01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmxoxo/BERT-train2deploy/b03cb0a1b693e91fddab74eb7945c1de2b33a18f/images/cap01.png -------------------------------------------------------------------------------- /images/cap02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmxoxo/BERT-train2deploy/b03cb0a1b693e91fddab74eb7945c1de2b33a18f/images/cap02.png -------------------------------------------------------------------------------- /images/cap05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmxoxo/BERT-train2deploy/b03cb0a1b693e91fddab74eb7945c1de2b33a18f/images/cap05.png -------------------------------------------------------------------------------- /mobile_apisvr/api_service.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | #coding:utf-8 3 | 4 | """ 5 | @Time : 2019/2/28 15:31 6 | @Author : xmxoxo (xmhexi@163.com) 7 | @File : tran_service.py 8 | """ 9 | import argparse 10 | import flask 11 | import logging 12 | import json 13 | import os 14 | import re 15 | import sys 16 | import string 17 | import time 18 | import numpy as np 19 | 20 | 21 | from bert_base.client import BertClient 22 | 23 | 24 | # 切分句子 25 | def cut_sent(txt): 26 | #先预处理去空格等 27 | txt = re.sub('([  \t]+)',r" ",txt) # blank word 28 | txt = txt.rstrip() # 段尾如果有多余的\n就去掉它 29 | nlist = txt.split("\n") 30 | nnlist = [x for x in nlist if x.strip()!=''] # 过滤掉空行 31 | return nnlist 32 | 33 | 34 | #对句子进行预测识别 35 | def class_pred(list_text): 36 | #文本拆分成句子 37 | #list_text = cut_sent(text) 38 | print("total setance: %d" % (len(list_text)) ) 39 | with BertClient(ip='192.168.15.111', port=5575, port_out=5576, show_server_config=False, check_version=False, check_length=False,timeout=10000 , mode='CLASS') as bc: 40 | start_t = time.perf_counter() 41 | rst = bc.encode(list_text) 42 | print('result:', rst) 43 | print('time used:{}'.format(time.perf_counter() - start_t)) 44 | #返回结构为: 45 | # rst: [{'pred_label': ['0', '1', '0'], 'score': [0.9983683228492737, 0.9988993406295776, 0.9997349381446838]}] 46 | #抽取出标注结果 47 | pred_label = rst[0]["pred_label"] 48 | result_txt = [ [pred_label[i],list_text[i] ] for i in range(len(pred_label))] 49 | return result_txt 50 | 51 | def flask_server(args): 52 | pass 53 | from flask import Flask,request,render_template,jsonify 54 | 55 | app = Flask(__name__) 56 | #from app import routes 57 | 58 | @app.route('/') 59 | def index(): 60 | return render_template('index.html', version='V 0.1.2') 61 | 62 | @app.route('/api/v0.1/query', methods=['POST']) 63 | def query (): 64 | res = {} 65 | txt = request.values['text'] 66 | if not txt : 67 | res["result"]="error" 68 | return jsonify(res) 69 | lstseg = cut_sent(txt) 70 | print('-'*30) 71 | print('结果,共%d个句子:' % ( len(lstseg) ) ) 72 | for x in lstseg: 73 | print("第%d句:【 %s】" %(lstseg.index(x),x)) 74 | print('-'*30) 75 | if request.method == 'POST' or 1: 76 | res['result'] = class_pred(lstseg) 77 | print('result:%s' % str(res)) 78 | return jsonify(res) 79 | 80 | 81 | app.run( 82 | host = args.ip, #'0.0.0.0', 83 | port = args.port, #8910, 84 | debug = True 85 | ) 86 | 87 | 88 | def main_cli (): 89 | pass 90 | parser = argparse.ArgumentParser(description='API demo server') 91 | parser.add_argument('-ip', type=str, default="0.0.0.0", 92 | help='chinese google bert model serving') 93 | parser.add_argument('-port', type=int, default=8910, 94 | help='listen port,default:8910') 95 | 96 | args = parser.parse_args() 97 | 98 | flask_server(args) 99 | 100 | if __name__ == '__main__': 101 | main_cli() 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /mobile_apisvr/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 政策文本句子分类演示 5 | 6 | 7 | 8 | 9 | 10 | 21 | 22 | 23 | 24 | 95 | 96 | 97 | 98 | 99 |
100 |
政策文本语句分类演示 版本: {{ version }}
101 |
102 |
103 |
104 | 请输入待分析的文本: 105 | 107 |
108 | 169 |
提示:无需处理格式,直接复制文本内容即可
170 | 171 |
172 |
173 | 174 |
175 |
文本语句分类提取: 176 | 177 | 178 |
179 | 180 |
181 |
182 | 183 | 184 | 185 |
186 | 187 | 188 | 189 | -------------------------------------------------------------------------------- /mobile_apisvr/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 手机评论情感分类演示 5 | 6 | 7 | 8 | 9 | 10 | 21 | 22 | 23 | 24 | 73 | 74 | 75 | 76 | 77 |
78 |
手机评论情感分类演示 版本: {{ version }}
79 |
80 |
81 |
82 | 请输入待分析的文本: 83 |
84 | 115 |
提示:无需处理格式,直接复制文本内容即可
116 |
117 |
118 |
119 |
分类结果: 120 | 121 |
122 | 123 |
124 |
125 |
126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /mobile_svr/bertsvr.sh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmxoxo/BERT-train2deploy/b03cb0a1b693e91fddab74eb7945c1de2b33a18f/mobile_svr/bertsvr.sh -------------------------------------------------------------------------------- /model/eval_results.txt: -------------------------------------------------------------------------------- 1 | eval_accuracy = 0.861643 2 | eval_f1 = 0.9536328 3 | eval_loss = 0.56324786 4 | eval_precision = 0.9491279 5 | eval_recall = 0.9581805 6 | global_step = 759 7 | loss = 0.5615213 8 | -------------------------------------------------------------------------------- /model/label2id.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmxoxo/BERT-train2deploy/b03cb0a1b693e91fddab74eb7945c1de2b33a18f/model/label2id.pkl -------------------------------------------------------------------------------- /modeling.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # Copyright 2018 The Google AI Language Team Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | """The main BERT model and related functions.""" 16 | 17 | from __future__ import absolute_import 18 | from __future__ import division 19 | from __future__ import print_function 20 | 21 | import collections 22 | import copy 23 | import json 24 | import math 25 | import re 26 | import six 27 | import tensorflow as tf 28 | 29 | 30 | class BertConfig(object): 31 | """Configuration for `BertModel`.""" 32 | 33 | def __init__(self, 34 | vocab_size, 35 | hidden_size=768, 36 | num_hidden_layers=12, 37 | num_attention_heads=12, 38 | intermediate_size=3072, 39 | hidden_act="gelu", 40 | hidden_dropout_prob=0.1, 41 | attention_probs_dropout_prob=0.1, 42 | max_position_embeddings=512, 43 | type_vocab_size=16, 44 | initializer_range=0.02): 45 | """Constructs BertConfig. 46 | 47 | Args: 48 | vocab_size: Vocabulary size of `inputs_ids` in `BertModel`. 49 | hidden_size: Size of the encoder layers and the pooler layer. 50 | num_hidden_layers: Number of hidden layers in the Transformer encoder. 51 | num_attention_heads: Number of attention heads for each attention layer in 52 | the Transformer encoder. 53 | intermediate_size: The size of the "intermediate" (i.e., feed-forward) 54 | layer in the Transformer encoder. 55 | hidden_act: The non-linear activation function (function or string) in the 56 | encoder and pooler. 57 | hidden_dropout_prob: The dropout probability for all fully connected 58 | layers in the embeddings, encoder, and pooler. 59 | attention_probs_dropout_prob: The dropout ratio for the attention 60 | probabilities. 61 | max_position_embeddings: The maximum sequence length that this model might 62 | ever be used with. Typically set this to something large just in case 63 | (e.g., 512 or 1024 or 2048). 64 | type_vocab_size: The vocabulary size of the `token_type_ids` passed into 65 | `BertModel`. 66 | initializer_range: The stdev of the truncated_normal_initializer for 67 | initializing all weight matrices. 68 | """ 69 | self.vocab_size = vocab_size 70 | self.hidden_size = hidden_size 71 | self.num_hidden_layers = num_hidden_layers 72 | self.num_attention_heads = num_attention_heads 73 | self.hidden_act = hidden_act 74 | self.intermediate_size = intermediate_size 75 | self.hidden_dropout_prob = hidden_dropout_prob 76 | self.attention_probs_dropout_prob = attention_probs_dropout_prob 77 | self.max_position_embeddings = max_position_embeddings 78 | self.type_vocab_size = type_vocab_size 79 | self.initializer_range = initializer_range 80 | 81 | @classmethod 82 | def from_dict(cls, json_object): 83 | """Constructs a `BertConfig` from a Python dictionary of parameters.""" 84 | config = BertConfig(vocab_size=None) 85 | for (key, value) in six.iteritems(json_object): 86 | config.__dict__[key] = value 87 | return config 88 | 89 | @classmethod 90 | def from_json_file(cls, json_file): 91 | """Constructs a `BertConfig` from a json file of parameters.""" 92 | with tf.gfile.GFile(json_file, "r") as reader: 93 | text = reader.read() 94 | return cls.from_dict(json.loads(text)) 95 | 96 | def to_dict(self): 97 | """Serializes this instance to a Python dictionary.""" 98 | output = copy.deepcopy(self.__dict__) 99 | return output 100 | 101 | def to_json_string(self): 102 | """Serializes this instance to a JSON string.""" 103 | return json.dumps(self.to_dict(), indent=2, sort_keys=True) + "\n" 104 | 105 | 106 | class BertModel(object): 107 | """BERT model ("Bidirectional Encoder Representations from Transformers"). 108 | 109 | Example usage: 110 | 111 | ```python 112 | # Already been converted into WordPiece token ids 113 | input_ids = tf.constant([[31, 51, 99], [15, 5, 0]]) 114 | input_mask = tf.constant([[1, 1, 1], [1, 1, 0]]) 115 | token_type_ids = tf.constant([[0, 0, 1], [0, 2, 0]]) 116 | 117 | config = modeling.BertConfig(vocab_size=32000, hidden_size=512, 118 | num_hidden_layers=8, num_attention_heads=6, intermediate_size=1024) 119 | 120 | model = modeling.BertModel(config=config, is_training=True, 121 | input_ids=input_ids, input_mask=input_mask, token_type_ids=token_type_ids) 122 | 123 | label_embeddings = tf.get_variable(...) 124 | pooled_output = model.get_pooled_output() 125 | logits = tf.matmul(pooled_output, label_embeddings) 126 | ... 127 | ``` 128 | """ 129 | 130 | def __init__(self, 131 | config, 132 | is_training, 133 | input_ids, 134 | input_mask=None, 135 | token_type_ids=None, 136 | use_one_hot_embeddings=True, 137 | scope=None): 138 | """Constructor for BertModel. 139 | 140 | Args: 141 | config: `BertConfig` instance. 142 | is_training: bool. true for training model, false for eval model. Controls 143 | whether dropout will be applied. 144 | input_ids: int32 Tensor of shape [batch_size, seq_length]. 145 | input_mask: (optional) int32 Tensor of shape [batch_size, seq_length]. 146 | token_type_ids: (optional) int32 Tensor of shape [batch_size, seq_length]. 147 | use_one_hot_embeddings: (optional) bool. Whether to use one-hot word 148 | embeddings or tf.embedding_lookup() for the word embeddings. On the TPU, 149 | it is much faster if this is True, on the CPU or GPU, it is faster if 150 | this is False. 151 | scope: (optional) variable scope. Defaults to "bert". 152 | 153 | Raises: 154 | ValueError: The config is invalid or one of the input tensor shapes 155 | is invalid. 156 | """ 157 | config = copy.deepcopy(config) 158 | if not is_training: 159 | config.hidden_dropout_prob = 0.0 160 | config.attention_probs_dropout_prob = 0.0 161 | 162 | input_shape = get_shape_list(input_ids, expected_rank=2) 163 | batch_size = input_shape[0] 164 | seq_length = input_shape[1] 165 | 166 | if input_mask is None: 167 | input_mask = tf.ones(shape=[batch_size, seq_length], dtype=tf.int32) 168 | 169 | if token_type_ids is None: 170 | token_type_ids = tf.zeros(shape=[batch_size, seq_length], dtype=tf.int32) 171 | 172 | with tf.variable_scope(scope, default_name="bert"): 173 | with tf.variable_scope("embeddings"): 174 | # Perform embedding lookup on the word ids. 175 | (self.embedding_output, self.embedding_table) = embedding_lookup( 176 | input_ids=input_ids, 177 | vocab_size=config.vocab_size, 178 | embedding_size=config.hidden_size, 179 | initializer_range=config.initializer_range, 180 | word_embedding_name="word_embeddings", 181 | use_one_hot_embeddings=use_one_hot_embeddings) 182 | 183 | # Add positional embeddings and token type embeddings, then layer 184 | # normalize and perform dropout. 185 | self.embedding_output = embedding_postprocessor( 186 | input_tensor=self.embedding_output, 187 | use_token_type=True, 188 | token_type_ids=token_type_ids, 189 | token_type_vocab_size=config.type_vocab_size, 190 | token_type_embedding_name="token_type_embeddings", 191 | use_position_embeddings=True, 192 | position_embedding_name="position_embeddings", 193 | initializer_range=config.initializer_range, 194 | max_position_embeddings=config.max_position_embeddings, 195 | dropout_prob=config.hidden_dropout_prob) 196 | 197 | with tf.variable_scope("encoder"): 198 | # This converts a 2D mask of shape [batch_size, seq_length] to a 3D 199 | # mask of shape [batch_size, seq_length, seq_length] which is used 200 | # for the attention scores. 201 | attention_mask = create_attention_mask_from_input_mask( 202 | input_ids, input_mask) 203 | 204 | # Run the stacked transformer. 205 | # `sequence_output` shape = [batch_size, seq_length, hidden_size]. 206 | self.all_encoder_layers = transformer_model( 207 | input_tensor=self.embedding_output, 208 | attention_mask=attention_mask, 209 | hidden_size=config.hidden_size, 210 | num_hidden_layers=config.num_hidden_layers, 211 | num_attention_heads=config.num_attention_heads, 212 | intermediate_size=config.intermediate_size, 213 | intermediate_act_fn=get_activation(config.hidden_act), 214 | hidden_dropout_prob=config.hidden_dropout_prob, 215 | attention_probs_dropout_prob=config.attention_probs_dropout_prob, 216 | initializer_range=config.initializer_range, 217 | do_return_all_layers=True) 218 | 219 | self.sequence_output = self.all_encoder_layers[-1] 220 | # The "pooler" converts the encoded sequence tensor of shape 221 | # [batch_size, seq_length, hidden_size] to a tensor of shape 222 | # [batch_size, hidden_size]. This is necessary for segment-level 223 | # (or segment-pair-level) classification tasks where we need a fixed 224 | # dimensional representation of the segment. 225 | with tf.variable_scope("pooler"): 226 | # We "pool" the model by simply taking the hidden state corresponding 227 | # to the first token. We assume that this has been pre-trained 228 | first_token_tensor = tf.squeeze(self.sequence_output[:, 0:1, :], axis=1) 229 | self.pooled_output = tf.layers.dense( 230 | first_token_tensor, 231 | config.hidden_size, 232 | activation=tf.tanh, 233 | kernel_initializer=create_initializer(config.initializer_range)) 234 | 235 | def get_pooled_output(self): 236 | return self.pooled_output 237 | 238 | def get_sequence_output(self): 239 | """Gets final hidden layer of encoder. 240 | 241 | Returns: 242 | float Tensor of shape [batch_size, seq_length, hidden_size] corresponding 243 | to the final hidden of the transformer encoder. 244 | """ 245 | return self.sequence_output 246 | 247 | def get_all_encoder_layers(self): 248 | return self.all_encoder_layers 249 | 250 | def get_embedding_output(self): 251 | """Gets output of the embedding lookup (i.e., input to the transformer). 252 | 253 | Returns: 254 | float Tensor of shape [batch_size, seq_length, hidden_size] corresponding 255 | to the output of the embedding layer, after summing the word 256 | embeddings with the positional embeddings and the token type embeddings, 257 | then performing layer normalization. This is the input to the transformer. 258 | """ 259 | return self.embedding_output 260 | 261 | def get_embedding_table(self): 262 | return self.embedding_table 263 | 264 | 265 | def gelu(input_tensor): 266 | """Gaussian Error Linear Unit. 267 | 268 | This is a smoother version of the RELU. 269 | Original paper: https://arxiv.org/abs/1606.08415 270 | 271 | Args: 272 | input_tensor: float Tensor to perform activation. 273 | 274 | Returns: 275 | `input_tensor` with the GELU activation applied. 276 | """ 277 | cdf = 0.5 * (1.0 + tf.erf(input_tensor / tf.sqrt(2.0))) 278 | return input_tensor * cdf 279 | 280 | 281 | def get_activation(activation_string): 282 | """Maps a string to a Python function, e.g., "relu" => `tf.nn.relu`. 283 | 284 | Args: 285 | activation_string: String name of the activation function. 286 | 287 | Returns: 288 | A Python function corresponding to the activation function. If 289 | `activation_string` is None, empty, or "linear", this will return None. 290 | If `activation_string` is not a string, it will return `activation_string`. 291 | 292 | Raises: 293 | ValueError: The `activation_string` does not correspond to a known 294 | activation. 295 | """ 296 | 297 | # We assume that anything that"s not a string is already an activation 298 | # function, so we just return it. 299 | if not isinstance(activation_string, six.string_types): 300 | return activation_string 301 | 302 | if not activation_string: 303 | return None 304 | 305 | act = activation_string.lower() 306 | if act == "linear": 307 | return None 308 | elif act == "relu": 309 | return tf.nn.relu 310 | elif act == "gelu": 311 | return gelu 312 | elif act == "tanh": 313 | return tf.tanh 314 | else: 315 | raise ValueError("Unsupported activation: %s" % act) 316 | 317 | 318 | def get_assignment_map_from_checkpoint(tvars, init_checkpoint): 319 | """Compute the union of the current variables and checkpoint variables.""" 320 | assignment_map = {} 321 | initialized_variable_names = {} 322 | 323 | name_to_variable = collections.OrderedDict() 324 | for var in tvars: 325 | name = var.name 326 | m = re.match("^(.*):\\d+$", name) 327 | if m is not None: 328 | name = m.group(1) 329 | name_to_variable[name] = var 330 | 331 | init_vars = tf.train.list_variables(init_checkpoint) 332 | 333 | assignment_map = collections.OrderedDict() 334 | for x in init_vars: 335 | (name, var) = (x[0], x[1]) 336 | if name not in name_to_variable: 337 | continue 338 | assignment_map[name] = name 339 | initialized_variable_names[name] = 1 340 | initialized_variable_names[name + ":0"] = 1 341 | 342 | return (assignment_map, initialized_variable_names) 343 | 344 | 345 | def dropout(input_tensor, dropout_prob): 346 | """Perform dropout. 347 | 348 | Args: 349 | input_tensor: float Tensor. 350 | dropout_prob: Python float. The probability of dropping out a value (NOT of 351 | *keeping* a dimension as in `tf.nn.dropout`). 352 | 353 | Returns: 354 | A version of `input_tensor` with dropout applied. 355 | """ 356 | if dropout_prob is None or dropout_prob == 0.0: 357 | return input_tensor 358 | 359 | output = tf.nn.dropout(input_tensor, 1.0 - dropout_prob) 360 | return output 361 | 362 | 363 | def layer_norm(input_tensor, name=None): 364 | """Run layer normalization on the last dimension of the tensor.""" 365 | return tf.contrib.layers.layer_norm( 366 | inputs=input_tensor, begin_norm_axis=-1, begin_params_axis=-1, scope=name) 367 | 368 | 369 | def layer_norm_and_dropout(input_tensor, dropout_prob, name=None): 370 | """Runs layer normalization followed by dropout.""" 371 | output_tensor = layer_norm(input_tensor, name) 372 | output_tensor = dropout(output_tensor, dropout_prob) 373 | return output_tensor 374 | 375 | 376 | def create_initializer(initializer_range=0.02): 377 | """Creates a `truncated_normal_initializer` with the given range.""" 378 | return tf.truncated_normal_initializer(stddev=initializer_range) 379 | 380 | 381 | def embedding_lookup(input_ids, 382 | vocab_size, 383 | embedding_size=128, 384 | initializer_range=0.02, 385 | word_embedding_name="word_embeddings", 386 | use_one_hot_embeddings=False): 387 | """Looks up words embeddings for id tensor. 388 | 389 | Args: 390 | input_ids: int32 Tensor of shape [batch_size, seq_length] containing word 391 | ids. 392 | vocab_size: int. Size of the embedding vocabulary. 393 | embedding_size: int. Width of the word embeddings. 394 | initializer_range: float. Embedding initialization range. 395 | word_embedding_name: string. Name of the embedding table. 396 | use_one_hot_embeddings: bool. If True, use one-hot method for word 397 | embeddings. If False, use `tf.nn.embedding_lookup()`. One hot is better 398 | for TPUs. 399 | 400 | Returns: 401 | float Tensor of shape [batch_size, seq_length, embedding_size]. 402 | """ 403 | # This function assumes that the input is of shape [batch_size, seq_length, 404 | # num_inputs]. 405 | # 406 | # If the input is a 2D tensor of shape [batch_size, seq_length], we 407 | # reshape to [batch_size, seq_length, 1]. 408 | if input_ids.shape.ndims == 2: 409 | input_ids = tf.expand_dims(input_ids, axis=[-1]) 410 | 411 | embedding_table = tf.get_variable( 412 | name=word_embedding_name, 413 | shape=[vocab_size, embedding_size], 414 | initializer=create_initializer(initializer_range)) 415 | 416 | if use_one_hot_embeddings: 417 | flat_input_ids = tf.reshape(input_ids, [-1]) 418 | one_hot_input_ids = tf.one_hot(flat_input_ids, depth=vocab_size) 419 | output = tf.matmul(one_hot_input_ids, embedding_table) 420 | else: 421 | output = tf.nn.embedding_lookup(embedding_table, input_ids) 422 | 423 | input_shape = get_shape_list(input_ids) 424 | 425 | output = tf.reshape(output, 426 | input_shape[0:-1] + [input_shape[-1] * embedding_size]) 427 | return (output, embedding_table) 428 | 429 | 430 | def embedding_postprocessor(input_tensor, 431 | use_token_type=False, 432 | token_type_ids=None, 433 | token_type_vocab_size=16, 434 | token_type_embedding_name="token_type_embeddings", 435 | use_position_embeddings=True, 436 | position_embedding_name="position_embeddings", 437 | initializer_range=0.02, 438 | max_position_embeddings=512, 439 | dropout_prob=0.1): 440 | """Performs various post-processing on a word embedding tensor. 441 | 442 | Args: 443 | input_tensor: float Tensor of shape [batch_size, seq_length, 444 | embedding_size]. 445 | use_token_type: bool. Whether to add embeddings for `token_type_ids`. 446 | token_type_ids: (optional) int32 Tensor of shape [batch_size, seq_length]. 447 | Must be specified if `use_token_type` is True. 448 | token_type_vocab_size: int. The vocabulary size of `token_type_ids`. 449 | token_type_embedding_name: string. The name of the embedding table variable 450 | for token type ids. 451 | use_position_embeddings: bool. Whether to add position embeddings for the 452 | position of each token in the sequence. 453 | position_embedding_name: string. The name of the embedding table variable 454 | for positional embeddings. 455 | initializer_range: float. Range of the weight initialization. 456 | max_position_embeddings: int. Maximum sequence length that might ever be 457 | used with this model. This can be longer than the sequence length of 458 | input_tensor, but cannot be shorter. 459 | dropout_prob: float. Dropout probability applied to the final output tensor. 460 | 461 | Returns: 462 | float tensor with same shape as `input_tensor`. 463 | 464 | Raises: 465 | ValueError: One of the tensor shapes or input values is invalid. 466 | """ 467 | input_shape = get_shape_list(input_tensor, expected_rank=3) 468 | batch_size = input_shape[0] 469 | seq_length = input_shape[1] 470 | width = input_shape[2] 471 | 472 | output = input_tensor 473 | 474 | if use_token_type: 475 | if token_type_ids is None: 476 | raise ValueError("`token_type_ids` must be specified if" 477 | "`use_token_type` is True.") 478 | token_type_table = tf.get_variable( 479 | name=token_type_embedding_name, 480 | shape=[token_type_vocab_size, width], 481 | initializer=create_initializer(initializer_range)) 482 | # This vocab will be small so we always do one-hot here, since it is always 483 | # faster for a small vocabulary. 484 | flat_token_type_ids = tf.reshape(token_type_ids, [-1]) 485 | one_hot_ids = tf.one_hot(flat_token_type_ids, depth=token_type_vocab_size) 486 | token_type_embeddings = tf.matmul(one_hot_ids, token_type_table) 487 | token_type_embeddings = tf.reshape(token_type_embeddings, 488 | [batch_size, seq_length, width]) 489 | output += token_type_embeddings 490 | 491 | if use_position_embeddings: 492 | assert_op = tf.assert_less_equal(seq_length, max_position_embeddings) 493 | with tf.control_dependencies([assert_op]): 494 | full_position_embeddings = tf.get_variable( 495 | name=position_embedding_name, 496 | shape=[max_position_embeddings, width], 497 | initializer=create_initializer(initializer_range)) 498 | # Since the position embedding table is a learned variable, we create it 499 | # using a (long) sequence length `max_position_embeddings`. The actual 500 | # sequence length might be shorter than this, for faster training of 501 | # tasks that do not have long sequences. 502 | # 503 | # So `full_position_embeddings` is effectively an embedding table 504 | # for position [0, 1, 2, ..., max_position_embeddings-1], and the current 505 | # sequence has positions [0, 1, 2, ... seq_length-1], so we can just 506 | # perform a slice. 507 | position_embeddings = tf.slice(full_position_embeddings, [0, 0], 508 | [seq_length, -1]) 509 | num_dims = len(output.shape.as_list()) 510 | 511 | # Only the last two dimensions are relevant (`seq_length` and `width`), so 512 | # we broadcast among the first dimensions, which is typically just 513 | # the batch size. 514 | position_broadcast_shape = [] 515 | for _ in range(num_dims - 2): 516 | position_broadcast_shape.append(1) 517 | position_broadcast_shape.extend([seq_length, width]) 518 | position_embeddings = tf.reshape(position_embeddings, 519 | position_broadcast_shape) 520 | output += position_embeddings 521 | 522 | output = layer_norm_and_dropout(output, dropout_prob) 523 | return output 524 | 525 | 526 | def create_attention_mask_from_input_mask(from_tensor, to_mask): 527 | """Create 3D attention mask from a 2D tensor mask. 528 | 529 | Args: 530 | from_tensor: 2D or 3D Tensor of shape [batch_size, from_seq_length, ...]. 531 | to_mask: int32 Tensor of shape [batch_size, to_seq_length]. 532 | 533 | Returns: 534 | float Tensor of shape [batch_size, from_seq_length, to_seq_length]. 535 | """ 536 | from_shape = get_shape_list(from_tensor, expected_rank=[2, 3]) 537 | batch_size = from_shape[0] 538 | from_seq_length = from_shape[1] 539 | 540 | to_shape = get_shape_list(to_mask, expected_rank=2) 541 | to_seq_length = to_shape[1] 542 | 543 | to_mask = tf.cast( 544 | tf.reshape(to_mask, [batch_size, 1, to_seq_length]), tf.float32) 545 | 546 | # We don't assume that `from_tensor` is a mask (although it could be). We 547 | # don't actually care if we attend *from* padding tokens (only *to* padding) 548 | # tokens so we create a tensor of all ones. 549 | # 550 | # `broadcast_ones` = [batch_size, from_seq_length, 1] 551 | broadcast_ones = tf.ones( 552 | shape=[batch_size, from_seq_length, 1], dtype=tf.float32) 553 | 554 | # Here we broadcast along two dimensions to create the mask. 555 | mask = broadcast_ones * to_mask 556 | 557 | return mask 558 | 559 | 560 | def attention_layer(from_tensor, 561 | to_tensor, 562 | attention_mask=None, 563 | num_attention_heads=1, 564 | size_per_head=512, 565 | query_act=None, 566 | key_act=None, 567 | value_act=None, 568 | attention_probs_dropout_prob=0.0, 569 | initializer_range=0.02, 570 | do_return_2d_tensor=False, 571 | batch_size=None, 572 | from_seq_length=None, 573 | to_seq_length=None): 574 | """Performs multi-headed attention from `from_tensor` to `to_tensor`. 575 | 576 | This is an implementation of multi-headed attention based on "Attention 577 | is all you Need". If `from_tensor` and `to_tensor` are the same, then 578 | this is self-attention. Each timestep in `from_tensor` attends to the 579 | corresponding sequence in `to_tensor`, and returns a fixed-with vector. 580 | 581 | This function first projects `from_tensor` into a "query" tensor and 582 | `to_tensor` into "key" and "value" tensors. These are (effectively) a list 583 | of tensors of length `num_attention_heads`, where each tensor is of shape 584 | [batch_size, seq_length, size_per_head]. 585 | 586 | Then, the query and key tensors are dot-producted and scaled. These are 587 | softmaxed to obtain attention probabilities. The value tensors are then 588 | interpolated by these probabilities, then concatenated back to a single 589 | tensor and returned. 590 | 591 | In practice, the multi-headed attention are done with transposes and 592 | reshapes rather than actual separate tensors. 593 | 594 | Args: 595 | from_tensor: float Tensor of shape [batch_size, from_seq_length, 596 | from_width]. 597 | to_tensor: float Tensor of shape [batch_size, to_seq_length, to_width]. 598 | attention_mask: (optional) int32 Tensor of shape [batch_size, 599 | from_seq_length, to_seq_length]. The values should be 1 or 0. The 600 | attention scores will effectively be set to -infinity for any positions in 601 | the mask that are 0, and will be unchanged for positions that are 1. 602 | num_attention_heads: int. Number of attention heads. 603 | size_per_head: int. Size of each attention head. 604 | query_act: (optional) Activation function for the query transform. 605 | key_act: (optional) Activation function for the key transform. 606 | value_act: (optional) Activation function for the value transform. 607 | attention_probs_dropout_prob: (optional) float. Dropout probability of the 608 | attention probabilities. 609 | initializer_range: float. Range of the weight initializer. 610 | do_return_2d_tensor: bool. If True, the output will be of shape [batch_size 611 | * from_seq_length, num_attention_heads * size_per_head]. If False, the 612 | output will be of shape [batch_size, from_seq_length, num_attention_heads 613 | * size_per_head]. 614 | batch_size: (Optional) int. If the input is 2D, this might be the batch size 615 | of the 3D version of the `from_tensor` and `to_tensor`. 616 | from_seq_length: (Optional) If the input is 2D, this might be the seq length 617 | of the 3D version of the `from_tensor`. 618 | to_seq_length: (Optional) If the input is 2D, this might be the seq length 619 | of the 3D version of the `to_tensor`. 620 | 621 | Returns: 622 | float Tensor of shape [batch_size, from_seq_length, 623 | num_attention_heads * size_per_head]. (If `do_return_2d_tensor` is 624 | true, this will be of shape [batch_size * from_seq_length, 625 | num_attention_heads * size_per_head]). 626 | 627 | Raises: 628 | ValueError: Any of the arguments or tensor shapes are invalid. 629 | """ 630 | 631 | def transpose_for_scores(input_tensor, batch_size, num_attention_heads, 632 | seq_length, width): 633 | output_tensor = tf.reshape( 634 | input_tensor, [batch_size, seq_length, num_attention_heads, width]) 635 | 636 | output_tensor = tf.transpose(output_tensor, [0, 2, 1, 3]) 637 | return output_tensor 638 | 639 | from_shape = get_shape_list(from_tensor, expected_rank=[2, 3]) 640 | to_shape = get_shape_list(to_tensor, expected_rank=[2, 3]) 641 | 642 | if len(from_shape) != len(to_shape): 643 | raise ValueError( 644 | "The rank of `from_tensor` must match the rank of `to_tensor`.") 645 | 646 | if len(from_shape) == 3: 647 | batch_size = from_shape[0] 648 | from_seq_length = from_shape[1] 649 | to_seq_length = to_shape[1] 650 | elif len(from_shape) == 2: 651 | if (batch_size is None or from_seq_length is None or to_seq_length is None): 652 | raise ValueError( 653 | "When passing in rank 2 tensors to attention_layer, the values " 654 | "for `batch_size`, `from_seq_length`, and `to_seq_length` " 655 | "must all be specified.") 656 | 657 | # Scalar dimensions referenced here: 658 | # B = batch size (number of sequences) 659 | # F = `from_tensor` sequence length 660 | # T = `to_tensor` sequence length 661 | # N = `num_attention_heads` 662 | # H = `size_per_head` 663 | 664 | from_tensor_2d = reshape_to_matrix(from_tensor) 665 | to_tensor_2d = reshape_to_matrix(to_tensor) 666 | 667 | # `query_layer` = [B*F, N*H] 668 | query_layer = tf.layers.dense( 669 | from_tensor_2d, 670 | num_attention_heads * size_per_head, 671 | activation=query_act, 672 | name="query", 673 | kernel_initializer=create_initializer(initializer_range)) 674 | 675 | # `key_layer` = [B*T, N*H] 676 | key_layer = tf.layers.dense( 677 | to_tensor_2d, 678 | num_attention_heads * size_per_head, 679 | activation=key_act, 680 | name="key", 681 | kernel_initializer=create_initializer(initializer_range)) 682 | 683 | # `value_layer` = [B*T, N*H] 684 | value_layer = tf.layers.dense( 685 | to_tensor_2d, 686 | num_attention_heads * size_per_head, 687 | activation=value_act, 688 | name="value", 689 | kernel_initializer=create_initializer(initializer_range)) 690 | 691 | # `query_layer` = [B, N, F, H] 692 | query_layer = transpose_for_scores(query_layer, batch_size, 693 | num_attention_heads, from_seq_length, 694 | size_per_head) 695 | 696 | # `key_layer` = [B, N, T, H] 697 | key_layer = transpose_for_scores(key_layer, batch_size, num_attention_heads, 698 | to_seq_length, size_per_head) 699 | 700 | # Take the dot product between "query" and "key" to get the raw 701 | # attention scores. 702 | # `attention_scores` = [B, N, F, T] 703 | attention_scores = tf.matmul(query_layer, key_layer, transpose_b=True) 704 | attention_scores = tf.multiply(attention_scores, 705 | 1.0 / math.sqrt(float(size_per_head))) 706 | 707 | if attention_mask is not None: 708 | # `attention_mask` = [B, 1, F, T] 709 | attention_mask = tf.expand_dims(attention_mask, axis=[1]) 710 | 711 | # Since attention_mask is 1.0 for positions we want to attend and 0.0 for 712 | # masked positions, this operation will create a tensor which is 0.0 for 713 | # positions we want to attend and -10000.0 for masked positions. 714 | adder = (1.0 - tf.cast(attention_mask, tf.float32)) * -10000.0 715 | 716 | # Since we are adding it to the raw scores before the softmax, this is 717 | # effectively the same as removing these entirely. 718 | attention_scores += adder 719 | 720 | # Normalize the attention scores to probabilities. 721 | # `attention_probs` = [B, N, F, T] 722 | attention_probs = tf.nn.softmax(attention_scores) 723 | 724 | # This is actually dropping out entire tokens to attend to, which might 725 | # seem a bit unusual, but is taken from the original Transformer paper. 726 | attention_probs = dropout(attention_probs, attention_probs_dropout_prob) 727 | 728 | # `value_layer` = [B, T, N, H] 729 | value_layer = tf.reshape( 730 | value_layer, 731 | [batch_size, to_seq_length, num_attention_heads, size_per_head]) 732 | 733 | # `value_layer` = [B, N, T, H] 734 | value_layer = tf.transpose(value_layer, [0, 2, 1, 3]) 735 | 736 | # `context_layer` = [B, N, F, H] 737 | context_layer = tf.matmul(attention_probs, value_layer) 738 | 739 | # `context_layer` = [B, F, N, H] 740 | context_layer = tf.transpose(context_layer, [0, 2, 1, 3]) 741 | 742 | if do_return_2d_tensor: 743 | # `context_layer` = [B*F, N*H] 744 | context_layer = tf.reshape( 745 | context_layer, 746 | [batch_size * from_seq_length, num_attention_heads * size_per_head]) 747 | else: 748 | # `context_layer` = [B, F, N*H] 749 | context_layer = tf.reshape( 750 | context_layer, 751 | [batch_size, from_seq_length, num_attention_heads * size_per_head]) 752 | 753 | return context_layer 754 | 755 | 756 | def transformer_model(input_tensor, 757 | attention_mask=None, 758 | hidden_size=768, 759 | num_hidden_layers=12, 760 | num_attention_heads=12, 761 | intermediate_size=3072, 762 | intermediate_act_fn=gelu, 763 | hidden_dropout_prob=0.1, 764 | attention_probs_dropout_prob=0.1, 765 | initializer_range=0.02, 766 | do_return_all_layers=False): 767 | """Multi-headed, multi-layer Transformer from "Attention is All You Need". 768 | 769 | This is almost an exact implementation of the original Transformer encoder. 770 | 771 | See the original paper: 772 | https://arxiv.org/abs/1706.03762 773 | 774 | Also see: 775 | https://github.com/tensorflow/tensor2tensor/blob/master/tensor2tensor/models/transformer.py 776 | 777 | Args: 778 | input_tensor: float Tensor of shape [batch_size, seq_length, hidden_size]. 779 | attention_mask: (optional) int32 Tensor of shape [batch_size, seq_length, 780 | seq_length], with 1 for positions that can be attended to and 0 in 781 | positions that should not be. 782 | hidden_size: int. Hidden size of the Transformer. 783 | num_hidden_layers: int. Number of layers (blocks) in the Transformer. 784 | num_attention_heads: int. Number of attention heads in the Transformer. 785 | intermediate_size: int. The size of the "intermediate" (a.k.a., feed 786 | forward) layer. 787 | intermediate_act_fn: function. The non-linear activation function to apply 788 | to the output of the intermediate/feed-forward layer. 789 | hidden_dropout_prob: float. Dropout probability for the hidden layers. 790 | attention_probs_dropout_prob: float. Dropout probability of the attention 791 | probabilities. 792 | initializer_range: float. Range of the initializer (stddev of truncated 793 | normal). 794 | do_return_all_layers: Whether to also return all layers or just the final 795 | layer. 796 | 797 | Returns: 798 | float Tensor of shape [batch_size, seq_length, hidden_size], the final 799 | hidden layer of the Transformer. 800 | 801 | Raises: 802 | ValueError: A Tensor shape or parameter is invalid. 803 | """ 804 | if hidden_size % num_attention_heads != 0: 805 | raise ValueError( 806 | "The hidden size (%d) is not a multiple of the number of attention " 807 | "heads (%d)" % (hidden_size, num_attention_heads)) 808 | 809 | attention_head_size = int(hidden_size / num_attention_heads) 810 | input_shape = get_shape_list(input_tensor, expected_rank=3) 811 | batch_size = input_shape[0] 812 | seq_length = input_shape[1] 813 | input_width = input_shape[2] 814 | 815 | # The Transformer performs sum residuals on all layers so the input needs 816 | # to be the same as the hidden size. 817 | if input_width != hidden_size: 818 | raise ValueError("The width of the input tensor (%d) != hidden size (%d)" % 819 | (input_width, hidden_size)) 820 | 821 | # We keep the representation as a 2D tensor to avoid re-shaping it back and 822 | # forth from a 3D tensor to a 2D tensor. Re-shapes are normally free on 823 | # the GPU/CPU but may not be free on the TPU, so we want to minimize them to 824 | # help the optimizer. 825 | prev_output = reshape_to_matrix(input_tensor) 826 | 827 | all_layer_outputs = [] 828 | for layer_idx in range(num_hidden_layers): 829 | with tf.variable_scope("layer_%d" % layer_idx): 830 | layer_input = prev_output 831 | 832 | with tf.variable_scope("attention"): 833 | attention_heads = [] 834 | with tf.variable_scope("self"): 835 | attention_head = attention_layer( 836 | from_tensor=layer_input, 837 | to_tensor=layer_input, 838 | attention_mask=attention_mask, 839 | num_attention_heads=num_attention_heads, 840 | size_per_head=attention_head_size, 841 | attention_probs_dropout_prob=attention_probs_dropout_prob, 842 | initializer_range=initializer_range, 843 | do_return_2d_tensor=True, 844 | batch_size=batch_size, 845 | from_seq_length=seq_length, 846 | to_seq_length=seq_length) 847 | attention_heads.append(attention_head) 848 | 849 | attention_output = None 850 | if len(attention_heads) == 1: 851 | attention_output = attention_heads[0] 852 | else: 853 | # In the case where we have other sequences, we just concatenate 854 | # them to the self-attention head before the projection. 855 | attention_output = tf.concat(attention_heads, axis=-1) 856 | 857 | # Run a linear projection of `hidden_size` then add a residual 858 | # with `layer_input`. 859 | with tf.variable_scope("output"): 860 | attention_output = tf.layers.dense( 861 | attention_output, 862 | hidden_size, 863 | kernel_initializer=create_initializer(initializer_range)) 864 | attention_output = dropout(attention_output, hidden_dropout_prob) 865 | attention_output = layer_norm(attention_output + layer_input) 866 | 867 | # The activation is only applied to the "intermediate" hidden layer. 868 | with tf.variable_scope("intermediate"): 869 | intermediate_output = tf.layers.dense( 870 | attention_output, 871 | intermediate_size, 872 | activation=intermediate_act_fn, 873 | kernel_initializer=create_initializer(initializer_range)) 874 | 875 | # Down-project back to `hidden_size` then add the residual. 876 | with tf.variable_scope("output"): 877 | layer_output = tf.layers.dense( 878 | intermediate_output, 879 | hidden_size, 880 | kernel_initializer=create_initializer(initializer_range)) 881 | layer_output = dropout(layer_output, hidden_dropout_prob) 882 | layer_output = layer_norm(layer_output + attention_output) 883 | prev_output = layer_output 884 | all_layer_outputs.append(layer_output) 885 | 886 | if do_return_all_layers: 887 | final_outputs = [] 888 | for layer_output in all_layer_outputs: 889 | final_output = reshape_from_matrix(layer_output, input_shape) 890 | final_outputs.append(final_output) 891 | return final_outputs 892 | else: 893 | final_output = reshape_from_matrix(prev_output, input_shape) 894 | return final_output 895 | 896 | 897 | def get_shape_list(tensor, expected_rank=None, name=None): 898 | """Returns a list of the shape of tensor, preferring static dimensions. 899 | 900 | Args: 901 | tensor: A tf.Tensor object to find the shape of. 902 | expected_rank: (optional) int. The expected rank of `tensor`. If this is 903 | specified and the `tensor` has a different rank, and exception will be 904 | thrown. 905 | name: Optional name of the tensor for the error message. 906 | 907 | Returns: 908 | A list of dimensions of the shape of tensor. All static dimensions will 909 | be returned as python integers, and dynamic dimensions will be returned 910 | as tf.Tensor scalars. 911 | """ 912 | if name is None: 913 | name = tensor.name 914 | 915 | if expected_rank is not None: 916 | assert_rank(tensor, expected_rank, name) 917 | 918 | shape = tensor.shape.as_list() 919 | 920 | non_static_indexes = [] 921 | for (index, dim) in enumerate(shape): 922 | if dim is None: 923 | non_static_indexes.append(index) 924 | 925 | if not non_static_indexes: 926 | return shape 927 | 928 | dyn_shape = tf.shape(tensor) 929 | for index in non_static_indexes: 930 | shape[index] = dyn_shape[index] 931 | return shape 932 | 933 | 934 | def reshape_to_matrix(input_tensor): 935 | """Reshapes a >= rank 2 tensor to a rank 2 tensor (i.e., a matrix).""" 936 | ndims = input_tensor.shape.ndims 937 | if ndims < 2: 938 | raise ValueError("Input tensor must have at least rank 2. Shape = %s" % 939 | (input_tensor.shape)) 940 | if ndims == 2: 941 | return input_tensor 942 | 943 | width = input_tensor.shape[-1] 944 | output_tensor = tf.reshape(input_tensor, [-1, width]) 945 | return output_tensor 946 | 947 | 948 | def reshape_from_matrix(output_tensor, orig_shape_list): 949 | """Reshapes a rank 2 tensor back to its original rank >= 2 tensor.""" 950 | if len(orig_shape_list) == 2: 951 | return output_tensor 952 | 953 | output_shape = get_shape_list(output_tensor) 954 | 955 | orig_dims = orig_shape_list[0:-1] 956 | width = output_shape[-1] 957 | 958 | return tf.reshape(output_tensor, orig_dims + [width]) 959 | 960 | 961 | def assert_rank(tensor, expected_rank, name=None): 962 | """Raises an exception if the tensor rank is not of the expected rank. 963 | 964 | Args: 965 | tensor: A tf.Tensor to check the rank of. 966 | expected_rank: Python integer or list of integers, expected rank. 967 | name: Optional name of the tensor for the error message. 968 | 969 | Raises: 970 | ValueError: If the expected shape doesn't match the actual shape. 971 | """ 972 | if name is None: 973 | name = tensor.name 974 | 975 | expected_rank_dict = {} 976 | if isinstance(expected_rank, six.integer_types): 977 | expected_rank_dict[expected_rank] = True 978 | else: 979 | for x in expected_rank: 980 | expected_rank_dict[x] = True 981 | 982 | actual_rank = tensor.shape.ndims 983 | if actual_rank not in expected_rank_dict: 984 | scope_name = tf.get_variable_scope().name 985 | raise ValueError( 986 | "For the tensor `%s` in scope `%s`, the actual rank " 987 | "`%d` (shape = %s) is not equal to the expected rank `%s`" % 988 | (name, scope_name, actual_rank, str(tensor.shape), str(expected_rank))) 989 | -------------------------------------------------------------------------------- /optimization.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # Copyright 2018 The Google AI Language Team Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | """Functions and classes related to optimization (weight updates).""" 16 | 17 | from __future__ import absolute_import 18 | from __future__ import division 19 | from __future__ import print_function 20 | 21 | import re 22 | import tensorflow as tf 23 | 24 | 25 | def create_optimizer(loss, init_lr, num_train_steps, num_warmup_steps, use_tpu): 26 | """Creates an optimizer training op.""" 27 | global_step = tf.train.get_or_create_global_step() 28 | 29 | learning_rate = tf.constant(value=init_lr, shape=[], dtype=tf.float32) 30 | 31 | # Implements linear decay of the learning rate. 32 | learning_rate = tf.train.polynomial_decay( 33 | learning_rate, 34 | global_step, 35 | num_train_steps, 36 | end_learning_rate=0.0, 37 | power=1.0, 38 | cycle=False) 39 | 40 | # Implements linear warmup. I.e., if global_step < num_warmup_steps, the 41 | # learning rate will be `global_step/num_warmup_steps * init_lr`. 42 | if num_warmup_steps: 43 | global_steps_int = tf.cast(global_step, tf.int32) 44 | warmup_steps_int = tf.constant(num_warmup_steps, dtype=tf.int32) 45 | 46 | global_steps_float = tf.cast(global_steps_int, tf.float32) 47 | warmup_steps_float = tf.cast(warmup_steps_int, tf.float32) 48 | 49 | warmup_percent_done = global_steps_float / warmup_steps_float 50 | warmup_learning_rate = init_lr * warmup_percent_done 51 | 52 | is_warmup = tf.cast(global_steps_int < warmup_steps_int, tf.float32) 53 | learning_rate = ( 54 | (1.0 - is_warmup) * learning_rate + is_warmup * warmup_learning_rate) 55 | 56 | # It is recommended that you use this optimizer for fine tuning, since this 57 | # is how the model was trained (note that the Adam m/v variables are NOT 58 | # loaded from init_checkpoint.) 59 | optimizer = AdamWeightDecayOptimizer( 60 | learning_rate=learning_rate, 61 | weight_decay_rate=0.01, 62 | beta_1=0.9, 63 | beta_2=0.999, 64 | epsilon=1e-6, 65 | exclude_from_weight_decay=["LayerNorm", "layer_norm", "bias"]) 66 | 67 | if use_tpu: 68 | optimizer = tf.contrib.tpu.CrossShardOptimizer(optimizer) 69 | 70 | tvars = tf.trainable_variables() 71 | grads = tf.gradients(loss, tvars) 72 | 73 | # This is how the model was pre-trained. 74 | (grads, _) = tf.clip_by_global_norm(grads, clip_norm=1.0) 75 | 76 | train_op = optimizer.apply_gradients( 77 | zip(grads, tvars), global_step=global_step) 78 | 79 | # Normally the global step update is done inside of `apply_gradients`. 80 | # However, `AdamWeightDecayOptimizer` doesn't do this. But if you use 81 | # a different optimizer, you should probably take this line out. 82 | new_global_step = global_step + 1 83 | train_op = tf.group(train_op, [global_step.assign(new_global_step)]) 84 | return train_op 85 | 86 | 87 | class AdamWeightDecayOptimizer(tf.train.Optimizer): 88 | """A basic Adam optimizer that includes "correct" L2 weight decay.""" 89 | 90 | def __init__(self, 91 | learning_rate, 92 | weight_decay_rate=0.0, 93 | beta_1=0.9, 94 | beta_2=0.999, 95 | epsilon=1e-6, 96 | exclude_from_weight_decay=None, 97 | name="AdamWeightDecayOptimizer"): 98 | """Constructs a AdamWeightDecayOptimizer.""" 99 | super(AdamWeightDecayOptimizer, self).__init__(False, name) 100 | 101 | self.learning_rate = learning_rate 102 | self.weight_decay_rate = weight_decay_rate 103 | self.beta_1 = beta_1 104 | self.beta_2 = beta_2 105 | self.epsilon = epsilon 106 | self.exclude_from_weight_decay = exclude_from_weight_decay 107 | 108 | def apply_gradients(self, grads_and_vars, global_step=None, name=None): 109 | """See base class.""" 110 | assignments = [] 111 | for (grad, param) in grads_and_vars: 112 | if grad is None or param is None: 113 | continue 114 | 115 | param_name = self._get_variable_name(param.name) 116 | 117 | m = tf.get_variable( 118 | name=param_name + "/adam_m", 119 | shape=param.shape.as_list(), 120 | dtype=tf.float32, 121 | trainable=False, 122 | initializer=tf.zeros_initializer()) 123 | v = tf.get_variable( 124 | name=param_name + "/adam_v", 125 | shape=param.shape.as_list(), 126 | dtype=tf.float32, 127 | trainable=False, 128 | initializer=tf.zeros_initializer()) 129 | 130 | # Standard Adam update. 131 | next_m = ( 132 | tf.multiply(self.beta_1, m) + tf.multiply(1.0 - self.beta_1, grad)) 133 | next_v = ( 134 | tf.multiply(self.beta_2, v) + tf.multiply(1.0 - self.beta_2, 135 | tf.square(grad))) 136 | 137 | update = next_m / (tf.sqrt(next_v) + self.epsilon) 138 | 139 | # Just adding the square of the weights to the loss function is *not* 140 | # the correct way of using L2 regularization/weight decay with Adam, 141 | # since that will interact with the m and v parameters in strange ways. 142 | # 143 | # Instead we want ot decay the weights in a manner that doesn't interact 144 | # with the m/v parameters. This is equivalent to adding the square 145 | # of the weights to the loss with plain (non-momentum) SGD. 146 | if self._do_use_weight_decay(param_name): 147 | update += self.weight_decay_rate * param 148 | 149 | update_with_lr = self.learning_rate * update 150 | 151 | next_param = param - update_with_lr 152 | 153 | assignments.extend( 154 | [param.assign(next_param), 155 | m.assign(next_m), 156 | v.assign(next_v)]) 157 | return tf.group(*assignments, name=name) 158 | 159 | def _do_use_weight_decay(self, param_name): 160 | """Whether to use L2 weight decay for `param_name`.""" 161 | if not self.weight_decay_rate: 162 | return False 163 | if self.exclude_from_weight_decay: 164 | for r in self.exclude_from_weight_decay: 165 | if re.search(r, param_name) is not None: 166 | return False 167 | return True 168 | 169 | def _get_variable_name(self, param_name): 170 | """Get the variable name from the tensor name.""" 171 | m = re.match("^(.*):\\d+$", param_name) 172 | if m is not None: 173 | param_name = m.group(1) 174 | return param_name 175 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | tensorflow >= 1.11.0 # CPU Version of TensorFlow. 2 | # tensorflow-gpu >= 1.11.0 # GPU version of TensorFlow. 3 | -------------------------------------------------------------------------------- /run_mobile.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # Copyright 2018 The Google AI Language Team Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | """BERT finetuning runner.""" 16 | 17 | from __future__ import absolute_import 18 | from __future__ import division 19 | from __future__ import print_function 20 | 21 | import collections 22 | import csv 23 | import os 24 | import modeling 25 | import optimization 26 | import tokenization 27 | import tensorflow as tf 28 | import pickle 29 | 30 | flags = tf.flags 31 | 32 | FLAGS = flags.FLAGS 33 | 34 | ## Required parameters 35 | flags.DEFINE_string( 36 | "data_dir", None, 37 | "The input data dir. Should contain the .tsv files (or other data files) " 38 | "for the task.") 39 | 40 | flags.DEFINE_string( 41 | "bert_config_file", None, 42 | "The config json file corresponding to the pre-trained BERT model. " 43 | "This specifies the model architecture.") 44 | 45 | flags.DEFINE_string("task_name", None, "The name of the task to train.") 46 | 47 | flags.DEFINE_string("vocab_file", None, 48 | "The vocabulary file that the BERT model was trained on.") 49 | 50 | flags.DEFINE_string( 51 | "output_dir", None, 52 | "The output directory where the model checkpoints will be written.") 53 | 54 | ## Other parameters 55 | 56 | flags.DEFINE_string( 57 | "init_checkpoint", None, 58 | "Initial checkpoint (usually from a pre-trained BERT model).") 59 | 60 | flags.DEFINE_bool( 61 | "do_lower_case", True, 62 | "Whether to lower case the input text. Should be True for uncased " 63 | "models and False for cased models.") 64 | 65 | flags.DEFINE_integer( 66 | "max_seq_length", 128, 67 | "The maximum total input sequence length after WordPiece tokenization. " 68 | "Sequences longer than this will be truncated, and sequences shorter " 69 | "than this will be padded.") 70 | 71 | flags.DEFINE_bool("do_train", False, "Whether to run training.") 72 | 73 | flags.DEFINE_bool("do_eval", False, "Whether to run eval on the dev set.") 74 | 75 | flags.DEFINE_bool( 76 | "do_predict", False, 77 | "Whether to run the model in inference mode on the test set.") 78 | 79 | flags.DEFINE_integer("train_batch_size", 32, "Total batch size for training.") 80 | 81 | flags.DEFINE_integer("eval_batch_size", 8, "Total batch size for eval.") 82 | 83 | flags.DEFINE_integer("predict_batch_size", 8, "Total batch size for predict.") 84 | 85 | flags.DEFINE_float("learning_rate", 5e-5, "The initial learning rate for Adam.") 86 | 87 | flags.DEFINE_float("num_train_epochs", 3.0, 88 | "Total number of training epochs to perform.") 89 | 90 | flags.DEFINE_float( 91 | "warmup_proportion", 0.1, 92 | "Proportion of training to perform linear learning rate warmup for. " 93 | "E.g., 0.1 = 10% of training.") 94 | 95 | flags.DEFINE_integer("save_checkpoints_steps", 1000, 96 | "How often to save the model checkpoint.") 97 | 98 | flags.DEFINE_integer("iterations_per_loop", 1000, 99 | "How many steps to make in each estimator call.") 100 | 101 | flags.DEFINE_bool("use_tpu", False, "Whether to use TPU or GPU/CPU.") 102 | 103 | tf.flags.DEFINE_string( 104 | "tpu_name", None, 105 | "The Cloud TPU to use for training. This should be either the name " 106 | "used when creating the Cloud TPU, or a grpc://ip.address.of.tpu:8470 " 107 | "url.") 108 | 109 | tf.flags.DEFINE_string( 110 | "tpu_zone", None, 111 | "[Optional] GCE zone where the Cloud TPU is located in. If not " 112 | "specified, we will attempt to automatically detect the GCE project from " 113 | "metadata.") 114 | 115 | tf.flags.DEFINE_string( 116 | "gcp_project", None, 117 | "[Optional] Project name for the Cloud TPU-enabled project. If not " 118 | "specified, we will attempt to automatically detect the GCE project from " 119 | "metadata.") 120 | 121 | tf.flags.DEFINE_string("master", None, "[Optional] TensorFlow master URL.") 122 | 123 | flags.DEFINE_integer( 124 | "num_tpu_cores", 8, 125 | "Only used if `use_tpu` is True. Total number of TPU cores to use.") 126 | 127 | 128 | class InputExample(object): 129 | """A single training/test example for simple sequence classification.""" 130 | 131 | def __init__(self, guid, text_a, text_b=None, label=None): 132 | """Constructs a InputExample. 133 | 134 | Args: 135 | guid: Unique id for the example. 136 | text_a: string. The untokenized text of the first sequence. For single 137 | sequence tasks, only this sequence must be specified. 138 | text_b: (Optional) string. The untokenized text of the second sequence. 139 | Only must be specified for sequence pair tasks. 140 | label: (Optional) string. The label of the example. This should be 141 | specified for train and dev examples, but not for test examples. 142 | """ 143 | self.guid = guid 144 | self.text_a = text_a 145 | self.text_b = text_b 146 | self.label = label 147 | 148 | 149 | class PaddingInputExample(object): 150 | """Fake example so the num input examples is a multiple of the batch size. 151 | 152 | When running eval/predict on the TPU, we need to pad the number of examples 153 | to be a multiple of the batch size, because the TPU requires a fixed batch 154 | size. The alternative is to drop the last batch, which is bad because it means 155 | the entire output data won't be generated. 156 | 157 | We use this class instead of `None` because treating `None` as padding 158 | battches could cause silent errors. 159 | """ 160 | 161 | 162 | class InputFeatures(object): 163 | """A single set of features of data.""" 164 | 165 | def __init__(self, 166 | input_ids, 167 | input_mask, 168 | segment_ids, 169 | label_id, 170 | is_real_example=True): 171 | self.input_ids = input_ids 172 | self.input_mask = input_mask 173 | self.segment_ids = segment_ids 174 | self.label_id = label_id 175 | self.is_real_example = is_real_example 176 | 177 | 178 | class DataProcessor(object): 179 | """Base class for data converters for sequence classification data sets.""" 180 | 181 | def get_train_examples(self, data_dir): 182 | """Gets a collection of `InputExample`s for the train set.""" 183 | raise NotImplementedError() 184 | 185 | def get_dev_examples(self, data_dir): 186 | """Gets a collection of `InputExample`s for the dev set.""" 187 | raise NotImplementedError() 188 | 189 | def get_test_examples(self, data_dir): 190 | """Gets a collection of `InputExample`s for prediction.""" 191 | raise NotImplementedError() 192 | 193 | def get_labels(self): 194 | """Gets the list of labels for this data set.""" 195 | raise NotImplementedError() 196 | 197 | @classmethod 198 | def _read_tsv(cls, input_file, quotechar=None): 199 | """Reads a tab separated value file.""" 200 | with tf.gfile.Open(input_file, "r") as f: 201 | reader = csv.reader(f, delimiter="\t", quotechar=quotechar) 202 | lines = [] 203 | for line in reader: 204 | lines.append(line) 205 | return lines 206 | 207 | class XnliProcessor(DataProcessor): 208 | """Processor for the XNLI data set.""" 209 | 210 | def __init__(self): 211 | self.language = "zh" 212 | 213 | def get_train_examples(self, data_dir): 214 | """See base class.""" 215 | lines = self._read_tsv( 216 | os.path.join(data_dir, "multinli", 217 | "multinli.train.%s.tsv" % self.language)) 218 | examples = [] 219 | for (i, line) in enumerate(lines): 220 | if i == 0: 221 | continue 222 | guid = "train-%d" % (i) 223 | text_a = tokenization.convert_to_unicode(line[0]) 224 | text_b = tokenization.convert_to_unicode(line[1]) 225 | label = tokenization.convert_to_unicode(line[2]) 226 | if label == tokenization.convert_to_unicode("contradictory"): 227 | label = tokenization.convert_to_unicode("contradiction") 228 | examples.append( 229 | InputExample(guid=guid, text_a=text_a, text_b=text_b, label=label)) 230 | return examples 231 | 232 | def get_dev_examples(self, data_dir): 233 | """See base class.""" 234 | lines = self._read_tsv(os.path.join(data_dir, "xnli.dev.tsv")) 235 | examples = [] 236 | for (i, line) in enumerate(lines): 237 | if i == 0: 238 | continue 239 | guid = "dev-%d" % (i) 240 | language = tokenization.convert_to_unicode(line[0]) 241 | if language != tokenization.convert_to_unicode(self.language): 242 | continue 243 | text_a = tokenization.convert_to_unicode(line[6]) 244 | text_b = tokenization.convert_to_unicode(line[7]) 245 | label = tokenization.convert_to_unicode(line[1]) 246 | examples.append( 247 | InputExample(guid=guid, text_a=text_a, text_b=text_b, label=label)) 248 | return examples 249 | 250 | def get_labels(self): 251 | """See base class.""" 252 | return ["contradiction", "entailment", "neutral"] 253 | 254 | 255 | class MnliProcessor(DataProcessor): 256 | """Processor for the MultiNLI data set (GLUE version).""" 257 | 258 | def get_train_examples(self, data_dir): 259 | """See base class.""" 260 | return self._create_examples( 261 | self._read_tsv(os.path.join(data_dir, "train.tsv")), "train") 262 | 263 | def get_dev_examples(self, data_dir): 264 | """See base class.""" 265 | return self._create_examples( 266 | self._read_tsv(os.path.join(data_dir, "dev_matched.tsv")), 267 | "dev_matched") 268 | 269 | def get_test_examples(self, data_dir): 270 | """See base class.""" 271 | return self._create_examples( 272 | self._read_tsv(os.path.join(data_dir, "test_matched.tsv")), "test") 273 | 274 | def get_labels(self): 275 | """See base class.""" 276 | return ["contradiction", "entailment", "neutral"] 277 | 278 | def _create_examples(self, lines, set_type): 279 | """Creates examples for the training and dev sets.""" 280 | examples = [] 281 | for (i, line) in enumerate(lines): 282 | if i == 0: 283 | continue 284 | guid = "%s-%s" % (set_type, tokenization.convert_to_unicode(line[0])) 285 | text_a = tokenization.convert_to_unicode(line[8]) 286 | text_b = tokenization.convert_to_unicode(line[9]) 287 | if set_type == "test": 288 | label = "contradiction" 289 | else: 290 | label = tokenization.convert_to_unicode(line[-1]) 291 | examples.append( 292 | InputExample(guid=guid, text_a=text_a, text_b=text_b, label=label)) 293 | return examples 294 | #----------------------------------------- 295 | #手机评论情感分类数据处理 2019/3/12 296 | #labels: -1负面 0中性 1正面 297 | class SetimentProcessor(DataProcessor): 298 | def get_train_examples(self, data_dir): 299 | """See base class.""" 300 | return self._create_examples( 301 | self._read_tsv(os.path.join(data_dir, "train.tsv")), "train") 302 | 303 | def get_dev_examples(self, data_dir): 304 | """See base class.""" 305 | return self._create_examples( 306 | self._read_tsv(os.path.join(data_dir, "dev.tsv")), "dev") 307 | 308 | def get_test_examples(self, data_dir): 309 | """See base class.""" 310 | return self._create_examples( 311 | self._read_tsv(os.path.join(data_dir, "test.tsv")), "test") 312 | 313 | def get_labels(self): 314 | """See base class.""" 315 | 316 | """ 317 | if not os.path.exists(os.path.join(FLAGS.output_dir, 'label_list.pkl')): 318 | with codecs.open(os.path.join(FLAGS.output_dir, 'label_list.pkl'), 'wb') as fd: 319 | pickle.dump(self.labels, fd) 320 | """ 321 | return ["-1", "0", "1"] 322 | 323 | def _create_examples(self, lines, set_type): 324 | """Creates examples for the training and dev sets.""" 325 | examples = [] 326 | for (i, line) in enumerate(lines): 327 | if i == 0: 328 | continue 329 | guid = "%s-%s" % (set_type, i) 330 | 331 | #debug (by xmxoxo) 332 | #print("read line: No.%d" % i) 333 | 334 | text_a = tokenization.convert_to_unicode(line[1]) 335 | if set_type == "test": 336 | label = "0" 337 | else: 338 | label = tokenization.convert_to_unicode(line[0]) 339 | examples.append( 340 | InputExample(guid=guid, text_a=text_a, label=label)) 341 | return examples 342 | #----------------------------------------- 343 | 344 | class MrpcProcessor(DataProcessor): 345 | """Processor for the MRPC data set (GLUE version).""" 346 | 347 | def get_train_examples(self, data_dir): 348 | """See base class.""" 349 | return self._create_examples( 350 | self._read_tsv(os.path.join(data_dir, "train.tsv")), "train") 351 | 352 | def get_dev_examples(self, data_dir): 353 | """See base class.""" 354 | return self._create_examples( 355 | self._read_tsv(os.path.join(data_dir, "dev.tsv")), "dev") 356 | 357 | def get_test_examples(self, data_dir): 358 | """See base class.""" 359 | return self._create_examples( 360 | self._read_tsv(os.path.join(data_dir, "test.tsv")), "test") 361 | 362 | def get_labels(self): 363 | """See base class.""" 364 | return ["0", "1"] 365 | 366 | def _create_examples(self, lines, set_type): 367 | """Creates examples for the training and dev sets.""" 368 | examples = [] 369 | for (i, line) in enumerate(lines): 370 | if i == 0: 371 | continue 372 | guid = "%s-%s" % (set_type, i) 373 | text_a = tokenization.convert_to_unicode(line[3]) 374 | text_b = tokenization.convert_to_unicode(line[4]) 375 | if set_type == "test": 376 | label = "0" 377 | else: 378 | label = tokenization.convert_to_unicode(line[0]) 379 | examples.append( 380 | InputExample(guid=guid, text_a=text_a, text_b=text_b, label=label)) 381 | return examples 382 | 383 | 384 | class ColaProcessor(DataProcessor): 385 | """Processor for the CoLA data set (GLUE version).""" 386 | 387 | def get_train_examples(self, data_dir): 388 | """See base class.""" 389 | return self._create_examples( 390 | self._read_tsv(os.path.join(data_dir, "train.tsv")), "train") 391 | 392 | def get_dev_examples(self, data_dir): 393 | """See base class.""" 394 | return self._create_examples( 395 | self._read_tsv(os.path.join(data_dir, "dev.tsv")), "dev") 396 | 397 | def get_test_examples(self, data_dir): 398 | """See base class.""" 399 | return self._create_examples( 400 | self._read_tsv(os.path.join(data_dir, "test.tsv")), "test") 401 | 402 | def get_labels(self): 403 | """See base class.""" 404 | return ["0", "1"] 405 | 406 | def _create_examples(self, lines, set_type): 407 | """Creates examples for the training and dev sets.""" 408 | examples = [] 409 | for (i, line) in enumerate(lines): 410 | # Only the test set has a header 411 | if set_type == "test" and i == 0: 412 | continue 413 | guid = "%s-%s" % (set_type, i) 414 | if set_type == "test": 415 | text_a = tokenization.convert_to_unicode(line[1]) 416 | label = "0" 417 | else: 418 | text_a = tokenization.convert_to_unicode(line[3]) 419 | label = tokenization.convert_to_unicode(line[1]) 420 | examples.append( 421 | InputExample(guid=guid, text_a=text_a, text_b=None, label=label)) 422 | return examples 423 | 424 | ## 425 | def convert_single_example(ex_index, example, label_list, max_seq_length, 426 | tokenizer): 427 | """Converts a single `InputExample` into a single `InputFeatures`.""" 428 | 429 | if isinstance(example, PaddingInputExample): 430 | return InputFeatures( 431 | input_ids=[0] * max_seq_length, 432 | input_mask=[0] * max_seq_length, 433 | segment_ids=[0] * max_seq_length, 434 | label_id=0, 435 | is_real_example=False) 436 | 437 | label_map = {} 438 | for (i, label) in enumerate(label_list): 439 | label_map[label] = i 440 | 441 | #--- save label2id.pkl --- 442 | #在这里输出label2id.pkl , add by xmxoxo 2019/2/27 443 | output_label2id_file = os.path.join(FLAGS.output_dir, "label2id.pkl") 444 | if not os.path.exists(output_label2id_file): 445 | with open(output_label2id_file,'wb') as w: 446 | pickle.dump(label_map,w) 447 | 448 | #--- Add end --- 449 | 450 | 451 | 452 | tokens_a = tokenizer.tokenize(example.text_a) 453 | tokens_b = None 454 | if example.text_b: 455 | tokens_b = tokenizer.tokenize(example.text_b) 456 | 457 | if tokens_b: 458 | # Modifies `tokens_a` and `tokens_b` in place so that the total 459 | # length is less than the specified length. 460 | # Account for [CLS], [SEP], [SEP] with "- 3" 461 | _truncate_seq_pair(tokens_a, tokens_b, max_seq_length - 3) 462 | else: 463 | # Account for [CLS] and [SEP] with "- 2" 464 | if len(tokens_a) > max_seq_length - 2: 465 | tokens_a = tokens_a[0:(max_seq_length - 2)] 466 | 467 | # The convention in BERT is: 468 | # (a) For sequence pairs: 469 | # tokens: [CLS] is this jack ##son ##ville ? [SEP] no it is not . [SEP] 470 | # type_ids: 0 0 0 0 0 0 0 0 1 1 1 1 1 1 471 | # (b) For single sequences: 472 | # tokens: [CLS] the dog is hairy . [SEP] 473 | # type_ids: 0 0 0 0 0 0 0 474 | # 475 | # Where "type_ids" are used to indicate whether this is the first 476 | # sequence or the second sequence. The embedding vectors for `type=0` and 477 | # `type=1` were learned during pre-training and are added to the wordpiece 478 | # embedding vector (and position vector). This is not *strictly* necessary 479 | # since the [SEP] token unambiguously separates the sequences, but it makes 480 | # it easier for the model to learn the concept of sequences. 481 | # 482 | # For classification tasks, the first vector (corresponding to [CLS]) is 483 | # used as the "sentence vector". Note that this only makes sense because 484 | # the entire model is fine-tuned. 485 | tokens = [] 486 | segment_ids = [] 487 | tokens.append("[CLS]") 488 | segment_ids.append(0) 489 | for token in tokens_a: 490 | tokens.append(token) 491 | segment_ids.append(0) 492 | tokens.append("[SEP]") 493 | segment_ids.append(0) 494 | 495 | if tokens_b: 496 | for token in tokens_b: 497 | tokens.append(token) 498 | segment_ids.append(1) 499 | tokens.append("[SEP]") 500 | segment_ids.append(1) 501 | 502 | input_ids = tokenizer.convert_tokens_to_ids(tokens) 503 | 504 | # The mask has 1 for real tokens and 0 for padding tokens. Only real 505 | # tokens are attended to. 506 | input_mask = [1] * len(input_ids) 507 | 508 | # Zero-pad up to the sequence length. 509 | while len(input_ids) < max_seq_length: 510 | input_ids.append(0) 511 | input_mask.append(0) 512 | segment_ids.append(0) 513 | 514 | assert len(input_ids) == max_seq_length 515 | assert len(input_mask) == max_seq_length 516 | assert len(segment_ids) == max_seq_length 517 | 518 | #debug xmxoxo 2019/3/13 519 | #print(ex_index,example.text_a) 520 | 521 | label_id = label_map[example.label] 522 | if ex_index < 5: 523 | tf.logging.info("*** Example ***") 524 | tf.logging.info("guid: %s" % (example.guid)) 525 | tf.logging.info("tokens: %s" % " ".join( 526 | [tokenization.printable_text(x) for x in tokens])) 527 | tf.logging.info("input_ids: %s" % " ".join([str(x) for x in input_ids])) 528 | tf.logging.info("input_mask: %s" % " ".join([str(x) for x in input_mask])) 529 | tf.logging.info("segment_ids: %s" % " ".join([str(x) for x in segment_ids])) 530 | tf.logging.info("label: %s (id = %d)" % (example.label, label_id)) 531 | 532 | feature = InputFeatures( 533 | input_ids=input_ids, 534 | input_mask=input_mask, 535 | segment_ids=segment_ids, 536 | label_id=label_id, 537 | is_real_example=True) 538 | return feature 539 | 540 | 541 | def file_based_convert_examples_to_features( 542 | examples, label_list, max_seq_length, tokenizer, output_file): 543 | """Convert a set of `InputExample`s to a TFRecord file.""" 544 | 545 | writer = tf.python_io.TFRecordWriter(output_file) 546 | 547 | for (ex_index, example) in enumerate(examples): 548 | if ex_index % 10000 == 0: 549 | tf.logging.info("Writing example %d of %d" % (ex_index, len(examples))) 550 | 551 | feature = convert_single_example(ex_index, example, label_list, 552 | max_seq_length, tokenizer) 553 | 554 | def create_int_feature(values): 555 | f = tf.train.Feature(int64_list=tf.train.Int64List(value=list(values))) 556 | return f 557 | 558 | features = collections.OrderedDict() 559 | features["input_ids"] = create_int_feature(feature.input_ids) 560 | features["input_mask"] = create_int_feature(feature.input_mask) 561 | features["segment_ids"] = create_int_feature(feature.segment_ids) 562 | features["label_ids"] = create_int_feature([feature.label_id]) 563 | features["is_real_example"] = create_int_feature( 564 | [int(feature.is_real_example)]) 565 | 566 | tf_example = tf.train.Example(features=tf.train.Features(feature=features)) 567 | writer.write(tf_example.SerializeToString()) 568 | writer.close() 569 | 570 | 571 | def file_based_input_fn_builder(input_file, seq_length, is_training, 572 | drop_remainder): 573 | """Creates an `input_fn` closure to be passed to TPUEstimator.""" 574 | 575 | name_to_features = { 576 | "input_ids": tf.FixedLenFeature([seq_length], tf.int64), 577 | "input_mask": tf.FixedLenFeature([seq_length], tf.int64), 578 | "segment_ids": tf.FixedLenFeature([seq_length], tf.int64), 579 | "label_ids": tf.FixedLenFeature([], tf.int64), 580 | "is_real_example": tf.FixedLenFeature([], tf.int64), 581 | } 582 | 583 | def _decode_record(record, name_to_features): 584 | """Decodes a record to a TensorFlow example.""" 585 | example = tf.parse_single_example(record, name_to_features) 586 | 587 | # tf.Example only supports tf.int64, but the TPU only supports tf.int32. 588 | # So cast all int64 to int32. 589 | for name in list(example.keys()): 590 | t = example[name] 591 | if t.dtype == tf.int64: 592 | t = tf.to_int32(t) 593 | example[name] = t 594 | 595 | return example 596 | 597 | def input_fn(params): 598 | """The actual input function.""" 599 | batch_size = params["batch_size"] 600 | 601 | # For training, we want a lot of parallel reading and shuffling. 602 | # For eval, we want no shuffling and parallel reading doesn't matter. 603 | d = tf.data.TFRecordDataset(input_file) 604 | if is_training: 605 | d = d.repeat() 606 | d = d.shuffle(buffer_size=100) 607 | 608 | d = d.apply( 609 | tf.contrib.data.map_and_batch( 610 | lambda record: _decode_record(record, name_to_features), 611 | batch_size=batch_size, 612 | drop_remainder=drop_remainder)) 613 | 614 | return d 615 | 616 | return input_fn 617 | 618 | 619 | def _truncate_seq_pair(tokens_a, tokens_b, max_length): 620 | """Truncates a sequence pair in place to the maximum length.""" 621 | 622 | # This is a simple heuristic which will always truncate the longer sequence 623 | # one token at a time. This makes more sense than truncating an equal percent 624 | # of tokens from each, since if one sequence is very short then each token 625 | # that's truncated likely contains more information than a longer sequence. 626 | while True: 627 | total_length = len(tokens_a) + len(tokens_b) 628 | if total_length <= max_length: 629 | break 630 | if len(tokens_a) > len(tokens_b): 631 | tokens_a.pop() 632 | else: 633 | tokens_b.pop() 634 | 635 | 636 | def create_model(bert_config, is_training, input_ids, input_mask, segment_ids, 637 | labels, num_labels, use_one_hot_embeddings): 638 | """Creates a classification model.""" 639 | model = modeling.BertModel( 640 | config=bert_config, 641 | is_training=is_training, 642 | input_ids=input_ids, 643 | input_mask=input_mask, 644 | token_type_ids=segment_ids, 645 | use_one_hot_embeddings=use_one_hot_embeddings) 646 | 647 | # In the demo, we are doing a simple classification task on the entire 648 | # segment. 649 | # 650 | # If you want to use the token-level output, use model.get_sequence_output() 651 | # instead. 652 | output_layer = model.get_pooled_output() 653 | 654 | hidden_size = output_layer.shape[-1].value 655 | 656 | output_weights = tf.get_variable( 657 | "output_weights", [num_labels, hidden_size], 658 | initializer=tf.truncated_normal_initializer(stddev=0.02)) 659 | 660 | output_bias = tf.get_variable( 661 | "output_bias", [num_labels], initializer=tf.zeros_initializer()) 662 | 663 | with tf.variable_scope("loss"): 664 | if is_training: 665 | # I.e., 0.1 dropout 666 | output_layer = tf.nn.dropout(output_layer, keep_prob=0.9) 667 | 668 | logits = tf.matmul(output_layer, output_weights, transpose_b=True) 669 | logits = tf.nn.bias_add(logits, output_bias) 670 | probabilities = tf.nn.softmax(logits, axis=-1) 671 | log_probs = tf.nn.log_softmax(logits, axis=-1) 672 | 673 | one_hot_labels = tf.one_hot(labels, depth=num_labels, dtype=tf.float32) 674 | 675 | per_example_loss = -tf.reduce_sum(one_hot_labels * log_probs, axis=-1) 676 | loss = tf.reduce_mean(per_example_loss) 677 | 678 | return (loss, per_example_loss, logits, probabilities) 679 | 680 | 681 | def model_fn_builder(bert_config, num_labels, init_checkpoint, learning_rate, 682 | num_train_steps, num_warmup_steps, use_tpu, 683 | use_one_hot_embeddings): 684 | """Returns `model_fn` closure for TPUEstimator.""" 685 | 686 | def model_fn(features, labels, mode, params): # pylint: disable=unused-argument 687 | """The `model_fn` for TPUEstimator.""" 688 | 689 | tf.logging.info("*** Features ***") 690 | for name in sorted(features.keys()): 691 | tf.logging.info(" name = %s, shape = %s" % (name, features[name].shape)) 692 | 693 | input_ids = features["input_ids"] 694 | input_mask = features["input_mask"] 695 | segment_ids = features["segment_ids"] 696 | label_ids = features["label_ids"] 697 | is_real_example = None 698 | if "is_real_example" in features: 699 | is_real_example = tf.cast(features["is_real_example"], dtype=tf.float32) 700 | else: 701 | is_real_example = tf.ones(tf.shape(label_ids), dtype=tf.float32) 702 | 703 | is_training = (mode == tf.estimator.ModeKeys.TRAIN) 704 | 705 | (total_loss, per_example_loss, logits, probabilities) = create_model( 706 | bert_config, is_training, input_ids, input_mask, segment_ids, label_ids, 707 | num_labels, use_one_hot_embeddings) 708 | 709 | tvars = tf.trainable_variables() 710 | initialized_variable_names = {} 711 | scaffold_fn = None 712 | if init_checkpoint: 713 | (assignment_map, initialized_variable_names 714 | ) = modeling.get_assignment_map_from_checkpoint(tvars, init_checkpoint) 715 | if use_tpu: 716 | 717 | def tpu_scaffold(): 718 | tf.train.init_from_checkpoint(init_checkpoint, assignment_map) 719 | return tf.train.Scaffold() 720 | 721 | scaffold_fn = tpu_scaffold 722 | else: 723 | tf.train.init_from_checkpoint(init_checkpoint, assignment_map) 724 | 725 | tf.logging.info("**** Trainable Variables ****") 726 | for var in tvars: 727 | init_string = "" 728 | if var.name in initialized_variable_names: 729 | init_string = ", *INIT_FROM_CKPT*" 730 | tf.logging.info(" name = %s, shape = %s%s", var.name, var.shape, 731 | init_string) 732 | 733 | output_spec = None 734 | if mode == tf.estimator.ModeKeys.TRAIN: 735 | 736 | train_op = optimization.create_optimizer( 737 | total_loss, learning_rate, num_train_steps, num_warmup_steps, use_tpu) 738 | 739 | output_spec = tf.contrib.tpu.TPUEstimatorSpec( 740 | mode=mode, 741 | loss=total_loss, 742 | train_op=train_op, 743 | scaffold_fn=scaffold_fn) 744 | elif mode == tf.estimator.ModeKeys.EVAL: 745 | 746 | def metric_fn(per_example_loss, label_ids, logits, is_real_example): 747 | predictions = tf.argmax(logits, axis=-1, output_type=tf.int32) 748 | 749 | ## modify by xmxoxo 2019/1/25 750 | # add precision,recall,f1 751 | precision = tf.metrics.precision(labels=label_ids, predictions=predictions, weights=is_real_example) 752 | recall = tf.metrics.recall(labels=label_ids, predictions=predictions, weights=is_real_example) 753 | f1 = (2 * precision[0] * recall[0] / (precision[0] + recall[0]),recall[1]) 754 | accuracy = tf.metrics.accuracy( 755 | labels=label_ids, predictions=predictions, weights=is_real_example) 756 | loss = tf.metrics.mean(values=per_example_loss, weights=is_real_example) 757 | return { 758 | "eval_accuracy": accuracy, 759 | "eval_precision": precision, 760 | "eval_recall": recall, 761 | "eval_f1": f1, 762 | "eval_loss": loss, 763 | } 764 | ## modify end 765 | 766 | eval_metrics = (metric_fn, 767 | [per_example_loss, label_ids, logits, is_real_example]) 768 | output_spec = tf.contrib.tpu.TPUEstimatorSpec( 769 | mode=mode, 770 | loss=total_loss, 771 | eval_metrics=eval_metrics, 772 | scaffold_fn=scaffold_fn) 773 | else: 774 | output_spec = tf.contrib.tpu.TPUEstimatorSpec( 775 | mode=mode, 776 | predictions={"probabilities": probabilities}, 777 | scaffold_fn=scaffold_fn) 778 | return output_spec 779 | 780 | return model_fn 781 | 782 | 783 | # This function is not used by this file but is still used by the Colab and 784 | # people who depend on it. 785 | def input_fn_builder(features, seq_length, is_training, drop_remainder): 786 | """Creates an `input_fn` closure to be passed to TPUEstimator.""" 787 | 788 | all_input_ids = [] 789 | all_input_mask = [] 790 | all_segment_ids = [] 791 | all_label_ids = [] 792 | 793 | for feature in features: 794 | all_input_ids.append(feature.input_ids) 795 | all_input_mask.append(feature.input_mask) 796 | all_segment_ids.append(feature.segment_ids) 797 | all_label_ids.append(feature.label_id) 798 | 799 | def input_fn(params): 800 | """The actual input function.""" 801 | batch_size = params["batch_size"] 802 | 803 | num_examples = len(features) 804 | 805 | # This is for demo purposes and does NOT scale to large data sets. We do 806 | # not use Dataset.from_generator() because that uses tf.py_func which is 807 | # not TPU compatible. The right way to load data is with TFRecordReader. 808 | d = tf.data.Dataset.from_tensor_slices({ 809 | "input_ids": 810 | tf.constant( 811 | all_input_ids, shape=[num_examples, seq_length], 812 | dtype=tf.int32), 813 | "input_mask": 814 | tf.constant( 815 | all_input_mask, 816 | shape=[num_examples, seq_length], 817 | dtype=tf.int32), 818 | "segment_ids": 819 | tf.constant( 820 | all_segment_ids, 821 | shape=[num_examples, seq_length], 822 | dtype=tf.int32), 823 | "label_ids": 824 | tf.constant(all_label_ids, shape=[num_examples], dtype=tf.int32), 825 | }) 826 | 827 | if is_training: 828 | d = d.repeat() 829 | d = d.shuffle(buffer_size=100) 830 | 831 | d = d.batch(batch_size=batch_size, drop_remainder=drop_remainder) 832 | return d 833 | 834 | return input_fn 835 | 836 | 837 | # This function is not used by this file but is still used by the Colab and 838 | # people who depend on it. 839 | def convert_examples_to_features(examples, label_list, max_seq_length, 840 | tokenizer): 841 | """Convert a set of `InputExample`s to a list of `InputFeatures`.""" 842 | 843 | features = [] 844 | for (ex_index, example) in enumerate(examples): 845 | if ex_index % 10000 == 0: 846 | tf.logging.info("Writing example %d of %d" % (ex_index, len(examples))) 847 | 848 | feature = convert_single_example(ex_index, example, label_list, 849 | max_seq_length, tokenizer) 850 | 851 | features.append(feature) 852 | return features 853 | 854 | 855 | def main(_): 856 | tf.logging.set_verbosity(tf.logging.INFO) 857 | 858 | processors = { 859 | "cola": ColaProcessor, 860 | "mnli": MnliProcessor, 861 | "mrpc": MrpcProcessor, 862 | "xnli": XnliProcessor, 863 | "setiment": SetimentProcessor, #2019/3/27 add by Echo 864 | } 865 | 866 | tokenization.validate_case_matches_checkpoint(FLAGS.do_lower_case, 867 | FLAGS.init_checkpoint) 868 | 869 | if not FLAGS.do_train and not FLAGS.do_eval and not FLAGS.do_predict: 870 | raise ValueError( 871 | "At least one of `do_train`, `do_eval` or `do_predict' must be True.") 872 | 873 | bert_config = modeling.BertConfig.from_json_file(FLAGS.bert_config_file) 874 | 875 | if FLAGS.max_seq_length > bert_config.max_position_embeddings: 876 | raise ValueError( 877 | "Cannot use sequence length %d because the BERT model " 878 | "was only trained up to sequence length %d" % 879 | (FLAGS.max_seq_length, bert_config.max_position_embeddings)) 880 | 881 | tf.gfile.MakeDirs(FLAGS.output_dir) 882 | 883 | task_name = FLAGS.task_name.lower() 884 | 885 | if task_name not in processors: 886 | raise ValueError("Task not found: %s" % (task_name)) 887 | 888 | processor = processors[task_name]() 889 | 890 | label_list = processor.get_labels() 891 | 892 | tokenizer = tokenization.FullTokenizer( 893 | vocab_file=FLAGS.vocab_file, do_lower_case=FLAGS.do_lower_case) 894 | 895 | tpu_cluster_resolver = None 896 | if FLAGS.use_tpu and FLAGS.tpu_name: 897 | tpu_cluster_resolver = tf.contrib.cluster_resolver.TPUClusterResolver( 898 | FLAGS.tpu_name, zone=FLAGS.tpu_zone, project=FLAGS.gcp_project) 899 | 900 | is_per_host = tf.contrib.tpu.InputPipelineConfig.PER_HOST_V2 901 | run_config = tf.contrib.tpu.RunConfig( 902 | cluster=tpu_cluster_resolver, 903 | master=FLAGS.master, 904 | model_dir=FLAGS.output_dir, 905 | save_checkpoints_steps=FLAGS.save_checkpoints_steps, 906 | tpu_config=tf.contrib.tpu.TPUConfig( 907 | iterations_per_loop=FLAGS.iterations_per_loop, 908 | num_shards=FLAGS.num_tpu_cores, 909 | per_host_input_for_training=is_per_host)) 910 | 911 | train_examples = None 912 | num_train_steps = None 913 | num_warmup_steps = None 914 | if FLAGS.do_train: 915 | train_examples = processor.get_train_examples(FLAGS.data_dir) 916 | num_train_steps = int( 917 | len(train_examples) / FLAGS.train_batch_size * FLAGS.num_train_epochs) 918 | num_warmup_steps = int(num_train_steps * FLAGS.warmup_proportion) 919 | 920 | model_fn = model_fn_builder( 921 | bert_config=bert_config, 922 | num_labels=len(label_list), 923 | init_checkpoint=FLAGS.init_checkpoint, 924 | learning_rate=FLAGS.learning_rate, 925 | num_train_steps=num_train_steps, 926 | num_warmup_steps=num_warmup_steps, 927 | use_tpu=FLAGS.use_tpu, 928 | use_one_hot_embeddings=FLAGS.use_tpu) 929 | 930 | # If TPU is not available, this will fall back to normal Estimator on CPU 931 | # or GPU. 932 | estimator = tf.contrib.tpu.TPUEstimator( 933 | use_tpu=FLAGS.use_tpu, 934 | model_fn=model_fn, 935 | config=run_config, 936 | train_batch_size=FLAGS.train_batch_size, 937 | eval_batch_size=FLAGS.eval_batch_size, 938 | predict_batch_size=FLAGS.predict_batch_size) 939 | 940 | if FLAGS.do_train: 941 | train_file = os.path.join(FLAGS.output_dir, "train.tf_record") 942 | file_based_convert_examples_to_features( 943 | train_examples, label_list, FLAGS.max_seq_length, tokenizer, train_file) 944 | tf.logging.info("***** Running training *****") 945 | tf.logging.info(" Num examples = %d", len(train_examples)) 946 | tf.logging.info(" Batch size = %d", FLAGS.train_batch_size) 947 | tf.logging.info(" Num steps = %d", num_train_steps) 948 | train_input_fn = file_based_input_fn_builder( 949 | input_file=train_file, 950 | seq_length=FLAGS.max_seq_length, 951 | is_training=True, 952 | drop_remainder=True) 953 | estimator.train(input_fn=train_input_fn, max_steps=num_train_steps) 954 | 955 | if FLAGS.do_eval: 956 | eval_examples = processor.get_dev_examples(FLAGS.data_dir) 957 | num_actual_eval_examples = len(eval_examples) 958 | if FLAGS.use_tpu: 959 | # TPU requires a fixed batch size for all batches, therefore the number 960 | # of examples must be a multiple of the batch size, or else examples 961 | # will get dropped. So we pad with fake examples which are ignored 962 | # later on. These do NOT count towards the metric (all tf.metrics 963 | # support a per-instance weight, and these get a weight of 0.0). 964 | while len(eval_examples) % FLAGS.eval_batch_size != 0: 965 | eval_examples.append(PaddingInputExample()) 966 | 967 | eval_file = os.path.join(FLAGS.output_dir, "eval.tf_record") 968 | file_based_convert_examples_to_features( 969 | eval_examples, label_list, FLAGS.max_seq_length, tokenizer, eval_file) 970 | 971 | tf.logging.info("***** Running evaluation *****") 972 | tf.logging.info(" Num examples = %d (%d actual, %d padding)", 973 | len(eval_examples), num_actual_eval_examples, 974 | len(eval_examples) - num_actual_eval_examples) 975 | tf.logging.info(" Batch size = %d", FLAGS.eval_batch_size) 976 | 977 | # This tells the estimator to run through the entire set. 978 | eval_steps = None 979 | # However, if running eval on the TPU, you will need to specify the 980 | # number of steps. 981 | if FLAGS.use_tpu: 982 | assert len(eval_examples) % FLAGS.eval_batch_size == 0 983 | eval_steps = int(len(eval_examples) // FLAGS.eval_batch_size) 984 | 985 | eval_drop_remainder = True if FLAGS.use_tpu else False 986 | eval_input_fn = file_based_input_fn_builder( 987 | input_file=eval_file, 988 | seq_length=FLAGS.max_seq_length, 989 | is_training=False, 990 | drop_remainder=eval_drop_remainder) 991 | 992 | result = estimator.evaluate(input_fn=eval_input_fn, steps=eval_steps) 993 | 994 | output_eval_file = os.path.join(FLAGS.output_dir, "eval_results.txt") 995 | with tf.gfile.GFile(output_eval_file, "w") as writer: 996 | tf.logging.info("***** Eval results *****") 997 | for key in sorted(result.keys()): 998 | tf.logging.info(" %s = %s", key, str(result[key])) 999 | writer.write("%s = %s\n" % (key, str(result[key]))) 1000 | 1001 | if FLAGS.do_predict: 1002 | predict_examples = processor.get_test_examples(FLAGS.data_dir) 1003 | num_actual_predict_examples = len(predict_examples) 1004 | if FLAGS.use_tpu: 1005 | # TPU requires a fixed batch size for all batches, therefore the number 1006 | # of examples must be a multiple of the batch size, or else examples 1007 | # will get dropped. So we pad with fake examples which are ignored 1008 | # later on. 1009 | while len(predict_examples) % FLAGS.predict_batch_size != 0: 1010 | predict_examples.append(PaddingInputExample()) 1011 | 1012 | predict_file = os.path.join(FLAGS.output_dir, "predict.tf_record") 1013 | file_based_convert_examples_to_features(predict_examples, label_list, 1014 | FLAGS.max_seq_length, tokenizer, 1015 | predict_file) 1016 | 1017 | tf.logging.info("***** Running prediction*****") 1018 | tf.logging.info(" Num examples = %d (%d actual, %d padding)", 1019 | len(predict_examples), num_actual_predict_examples, 1020 | len(predict_examples) - num_actual_predict_examples) 1021 | tf.logging.info(" Batch size = %d", FLAGS.predict_batch_size) 1022 | 1023 | predict_drop_remainder = True if FLAGS.use_tpu else False 1024 | predict_input_fn = file_based_input_fn_builder( 1025 | input_file=predict_file, 1026 | seq_length=FLAGS.max_seq_length, 1027 | is_training=False, 1028 | drop_remainder=predict_drop_remainder) 1029 | 1030 | result = estimator.predict(input_fn=predict_input_fn) 1031 | 1032 | output_predict_file = os.path.join(FLAGS.output_dir, "test_results.tsv") 1033 | with tf.gfile.GFile(output_predict_file, "w") as writer: 1034 | num_written_lines = 0 1035 | tf.logging.info("***** Predict results *****") 1036 | for (i, prediction) in enumerate(result): 1037 | probabilities = prediction["probabilities"] 1038 | if i >= num_actual_predict_examples: 1039 | break 1040 | output_line = "\t".join( 1041 | str(class_probability) 1042 | for class_probability in probabilities) + "\n" 1043 | writer.write(output_line) 1044 | num_written_lines += 1 1045 | assert num_written_lines == num_actual_predict_examples 1046 | 1047 | 1048 | if __name__ == "__main__": 1049 | flags.mark_flag_as_required("data_dir") 1050 | flags.mark_flag_as_required("task_name") 1051 | flags.mark_flag_as_required("vocab_file") 1052 | flags.mark_flag_as_required("bert_config_file") 1053 | flags.mark_flag_as_required("output_dir") 1054 | tf.app.run() 1055 | -------------------------------------------------------------------------------- /tokenization.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # Copyright 2018 The Google AI Language Team Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | """Tokenization classes.""" 16 | 17 | from __future__ import absolute_import 18 | from __future__ import division 19 | from __future__ import print_function 20 | 21 | import collections 22 | import re 23 | import unicodedata 24 | import six 25 | import tensorflow as tf 26 | 27 | 28 | def validate_case_matches_checkpoint(do_lower_case, init_checkpoint): 29 | """Checks whether the casing config is consistent with the checkpoint name.""" 30 | 31 | # The casing has to be passed in by the user and there is no explicit check 32 | # as to whether it matches the checkpoint. The casing information probably 33 | # should have been stored in the bert_config.json file, but it's not, so 34 | # we have to heuristically detect it to validate. 35 | 36 | if not init_checkpoint: 37 | return 38 | 39 | m = re.match("^.*?([A-Za-z0-9_-]+)/bert_model.ckpt", init_checkpoint) 40 | if m is None: 41 | return 42 | 43 | model_name = m.group(1) 44 | 45 | lower_models = [ 46 | "uncased_L-24_H-1024_A-16", "uncased_L-12_H-768_A-12", 47 | "multilingual_L-12_H-768_A-12", "chinese_L-12_H-768_A-12" 48 | ] 49 | 50 | cased_models = [ 51 | "cased_L-12_H-768_A-12", "cased_L-24_H-1024_A-16", 52 | "multi_cased_L-12_H-768_A-12" 53 | ] 54 | 55 | is_bad_config = False 56 | if model_name in lower_models and not do_lower_case: 57 | is_bad_config = True 58 | actual_flag = "False" 59 | case_name = "lowercased" 60 | opposite_flag = "True" 61 | 62 | if model_name in cased_models and do_lower_case: 63 | is_bad_config = True 64 | actual_flag = "True" 65 | case_name = "cased" 66 | opposite_flag = "False" 67 | 68 | if is_bad_config: 69 | raise ValueError( 70 | "You passed in `--do_lower_case=%s` with `--init_checkpoint=%s`. " 71 | "However, `%s` seems to be a %s model, so you " 72 | "should pass in `--do_lower_case=%s` so that the fine-tuning matches " 73 | "how the model was pre-training. If this error is wrong, please " 74 | "just comment out this check." % (actual_flag, init_checkpoint, 75 | model_name, case_name, opposite_flag)) 76 | 77 | 78 | def convert_to_unicode(text): 79 | """Converts `text` to Unicode (if it's not already), assuming utf-8 input.""" 80 | if six.PY3: 81 | if isinstance(text, str): 82 | return text 83 | elif isinstance(text, bytes): 84 | return text.decode("utf-8", "ignore") 85 | else: 86 | raise ValueError("Unsupported string type: %s" % (type(text))) 87 | elif six.PY2: 88 | if isinstance(text, str): 89 | return text.decode("utf-8", "ignore") 90 | elif isinstance(text, unicode): 91 | return text 92 | else: 93 | raise ValueError("Unsupported string type: %s" % (type(text))) 94 | else: 95 | raise ValueError("Not running on Python2 or Python 3?") 96 | 97 | 98 | def printable_text(text): 99 | """Returns text encoded in a way suitable for print or `tf.logging`.""" 100 | 101 | # These functions want `str` for both Python2 and Python3, but in one case 102 | # it's a Unicode string and in the other it's a byte string. 103 | if six.PY3: 104 | if isinstance(text, str): 105 | return text 106 | elif isinstance(text, bytes): 107 | return text.decode("utf-8", "ignore") 108 | else: 109 | raise ValueError("Unsupported string type: %s" % (type(text))) 110 | elif six.PY2: 111 | if isinstance(text, str): 112 | return text 113 | elif isinstance(text, unicode): 114 | return text.encode("utf-8") 115 | else: 116 | raise ValueError("Unsupported string type: %s" % (type(text))) 117 | else: 118 | raise ValueError("Not running on Python2 or Python 3?") 119 | 120 | 121 | def load_vocab(vocab_file): 122 | """Loads a vocabulary file into a dictionary.""" 123 | vocab = collections.OrderedDict() 124 | index = 0 125 | with tf.gfile.GFile(vocab_file, "r") as reader: 126 | while True: 127 | token = convert_to_unicode(reader.readline()) 128 | if not token: 129 | break 130 | token = token.strip() 131 | vocab[token] = index 132 | index += 1 133 | return vocab 134 | 135 | 136 | def convert_by_vocab(vocab, items): 137 | """Converts a sequence of [tokens|ids] using the vocab.""" 138 | output = [] 139 | for item in items: 140 | output.append(vocab[item]) 141 | return output 142 | 143 | 144 | def convert_tokens_to_ids(vocab, tokens): 145 | return convert_by_vocab(vocab, tokens) 146 | 147 | 148 | def convert_ids_to_tokens(inv_vocab, ids): 149 | return convert_by_vocab(inv_vocab, ids) 150 | 151 | 152 | def whitespace_tokenize(text): 153 | """Runs basic whitespace cleaning and splitting on a piece of text.""" 154 | text = text.strip() 155 | if not text: 156 | return [] 157 | tokens = text.split() 158 | return tokens 159 | 160 | 161 | class FullTokenizer(object): 162 | """Runs end-to-end tokenziation.""" 163 | 164 | def __init__(self, vocab_file, do_lower_case=True): 165 | self.vocab = load_vocab(vocab_file) 166 | self.inv_vocab = {v: k for k, v in self.vocab.items()} 167 | self.basic_tokenizer = BasicTokenizer(do_lower_case=do_lower_case) 168 | self.wordpiece_tokenizer = WordpieceTokenizer(vocab=self.vocab) 169 | 170 | def tokenize(self, text): 171 | split_tokens = [] 172 | for token in self.basic_tokenizer.tokenize(text): 173 | for sub_token in self.wordpiece_tokenizer.tokenize(token): 174 | split_tokens.append(sub_token) 175 | 176 | return split_tokens 177 | 178 | def convert_tokens_to_ids(self, tokens): 179 | return convert_by_vocab(self.vocab, tokens) 180 | 181 | def convert_ids_to_tokens(self, ids): 182 | return convert_by_vocab(self.inv_vocab, ids) 183 | 184 | 185 | class BasicTokenizer(object): 186 | """Runs basic tokenization (punctuation splitting, lower casing, etc.).""" 187 | 188 | def __init__(self, do_lower_case=True): 189 | """Constructs a BasicTokenizer. 190 | 191 | Args: 192 | do_lower_case: Whether to lower case the input. 193 | """ 194 | self.do_lower_case = do_lower_case 195 | 196 | def tokenize(self, text): 197 | """Tokenizes a piece of text.""" 198 | text = convert_to_unicode(text) 199 | text = self._clean_text(text) 200 | 201 | # This was added on November 1st, 2018 for the multilingual and Chinese 202 | # models. This is also applied to the English models now, but it doesn't 203 | # matter since the English models were not trained on any Chinese data 204 | # and generally don't have any Chinese data in them (there are Chinese 205 | # characters in the vocabulary because Wikipedia does have some Chinese 206 | # words in the English Wikipedia.). 207 | text = self._tokenize_chinese_chars(text) 208 | 209 | orig_tokens = whitespace_tokenize(text) 210 | split_tokens = [] 211 | for token in orig_tokens: 212 | if self.do_lower_case: 213 | token = token.lower() 214 | token = self._run_strip_accents(token) 215 | split_tokens.extend(self._run_split_on_punc(token)) 216 | 217 | output_tokens = whitespace_tokenize(" ".join(split_tokens)) 218 | return output_tokens 219 | 220 | def _run_strip_accents(self, text): 221 | """Strips accents from a piece of text.""" 222 | text = unicodedata.normalize("NFD", text) 223 | output = [] 224 | for char in text: 225 | cat = unicodedata.category(char) 226 | if cat == "Mn": 227 | continue 228 | output.append(char) 229 | return "".join(output) 230 | 231 | def _run_split_on_punc(self, text): 232 | """Splits punctuation on a piece of text.""" 233 | chars = list(text) 234 | i = 0 235 | start_new_word = True 236 | output = [] 237 | while i < len(chars): 238 | char = chars[i] 239 | if _is_punctuation(char): 240 | output.append([char]) 241 | start_new_word = True 242 | else: 243 | if start_new_word: 244 | output.append([]) 245 | start_new_word = False 246 | output[-1].append(char) 247 | i += 1 248 | 249 | return ["".join(x) for x in output] 250 | 251 | def _tokenize_chinese_chars(self, text): 252 | """Adds whitespace around any CJK character.""" 253 | output = [] 254 | for char in text: 255 | cp = ord(char) 256 | if self._is_chinese_char(cp): 257 | output.append(" ") 258 | output.append(char) 259 | output.append(" ") 260 | else: 261 | output.append(char) 262 | return "".join(output) 263 | 264 | def _is_chinese_char(self, cp): 265 | """Checks whether CP is the codepoint of a CJK character.""" 266 | # This defines a "chinese character" as anything in the CJK Unicode block: 267 | # https://en.wikipedia.org/wiki/CJK_Unified_Ideographs_(Unicode_block) 268 | # 269 | # Note that the CJK Unicode block is NOT all Japanese and Korean characters, 270 | # despite its name. The modern Korean Hangul alphabet is a different block, 271 | # as is Japanese Hiragana and Katakana. Those alphabets are used to write 272 | # space-separated words, so they are not treated specially and handled 273 | # like the all of the other languages. 274 | if ((cp >= 0x4E00 and cp <= 0x9FFF) or # 275 | (cp >= 0x3400 and cp <= 0x4DBF) or # 276 | (cp >= 0x20000 and cp <= 0x2A6DF) or # 277 | (cp >= 0x2A700 and cp <= 0x2B73F) or # 278 | (cp >= 0x2B740 and cp <= 0x2B81F) or # 279 | (cp >= 0x2B820 and cp <= 0x2CEAF) or 280 | (cp >= 0xF900 and cp <= 0xFAFF) or # 281 | (cp >= 0x2F800 and cp <= 0x2FA1F)): # 282 | return True 283 | 284 | return False 285 | 286 | def _clean_text(self, text): 287 | """Performs invalid character removal and whitespace cleanup on text.""" 288 | output = [] 289 | for char in text: 290 | cp = ord(char) 291 | if cp == 0 or cp == 0xfffd or _is_control(char): 292 | continue 293 | if _is_whitespace(char): 294 | output.append(" ") 295 | else: 296 | output.append(char) 297 | return "".join(output) 298 | 299 | 300 | class WordpieceTokenizer(object): 301 | """Runs WordPiece tokenziation.""" 302 | 303 | def __init__(self, vocab, unk_token="[UNK]", max_input_chars_per_word=200): 304 | self.vocab = vocab 305 | self.unk_token = unk_token 306 | self.max_input_chars_per_word = max_input_chars_per_word 307 | 308 | def tokenize(self, text): 309 | """Tokenizes a piece of text into its word pieces. 310 | 311 | This uses a greedy longest-match-first algorithm to perform tokenization 312 | using the given vocabulary. 313 | 314 | For example: 315 | input = "unaffable" 316 | output = ["un", "##aff", "##able"] 317 | 318 | Args: 319 | text: A single token or whitespace separated tokens. This should have 320 | already been passed through `BasicTokenizer. 321 | 322 | Returns: 323 | A list of wordpiece tokens. 324 | """ 325 | 326 | text = convert_to_unicode(text) 327 | 328 | output_tokens = [] 329 | for token in whitespace_tokenize(text): 330 | chars = list(token) 331 | if len(chars) > self.max_input_chars_per_word: 332 | output_tokens.append(self.unk_token) 333 | continue 334 | 335 | is_bad = False 336 | start = 0 337 | sub_tokens = [] 338 | while start < len(chars): 339 | end = len(chars) 340 | cur_substr = None 341 | while start < end: 342 | substr = "".join(chars[start:end]) 343 | if start > 0: 344 | substr = "##" + substr 345 | if substr in self.vocab: 346 | cur_substr = substr 347 | break 348 | end -= 1 349 | if cur_substr is None: 350 | is_bad = True 351 | break 352 | sub_tokens.append(cur_substr) 353 | start = end 354 | 355 | if is_bad: 356 | output_tokens.append(self.unk_token) 357 | else: 358 | output_tokens.extend(sub_tokens) 359 | return output_tokens 360 | 361 | 362 | def _is_whitespace(char): 363 | """Checks whether `chars` is a whitespace character.""" 364 | # \t, \n, and \r are technically contorl characters but we treat them 365 | # as whitespace since they are generally considered as such. 366 | if char == " " or char == "\t" or char == "\n" or char == "\r": 367 | return True 368 | cat = unicodedata.category(char) 369 | if cat == "Zs": 370 | return True 371 | return False 372 | 373 | 374 | def _is_control(char): 375 | """Checks whether `chars` is a control character.""" 376 | # These are technically control characters but we count them as whitespace 377 | # characters. 378 | if char == "\t" or char == "\n" or char == "\r": 379 | return False 380 | cat = unicodedata.category(char) 381 | if cat.startswith("C"): 382 | return True 383 | return False 384 | 385 | 386 | def _is_punctuation(char): 387 | """Checks whether `chars` is a punctuation character.""" 388 | cp = ord(char) 389 | # We treat all non-letter/number ASCII as punctuation. 390 | # Characters such as "^", "$", and "`" are not in the Unicode 391 | # Punctuation class but we treat them as punctuation anyways, for 392 | # consistency. 393 | if ((cp >= 33 and cp <= 47) or (cp >= 58 and cp <= 64) or 394 | (cp >= 91 and cp <= 96) or (cp >= 123 and cp <= 126)): 395 | return True 396 | cat = unicodedata.category(char) 397 | if cat.startswith("P"): 398 | return True 399 | return False 400 | --------------------------------------------------------------------------------