textCNN在tensorflow上的故事——记一个tf入门者的学习之路

数据科学实战课:问题驱动的数据分析与业务闭环 数据科学不是统计学的简化版,而是连接数据与业务决策的工程实践。它以真实问题为起点,通过数据采集、清洗、探索、建模到交付的完整生命周期,构建可解释、可行动、可落地的分析闭环。核心在于将业务目标转化为可计算指标(如复购率、转化漏斗、用户分群),用Python+Pandas+Scikit-learn等工业级工具实现快速验证与迭代,强调特征背后的业务逻辑、模型输出的业务语言,以及结果对运营动作的直接支撑。本文聚焦‘问题驱动型’数据工作方法论,覆盖A/B测试归因、RFM行为聚类、清洗即规则翻译、评估指标与业务目标对齐 阅读详情

背景

这篇博客主要用来记录一个从不会tensorflow到第一个project(textCNN—中文短文本分类)正式开张的故事,用来与同样刚入门tf的童鞋交流,大神就不必看了:

  • 本人有一定机器学习的理论基础,如果你对CNN原理不了解的可以去Coursera上看看Andrew Ng的Machine Learning课程关于NN部分,遇到不懂的百度/Google翻阅博客,基本看一部分再把不懂得琢磨查资料思考后对NN大致会有了解了,然后查查各种博客看看CNN的原理与过程,理论上就大致有个印象了
  • 之前在torch上实现了4层CNN对cifar-10的78%准确率识别,之所以没有直接用VGG或者GoogleNet这种已经有的大佬网络,主要是方便自己感受下CNN的搭建使用以及框架的熟悉。tensorflow这次是第一次用。
  • 本人仍然是在笔记本(mac pro 2015)上进行textCNN代码试运行后再考虑去台式机带GPU上调参,本子cpu跑3s一个batch,台式带gpu(linux系统)1s三个batch,心累。。
  • 主要描述我这种业余选手从不会tf到运行project v1的经历,并不高大上。

tensorflow初次见面

  • 安装:直接去官网,上面有完整指南。个人不建议windows, 在linux、mac、windows都装过,在windows上面第一个程序关于mnist手写识别的就崩了,mac安然无恙。可能是我水平次,但win给我的印象太…
  • 官方tf教程:如果英文看起来吃力,给个传送门http://wiki.jikexueyuan.com/project/tensorflow-zh/get_started/introduction.html,中文版,但是像我这种性格官方版本过于官方不够细致和通俗,显然是看不太下的。
  • 如果官方版本看不下去,有个B站的系列视频做的不错,传送门在此http://www.bilibili.com/video/av6653880/,不过up主貌似是双系统(刚刚被我黑的win…)。
  • 经过理论的饲养(Andrew Ng+各种博客),再加上上述官方文档和视频(不懂再去查资料看博客)的熏陶,基本上对tf这个框架和CNN都有个大致了解了。
  • 接下来进行textCNN对短文本分类,因为不像图形处理那样直接数据就是像素矩阵,所以相对麻烦一些,原始代码是Github上的某位大佬的,表示感谢,帮了我大忙链接在此https://github.com/dennybritz/cnn-text-classification-tf
  • 感觉使用实际代码来操作几波对textCNN和tensorflow熟悉感增加不少,直接看论文,真的看不太动。

正片是啥

对上述Github上代码的做一些注释,帮助类似我的初学者理解,代码可能有不同,请与原来的代码对比,下面会陆续贴部分代码,主要用到了data_helpers.py、text_cnn.py、train.py,第三个可以看做是主函数

data_helpers.py相关解释

这部分主要是定义了两个函数:

(1)第一个是数据载入函数
输入样本文档,输出样本data、样本label的list,这个没啥好说的。不过值得注意的是,这里作者是一次性将所有样本塞进去内存了,存在一个隐患问题,样本大了后会爆内存,别问我为什么会知道。解决方案可能稍后会做一些对比尝试或许更新博客,比如对超大大样本随机抽样(有放回和无放回到底哪样最合适待验证)出100个不爆内存的样本,然后按照随机顺序放进模型训练,训练仍采用minibatch。(为什么使用minibatch训练,我直接给个链接http://hp.stuhome.net/index.php/2016/09/20/tensorflow_batch_minibatch/,其实大家应该都知道原委)

这部分代码请根据自己的样本文档特征修改,我的就不贴了,可能大家的样本情况格式都不一样。

(2)第二个函数为一个batch样本生成器

def batch_iter(data, batch_size, num_epochs, shuffle=True):
    """
    Generates a batch iterator for a dataset.批量数据batchsize生成器
    定义一个函数,输出batch样本,参数为data(包括feature和label),batchsize,epoch
    """
    data = np.array(data)#全部数据转化为array
    data_size = len(data)
    num_batches_per_epoch = int((len(data)-1)/batch_size) + 1#每个epoch有多少个batch,个数
    for epoch in range(num_epochs):
        # Shuffle the data at each epoch
        if shuffle:
            shuffle_indices = np.random.permutation(np.arange(data_size))
            shuffled_data = data[shuffle_indices]# shuffled_data按照上述乱序得到新的样本
        else:
            shuffled_data = data
        for batch_num in range(num_batches_per_epoch):#开始生成batch
            start_index = batch_num * batch_size
            end_index = min((batch_num + 1) * batch_size, data_size)#这里主要是最后一个batch可能不足batchsize的处理
            yield shuffled_data[start_index:end_index]
            #yield,在for循环执行时,每次返回一个batch的data,占用的内存为常数

这里可以看出作者的细心,第一个是end_index = min((batch_num + 1) * batch_size, data_size),考虑最后最后一个batch可能大小不够batchsize了,这在上一篇博客也见到过,第二个是生成器,而不是返回一个包含各个batch样本的list(这一点是否是我多虑了呢,没有仔细观察内存状况对比)

text_cnn.py相关解释

这部分主要是建立了一个text_cnn结构的类
结构比较简单,一个embedding layer+一个convolution layer(Relu)+一个maxpooling层+softmax
主要会引起思考的问题在哪呢,如果你一行行敲代码就会发现:

(1)每个层的参数设置问题
(2)embedding layer和所谓的word2vec是个什么关系

先回答第二个问题,一开始我接触这个project的时候,天真的想,word2vec不就是一个把词的one-hot形式转化为稠密的短向量表示的工具么,用过后一个文本就变成了稠密矩阵,再当图像处理不行么?当然不行!
为什么?

reason one > 如果你仔细看下word2vec的原理,会发现vector其实是一个中间产物,本质上是模型的一部分参数,那意味着什么,不同的训练目标和样本结构得到的最优参数是不一样的,所以不存在固定的vector来表示某个word,具体分析贴一个链接http://spaces.ac.cn/archives/4122/,这是找了数篇资料才发现的解答,贼棒!当然,上面提到的B站up主也有相关解释,也不错。

reason two > 图像处理的卷积核比如3*3,可以横向和纵向两个方向移动,而文本是不行的,因为一个word的表示就是一个横向量,你不能通过原来这种卷积核把一个单词的表示拆开,破坏单词的表示,在这里,一个单词应该和图像的像素点对应即最小单元(但是实际效果我还没去对比过,后续有时间我可能会做以下对比试验),所以卷积核只会在一个维度上移动,比如词的vector为256长度,那么卷积核应该为3*256。

—另外注意他的maxpooling参数设置,好好感受下,利用CNN解决文本分类问题的文章还是很多的,比如这篇 A Convolutional Neural Network for Modelling Sentences 最有意思的输入是在 pooling 改成 (dynamic) k-max pooling ,pooling阶段保留 k 个最大的信息,保留了全局的序列信息,效果我暂时还没去尝试,后续有兴趣了再更新吧。

然后回答第一个问题:
我当时用torch的时候没有遇到这种问题,因为torch写CNN太轻松了,一个卷积层你直接add一个卷积模块就行了,但是tensorflow很细节化,需要你写出参数矩阵w、b的tensor规格,所以这里涉及卷积核参数维度、移动维度等问题,这里接着贴一个链接,也是找了一些资料才发现回答的比较好的。http://blog.youkuaiyun.com/hymanyoung/article/details/65444288直接看“TensorFlow卷积神经网络实践”后面的部分,比较清楚的说明了各参数的结构

这一部分我的整体加注释的代码,可能不专业,但希望有助于理解。

import tensorflow as tf
import numpy as np


class TextCNN(object):#定义了1个TEXTCNN的类,包含一张大的graph
    """
    A CNN for text classification.
    Uses an embedding layer, followed by a convolutional, max-pooling and softmax layer.
    embedding层,卷积层,池化层,softmax层
    """
    def __init__(
      self, sequence_length, num_classes, vocab_size,
      embedding_size, filter_sizes, num_filters, l2_reg_lambda=0.0):#定义各种输入参数,这里的输入是句子各词的索引?

        # Placeholders for input, output and dropout
        self.input_x = tf.placeholder(tf.int32, [None, sequence_length], name="input_x")
        #定义一个operation,名称input_x,利用参数sequence_length,None表示样本数不定,
        #不一定是一个batchsize,训练的时候是,验证的时候None不是batchsize
        #这是一个placeholder,
        #数据类型int32,(样本数*句子长度)的tensor,每个元素为一个单词
        self.input_y = tf.placeholder(tf.float32, [None, num_classes], name="input_y")
        #这个placeholder的数据输入类型为float,(样本数*类别)的tensor
        self.dropout_keep_prob = tf.placeholder(tf.float32, name="dropout_keep_prob")
        #placeholder表示图的一个操作或者节点,用来喂数据,进行name命名方便可视化

        # Keeping track of l2 regularization loss (optional)
        l2_loss = tf.constant(0.0)
        #l2正则的初始化,有点像sum=0
        #其实softmax是需要的

        # Embedding layer
        #参见
        with tf.device('/cpu:0'), tf.name_scope("embedding"):#封装了一个叫做“embedding'的模块,使用设备cpu,模块里3个operation
            self.W = tf.Variable(
                tf.random_uniform([vocab_size, embedding_size], -1.0, 1.0),
                name="W")#operation1,一个(词典长度*embedsize)tensor,作为W,也就是最后的词向量
            self.embedded_chars = tf.nn.embedding_lookup(self.W, self.input_x)
            #operation2,input_x的tensor维度为[none,seq_len],那么这个操作的输出为none*seq_len*em_size
            self.embedded_chars_expanded = tf.expand_dims(self.embedded_chars, -1)
            #增加一个维度,变成,batch_size*seq_len*em_size*channel(=1)的4维tensor,符合图像的习惯

        # Create a convolution + maxpool layer for each filter size
        pooled_outputs = []#空list
        for i, filter_size in enumerate(filter_sizes):#比如(0,3),(1,4),(2,5)
            with tf.name_scope("conv-maxpool-%s" % filter_size):#循环第一次,建立一个名称为如”conv-ma-3“的模块
                # Convolution Layer
                filter_shape = [filter_size, embedding_size, 1, num_filters]
                #operation1,没名称,卷积核参数,高*宽*通道*卷积个数
                W = tf.Variable(tf.truncated_normal(filter_shape, stddev=0.1), name="W")
                #operation2,名称”W“,变量维度filter_shape的tensor
                b = tf.Variable(tf.constant(0.1, shape=[num_filters]), name="b")
                #operation3,名称"b",变量维度卷积核个数的tensor
                conv = tf.nn.conv2d(
                    self.embedded_chars_expanded,
                    W,
                    strides=[1, 1, 1, 1],#样本,height,width,channel移动距离
                    padding="VALID",
                    name="conv")
                #operation4,卷积操作,名称”conv“,与w系数相乘得到一个矩阵
                # Apply nonlinearity
                h = tf.nn.relu(tf.nn.bias_add(conv, b), name="relu")
                #operation5,加上偏置,进行relu,名称"relu"
                # Maxpooling over the outputs
                pooled = tf.nn.max_pool(
                    h,
                    ksize=[1, sequence_length - filter_size + 1, 1, 1],
                    strides=[1, 1, 1, 1],
                    padding='VALID',
                    name="pool")
                pooled_outputs.append(pooled)
                #每个卷积核和pool处理一个样本后得到一个值,这里维度如batchsize*1*1*卷积核个数
                #三种卷积核,appen3次

        # Combine all the pooled features
        num_filters_total = num_filters * len(filter_sizes)
        #operation,每种卷积核个数与卷积核种类的积
        self.h_pool = tf.concat(pooled_outputs, 3)
        #operation,将outpus在第4个维度上拼接,如本来是128*1*1*64的结果3个,拼接后为128*1*1*192的tensor
        self.h_pool_flat = tf.reshape(self.h_pool, [-1, num_filters_total])
        #operation,结果reshape为128*192的tensor

        # Add dropout
        with tf.name_scope("dropout"):
            self.h_drop = tf.nn.dropout(self.h_pool_flat, self.dropout_keep_prob)
        #添加一个"dropout"的模块,里面一个操作,输出为dropout过后的128*192的tensor

        # Final (unnormalized) scores and predictions
        with tf.name_scope("output"):#添加一个”output“的模块,多个operation
            W = tf.get_variable(
                "W",
                shape=[num_filters_total, num_classes],
                initializer=tf.contrib.layers.xavier_initializer())
            #operation1,系数tensor,如192*2,192个features分2类,名称为"W",注意这里用的是get_variables
            b = tf.Variable(tf.constant(0.1, shape=[num_classes]), name="b")
            #operation2,偏置tensor,如2,名称"b"
            l2_loss += tf.nn.l2_loss(W)
            #operation3,loss上加入w的l2正则
            l2_loss += tf.nn.l2_loss(b)
            #operation4,loss上加入b的l2正则
            self.scores = tf.nn.xw_plus_b(self.h_drop, W, b, name="scores")
            #operation5,scores计算全连接后的输出,如[0.2,0.7]名称”scores“
            self.predictions = tf.argmax(self.scores, 1, name="predictions")
            #operations,计算预测值,输出最大值的索引,0或者1,名称”predictions“

        # CalculateMean cross-entropy loss
        with tf.name_scope("loss"):#定义一个”loss“的模块
            losses = tf.nn.softmax_cross_entropy_with_logits(logits=self.scores, labels=self.input_y)
            #operation1,定义losses,交叉熵,如果是一个batch,那么是一个长度为batchsize1的tensor?
            self.loss = tf.reduce_mean(losses) + l2_reg_lambda * l2_loss
            #operation2,计算一个batch的平均交叉熵,加上全连接层参数的正则

        # Accuracy
        with tf.name_scope("accuracy"):#定义一个名称”accuracy“的模块
            correct_predictions = tf.equal(self.predictions, tf.argmax(self.input_y, 1))
            #operation1,根据input_y和predictions是否相同,得到一个矩阵batchsize大小的tensor
            self.accuracy = tf.reduce_mean(tf.cast(correct_predictions, "float"), name="accuracy")
            #operation2,计算均值即为准确率,名称”accuracy“

train.py相关解释

就是主函数了,输入样本和超参数,训练网络、存储参数、计算准确率等,带“summary”的函数或者模块是tensorflow储存参数和可视化的工具,我暂时也不怎么熟练,就没怎么写注释,不过不影响功能。

这一节没什么大的引起思考的问题,加了一点点注释和改了一点点参数:

import tensorflow as tf
import numpy as np
import os
import time
import datetime
import data_helpers
from text_cnn import TextCNN
from tensorflow.contrib import learn

# Parameters
# ==================================================

# Data loading params,
#数据集里10%为验证集
tf.flags.DEFINE_float("dev_sample_percentage", .1, "Percentage of the training data to use for validation")
#原数据的文件路径
tf.flags.DEFINE_string("data_file", "/Users/xuhy/Downloads/cnn-text-wujun/data/after_fenci_wujuncnndata", "Data source.")

# Model Hyperparameters
#embedding维度256,4种卷积核,每种128个,0.5的dropout
tf.flags.DEFINE_integer("embedding_dim", 256, "Dimensionality of character embedding (default: 128)")
tf.flags.DEFINE_string("filter_sizes", "2,3,4,5", "Comma-separated filter sizes (default: '2,3,4,5')")
tf.flags.DEFINE_integer("num_filters", 128, "Number of filters per filter size (default: 128)")
tf.flags.DEFINE_float("dropout_keep_prob", 0.5, "Dropout keep probability (default: 0.5)")
tf.flags.DEFINE_float("l2_reg_lambda", 0.0, "L2 regularization lambda (default: 0.0)")

# Training parameters
#batchsize为64,20个epoch,每100个batch后,计算验证集上的表现,每100个batch后保存模型,checkpoint是个啥?
tf.flags.DEFINE_integer("batch_size", 64, "Batch Size (default: 64)")
tf.flags.DEFINE_integer("num_epochs", 20, "Number of training epochs (default: 200)")
tf.flags.DEFINE_integer("evaluate_every", 100, "Evaluate model on dev set after this many steps (default: 100)")
tf.flags.DEFINE_integer("checkpoint_every", 100, "Save model after this many steps (default: 100)")
tf.flags.DEFINE_integer("num_checkpoints", 5, "Number of checkpoints to store (default: 5)")

# Misc Parameters
#true表示自动寻找一个存在并支持的cpu或者gpu,防止指定的设备不存在
#如果将False改为True,可以看到operations被指派到哪个设备运行
tf.flags.DEFINE_boolean("allow_soft_placement", True, "Allow device soft device placement")
tf.flags.DEFINE_boolean("log_device_placement", False, "Log placement of ops on devices")

FLAGS = tf.flags.FLAGS#FLAGS是一个对象,保存了解析后的命令行参数
FLAGS._parse_flags()
print("\nParameters:")
for attr, value in sorted(FLAGS.__flags.items()):
    print("{}={}".format(attr.upper(), value))
print("")


# Data Preparation
# ==================================================

# Load data

print("Loading data...")
print("start_time"+"\t\t"+str(datetime.datetime.now().isoformat()))
x_text, y = data_helpers.load_data_and_labels(FLAGS.data_file)
print("end_time"+"\t\t"+str(datetime.datetime.now().isoformat()))
#这里的y是数值,x还是单词序列
#!!!这里一次性载入所有数据,注意考虑内存,大数据的情况下如何载入需要分析

# Build vocabulary
print("生成单词索引,构成样本索引矩阵...")
print("start_time"+"\t\t"+str(datetime.datetime.now().isoformat()))
max_document_length = 298#每一条评价的最多单词数字
vocab_processor = learn.preprocessing.VocabularyProcessor(max_document_length)
#单词转化为在字典中的位置,这是一个操作
x = np.array(list(vocab_processor.fit_transform(x_text)))
y = np.array(y)
print("end_time"+"\t\t"+str(datetime.datetime.now().isoformat()))
#在不够长度的评价最后加0,样本变成了索引数值矩阵,这里的x已经是索引序列了,n*seq_len的tensor

# Randomly shuffle data
print("打乱样本顺序...")
print("start_time"+"\t\t"+str(datetime.datetime.now().isoformat()))
np.random.seed(10)
shuffle_indices = np.random.permutation(np.arange(len(y)))#打乱样本
x_shuffled = x[shuffle_indices]#新的乱序样本
y_shuffled = y[shuffle_indices]#新的乱序label
print("end_time"+"\t\t"+str(datetime.datetime.now().isoformat()))

# Split train/test set
# TODO: This is very crude, should use cross-validation训练集、验证集划分完毕,全部是索引数值
print("生成训练集和验证集...")
print("start_time"+"\t\t"+str(datetime.datetime.now().isoformat()))
dev_sample_index = -1 * int(FLAGS.dev_sample_percentage * float(len(y)))#负数,倒过来数
x_train, x_dev = x_shuffled[:dev_sample_index], x_shuffled[dev_sample_index:]#切片
y_train, y_dev = y_shuffled[:dev_sample_index], y_shuffled[dev_sample_index:]
print("Vocabulary Size: {:d}".format(len(vocab_processor.vocabulary_)))#字典长度
print("Train/Dev split: {:d}/{:d}".format(len(y_train), len(y_dev)))#训练集和验证集长度
print("end_time"+"\t\t"+str(datetime.datetime.now().isoformat()))

# Training
# ==================================================

with tf.Graph().as_default():
    session_conf = tf.ConfigProto(
      allow_soft_placement=FLAGS.allow_soft_placement,
      log_device_placement=FLAGS.log_device_placement)#这个session配置,按照前面的gpu,cpu自动选择
    sess = tf.Session(config=session_conf)#建立一个配置如上的会话
    with sess.as_default():#在上述session填充内容
        cnn = TextCNN(
            sequence_length=x_train.shape[1],#[0]是样本维度,样本数量,[1]是单个样本的长度
            num_classes=y_train.shape[1],#同理,这里是类别数量
            vocab_size=len(vocab_processor.vocabulary_),#字典长度
            embedding_size=FLAGS.embedding_dim,
            filter_sizes=list(map(int, FLAGS.filter_sizes.split(","))),
            num_filters=FLAGS.num_filters,
            l2_reg_lambda=FLAGS.l2_reg_lambda)  #包含一个CNN
        #TextCNN是一个类,输入参数,得到一个CNN结构

        # Define Training procedure
        global_step = tf.Variable(0, name="global_step", trainable=False)#定义一个变量step
        optimizer = tf.train.AdamOptimizer(1e-3)#里面是学习速率,选择优化算法,建立优化器
        grads_and_vars = optimizer.compute_gradients(cnn.loss)#选择目标函数,计算梯度;返回的是梯度和变量
        #函数minimize() 与compute_gradients()都含有一个参数gate_gradient,用于控制在应用这些梯度时并行化的程度。这里没有?
        train_op = optimizer.apply_gradients(grads_and_vars, global_step=global_step)#运用梯度

中间summary环节我就没怎么写,就不贴了,直接帖后面的。

        # Initialize all variables
        sess.run(tf.global_variables_initializer())#初始化所有变量

        #定义了一个函数,输入为1个batch
        def train_step(x_batch, y_batch):
            """
            A single training step
            """
            feed_dict = {
              cnn.input_x: x_batch,
              cnn.input_y: y_batch,
              cnn.dropout_keep_prob: FLAGS.dropout_keep_prob
            }
            _, step, summaries, loss, accuracy = sess.run(
                [train_op, global_step, train_summary_op, cnn.loss, cnn.accuracy],
                feed_dict)
            #梯度更新(更新模型),步骤加一,存储数据,计算一个batch的损失,计算一个batch的准确率
            time_str = datetime.datetime.now().isoformat()#当时时间
            print("{}: step {}, loss {:g}, acc {:g}".format(time_str, step, loss, accuracy))
            train_summary_writer.add_summary(summaries, step)

        #定义了一个函数,用于验证集,输入为一个batch
        def dev_step(x_batch, y_batch, writer=None):
            """
            Evaluates model on a dev set
            """
            #验证集太大,会爆内存,采用batch的思想进行计算,下面生成多个子验证集
            num=20
            x_batch=x_batch.tolist()
            y_batch=y_batch.tolist()
            l=len(y_batch)
            l_20=int(l/num)
            x_set=[]
            y_set=[]
            for i in range(num-1):
                x_temp=x_batch[i*l_20:(i+1)*l_20]
                x_set.append(x_temp)
                y_temp=y_batch[i*l_20:(i+1)*l_20]
                y_set.append(y_temp)
            x_temp=x_batch[(num-1)*l_20:]
            x_set.append(x_temp)
            y_temp=y_batch[(num-1)*l_20:]
            y_set.append(y_temp)

            #每个batch验证集计算一下准确率,num个batch再平均
            lis_loss=[]
            lis_accu=[]
            for i in range(num):    
                feed_dict = {
                cnn.input_x: np.array(x_set[i]),
                cnn.input_y: np.array(y_set[i]),
                cnn.dropout_keep_prob: 1.0
                }
                step, summaries, loss, accuracy = sess.run(
                    [global_step, dev_summary_op, cnn.loss, cnn.accuracy],
                    feed_dict)
                lis_loss.append(loss)
                lis_accu.append(accuracy)
                time_str = datetime.datetime.now().isoformat()
                print("{}: step {}, loss {:g}, acc {:g}".format(time_str, step, loss, accuracy))
            print("test_loss and test_acc"+"\t\t"+str(sum(lis_loss)/num)+"\t\t"+str(sum(lis_accu)/num))
            if writer:
                writer.add_summary(summaries, step)


        # Generate batches(生成器),得到一个generator,每一次返回一个batch,没有构成list[batch1,batch2,batch3,...]
        batches = data_helpers.batch_iter(
            list(zip(x_train, y_train)), FLAGS.batch_size, FLAGS.num_epochs)
        #zip将样本与label配对,
        # Training loop. For each batch...
        for batch in batches:
            x_batch, y_batch = zip(*batch)#unzip,将配对的样本,分离出来data和label
            train_step(x_batch, y_batch)#训练,输入batch样本,更新模型
            current_step = tf.train.global_step(sess, global_step)
            if current_step % FLAGS.evaluate_every == 0:#每多少步,算一下验证集效果
                print("\nEvaluation:")
                dev_step(x_dev, y_dev, writer=dev_summary_writer)#喂的数据为验证集,此时大小不止一个batchsize1的大小
                print("")
            if current_step % FLAGS.checkpoint_every == 0:#每多少步,保存模型
                path = saver.save(sess, checkpoint_prefix, global_step=current_step)
                print("Saved model checkpoint to {}\n".format(path))

这里当时遇到了一个问题,就是每次验证集计算的时候,内存就爆了,然后我就采用minibatch的想法改进了以下,没毛病了。

最后贴一个效果

初级版本,后续会尽量优化
目前,23w+样本,类别25+,下面是训练不到2个epoch的情况,测试集准确率86.17%:

test_loss and test_acc 0.475186523795 0.861730447412

Saved model checkpoint to /Users/xuhy/runs/1498792747/checkpoints/model-6800

后面有空更。
谢谢!

Selenium常见报错排查指南:从环境配置到元素定位的实战解决方案 在Web自动化测试与数据爬取领域,Selenium作为核心工具,通过模拟用户操作实现浏览器自动化。其工作原理基于WebDriver协议,通过驱动与浏览器通信执行指令。掌握Selenium的调试技巧对于提升自动化脚本的稳定性和开发效率至关重要,尤其在处理动态网页和复杂交互场景时。本文聚焦Selenium实践中的高频问题,针对元素定位异常、浏览器驱动匹配、页面等待机制等关键环节,提供系统化的排查思路与解决方案。通过解析NoSuchElementException、StaleElementReferenceExc 阅读详情

相关推荐

TextCNN的TensorFlow实现

TextCNN的核心点在于可以捕获信息的局部相关性,具体到文本分类任务中可以利用CNN来提取句子中类似N-Gram的关键信息。

TextCNN文本分类与tensorflow实现

1.引言     我们知道,卷积神经网络(CNN)主要是在计算机视觉方面已经取得了很多很好的成就,但是,CNN在自然语言处理方面同样也可以拥有很好的应用。本文将介绍一个有关CNN的模型,用来对文本进行分类,并将它应用在文本分类的热门任务——情感分析上,模型的名称叫TextCNN,模型的论文地址如下: 论文地址:《Convolutional Neural Networks for Sentenc...

linchuhai的博客 7478

告别AT串口线!用STM32F407的USB FS口直连EC800M进行物联网通信

本文介绍了一种创新的物联网通信方案,利用STM32F407的USB FS接口直连EC800M模块,替代传统的AT串口线连接。通过详细的硬件对比、STM32CubeMX配置和USB驱动调试步骤,展示了如何实现更高效的AT指令通信,同时降低硬件复杂度和功耗。

weixin_29189987的博客 706

使用Tensorflow搭建并训练TextCNN模型,对文本进行分类

最近有学习关于文本分类的深度学习模型,最先接触的就是TextCNN模型,该模型看起来非常简单效果也非常好,在此简单记录下整个模型的搭建以及训练过程。通过本博文,你可以自己搭建并训练一个简单的文本分类模型,本文的代码注释非常详细。 使用的开发环境:python3(Anaconda管理)、Tensorflow1.13.1 本文主要分为以下几个部分进行展开讲解: (1)TextCNN原理 (2)...

霹雳吧啦Wz 8297

【3d打印】基于Klipper的3d打印远程上位机系统(Qt),klipper源码,通信解析,打印参数设置

基于Klipper的3d打印远程上位机系统(Qt),klipper源码,通信解析,打印参数设置(启庞Kp3s V1)

共享IT之美,共创机器未来 3192

基于ADRC算法的多旋翼飞行器抗扰动控制实践

本文详细介绍了基于ADRC算法的多旋翼飞行器抗扰动控制实践,通过线性扩张状态观测器(LESO)实时估算风力等扰动,实现提前补偿,显著提升飞行稳定性。文章结合具体案例和工程实现技巧,展示了ADRC在突风条件下的优异表现,为无人机控制提供了高效解决方案。

weixin_29284885的博客 191

【自然语言处理】文本分类模型_TextCNN_TensorFlow实现

一、模型主要思想 将CNN结构应用到文本分类中,使用不同尺寸的filter提取文本特征,从而捕获文本的局部信息。 二、模型结构 1.Embedding层:获得词的分布式表示; 2.卷积层:使用多个不同尺寸的filter对Embedding层的输出提取特征; 3.最大池化层:将不同长度的句子变为定长表示(这里不使用avg pooling是因为之前对句子进行padding) 4.全连接层 三、使用T...

bqw的博客 1985

SOC-ATF 安全启动BL2流程分析(2)

Bl2的启动流程与bl1类似,主要区别是bl2的初始化流程比bl1更简单,但其可能需要加载更多的镜像,如bl31、bl32和bl33。由于bl2可以运行于el3或s-el1,它们的入口函数和处理流程都有所区别,为了简化分析我们选取比较常见的s-el1方式,以下为其总体执行流程:上图仅供参考,实际看一下代码结构:上面截图展示了 链接汇编文件,bl2_el3.ld.S 是指bl2 运行于el3;bl2.ld.S 是实现bl2运行于s-el1 .

z20230508的博客 1388

TextCNN文本分类详解--使用TensorFlow一步步带你实现简单TextCNN

TextCNN文本分类详解–使用TensorFlow一步步带你实现简单TextCNN 前言 近期在项目组工作中,使用TextCNN对文本分类取得了不错的准确率,为了更清晰地了解TextCNN的结构,特翻译TensorFlow实现的TextCNN一文。 一、什么是TextCNN TextCNN 是利用卷积神经网络对文本进行分类的算法,由 Yoon Kim 在 《Convolutional Neura...

ParadiseHeaven的博客 2916

【华为OD机试真题】45、 分糖果 | 机试真题+思路参考+代码解析(C++、Java、Py、JS)

### 🎃题目描述 >小明从糖果盒中随意抓一把糖果,每次小明会取出一半的糖果分给同学们。 >  当糖果不能平均分配时,小明可以选择从糖果盒中(假设盒中糖果足够)取出一个糖果或放回一个糖果。 >  小明最少需要多少次(取出、放回和平均分配均记一次),能将手中糖果分至只剩一颗。

正在更新最新华为OD机试2025B卷,提供OJ在线刷题 1290

使用MATLAB实现PAC2002轮胎模型的TIR文件解析和模型计算详解

PAC2002轮胎模型是由荷兰TNO公司开发的一种半经验的轮胎模型,用于描述轮胎在不同工况下的力学特性。该模型基于一系列物理和经验参数,通过复杂的数学表达式来模拟轮胎的力学行为,包括纵向力、侧向力、回正力矩等。

qq_38334677的博客 2429

深度学习实战3-文本卷积神经网络(TextCNN)新闻文本分类

大家好,我是微学AI,今天给大家带来一个简单的中文新闻分类模型,利用TextCNN模型进行训练,TextCNN的主要流程是:获取文本的局部特征:通过不同的卷积核尺寸来提取文本的N-Gram信息,然后通过最大池化操作来突出各个卷积操作提取的最关键信息,拼接后通过全连接层对特征进行组合,最后通过交叉熵损失函数来训练模型。

微学AI的博客 1万+

财务数字化——解读美的战略规划之财务组织体系建设【附全文阅读】

本文提出适用于集团企业的财务管控方案,面向财务负责人、HR及战略规划人员。方案整合四种管控模式,结合500强案例,构建"职能定位-架构设计-权责划分-人才发展"体系,涵盖财务五大模块。通过明确总部与事业部权责边界,提供组织架构等实操框架,旨在平衡财务管控与业务支持,提升效率与风控能力,满足集团财务体系规范化建设需求。

cdfunlove的博客 663

一文带你了解HuggingFace Transformer 理论基础,Transformer 实战,十万字精读

在 Hugging Face 的库中,Pipeline(流水线)是最高层、最易用的推理 API。如果把直接调用 PyTorch 底层代码比作“驾驶手动挡赛车”(需要精细控制离合、油门和换挡),那么 Pipeline 就是一辆开箱即用的“全自动无人驾驶汽车”。你只需要输入目的地(文本),它就能直接把你送到终点(预测结果)。你不需要知道到底该用 BERT 还是 T5。你只需要告诉 Pipeline 你的任务目标文本生成、翻译、问答、图像分类),它就会自动为你匹配一套默认的最佳预训练模型和分词器。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 553

ESP32-C3模组上实现蓝牙BLE配网功能(1)

ESP32-C3模组上实现蓝牙BLE配网功能(1)

phmatthaus的专栏 2279

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

TensorFlow 实现简单的TextCNN(回归)

直接上代码,因为此前都是使用keras,所以在过程中有一些和keras的对比(主要是使用习惯的对比,不是性能)。import tensorflow as tf import pandas as pd import jieba import numpy as np当使用tensorflow的时候,要引用的包就很少了,就一个tensorflow就够用了,不像keras,需要从layers到activa...

coolkid09100的博客 3216

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Python自学篇——你需要的模块(库)没有应该怎么办?

此乃本人学习Python时经常会遇到的问题,亲测有效,如有遗漏还望各位大佬补充 如果你想实现某项功能却又不知道该用哪个模块(库)可以参考以下文章 500个Python模块(库)的详细分类介绍 调用的模块(库)没有会出现红线,下列两种解决办法 一、在设置中找到Project Interpreter选项点击加号,然后搜索需要安装的模块名,如果有点击Install Package安装即可,没有则试...

爱国小白帽 1万+

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

心法利器[4] | tf.keras文本分类小例子

【前沿重器】全新栏目,本栏目主要和大家一起讨论近期自己学习的心得和体会,与大家一起成长。具体介绍:仓颉专项:飞机大炮我都会,利器心法我还有。往期回顾前沿重器[1] | 微软小冰-多轮和情...

baidu_25854831的博客 410

TextCNN实现 --Tensorflow

TextCNN实现 和传统模型的对比 n-grams 当词典比较大时,计算n大于3时代价迅速上升(?) CNN 卷积神经网络可以自动学得单词的很好的表示,而不需要表示整个词典 而且,当卷积核的尺寸大于5时,可以得到类似于5-gram的结果,而且不止限于此,可以包含更多的信息,但是和传统方法比将表示压缩了。 CNN超参数的选择 词的表示 word2vec GloVe one-hot 是否使用ze...

weixin_39584132的博客 712

TextCNN tensorflow实现

1.导入库 import os import numpy as np import tensorflow as tf from tensorflow.contrib import slim 2.定义TextCNN类 class TextCNN(object): def __init__(self): def model(self): def fit(self): def batch_it...

jiang199912的博客 1241

tensorflow1.x(2)如何使用tf.layer和tf.contrib简化代码

tf.layer和tf.contrib是对一些模块比较高级的封装,学会他们的使用可以避免我们在开发的时候重复造轮子 如果单纯用基础算子进行实现一个多层感知机 import tensorflow as tf import numpy as np import matplotlib.pyplot as plt def fc(input_size, hidden_size, layer_cnt, input_var): """ 全连接层实现 :param input_size

qq_42787229的博客 775

TextCNN网络详解(pytorch实现文本分类)

textcnn网络在NLP文档分类任务上有较好的性能,让我们来了解一个TextCNN的网络结构及pytorch代码实现

weixin_64017116的博客 2058

python入门:常用模块—模块,包介绍

是因为路径找不到,proj/settings.py 相当于是crm/views.py的父亲(crm)的兄弟(proj)的儿子(settings.py),settings.py算是views.py的表弟啦,在views.py里只能导入同级别兄弟模块代码,或者子级别包里的模块,根本不知道表弟表哥的存在。Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。就是指相对路径,在python里,导入也可以通过。

m0_59236602的博客 1171

计算机视觉作业(三)Scene Recognition with Bag of Words

一、实验原理 本次实验是基于词袋模型的图像分类技术,利用提取的局部区域的分布对图像进行识别。在图像分类中,词袋模型算法需要通过监督或非监督的学习来获得视觉词典。基于词袋模型的图像分类算法一般分为四步,首先对图像进行局部特征向量的提取(本次实验采用HOG);其次利用上一步得到的特征向量集,抽取其中有代表性的向量,作为单词,形成视觉词典(本实验采用K-means聚类算法);然后对图像进行视觉单词的统计,一般判断图像的局部区域和某一单词的相似性是否超过某一阈值,这样即可将图像表示成单词的分布,即完成了图像的表示

sinat_41942180的博客 4432

【错误解决】tf.contrib.layers.xavier_initializer的tensorflow2.0版本

问题描述 tensorflow1.0版本中的 tf.contrib.layers.xavier_initializer() 可以替换为tensorflow2.0版本中的 tf.keras.initializers.glorot_normal (Xavier and Glorot are 2 names for the same initializer algorithm) 编译器相关算法完全相同 if dtype is important for some compatibility.

wongwongwong 7433
上一篇: 初学者的CNN搭建示例(torch,cifar10数据集)
下一篇: 接上篇,CNN在短文本分类中的应用遇到的一些问题/GPU/cuda/tensorflow
滚滚的纸盒子
博客等级 码龄10年 136粉丝 31原创
评论 12
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值