import os
import tensorflow as tf
class CBOWNetwork(object):
def __init__(self, name="W2V", num_sampled=100, window=4, vocab_size=3365, embedding_size=128, is_mean=True,
regularization=0.001, optimizer_name='adam', learning_rate=0.01, checkpoint_dir="./running/model"):
self.name = name
self.vocab_size = vocab_size
self.embedding_size = embedding_size
self.is_mean = is_mean
self.window = window
self.num_sampled = num_sampled
self.regularization = regularization
self.optimizer_name = optimizer_name.lower()
self.learning_rate = learning_rate
self.adam_beta1 = 0.9
self.adam_beta2 = 0.999
self.epsilon = 1e-8
self.adadelta_rho = 0.95
self.checkpoint_dir = checkpoint_dir
self.checkpoint_path = os.path.join(self.checkpoint_dir, "{}.ckpt".format(self.name.lower()))
if not os.path.exists(self.checkpoint_dir):
os.makedirs(self.checkpoint_dir)
self.input_x = None
self.target = None
self.training = None
self.global_step = None
self.features = None
self.embedding_table = None
self.saver = None
def interface(self):
"""
前向网络的构建
:return:
"""
with tf.variable_scope(self.name):
with tf.variable_scope("placeholder"):
self.input_x = tf.placeholder(dtype=tf.int32, shape=[None, self.window], name="input_x")
self.target = tf.placeholder(dtype=tf.int32, shape=[None, 1], name="target")
self.training = tf.placeholder_with_default(True, shape=[], name="training")
self.global_step = tf.train.get_or_create_global_step()
with tf.variable_scope("embedding"), tf.device("/cpu:0"):
self.embedding_table = tf.get_variable("embedding_table",
shape=[self.vocab_size, self.embedding_size],
dtype=tf.float32)
vectors = tf.nn.embedding_lookup(params=self.embedding_table, ids=self.input_x)
with tf.variable_scope("merge"):
if self.is_mean:
features = tf.reduce_mean(vectors, axis=1)
else:
features = tf.reduce_sum(vectors, axis=1)
self.features = tf.identity(features, "features")
def losses(self):
"""
损失函数的构建
:return:
"""
with tf.variable_scope("loss"):
weight = tf.get_variable(name="weight", shape=[self.vocab_size, self.embedding_size])
bias = tf.get_variable(name="bias", shape=[self.vocab_size])
def train_loss():
"""
训练阶段的损失函数构建
:return:
"""
_loss = tf.nn.sampled_softmax_loss(
weights=weight,
biases=bias,
labels=self.target,
inputs=self.features,
num_sampled=self.num_sampled,
num_classes=self.vocab_size,
num_true=1
)
_loss = tf.reduce_mean(_loss, name="train_loss")
return _loss
def eval_loss():
"""
数据验证时候的损失函数构建(不能够近似的计算,那么必须全连接)
:return:
"""
logits = tf.nn.bias_add(tf.matmul(self.features, weight, transpose_b=True), bias=bias)
labels = tf.reshape(self.target, shape=[-1])
_loss = tf.nn.sparse_softmax_cross_entropy_with_logits(
labels=labels,
logits=logits
)
_loss = tf.reduce_mean(_loss, name="eval_loss")
return _loss
loss = tf.cond(
pred=self.training,
true_fn=train_loss,
false_fn=eval_loss
)
tf.summary.scalar('loss', loss)
l2_loss = tf.nn.l2_loss(self.embedding_table) + tf.nn.l2_loss(weight) + tf.nn.l2_loss(bias)
l2_loss = self.regularization * l2_loss
tf.summary.scalar('l2_loss', l2_loss)
total_loss = loss + l2_loss
tf.summary.scalar('total_loss', total_loss)
return total_loss
def optimizer(self, loss):
"""
损失函数的构建
:param loss:
:return:
"""
with tf.variable_scope("train"):
if self.optimizer_name == 'adam':
opt = tf.train.AdamOptimizer(
learning_rate=self.learning_rate,
beta1=self.adam_beta1,
beta2=self.adam_beta2,
epsilon=self.epsilon
)
elif self.optimizer_name == 'adadelta':
opt = tf.train.AdadeltaOptimizer(
learning_rate=self.learning_rate,
rho=self.adadelta_rho,
epsilon=self.epsilon
)
elif self.optimizer_name == 'adagrad':
opt = tf.train.AdagradOptimizer(learning_rate=self.learning_rate)
else:
opt = tf.train.GradientDescentOptimizer(learning_rate=self.learning_rate)
train_op = opt.minimize(loss=loss, global_step=self.global_step)
return opt, train_op
def metrics(self, loss=None):
"""
模型评估值的构建
:param loss:
:return:
"""
pass
def restore(self, session):
"""
模型参数恢复
:param session:
:return:
"""
if self.saver is None:
self.saver = tf.train.Saver()
session.run(tf.global_variables_initializer())
ckpt = tf.train.get_checkpoint_state(checkpoint_dir=self.checkpoint_dir)
if ckpt and ckpt.model_checkpoint_path:
tf.logging.info("Restore model weight from '{}'".format(ckpt.model_checkpoint_path))
self.saver.restore(session, save_path=ckpt.model_checkpoint_path)
self.saver.recover_last_checkpoints(ckpt.all_model_checkpoint_paths)
def save(self, session):
"""
模型持久化
:param session:
:return:
"""
if self.saver is None:
self.saver = tf.train.Saver()
tf.logging.info("Store the model weight to '{}'".format(self.checkpoint_path))
self.saver.save(session, save_path=self.checkpoint_path, global_step=self.global_step)
class SkipGramNetwork(object):
def __init__(self, name="W2V", num_sampled=100, window=4, vocab_size=3365, embedding_size=128,
regularization=0.001, optimizer_name='adam', learning_rate=0.01, checkpoint_dir="./running/model"):
self.name = name
self.vocab_size = vocab_size
self.embedding_size = embedding_size
self.window = window
self.num_sampled = num_sampled
self.regularization = regularization
self.optimizer_name = optimizer_name.lower()
self.learning_rate = learning_rate
self.adam_beta1 = 0.9
self.adam_beta2 = 0.999
self.epsilon = 1e-8
self.adadelta_rho = 0.95
self.checkpoint_dir = checkpoint_dir
self.checkpoint_path = os.path.join(self.checkpoint_dir, "{}.ckpt".format(self.name.lower()))
if not os.path.exists(self.checkpoint_dir):
os.makedirs(self.checkpoint_dir)
self.input_x = None
self.target = None
self.training = None
self.global_step = None
self.features = None
self.embedding_table = None
self.saver = None
def interface(self):
"""
前向网络的构建
:return:
"""
with tf.variable_scope(self.name):
with tf.variable_scope("placeholder"):
self.input_x = tf.placeholder(dtype=tf.int32, shape=[None, 1], name="input_x")
self.target = tf.placeholder(dtype=tf.int32, shape=[None, self.window], name="target")
self.training = tf.placeholder_with_default(True, shape=[], name="training")
self.global_step = tf.train.get_or_create_global_step()
with tf.variable_scope("embedding"), tf.device("/cpu:0"):
self.embedding_table = tf.get_variable("embedding_table",
shape=[self.vocab_size, self.embedding_size],
dtype=tf.float32)
vectors = tf.nn.embedding_lookup(params=self.embedding_table, ids=self.input_x)
with tf.variable_scope("merge"):
features = tf.squeeze(vectors, axis=1)
self.features = tf.identity(features, "features")
def losses(self):
"""
损失函数的构建
:return:
"""
with tf.variable_scope("loss"):
weight = tf.get_variable(name="weight", shape=[self.vocab_size, self.embedding_size])
bias = tf.get_variable(name="bias", shape=[self.vocab_size])
def train_loss():
"""
训练阶段的损失函数构建
:return:
"""
_loss = tf.nn.nce_loss(
weights=weight,
biases=bias,
labels=self.target,
inputs=self.features,
num_sampled=self.num_sampled,
num_classes=self.vocab_size,
num_true=self.window
)
_loss = tf.reduce_mean(_loss, name="train_loss")
return _loss
def eval_loss():
"""
数据验证时候的损失函数构建(不能够近似的计算,那么必须全连接)
:return:
"""
logits = tf.nn.bias_add(tf.matmul(self.features, weight, transpose_b=True), bias=bias)
labels = tf.one_hot(self.target, depth=self.vocab_size)
labels = tf.reduce_sum(labels, axis=1)
_loss = tf.nn.sigmoid_cross_entropy_with_logits(
labels=labels,
logits=logits
)
_loss = tf.reduce_mean(_loss, name="eval_loss")
return _loss
loss = tf.cond(
pred=self.training,
true_fn=train_loss,
false_fn=eval_loss
)
tf.summary.scalar('loss', loss)
l2_loss = tf.nn.l2_loss(self.embedding_table) + tf.nn.l2_loss(weight) + tf.nn.l2_loss(bias)
l2_loss = self.regularization * l2_loss
tf.summary.scalar('l2_loss', l2_loss)
total_loss = loss + l2_loss
tf.summary.scalar('total_loss', total_loss)
return total_loss
def optimizer(self, loss):
"""
损失函数的构建
:param loss:
:return:
"""
with tf.variable_scope("train"):
if self.optimizer_name == 'adam':
opt = tf.train.AdamOptimizer(
learning_rate=self.learning_rate,
beta1=self.adam_beta1,
beta2=self.adam_beta2,
epsilon=self.epsilon
)
elif self.optimizer_name == 'adadelta':
opt = tf.train.AdadeltaOptimizer(
learning_rate=self.learning_rate,
rho=self.adadelta_rho,
epsilon=self.epsilon
)
elif self.optimizer_name == 'adagrad':
opt = tf.train.AdagradOptimizer(learning_rate=self.learning_rate)
else:
opt = tf.train.GradientDescentOptimizer(learning_rate=self.learning_rate)
train_op = opt.minimize(loss=loss, global_step=self.global_step)
return opt, train_op
def metrics(self, loss=None):
"""
模型评估值的构建
:param loss:
:return:
"""
pass
def restore(self, session):
"""
模型参数恢复
:param session:
:return:
"""
if self.saver is None:
self.saver = tf.train.Saver()
session.run(tf.global_variables_initializer())
ckpt = tf.train.get_checkpoint_state(checkpoint_dir=self.checkpoint_dir)
if ckpt and ckpt.model_checkpoint_path:
tf.logging.info("Restore model weight from '{}'".format(ckpt.model_checkpoint_path))
self.saver.restore(session, save_path=ckpt.model_checkpoint_path)
self.saver.recover_last_checkpoints(ckpt.all_model_checkpoint_paths)
def save(self, session):
"""
模型持久化
:param session:
:return:
"""
if self.saver is None:
self.saver = tf.train.Saver()
tf.logging.info("Store the model weight to '{}'".format(self.checkpoint_path))
self.saver.save(session, save_path=self.checkpoint_path, global_step=self.global_step)