Deeplearning4j 实战 (13):基于TextCNN的文本分类实现

2023-10-26

Eclipse Deeplearning4j GitChat课程Deeplearning4j 快速入门_专栏
Eclipse Deeplearning4j 系列博客万宫玺的专栏_wangongxi_CSDN博客
Eclipse Deeplearning4j Githubhttps://github.com/eclipse/deeplearning4j

在之前的文章中,我们基于Embedding+LSTM的结构实现了一个文本分类的应用。本质上,这是循环神经网络Many-to-One架构下的一种应用。在那种结构中,我们将Embedding后的词向量依次投入到LSTM Cell中,循环结构依照时序逐步计算并且获取到整个文本的语义(向量化表示),在此基础上对文本的语义向量进行SoftMax,得到分类标签。这种基于循环神经网络的分类结构最主要的问题在于长距离依赖的问题。尽管我们可以采用LSTM或者GRU这种改进后的Cell,但是当文本较长的时候依然会存在这样的问题。对此我们可以运用一些trick来解决这些问题,比如Truncated-BPTT来训练循环神经网络,这里我们不讨论这些trick的细节,我们希望从另一个角度来重新审视文本分类的问题。这就是这篇文章讨论的重点:TextCNN。

在开始描述TextCNN的细节之前,我们先回顾下基于词袋模型(Bag-Of-Words)+ 分类器来解决文本分类的传统方法。词袋模型用于结构化文本特征。一般我们对所有语料切词后,统计下词空间的维度(一般会有几万甚至上百万),然后用One-Hot的方式对语料进行编码,每个词会占据这个达到几万甚至几十万维的向量中的一个位置。它的值可以是1或者0,也可以是一些类似TF-IDF的算法值。这个特征表示方式的明显缺陷在于维度高,并且丢失了时序信息。我们重点看第二点。针对于时序信息的丢失,直接的解决方案就是采用N-gram的语言模型进行扩充。一般,这里的N可以取2,3,4就可以了。语言模型是通过“绑定”连续的几个词来变相解决时序问题的一种方式,但毫无疑问,加入语言模型后的词空间维度又将上升,这对接下来分类器的训练会造成很大的影响,无论是存储还是算力都会有较大的消耗。

卷积神经网络(CNN)最成功的应用是在机器视觉领域的一些问题,但对于自然语言处理的问题同样适用。我们可以将语料中的词进行向量化之后,构成一个大的二维矩阵(每一个矩阵就代表一条语料)。我们将kernel size处理成N x VectorSize的大小,其中N代表N-gram语言模型中的N元的含义,这样就可以通过卷积操作抽取语料中的文本信息。当然,实际的操作可以是多尺度的kernel size同时对语料进行语义抽取,最终merge在一起就可以得到在不同维度语言模型下的文本语义。这就是TextCNN这篇文章的核心思想(https://arxiv.org/pdf/1408.5882.pdf)。下面看下论文中的截图:

截图的结构是Conv + Max-Pool + MLP-Classifier的经典结构。我们重点看Conv层的输入。这是一个9 x 6 x 1(Height x Width x Channel)的矩阵,该条训练语料中一共包含9个词,每个词的词向量维度是6。我们可以把这条语料矩阵化后的表示方式认为是一张9 x 6的灰度图。卷积操作后的featureMap的数量这里我们不讨论,这个超参数在实践的时候调优即可。我们需要关注的是每个featureMap其实是一个M x 1的向量。M的大小取决于stride纵向的步长,而featureMap的Width等于1显然是stride的横向步长等于vectorSize的结果。这在上面的阐述中我们已经有所提及。下面我们基于Deeplearning4j来搭建这样的一个TextCNN网络

public static ComputationGraph getTextCNN(final int vectorSize, final int numFeatureMap,
                                            final int corpusLenLimit){
        ComputationGraphConfiguration config = new NeuralNetConfiguration.Builder()
                        .weightInit(WeightInit.RELU)
                        .activation(Activation.LEAKYRELU)
                        .updater(new Adam(0.01))
                        .convolutionMode(ConvolutionMode.Same)
                        .l2(0.0001)
                        .graphBuilder()
                        .addInputs("input")
                        .addLayer("2-gram", new ConvolutionLayer.Builder()
                            .kernelSize(2,vectorSize)
                            .stride(1,vectorSize)
                            .nIn(1)
                            .nOut(numFeatureMap)
                            .build(), "input")
                        .addLayer("3-gram", new ConvolutionLayer.Builder()
                            .kernelSize(3,vectorSize)
                            .stride(1,vectorSize)
                            .nIn(1)
                            .nOut(numFeatureMap)
                            .build(), "input")
                        .addLayer("4-gram", new ConvolutionLayer.Builder()
                            .kernelSize(4,vectorSize)
                            .stride(1,vectorSize)
                            .nIn(1)
                            .nOut(numFeatureMap)
                            .build(), "input")
                        .addVertex("merge", new MergeVertex(), "2-gram", "3-gram", "4-gram")
                        .addLayer("globalPool", new GlobalPoolingLayer.Builder()
                            .poolingType(PoolingType.MAX)
                            .dropOut(0.5)
                            .build(), "merge")
                        .addLayer("out", new OutputLayer.Builder()
                            .lossFunction(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
                            .activation(Activation.SOFTMAX)
                            .nIn(300)
                            .nOut(2)
                            .build(), "globalPool")
                        .setOutputs("out")
                        .setInputTypes(InputType.convolutional(corpusLenLimit, vectorSize, 1))
                        .build();

           ComputationGraph net = new ComputationGraph(config);
           net.init();
           return net;
    }

我们来剖析一下这段建模逻辑。注意下,我这次用的Deeplearning4j的版本是1.0.0-beta2,部分API和之前的0.8.0版本有微调,需要注意下。

.setInputTypes(InputType.convolutional(corpusLenLimit, vectorSize, 1))

这段设置我们可以看到输入的结构。这和我们之前说的是类似的,corpusLenLimit x vectorSize代表了语料向量化矩阵的Height x Width。至于通道数,这里就是1。

.addLayer("2-gram", new ConvolutionLayer.Builder()
                            .kernelSize(2,vectorSize)
                            .stride(1,vectorSize)
                            .nIn(1)
                            .nOut(numFeatureMap)
                            .build(), "input")

这段设置的目的从Layer的名称为“2-gram”就可以看出这是基于2元语言模型来抽取语料的时序信息。卷积核的size是2 x vectorSize,步长stride为1 x vectorSize可以保证输出的featureMap是一个(corpusLen - 1)x 1的向量。corpusLen代表文本语料切词后的长度。其他的两个卷积操作是类似的,不过是提取的3-gram和4-gram的信息。

.addVertex("merge", new MergeVertex(), "2-gram", "3-gram", "4-gram")

这个Merge层比较重要。之前的三个卷积层都输出了numFeatureMap数量的feature map。这个Merge层就是将其合并在一起构成了3 x numFeatureMap数量的全局的feature map。

.addLayer("globalPool", new GlobalPoolingLayer.Builder()
                            .poolingType(PoolingType.MAX)
                            .dropOut(0.5)
                            .build(), "merge")

GlobalPoolingLayer和之前文章中介绍的SubsamplingLayer有相似的地方,都是做池化。但是它们也有不同的地方,就是GlobalPoolingLayer对于feature map会直接从矩阵(TextCNN实际就是一个向量)中抽取值最大的元素(如果是Max-Pool的话)作为池化结果。实际完成的是: [miniBatchSize, channels, height, width] -> 2d output [miniBatchSize, channels]的计算。因此在经过GlobalPoolingLayer的计算后,TextCNN输出的其实就是一个3 x numFeatureMap的向量。

以上就是对TextCNN结构中的一些关键部分的剖析。下面我们来构建训练数据集。语料部分和我之前在基于LSTM做文本分类的那篇博客用的语料是一样的。这里直接把图贴一下:

截图中涉及两个文件,一个是语料本身(已经用jieba切过词)并shuffle过,另一个是对应的标注信息。我们来看下数据集的构建。

private static DataSetIterator getDataSetIterator(WordVectors wordVectors, int minibatchSize,
                    int maxSentenceLength){
        String corpusPath = "comment/corpus.txt";
        String labelPath = "comment/label.txt";
        String line;
        List<String> sentences = new LinkedList<>();
        List<String> labels = new LinkedList<>();
        try(BufferedReader br = new BufferedReader(new FileReader(corpusPath))){
            while((line = br.readLine()) != null)sentences.add(line);
        }catch(Exception ex){
            ex.printStackTrace();
        }
        //
        try(BufferedReader br = new BufferedReader(new FileReader(labelPath))){
            while((line = br.readLine()) != null)labels.add(line);
        }catch(Exception ex){
            ex.printStackTrace();
        }
        //
        LabeledSentenceProvider sentenceProvider = new CollectionLabeledSentenceProvider(sentences, labels);
        TokenizerFactory tokenizerFactory = new DefaultTokenizerFactory();
        tokenizerFactory.setTokenPreProcessor(new CommonPreprocessor());
        System.out.println("DataSetIter 2 Current Num of Classes:" + sentenceProvider.numLabelClasses());
        System.out.println("DataSetIter 2 Total Num of samples: " + sentenceProvider.totalNumSentences());
        //
        return new CnnSentenceDataSetIterator.Builder(Format.CNN2D)
                        .sentenceProvider(sentenceProvider)
                        .wordVectors(wordVectors)
                        .minibatchSize(minibatchSize)
                        .maxSentenceLength(maxSentenceLength)
                        .tokenizerFactory(tokenizerFactory)
                        .useNormalizedWordVectors(false)
                        .build();
    }

这部分的逻辑主要可以分为两个部分。第一个是分别从语料文件和标注文件中读取所有的记录。第二个部分则是使用Deeplearning4j内置的CnnSentenceDataSetIterator工具类构建训练数据集。这里需要注意一点,wordVectors这个对象实例其实是我事先已经使用Word2Vec训练好的模型实例。我们可以通过下面的逻辑来加载已经训练好的模型:

WordVectors wordVectors = WordVectorSerializer.loadStaticModel(new File("w2v.mod"));

最后,我们把完整的训练逻辑贴一下。

        final int batchSize = 32;
        final int corpusLenLimit = 256;
        final int vectorSize = 128;
        final int numFeatureMap = 100;
        final int nEpochs = Integer.parseInt(args[0]);
        //读取预先训练好的Word2Vec的模型,并且构建训练和验证数据集
        WordVectors wordVectors = WordVectorSerializer.loadStaticModel(new File("w2v.mod"));
        DataSetIterator trainIter = getDataSetIterator(wordVectors, batchSize, corpusLenLimit);
        DataSetIterator testIter = getDataSetIterator(wordVectors, 1, corpusLenLimit);
        //生成TextCNN模型,并打印模型结构信息
        ComputationGraph net = getTextCNN(vectorSize, numFeatureMap, corpusLenLimit);
        System.out.println(net.summary());
        //使用单条记录并且打印每一层网络的输入和输出信息
        INDArray input = testIter.next().getFeatures();
        System.out.println(input.shapeInfoToString());
        Map<String,INDArray> map = net.feedForward(input, false);
        for( Map.Entry<String, INDArray> entry : map.entrySet() ){
            System.out.println(entry.getKey() + ":" + entry.getValue().shapeInfoToString());
            System.out.println();
        }
        //训练开始。。。
        System.out.println("Starting training");
        net.setListeners(new ScoreIterationListener(1));
        for (int i = 0; i < nEpochs; i++) {
            net.fit(trainIter);
            System.out.println("Epoch " + i + " complete. Starting evaluation:");
            Evaluation evaluation = net.evaluate(trainIter);
            trainIter.reset();
            testIter.reset();
            System.out.println(evaluation.stats());
        }

这段建模的主逻辑大致可以分为三个部分。首先是超参数的定义。这里我们直接把batchSize、vectorSize等参数进行硬编码,用户可以根据的实际需要进行定制。其次是基于之前提到的数据集构建逻辑来读取文本中的语料和标注并且生成完整的训练语料。再者则是生成TextCNN网络模型并且为了更好地分析模型,我们从测试集中选取了一条记录并通过打印在前向传播过程中每一层网络的输入和输出来得到网络的信息。最后一部分则是和之前文章中相似,进行模型训练并在每一轮训练后进行模型准确性的评估。我们先来看下模型的基本信息截图。

==========================================================================================================================================================================================================================================================
VertexName (VertexType)                 nIn,nOut  TotalParams ParamsShape                             Vertex Inputs                 
==========================================================================================================================================================================================================================================================
input (InputVertex)                     -,-       -           -                                       -                             
2-gram (ConvolutionLayer)               1,100     25700       W:{100,1,2,128}, b:{1,100}              [input]                       
3-gram (ConvolutionLayer)               1,100     38500       W:{100,1,3,128}, b:{1,100}              [input]                       
4-gram (ConvolutionLayer)               1,100     51300       W:{100,1,4,128}, b:{1,100}              [input]                       
merge (MergeVertex)                     -,-       -           -                                       [2-gram, 3-gram, 4-gram]      
globalPool (GlobalPoolingLayer)         -,-       0           -                                       [merge]                       
out (OutputLayer)                       300,2     602         W:{300,2}, b:{1,2}                      [globalPool]                  
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            Total Parameters:  116102
        Trainable Parameters:  116102
           Frozen Parameters:  0
==========================================================================================================================================================================================================================================================

这是TextCNN的基本信息截图。包括每一层网络的名称以及超参数的量。下面是我们选取一条记录后,通过TextCNN每一层前向传播过程中的输入输出数据的截图。

Rank: 4,Offset: 0
 Order: c Shape: [1,1,64,128],  stride: [8192,8192,128,1]
3-gram:Rank: 4,Offset: 0
 Order: c Shape: [1,100,64,1],  stride: [64,64,1,1]

input:Rank: 4,Offset: 0
 Order: c Shape: [1,1,64,128],  stride: [8192,8192,128,1]

globalPool:Rank: 2,Offset: 0
 Order: c Shape: [1,300],  stride: [1,1]

4-gram:Rank: 4,Offset: 0
 Order: c Shape: [1,100,64,1],  stride: [64,64,1,1]

merge:Rank: 4,Offset: 0
 Order: c Shape: [1,300,64,1],  stride: [19200,64,1,1]

2-gram:Rank: 4,Offset: 0
 Order: c Shape: [1,100,64,1],  stride: [64,64,1,1]

out:Rank: 2,Offset: 0
 Order: c Shape: [1,2],  stride: [1,1]

我们先单独看2-gram、3-gram、4-gram这几层的输出数据结构。可以看到,都是1x100x64x1的4维张量。第一个1代表的是mini-batch,因为我取的是1条数据,所以这里就是1,否则会随着batch的数量变化。这里的100代表的是Channel的数量,实际上也就是feature map的数量。64代表的是该条语料中有64 + 1 = 65 个词。最后一个1则是代表在经过卷积操作后,feature map的Width等于1,原因上面已经有过分析。接下来我们来看下merge这层的输出。这是一个1x300x64x1的4维张量。很显然,这是将上面三个卷积层输出也就是3个1x100x64x1的张量合成为一个1x300x64x1的张量。在globalPool之后,输出是一个1x300的向量。最后在输出层就是基于这个300维的向量进行分类。

我们来看下训练20轮后的指标。

从截图中我们可以看到20轮训练后达到了相对不错的指标。这个指标和之前基于LSTM的模型在20轮后结果比较起来相差不大。当然这样的比较没有太大的意义,毕竟两种网络结构并没有在一个相对等价的条件下进行比较的,仅供大家参考。

最后总结下这次的工作。在这篇文章中,我们给出了基于CNN的文本分类的解决方案。应当说,TextCNN是基于N-gram语言模型与神经网络结合的一种文本分类工具。对于传统2D-CNN结构的神经网络来说,时序的信息是比较难抽取的。因此,在TextCNN的论文中,作者其实是想通过语言模型来弥补这个缺陷。当然需要指出的是,这样的做法其实是比较有效的,尤其是针对文本分类的任务来说。文本分类的任务其实很多时候就是局部的两三个词的信息就可以决定了这条语料的类别,因此基于语言模型来做确实是一种较好的思路。需要指出的是,我们这里用的词向量是预先用Word2Vec训练好的,而不是直接随着建模的时候自动训练出来的。理论上,在训练的时候加入Embedding会使得最后的分类结果进一步提升,这在论文的结论中也有所提及,有兴趣的朋友可以自行尝试。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Deeplearning4j 实战 (13):基于TextCNN的文本分类实现 的相关文章

  • 正则表达式奇/偶数

    我有一个正则表达式问题 我不知道该怎么做 它必须匹配开头包含任意数量的 a 的所有字符串 如果 a 的数量为偶数 则匹配单个 0 如果 a 的数量为奇数 则匹配单个 1 如何跟踪偶数 奇数 Sample aaa1 aaaa0 a aa 1
  • 如何生成带logo的二维码?

    我正在为 Android 设备开发应用程序 我想生成带有徽标的二维码 With ZXing I know how to generate simple QR codes like this one But I want to generat
  • Java 拖放图像并在拖动时显示图像缩略图

    我有一个带有图像节点的网格布局 我想在我的应用程序中添加 dnd 功能 例如 当我将图像节点拖放到目标 JPanel 时 进行一些操作 例如以原始大小显示 删除等 我已经实现了这与一种使用 Transferhandler 的方法和一种使用
  • Glide:如何使用 Glide v4 调整 gif 大小并将其另存为文件?

    我想调整 gif 文件的大小并保存它 我尝试使用一些建议的方法 但这些方法给出了错误 后来我知道有些方法在 Glide 中已被弃用v4 byte bytes Glide with context asGif load url toBytes
  • Java程序在没有定义main方法的情况下如何运行?

    我正在浏览一些 Java 源代码并注意到main方法未定义 Java如何编译源码却无从下手 The main方法仅在 Java 虚拟机执行代码时使用 没有 a 则无法执行代码main方法 但仍然可以编译 编译代码时 通常在命令行上指定一组文
  • Java 中修剪字符串的可能前缀

    I have String str 我想从中提取不包括可能的前缀的子字符串 abc 我想到的第一个解决方案是 if str startsWith abc return str substring abc length return str
  • Checkstyle 规则防止调用某些方法和构造函数

    是否可以使用 Checkstyle 来禁止使用某些使用系统相关默认值 区域设置 字符集等 的构造函数或方法 我更喜欢强制执行一项政策 程序员应该明确了解系统相关的值 所以我认为以下物品是危险的 all the constructors of
  • antisamy 解析器强制关闭标签

    我使用 Antisamy 来验证 HTML 我的政策允许 iframe 例如 YouTube 视频 问题是 如果标签为空 像这样 清洗后会是这样的 但它应该有正常的结束标签 这会破坏之后页面上的所有内容 我已经将指令设置为使用大部分 HTM
  • Selenium 2:中断页面加载

    我在使用 FirefoxDriver 使用 Selenium 2 0b3 Java API 单击按钮时遇到问题 单击该按钮会将表单发送到网络服务器 然后浏览器会因表单提交而进入新页面 当使用 element click 单击某个元素时 se
  • 带有 Spock Stub 的泛型

    我无法为泛型类编译 Spock 存根 构造函数的签名如下 SomeClass SerSup
  • 当从搜索表单动态构建 WHERE 子句时,如何防止 SQL 注入?

    我知道在 Java 中保护 SQL 查询免受 SQL 注入的唯一真正正确的方法是使用准备好的语句 然而 这样的语句要求基本结构 选择的属性 连接的表 WHERE条件的结构 不会改变 我这里有一个 JSP 应用程序 其中包含一个带有大约十几个
  • Java TreeMap时间复杂度-lowerKey

    时间复杂度是多少lowerKey Java实现中的操作TreeMap 我认为它是 log n 但我在文档中找不到它 更基本操作的复杂性已有详细记录 此实现提供了有保证的 log n 时间成本 containsKey 获取 放置和删除操作 顺
  • 需要在 java api 中的 Solr 搜索中搜索文本及其周围的几行

    我正在使用 solr 7 7 2 并且我使用 solrj 在 Solr 中编写了一个 Java 程序 该程序在一个巨大的文本文件中搜索单词 我使用以下代码来显示代表整个文本的搜索结果 SolrQuery params new SolrQue
  • 如何从java程序中编译.java文件[重复]

    这个问题在这里已经有答案了 可能的重复 从 Java 内部编译外部 java 文件 https stackoverflow com questions 10889186 compiling external java files from
  • int 到 long 赋值

    我一直在尝试这个 int 和 long 转换 我尝试分配一个int变量为along多变的 代码如下 public static void main String args int i 1024 long j i long k i i i i
  • 策略模式的现实示例

    我一直在读关于OCP原理 http en wikipedia org wiki Open closed principle以及如何使用策略模式来实现这一目标 我打算尝试向几个人解释这一点 但我能想到的唯一例子是根据 订单 的状态使用不同的验
  • GAE、JPA、XG 事务、实体组过多异常

    我知道 GAE 上的 XG 交易有 5 个实体组的限制 但我认为我在一项交易中仅使用 3 个组 商品 类别 商品类别 但仍然遇到此异常 引起原因 java lang IllegalArgumentException 在单个事务中对太多实体组
  • 遍历多行字符串

    我得到一些数据 def data some useless text n even more n finally interesting text 我怎样才能得到其中 有趣的部分 所以基本上所有行都不是以 开头的 Groovy 的一种选择是
  • Activity 在 Android 上创建两次

    首先 我是 Android 开发新手 所以请耐心等待 我将从用户界面开始 我有一个按钮 一旦您点击它 就会启动一个活动以获取结果 public class GUIActivity extends Activity Override publ
  • 从 Web 服务器异步调用应用程序

    我有一个用 Spring 制作的 在 Tomcat 上运行的 Web 应用程序 在同一台机器上有一个普通的 Java 应用程序 我想通过从Web服务器调用Java应用程序来执行它 但我想让应用程序不会使用服务器的资源 它涉及分类器的训练 因

随机推荐

  • VScode调试php文件(详细且简单易操作)

    之前也不懂 看了网上好多帖子 按照它们步骤操作一遍之后 还是不行 头都大了 现在懂了 原来几步就搞定了 被它们搞得这么复杂 又是配置这个文件 又是配置那个文件 1 下载XAMPP Download XAMPP apachefriends o
  • Java程序员面试常问试题大全

    Java程序员面试常问试题大全 1 面向对象的特征有哪些方面 1 抽象 抽象就是忽略一个主题中与当前目标无关的那些方面 以便更充分地注意与当前目标有关的方面 抽象并不打算了解全部问题 而只是选择其中的一部分 暂时不用部分细节 抽象包括两个方
  • 详解 cryptogen 的内容和配置

    目录 1 cryptogen 模块命令说明 2 cryptogen 模块的配置文件 3 cryptogen 实例 创建测试配置文件 4 Fabric 证书文件的结构 cryptogen 模块主要用来生成组织结构和账号相关的文件 任何 Fab
  • 【react】实现数据双向绑定之不用柯里化的方式

    直接给onChange事件绑定一个箭头函数 这个箭头函数的参数就是event 在箭头函数内再调用saveFormData方法 saveFormData方法里面this setState dataType value
  • 学Python该看什么书?12本精华好书推荐!

    为了让更多想通过看书来学习Python的人能够把时间花在刀刃上 小编总结了Python目前所有热门方向上我个人觉得性价比很高 值得一看的书籍 今天小编来分享给大家 一 Python新手入门 新手学Python的话我推荐这本 Python编程
  • java:面向对象(多态中成员的特点)。

    这次我们说说多态中成员的特点 我们写这样一个代码 class Fu void method1 System out println fu method1 void method2 System out println fu method 2
  • 秒解小米bl锁 无需等待时间_小米全新系统曝光:小米9推送Android Q体验版

    点击上方蓝字订阅每日最新国产手机资讯 对于米粉来说 MIUI系统是他们坚持使用小米手机的重要原因 就在今天上午 MIUI官方微博发布消息 小米9的MIUI Android Q Beta优先体验版现已推送 已获得测试资格的朋友可以升级体验 据
  • 大厂笔试真题

    1 复数相乘 2 K个一组翻转链表 include
  • 浅谈 Python中if __name__ == ‘__main__‘:的工作原理

    为了理解if name main 的工作原理 我们需要先了解Python中的特殊变量 name 每个Python模块都有一个内置的变量 name 这个变量的值取决于如何执行模块 如果模块是被直接运行的 例如 你使用命令python mysc
  • 「网络安全」如何搭建MySQL恶意服务器读取文件?

    前言 注 本文不涉及对MySQL协议报文研究 仅讲解原理 并且做部分演示 搭建MySQL恶意服务器读取文件这件事 虽然直接利用门槛较高 但是由于在网上看到了一种比较新颖的利用方式 利用社会工程学引诱用户连接MySQL进而读取用户文件 个人觉
  • Day【4】字符串解码

    原题链接 思路 对于字符串k encoding 对于这样的形式 我们要加encoding重复k次 从左向右扫描字符串 如果说遇见字符 就直接将该字符添加到结果中 如果说 遇见 k encoding 的形式 我们首先要做的是就是将k和enco
  • GCC参数详解

    gcc and g 分别是gnu的c c 编译器 gcc g 在执行编译工作的时候 总共需要4步 1 预处理 生成 i的文件 预处理器cpp 2 将预处理后的文件不转换成汇编语言 生成文件 s 编译器egcs 3 有汇编变为目标代码 机器代
  • 9.OB4.0调用存储过程通过临时表返回多行记录

    MYSQL存储过程返回多行 1 表数据准备 drop table if exists t1 drop table if exists t2 drop table if exists t3 create table t1 id varchar
  • 任何程序都必须加载到什么中才能被cpu执行

    任何程序都必须加载到内存中才能被cpu执行 内存是计算机中的重要部件之一 它是外存与cpu进行沟通的桥梁 计算机中所有程序的运行都在内存中进行 内存性能的强弱影响计算机整体发挥的水平 任何程序都必须加载到内存中才能被cpu执行 学习视频分享
  • WPF 性能优化建议

    本章讲述 WPF 性能优化建议 20180930 WPF性能优化问题 运行软件发现CPU使用率很大 80 95 程序中含有委托 线程 定时器的处理 之前优化时 主要优化线程和定时器相关线程方面的处理 但是效果甚微 无意间看到博客中说程序界面
  • Android onInterceptTouchEvent与onTouchEvent调用关系

    概述 onInterceptTouchEvent 是用来拦截Touch事件 ViewGroup有 View没有 onTouchEvent 是Touch事件 ViewGroup与View都有 实例讲解 当一个Touch事件发生后 会由父布局开
  • connect错误:no route to host

    linux下 socket 用vmware装了两个虚拟机 分别运行客户端和服务器端 客户端连接的时候报错 connect error no route to host 但是在同一虚拟机下运行正常 我检查了socket返回值 正常 地址和端口
  • U-boot引导流程分析一

    U Boot 全称 Universal Boot Loader 即通用引导程序 是遵循GPL条款的开放源码项目 它的源码目录 编译形式与Linux内核很相似 事实上 不少U Boot源码就是相应的Linux内核源程序的简化 尤其是一些设备的
  • linuxptp源码研究

    目录 1 检查网卡是否支持相应的时间戳 2 linuxptp的目录架构 3 ptp4l的大致流程分析 4 gptp协议对应的sync follow up delay request delay response消息在代码的位置 5 slav
  • Deeplearning4j 实战 (13):基于TextCNN的文本分类实现

    Eclipse Deeplearning4j GitChat课程 Deeplearning4j 快速入门 专栏Eclipse Deeplearning4j 系列博客 万宫玺的专栏 wangongxi CSDN博客Eclipse Deeple