TensorFlow练习1: 对评论进行分类

TensorFlow是谷歌2015年开源的一个深度学习库,到现在正好一年。和TensorFlow类似的库还有Caffe、Theano、MXNet、Torch。但是论火爆程度,TensorFlow当之无愧,短短一年就在Github就收获了4万+颗星,把前面几个库获得的star加起来也不敌TensorFlow。

TensorFlow使用C++开发,并提供了Python等语言的封装。如命名一样,TensorFlow为张量从图一端流动到另一端的计算过程,可以把张量看作矩阵(矩阵rank为2,Tensor的rank更高)。TensorFlow并不是一个抽象程度特别高的库,但是它实现了所有深度学习所需的函数。貌似有几个高度抽象的库使用TensorFlow做为后端。

TensorFlow可被用于语音识别或图像识别等多项机器深度学习领域,它可在小到手机、大到数千台服务器上运行。

本帖展示怎么使用TensorFlow实现文本的简单分类,判断评论是正面的还是负面的。

使用的数据集

我本想使用Python爬一些淘宝评论,但是脚本做到一半卡壳了,搞得火起。然后我上网找现成的数据,只找到了英文的电影评论数据(其实不管是英文还是中文,处理逻辑都一样)。

TensorFlow练习1: 对评论进行分类

如果你有一些好数据愿意分享,感激不尽。

由于处理的是字符串,我们首先要想方法把字符串转换为向量/数字表示。一种解决方法是可以把单词映射为数字ID。

第二个问题是每行评论字数不同,而神经网络需要一致的输入(其实有些神经网络不需要,至少本帖需要),这可以使用词汇表解决。

代码部分

安装nltk(自然语言工具库 Natural Language Toolkit

下载nltk数据:

ntlk有详细安装文档。

测试nltk安装:

Python代码:

执行结果:

TensorFlow练习1: 对评论进行分类

准确率真tm喜人,才60%多,比瞎猜强点有限。

那么问题出在哪呢?

准确率低主要是因为数据量太小,同样的模型,如果使用超大数据训练,准确率会有显著的提升。

下文我会使用同样的模型,但是数据量要比本文使用的多得多,看看准确率能提高多少。由于本文使用的神经网络模型(feed-forward)过于简单,使用大数据也不一定有质的提升,尤其是涉及到自然语言处理。

相关文章

《TensorFlow练习1: 对评论进行分类》有27个想法

  1. 增加结点数量效果好了很多。
    n_layer_1 = 2000 # hide layer
    n_layer_2 = 2000 # hide layer(隐藏层)听着很神秘,其实就是除输入输出层外的中间层

    epochs = 10
    #config = tf.ConfigProto(log_device_placement=True)

    # config=tf.ConfigProto(log_device_placement=True)
    with tf.device(“/gpu:0”):
    with tf.Session() as session:
    session.run(tf.global_variables_initializer())
    epoch_loss = 0

    i = 0
    random.shuffle(train_dataset)
    train_x = dataset[:, 0]
    train_y = dataset[:, 1]
    for epoch in range(epochs):
    while i < len(train_x):
    start = i
    end = i + batch_size

    batch_x = train_x[start:end]
    batch_y = train_y[start:end]

    _, c = session.run([optimizer, cost_func], feed_dict={X: list(batch_x), Y: list(batch_y)})
    epoch_loss += c
    i += batch_size

    print(epoch, ' : ', epoch_loss)

    text_x = test_dataset[:, 0]
    text_y = test_dataset[:, 1]
    correct = tf.equal(tf.argmax(predict, 1), tf.argmax(Y, 1))
    accuracy = tf.reduce_mean(tf.cast(correct, 'float'))
    print('准确率: ', accuracy.eval({X: list(text_x), Y: list(text_y)}))

    0 : 639547.851576
    1 : 639547.851576
    2 : 639547.851576
    3 : 639547.851576
    4 : 639547.851576
    5 : 639547.851576
    6 : 639547.851576
    7 : 639547.851576
    8 : 639547.851576
    9 : 639547.851576
    准确率: 0.91182

  2. 我是一名小白,运行以上的代码时出现问题不知道是怎么回事儿,报错如下:
    “/Users/apple/anaconda/lib/python3.5/encodings/ascii.py”, line 26, in decode
    return codecs.ascii_decode(input, self.errors)[0]
    builtins.UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe8 in position 4645: ordinal not in range(128)
    望大侠们给予帮助

  3. 0 : 161880.120468
    1 : 44454.7335434
    2 : 19402.644618
    3 : 11012.3176503
    4 : 7502.47118509
    5 : 4813.6613276
    6 : 3717.54492438
    7 : 2935.52427715
    8 : 2343.01210514
    9 : 1825.98590671
    10 : 1544.88283711
    11 : 1211.68019958
    12 : 1082.50301955
    13 : 986.075972824
    14 : 830.262459563
    15 : 712.45051866
    16 : 719.769491395
    17 : 572.315391871
    18 : 558.06024103
    19 : 501.797473472
    20 : 440.458145358
    21 : 439.054949049
    22 : 372.898518044
    23 : 377.614312239
    24 : 378.971066926
    25 : 288.261114291
    26 : 293.548729711
    27 : 339.465822173
    28 : 279.877237613
    29 : 281.749216568
    30 : 236.349964639
    31 : 243.258463897
    32 : 268.585548623
    33 : 268.935334055
    34 : 307.464248186
    35 : 293.080421972
    36 : 330.144405167
    37 : 257.893546837
    38 : 282.801720913
    39 : 327.284410027
    40 : 291.993200428
    41 : 326.411648442
    42 : 296.159285459
    43 : 300.742347601
    44 : 345.599421181
    45 : 263.925570339
    46 : 181.766719678
    47 : 230.192739646
    48 : 216.616977498
    49 : 209.081691016
    准确率: 0.708255
    改了所有bug+改进model,加入激活因子,设置为0.5,并将字典的词频区间改为10-20000,训练50次的结果,仅供参考。

  4. tokenize 後有 230193 字
    lemmatize 後 word_count 裡有 18642 字
    用 20 < word_count[word] < 2000 篩選後剩下 1065 字
    篩掉太多了

  5. 这异常该怎么改呢?
    Traceback (most recent call last):
    File “06021.py”, line 92, in
    dataset = normalize_dataset(lex)
    File “06021.py”, line 86, in normalize_dataset
    one_sample = string_to_vector(lex, line, [0,1]) # [array([ 0., 0., 0., …, 0., 0., 0.]), [0,1]]]
    File “06021.py”, line 70, in string_to_vector
    words = [lemmatizer.lemmatize(word) for word in words]
    File “/usr/local/lib/python2.7/dist-packages/nltk/stem/wordnet.py”, line 40, in lemmatize
    lemmas = wordnet._morphy(word, pos)
    File “/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py”, line 1794, in _morphy
    forms = apply_rules([form])
    File “/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py”, line 1775, in apply_rules
    if form.endswith(old)]
    UnicodeDecodeError: ‘utf8’ codec can’t decode byte 0xc2 in position 4: unexpected end of data

  6. 感觉都是大神呀,终于跑通了一个程序,准备研究当中。。。。很显然我还没有非常懂里面的内容。。。

  7. 新手偷懒去掉了词形还原的步骤,直接把r’\w+’匹配的结果作为words,只保留出现次数<10次的单词,epochs和batch_size都设为为10,结果跑出来88%的正确率。。。

  8. 0 : 60996.565155
    1 : 60996.565155
    2 : 60996.565155
    3 : 60996.565155
    4 : 60996.565155
    5 : 60996.565155
    6 : 60996.565155
    7 : 60996.565155
    8 : 60996.565155
    9 : 60996.565155
    10 : 60996.565155
    11 : 60996.565155
    12 : 60996.565155
    准确率: 0.681989

    贴下我的系统版本,方便后来的同学,调试
    Python 3.6.1 (default, Mar 27 2017, 00:27:06)
    [GCC 6.3.1 20170306] on linux
    python-tensorflow 1.1.0-4
    改了两个,一处是Geoffrey说的
    def string_to_vector(lex, review, clf):
    words = word_tokenize(line.lower())
    Should be this instead?:
    def string_to_vector(lex, review, clf):
    words = word_tokenize(review.lower())
    要改成这个样子
    words = word_tokenize(review.lower())

    第二处是cost_func这里,可能是Tensorflow版本升级代来的改变
    cost_func = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(predict, Y))
    这句我是改成了下面这样的
    cost_func = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=predict, labels=Y))

    然后通过的
    对了 我用的Archlinux,都是新的软件,从库里安装的,没有手动安装

    机器里存在python2和python3搞半天没搞好,最后没办法只好安装了个pycharm去自动修改python的环境

  9. “named arguments (labels=…, logits=…, …)” % name)
    ValueError: Only call softmax_cross_entropy_with_logits with named arguments (labels=…, logits=…, …)
    一直出现这个问题,后来改了下参数可以了
    tf.nn.softmax_cross_entropy_with_logits(None,Y, predict)

    但是在win10系统上出现这个问题,一直没解决:
    E c:\tf_jenkins\home\workspace\release-win\device\cpu\os\windows\tensorflow\core\framework\op_kernel.cc:943] OpKernel (‘op: “BestSplits” device_type: “CPU”‘) for unknown op: BestSplits
    E c:\tf_jenkins\home\workspace\release-win\device\cpu\os\windows\tensorflow\core\framework\op_kernel.cc:943] OpKernel (‘op: “CountExtremelyRandomStats” device_type: “CPU”‘) for unknown op: CountExtremelyRandomStats
    E c:\tf_jenkins\home\workspace\release-win\device\cpu\os\windows\tensorflow\core\framework\op_kernel.cc:943] OpKernel (‘op: “FinishedNodes” device_type: “CPU”‘) for unknown op: FinishedNodes
    E c:\tf_jenkins\home\workspace\release-win\device\cpu\os\windows\tensorflow\core\framework\op_kernel.cc:943] OpKernel (‘op: “GrowTree” device_type: “CPU”‘) for unknown op: GrowTree
    E c:\tf_jenkins\home\workspace\release-win\device\cpu\os\windows\tensorflow\core\framework\op_kernel.cc:943] OpKernel (‘op: “ReinterpretStringToFloat” device_type: “CPU”‘) for unknown op: ReinterpretStringToFloat
    E c:\tf_jenkins\home\workspace\release-win\device\cpu\os\windows\tensorflow\core\framework\op_kernel.cc:943] OpKernel (‘op: “SampleInputs” device_type: “CPU”‘) for unknown op: SampleInputs
    E c:\tf_jenkins\home\workspace\release-win\device\cpu\os\windows\tensorflow\core\framework\op_kernel.cc:943] OpKernel (‘op: “ScatterAddNdim” device_type: “CPU”‘) for unknown op: ScatterAddNdim
    E c:\tf_jenkins\home\workspace\release-win\device\cpu\os\windows\tensorflow\core\framework\op_kernel.cc:943] OpKernel (‘op: “TopNInsert” device_type: “CPU”‘) for unknown op: TopNInsert
    E c:\tf_jenkins\home\workspace\release-win\device\cpu\os\windows\tensorflow\core\framework\op_kernel.cc:943] OpKernel (‘op: “TopNRemove” device_type: “CPU”‘) for unknown op: TopNRemove
    E c:\tf_jenkins\home\workspace\release-win\device\cpu\os\windows\tensorflow\core\framework\op_kernel.cc:943] OpKernel (‘op: “TreePredictions” device_type: “CPU”‘) for unknown op: TreePredictions
    E c:\tf_jenkins\home\workspace\release-win\device\cpu\os\windows\tensorflow\core\framework\op_kernel.cc:943] OpKernel (‘op: “UpdateFertileSlots” device_type: “CPU”‘) for unknown op: UpdateFertileSlots

    1. 你把 def train_neural_network(X, Y)里面的train_x = dataset[:, 0]改成了train_x = train_dataset[:, 0] 吗? 改了后准确率才六十多

  10. i和epoch_loss应该在每epoch开始的时候初始化为0吧,按照你现在的代码只会进行一epoch,后面的epoch由于i没再初始化,所以根本不做任何事啊。

  11. 多挑兩個小bug:
    line 28-29:
    def process_file(f):
    with open(pos_file, ‘r’) as f:
    Should be this instead?:
    def process_file(txtfile):
    with open(txtfile, ‘r’) as f:

    line 63-64:
    def string_to_vector(lex, review, clf):
    words = word_tokenize(line.lower())
    Should be this instead?:
    def string_to_vector(lex, review, clf):
    words = word_tokenize(review.lower())

    算出來才50中間, 比你的更喜感/-\ 從代碼學到處理文字數據和tensorflow挺多, 感謝!

  12. 请问def train_neural_network(X, Y)里面的train_x = dataset[:, 0]是否应该是train_x = train_dataset[:, 0],这里不应该拿全部数据去训练哇。

发表评论

电子邮件地址不会被公开。 必填项已用*标注