专栏名称: 雷克世界
赛迪研究院(CCID)主办的新媒体平台,每天跟你聊聊机器人、人工智能、智能制造领域的那些你想知道的事……
目录
相关文章推荐
51好读  ›  专栏  ›  雷克世界

全文解析!如何使用「TF-Hub」构建一个简单的文本分类器

雷克世界  · 公众号  · 机器人  · 2018-04-09 16:54

正文

图源:unsplash

原文来源 :TensorFlow

「雷克世界」编译:嗯~是阿童木呀、KABUDA、EVA


导语:TF-Hub是一个可以共享机器学习专业知识的平台,里面包含在可重用资源中打包的机器学习专业知识,特别是在预先训练的模块中的技能。接下来,本文将介绍该如何使用“TF-Hub”构建一个简单的文本分类器。本教程主要从两个部分展开:使用TF-Hub训练文本分类器和迁移学习的分析。


介绍:使用TF-Hub训练文本分类器


我们将使用一个TF-Hub文本嵌入模块来训练一个简单的情绪分类器,并具有合理的基线精确度。然后,我们将分析预测结果以确保我们的模型是合理的,并提出改进以提高准确度。


进阶:迁移学习分析


在本节中,我们将使用各种TF-Hub模块来比较它们对估计精确度的影响,并论证迁移学习的优点和缺点。


可选的先决条件


•对Tensorflow预制估计量框架的基本理解。


•对Pandas Library的熟悉。


准备环境


# Install the latest Tensorflow version.

# Install TF-Hub.

!pip install -q tensorflow-hub


关于安装Tensorflow的更多详细信息请见: https://www.tensorflow.org/install/


import tensorflow as tf

import tensorflow_hub as hub

import matplotlib.pyplot as plt

import numpy as np

import os

import pandas as pd

import re

import seaborn as sns


/usr/local/lib/python2.7/dist-packages/h5py/__init__.py:36: FutureWarning:Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.

from ._conv import register_converters as _register_converters


开始


数据


我们将尝试解决从群众Mass等获得的大型电影评论数据集(Large Movie Review Dataset)v1.0任务。该数据集由IMDB电影评论组成,并被根据积极性从1到10进行标注。我们的任务是将这些评论标注为 负面 正面


# Load all files from a directory in a DataFrame.

def load_directory_data(directory):

data = {}

data["sentence"] = []

data["sentiment"] = []

for file_path in os.listdir(directory):

with tf.gfile.GFile(os.path.join(directory, file_path), "r") as f:

data["sentence"].append(f.read())

data["sentiment"].append(re.match("\d+_(\d+)\.txt", file_path).group(1))

return pd.DataFrame.from_dict(data)


# Merge positive and negative examples, add a polarity column and shuffle.

def load_dataset(directory):

pos_df = load_directory_data(os.path.join(directory, "pos"))

neg_df = load_directory_data(os.path.join(directory, "neg"))

pos_df["polarity"] = 1

neg_df["polarity"] = 0

return pd.concat([pos_df, neg_df]).sample(frac=1).reset_index(drop=True)


# Download and process the dataset files.

def download_and_load_datasets(force_download=False):

dataset = tf.keras.utils.get_file(

fname="aclImdb.tar.gz",

origin="http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz",

extract=True)


train_df = load_dataset(os.path.join(os.path.dirname(dataset),

"aclImdb", "train"))

test_df = load_dataset(os.path.join(os.path.dirname(dataset),

"aclImdb", "test"))


return train_df, test_df


# Reduce logging output.

tf.logging.set_verbosity(tf.logging.ERROR)


train_df, test_df = download_and_load_datasets()

train_df.head()


Downloading data from http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz

84131840/84125825 [==============================] - 1s 0us/step

84140032/84125825 [==============================] - 1s 0us/step



模型


输入函数


估计框架(Estimator framework)提供了包装Pandas数据框的输入函数。


# Training input on the whole training set with no limit on training epochs.

train_input_fn = tf.estimator.inputs.pandas_input_fn(

train_df, train_df["polarity"], num_epochs=None, shuffle=True)


# Prediction on the whole training set.

predict_train_input_fn = tf.estimator.inputs.pandas_input_fn(

train_df, train_df["polarity"], shuffle=False)

# Prediction on the test set.

predict_test_input_fn = tf.estimator.inputs.pandas_input_fn(

test_df, test_df["polarity"], shuffle=False)


特征列


TF-Hub提供了一个特征列,它在给定的文本特征上应用了一个模块,并进一步传递了模块的输出。在本教程中,我们将使用nnlm-en-dim128模块。为了达成本教程的目的,几个最重要的事实是:


•该模块将 一组1-D的字符串张量中的句子 作为输入。


•该模块负责 对句子进行预处理 (例如,删除标点符号并分隔空格)。


•该模块可以处理任何输入(例如, nnlm-en-dim128 会将没有出现在词汇表中的单词散列到~20.000桶内)。


embedded_text_feature_column = hub.text_embedding_column(

key="sentence",

module_spec="https://tfhub.dev/google/nnlm-en-dim128/1")


估计


对于分类,我们可以使用DNN分类器(请注意,在本教程的最后有关于不同建模函数的进一步附注)。


estimator = tf.estimator.DNNClassifier(

hidden_units=[500, 100],

feature_columns=[embedded_text_feature_column],

n_classes=2,

optimizer=tf.train.AdagradOptimizer(learning_rate=0.003))


训练


以合理数量的步骤对估计量进行训练。


# Training for 1,000 steps means 128,000 training examples with the default

# batch size. This is roughly equivalent to 5 epochs since the training dataset

# contains 25,000 examples.

estimator.train(input_fn=train_input_fn, steps=1000);


预测


以对训练和测试集进行预测


train_eval_result = estimator.evaluate(input_fn=predict_train_input_fn)

test_eval_result = estimator.evaluate(input_fn=predict_test_input_fn)


print "Training set accuracy: {accuracy}".format(**train_eval_result)

print "Test set accuracy: {accuracy}".format(**test_eval_result)


Training set accuracy: 0.802160024643

Test set accuracy: 0.792879998684


混淆矩阵


我们可以直观地检查混淆矩阵来确定错误分类的分布。


def get_predictions(estimator, input_fn):

return [x["class_ids"][0] for x in estimator.predict(input_fn=input_fn)]


LABELS = [

"negative", "positive"

]


# Create a confusion matrix on training data.

with tf.Graph().as_default():

cm = tf.confusion_matrix(train_df["polarity"],

get_predictions(estimator, predict_train_input_fn))

with tf.Session() as session:

cm_out = session.run(cm)


# Normalize the confusion matrix so that each row sums to 1.

cm_out = cm_out.astype(float) / cm_out.sum(axis=1)[:, np.newaxis]


sns.heatmap(cm_out, annot=True, xticklabels=LABELS, yticklabels=LABELS);

plt.xlabel("Predicted");

plt.ylabel("True");



进一步改进


情绪回归 :我们使用分类器将每个样本分配到极性类中。但实际上,我们还有另一个分类特征——情绪。在这里,类实际上表示一种规模,基础值(正/负)可以很好地映射到一个连续的范围内。我们可以通过计算回归(DNN Regressor)而非分类(DNN Classifier)来利用这一特性。


更大的模块 :为了达到本教程的目的,我们使用了一个小模块来限制内存的使用。有些模块拥有更大的词汇量和更大的嵌入空间,可以提供更多的精准点。


参数调整 :我们可以通过调整学习速率或步骤数等元参数来提高精确度,尤其当我们使用不同模块时。如果要得到合理的结果,那么验证集是非常重要的,因为它很容易建立一个学习预测训练数据的模型,而不需要很好地泛化到测试集。


更复杂的模型 :我们使用了一个模块,通过嵌入每个单词,将它们与平均值相结合来计算句子嵌入。我们还可以使用序列模块(如通用句子编码器模块)来更好地捕捉句子的性质。或两个或多个TF-Hub模块的组合。


正则化 :为了防止过度拟合,我们可以尝试使用执行某种正则化的优化器,例如Proximal Adagrad Optimizer。


进阶:迁移学习分析


迁移学习可以 节省训练资源 并实现良好的模型泛化,即使 在小数据集上进行训练 时也是如此。在这一部分中,我们将通过使用两种不同的TF-Hub模块进行训练来证明这一点。


nnlm-en-dim128 – 预训练文本嵌入模块


random-nnlm-en-dim128 – 与 nnlm-en-dim128 具有相同词汇表和网络的文本嵌入模块,但权重只是随机初始化,从未在真实数据上进行过训练。


通过两种模式进行训练


•只训练分类器(即冻结模块)


•分类器同模块一起训练


让我们运行几组训练和评估,看看使用不同模块会给精确度带来哪些影响。


def train_and_evaluate_with_module(hub_module, train_module=False):

embedded_text_feature_column = hub.text_embedding_column(

key="sentence", module_spec=hub_module, trainable=train_module)


estimator = tf.estimator.DNNClassifier(

hidden_units=[500, 100],

feature_columns=[embedded_text_feature_column],

n_classes=2,

optimizer=tf.train.AdagradOptimizer(learning_rate=0.003))


estimator.train(input_fn=train_input_fn, steps=1000)


train_eval_result = estimator.evaluate(input_fn=predict_train_input_fn)

test_eval_result = estimator.evaluate(input_fn=predict_test_input_fn)


training_set_accuracy = train_eval_result["accuracy"]

test_set_accuracy = test_eval_result["accuracy"]


return {

"Training accuracy": training_set_accuracy,

"Test accuracy": test_set_accuracy

}


results = {}

results["nnlm-en-dim128"]=train_and_evaluate_with_module(

"https://tfhub.dev/google/nnlm-en-dim128/1")

results["nnlm-en-dim128-with-module-training"] = train_and_evaluate_with_module(







请到「今天看啥」查看全文


推荐文章
首席经济学家论坛  ·  陶冬:英国选举爆意外 联储会议酿新招
7 年前
独立精神  ·  试论汉语中的“诗语”
7 年前