精华内容
下载资源
问答
  • Stanford Topic Modeling Toolbox0.4.0翻译

    千次阅读 2016-04-13 17:10:11
    本文内容翻译自 http://nlp.stanford.edu/software/tmt/tmt-0.4/ 斯坦福大学的TMT(Topic Modeling Toolbox)0.4.0
    本文内容翻译自 http://nlp.stanford.edu/software/tmt/tmt-0.4/
    推荐一本书《LDA漫游指南》,对LDA的原理、应用均进行了详尽的介绍。
    目前斯坦福大学的TMT(Topic Modeling Toolbox)已经更新至0.4.0版本。笔者最近在研究这个小工具,特此做一些笔记,在使用中遇到一些问题也进行说明。
    这个小工具是scala写的,但是本机不需要安装scala,需要安装jre1.5以上版本,笔者使用的是1.7.79版本。
    按照官网的说明,运行一个最简单的例子:
    首先下载tmt-0.4.0.jar,example-0-test.scalapubmed-oa-subset.csv,这三个文件要放在同一个文件夹里。第一个文件是一个程序的jar包,也就是程序的主体;第二个文件是程序所运行的脚本,定义了处理的数据和显示结果等;第三个文件就是进行操作的数据了。
    以下就是主界面,点击File——>open script...打开脚本,比如之前下载的example-0-test.scala


    这些按钮中,Edit script可以修改脚本,比如修改处理的数据集。修改完成之后,按run就可以了。



    需要注意的是,在官网下载的示例数据集pubmed-oa-subset.csv中,存在类似中文的乱码,这些乱码会导致报错,所以要把这些乱码删除。至于网上说的要把字符集修改成utf-8,笔者没有遇到这样的问题。


    准备数据集

    本例中使用的代码是example-1-dataset.scala文件

    从一个CSV文件提取并且准备文本的过程可以被看做一个流水线:一个CSV文件经过一系列过程最终成为可以用来训练模型的结果。这里就是pubmed-oa-subset.csv数据文件的案例:

    01.val source = CSVFile("pubmed-oa-subset.csv") ~> IDColumn(1);
    02. 
    03.val tokenizer = {
    04.SimpleEnglishTokenizer() ~>            // tokenize on space and punctuation
    05.CaseFolder() ~>                        // lowercase everything
    06.WordsAndNumbersOnlyFilter() ~>         // ignore non-words and non-numbers
    07.MinimumLengthFilter(3)                 // take terms with >=3 characters
    08.}
    09. 
    10.val text = {
    11.source ~>                              // read from the source file
    12.Column(4) ~>                           // select column containing text
    13.TokenizeWith(tokenizer) ~>             // tokenize with tokenizer above
    14.TermCounter() ~>                       // collect counts (needed below)
    15.TermMinimumDocumentCountFilter(4) ~>   // filter terms in <4 docs
    16.TermDynamicStopListFilter(30) ~>       // filter out 30 most common terms
    17.DocumentMinimumLengthFilter(5)         // take only docs with >=5 terms
    18.}

    输入的数据文件(在代码变量中)是一个指向你先前下载的CSV文件的指针,随后我们将经过一系列的变形、过滤或者其他与数据交互的操作。第一行代码中,制定了TMT使用第一列(column 1)的值作为记录ID,这对文件中每一条记录都是独一无二的标志。如果你的sheet中的记录ID不在第一列,就把上文代码第一行中的1改成你自己的列数。如果你的sheet没有记录ID这一列,你可以删掉“~> IDColumn(1)”,TMT会用文件的行号作为记录ID。
    如果你的CSV文件第一行包含了列名,你可以删除第一行代码,改用Drop步骤:

    1.val source = CSVFile("your-csv-file.csv") ~> IDColumn(yourIdColumn) ~> Drop(1);

    分词Tokenizing

    第一步是定义分词器(tokenizer),以将数据集中包含文本的单元转化成话题模型分析的term。从第三行到第七行定义的分词器,制定了一系列的将一个字符串转化成一系列字符串的变形操作。
    笔者注:每两个步骤之间需要有~>符号,最后一个不需要
    首先,我们用SimpleEnglishTokenizer()去除单词结尾的标点符号,然后用空白符(tab、空格、回车等)将输入文本分解。如果你的文件已经进行过清洗了,你也可以用 WhitespaceTokenizer()。或者,你可以用RegexSplitTokenizer("your-regex-pattern"),通过正则表达式定制你自己的分词器。
    CaseFolder随后被用来将每个单词变成小写,这样“The”、“tHE”、“THE”都变成了“the”。CaseFolder通过把所有字符变成小写形式,减少了单词的不同形式。
    下面,使用WordsAndNumbersOnlyFilter(),纯标点、非单词非数字的字符会从产生的分词后的文档列表中删除。
    最后,使用MinimumLengthFilter()将短于3个字符的term去除
    作为可选功能,token可以用 PorterStemmer()在MinimumLengthFilter()之前提取词干。提取词干在信息检索中是一种常用的技术,将比如多元词转化成简单的常用term(“books”和“book”都映射成“book”)。但是,提取词干并不总对话题建模有益,因为有时提取词干会把一些term合并在一起,但是他们最好还是分开,而且同一个单词的变形会变成同一个话题。
    (笔者注:对Porter Stemmer有兴趣的话,可以去官网或者其他文章了解其原理)
    如果你想要去除标准的英语停用词(stop word),可以在分词器的最后一步用StopWordFilter("en")(笔者注:如果使用了这一步,那么这些很常用的停用词都会被过滤掉,在下面的步骤中,被过滤掉的前30个常用单词就很可能是有用单词了)


    在一个CSV文件中提取并且分词Extracting and tokenizing text in a CSV file

    定义好分词器之后,我们就可以用它从CSV文件中合适的列中提取文本了。如果你的文本数据存在于一列中(这里是第四列):

    1.source ~> Column(4) ~> TokenizeWith(tokenizer)以上的代码会加载CSV文件中的第四列文本
    如果你的文本不止存在于一列中:

    1.source ~> Columns(3,4) ~> Join(" ") ~> TokenizeWith(tokenizer)以上的代码会选择第三和第四列,然后把他们的内容用一个空格连在一起。


    寻找有意义的单词(Finding meaningful words)

    话题建模对于有意义单词的模式提取(extracting patterns)非常有用,但是在决定什么单词是有意义时并不一定奏效。通常,使用常见的单词比如“the”,并不代表着文档之间的相似性。为了在有意义的单词中提取模式,我们使用一系列的标准启发式算法:

    1.... ~>
    2.TermCounter ~>
    3.TermMinimumDocumentCountFilter(4) ~>
    4.TermDynamicStopListFilter(30) ~>
    5....
    上面的代码去除了在少于四篇文档中出现的term(因为很少见的单词几乎不对文档相似度做出贡献),还有在文本库中最常见的30个单词(因为太普遍的单词同样对文档相似度不做出贡献,他们通常被定义为停用词)。当你在处理很大或者很小(少于几千单词的文档)时,这些值可能需要更新。
    如果你有一个你想要出去的停用词的详细列表,你可以像这样额外增加一个过程:
    TermStopListFilter(List("positively","scrumptious")). 这里,在引号的List里添加你需要过滤的单词。记住,TermStopListFilter 运行在文档被分词之后,所以你提供的List要和你的分词器输出保持一致,就是说,如果你的分词器包括了CaseFolder和PorterStemmer,过滤的单词必须也要是小写的和词干。
    TermCounter步骤首先必须计算下一步骤需要的一些统计。这些数据存储在元数据中,使得任何下游步骤可以使用这些数据。这些步骤也会在硬盘上CSV文件的同一个文件夹下产生缓存文件,以保存文档数据。文件名会以CSV文件的名称开头,并且会包含流水线的标记"term-counts.cache"。

    去除空文档(Removing Empty Documents)

    数据集中的一些文档可能会丢失或者是空的(一些单词可能在最后一步被过滤掉)。可以通过使用DocumentMinimumLengthFilter(length) 在训练中舍弃一些文档,去除短于特定长度的文档。

    组合起来(Putting it all together)

    运行example1 (example-1-dataset.scala)。这个程序会首先加载数据流水线,然后打印加载数据集的信息,包括数据集的标志和文本库中的30个停用词。(注意在PubMed,因为“gene”被广泛使用所以被过滤掉了)

    学习一个话题模型

    这个例子展示了如何用你上面准备的数据集进行LDA训练。
    
    这个例子的代码在example-2-Ida-learn。scala里。


    载入数据文件(Load the data file

    01.val source = CSVFile("pubmed-oa-subset.csv") ~> IDColumn(1);
    02. 
    03.val tokenizer = {
    04.SimpleEnglishTokenizer() ~>            // tokenize on space and punctuation
    05.CaseFolder() ~>                        // lowercase everything
    06.WordsAndNumbersOnlyFilter() ~>         // ignore non-words and non-numbers
    07.MinimumLengthFilter(3)                 // take terms with >=3 characters
    08.}
    09. 
    10.val text = {
    11.source ~>                              // read from the source file
    12.Column(4) ~>                           // select column containing text
    13.TokenizeWith(tokenizer) ~>             // tokenize with tokenizer above
    14.TermCounter() ~>                       // collect counts (needed below)
    15.TermMinimumDocumentCountFilter(4) ~>   // filter terms in <4 docs
    16.TermDynamicStopListFilter(30) ~>       // filter out 30 most common terms
    17.DocumentMinimumLengthFilter(5)         // take only docs with >=5 terms
    18.}

    这个代码片段和之前的一样,它从示例数据集中提取并且准备了文本。


    选择训练LDA模型的参数(Select parameters for training an LDA model

    1.// turn the text into a dataset ready to be used with LDA
    2.val dataset = LDADataset(text);
    3. 
    4.// define the model parameters
    5.val params = LDAModelParams(numTopics = 30, dataset = dataset);

    这里你可以指定一定数量想要学习的topic。你也指定可以指定LDA模型使用的Dirichlet term和 topic smoothing参数,这些参数在第五行作为LDAModelParams额外的参数提供给构造函数。在默认情况下,第五行等价于已经设定了termSmoothing=SymmetricDirichletParams(.1) 和topicSmoothing=SymmetricDirichletParams(.1) 
    笔者注:在我下载的脚本中是这样一段代码,val params = LDAModelParams(numTopics = 30, dataset = dataset,topicSmoothing = 0.01, termSmoothing = 0.01); 这样把参数写的更加清晰了

    训练符合文档的模型(Train the model to fit the documents)

    从0.3版本起,本工具开始支持大多数模型上的多种形式的学习和推理,包括默认支持的多线程训练和多核机器上的推理。特别的,这个模型可以使用collapsed Gibbs sampler [T. L. Griffiths and M. Steyvers. 2004. Finding scientific topics. PNAS, 1:5228–35]或者collapsed variational Bayes approximation to the LDA objective [Asuncion, A., Welling, M., Smyth, P., & Teh, Y. W. (2009)). On Smoothing and Inference for Topic Models. UAI 2009]。


    01.// Name of the output model folder to generate
    02.val modelPath = file("lda-"+dataset.signature+"-"+params.signature);
    03. 
    04.// Trains the model: the model (and intermediate models) are written to the
    05.// output folder.  If a partially trained model with the same dataset and
    06.// parameters exists in that folder, training will be resumed.
    07.TrainCVB0LDA(params, dataset, output=modelPath, maxIterations=1000);
    08. 
    09.// To use the Gibbs sampler for inference, instead use
    10.// TrainGibbsLDA(params, dataset, output=modelPath, maxIterations=1500);


    该模型会在训练时产生状态信息,并且会把产生的模型写入当前目录的一个文件夹,在这个例子里名称为"lda-59ea15c7-30-75faccf7"。注意,默认情况下,使用CVB0LDA进行训练会使用本地所有可用的内核,而且因为它的收敛速率很快,CVB0LDA比GibbsLDA迭代次数更少,然而GibbsLDA在训练时需要更少的内存。


    产生输出文件夹之旅(A tour of the generated output folder)

    在这个例子中,产生的模型输出文件夹 lda-59ea15c7-30-75faccf7,包含了分析这个学习过程和把模型从磁盘加载回去所需要的一切。

    description.txt A description of the model saved in this folder.对这个模型生成流程的整体描述
    document-topic-distributions.csv A csv file containing the per-document topic distribution for each document in the dataset.
    数据集中每个文档的文档—话题分布
    [Snapshot]: 00000 - 01000 Snapshots of the model during training.训练中的模型快照
    [Snapshot]/params.txt Model parameters used during training.训练中应用的参数
    [Snapshot]/tokenizer.txt Tokenizer used to tokenize text for use with this model.建模中使用的分词器
    [Snapshot]/summary.txt Human readable summary of the topic model, with top-20 terms per topic and how many words instances of each have occurred.
    可读的话题模型摘要,包括了每个话的前20个term和产生了多少单词实例
    [Snapshot]/log-probability-estimate.txt Estimate of the log probability of the dataset at this iteration.
    [Snapshot]/term-index.txt Mapping from terms in the corpus to ID numbers (by line offset).
    [Snapshot]/topic-term-distributions.csv.gz For each topic, the probability of each term in that topic.对每个话题,每个term的分布

    决定这个模型是否已收敛(Determining if the model has converged)

    一种简单的判断模型的训练是否已经收敛的办法,是看计数文件夹中log-probability-estimate.txt.的值。这个文件包含了模型在训练时对数据概率估计的非正式估计。这些数字趋向于形成逐步向下但不会完全停止改变的曲线。如果这些数字看起来还没有稳定下来,你可能需要设定更高的迭代次数。


    新文本库的话题模型交互(topic model inference on a new corpus)

    在训练中,这个工具在产生的模型文件夹中的 document-topic-distributions.csv中记录了每个训练文档的话题分布。模型训练之后,它可以用来分析另外一个可能更大的文本,这个过程称作推理。这个教程展示了如何在一个新的数据集中用已经存在的话题模型中进行推理。
    这个例子的代码在example-3-Ida-infer.scala中

    载入训练好的LDA模型

    1.// the path of the model to load
    2.val modelPath = file("lda-59ea15c7-30-75faccf7");
    3. 
    4.println("Loading "+modelPath);
    5.val model = LoadCVB0LDA(modelPath);
    6.// Or, for a Gibbs model, use:
    7.// val model = LoadGibbsLDA(modelPath);

    这里我们再次载入上个例子中训练好的模型。
    笔者注:模型生成的文件夹名字可能和例子中不同,在这里载入的文件名(例子中的lda-59ea15c7-30-75faccf7)要改成自己硬盘里文件夹的名字。

    载入新的数据集进行推理(Load the new dataset for inference)

    01.// A new dataset for inference.  (Here we use the same dataset
    02.// that we trained against, but this file could be something new.)
    03.val source = CSVFile("pubmed-oa-subset.csv") ~> IDColumn(1);
    04. 
    05.val text = {
    06.source ~>                              // read from the source file
    07.Column(4) ~>                           // select column containing text
    08.TokenizeWith(model.tokenizer.get)      // tokenize with existing model's tokenizer
    09.}
    10. 
    11.// Base name of output files to generate
    12.val output = file(modelPath, source.meta[java.io.File].getName.replaceAll(".csv",""));
    13. 
    14.// turn the text into a dataset ready to be used with LDA
    15.val dataset = LDADataset(text, termIndex = model.termIndex);


    这里我们准备了一个新的数据集,用已载入模型的原始分词器进行了分词。注意:在这个特别的例子中,我们实际上使用的是之前训练的同样的文件。在实际使用中,推理的CSV文件将是磁盘中的其他文件。
    
    我们还创建了输出路径的文件名,下面输出的文件将出现在模型文件夹里,这些文件名将以推理的数据集名字开头。

    在潜在的话题上推测每个文档的分布(Infer per-document distributions over latent topic)

    1.println("Writing document distributions to "+output+"-document-topic-distributions.csv");
    2.val perDocTopicDistributions = InferCVB0DocumentTopicDistributions(model, dataset);
    3.CSVFile(output+"-document-topic-distributuions.csv").write(perDocTopicDistributions);
    4. 
    5.println("Writing topic usage to "+output+"-usage.csv");
    6.val usage = QueryTopicUsage(model, dataset, perDocTopicDistributions);
    7.CSVFile(output+"-usage.csv").write(usage)

    我们对推理数据集中的每个文档的话题分布进行推测,这些分布会写入模型文件夹中的一个新CSV文件。我们也会写入一个文件,其中包含了在推测数据集中,每个话题被使用的频率。

    在潜在话题上推测每个单词的分布(Infer per-word distributions over latent topics)

    .println("Estimating per-doc per-word topic distributions");
    2.val perDocWordTopicDistributions = EstimatePerWordTopicDistributions(
    3.model, dataset, perDocTopicDistributions);
    4. 
    5.println("Writing top terms to "+output+"-top-terms.csv");
    6.val topTerms = QueryTopTerms(model, dataset, perDocWordTopicDistributions, numTopTerms=50);
    7.CSVFile(output+"-top-terms.csv").write(topTerms);

    因为和已经产生训练模型的数据集不同,我们希望以不同于话题在训练中被使用的方式,推理数据集可以充分利用已经学习好的话题。这个工具可以产生数据集中每个话题的top-k个term。这里我们把这top-k个term放入-top-terms.csv。这个文件会和summary.txt文件中的输出结果或者在训练的数据集上的推理进行比较。
    
    

    将话题模型分片(Slicing a topic model's output)

    文档通常和特定的元数据相关联,比如文档创建的年份,它的数据源、作者等。在这篇教程中,我们展示了是如何用TMT来检查在数据切片中一个话题是如何使用的,切片是指和一个或多个绝对变量相关联的子集。

    这个例子的代码在example-4-Ida-slice.scala中


    载入训练好的LDA模型(Load the trained LDA model)

    1.// the path of the model to load
    2.val modelPath = file("lda-59ea15c7-30-75faccf7");
    3. 
    4.println("Loading "+modelPath);
    5.val model = LoadCVB0LDA(modelPath);
    6.// Or, for a Gibbs model, use:
    7.// val model = LoadGibbsLDA(modelPath);

    像以前一样,我们又从硬盘中载入一个模型

    准备数据集(Prepare the dataset)

    01.// A dataset for inference; here we use the training dataset
    02.val source = CSVFile("pubmed-oa-subset.csv") ~> IDColumn(1);
    03. 
    04.val text = {
    05.source ~>                              // read from the source file
    06.Column(4) ~>                           // select column containing text
    07.TokenizeWith(model.tokenizer.get)      // tokenize with existing model's tokenizer
    08.}
    09. 
    10.// turn the text into a dataset ready to be used with LDA
    11.val dataset = LDADataset(text, termIndex = model.termIndex);

    这里,我们重新载入训练用的同样的数据集,当然也可以用不同的数据集

    选择用于切片的列变量(Select column variables for slicing)

    1.// define fields from the dataset we are going to slice against
    2.val slice = source ~> Column(2);
    3.// could be multiple columns with: source ~> Columns(2,7,8)

    在这个例子中,每个文档被创建的年份存储在第2列中,我们将用年份作为分隔数据集的绝对变量。如果你希望用多个绝对变量来切片,你可以用Columns

    载入或者推测文档-话题分布(Load or infer per-document topic distributions)

    1.println("Loading document distributions");
    2.val perDocTopicDistributions = LoadLDADocumentTopicDistributions(
    3.CSVFile(modelPath,"document-topic-distributions.csv"));
    4.// This could be InferCVB0DocumentTopicDistributions(model, dataset)
    5.// for a new inference dataset.  Here we load the training output

    上面的代码载入了训练中产生的文档-话题分布,如果你用另一个数据集进行推测,你可能需要用InferCVB0DocumentTopicDistributions代替LoadLDADocumentTopicDistributions,或者从另一个路径载入。

    将LDA队列输出切片(Slicing the LDA query output)

    01.println("Writing topic usage to "+output+"-sliced-usage.csv");
    02.val usage = QueryTopicUsage(model, dataset, perDocTopicDistributions, grouping=slice);
    03.CSVFile(output+"-sliced-usage.csv").write(usage);
    04. 
    05.println("Estimating per-doc per-word topic distributions");
    06.val perDocWordTopicDistributions = EstimatePerWordTopicDistributions(
    07.model, dataset, perDocTopicDistributions);
    08. 
    09.println("Writing top terms to "+output+"-sliced-top-terms.csv");
    10.val topTerms = QueryTopTerms(model, dataset, perDocWordTopicDistributions, numTopTerms=50, grouping=slice);
    11.CSVFile(output+"-sliced-top-terms.csv").write(usage);


    这里我们通过对数据集分片产生了每个话题的(usage)。像之前例子中的QueryTopicUsage,我们在模型中查找关联与每个话题有多少文档(部分)和多少单词。但是,产生的CSV文件会包含破坏话题分组的额外的列。在之后的教程中,我们会在Excel中分析这样的输出,对应出随着时间推移每个话题的使用情况。

    我们还生成了每个组中每个话题关联的排名靠前的单词。产生的-sliced-top-terms.csv文件可以用来分析是否话题一直在子群中(sub-groups)被使用。

    在Excel中分析话题模型输出(Analyzing topic model outputs in Excel)

    之前产生的CSV文件可以直接导入Excel中进一步分析,以便于理解、绘图和处理话题模型的输出。如果结果似乎并无意义,你可能需要尝试其他的模型参数。


    以下的截图是基于0.1.2版本的输出结果。至于0.3版本,每个输出结果文件包括一个“文档”(Documents)列和一个“单词”(Words)列。前者包含了在每个切片中与每个话题相关的文档总数,后者包含了每个切片中与每个话题相关的单词总数。要注意的是,两个数字都是小数的,因为LDA并不是把文库(corpus)中的每个单词分配给单独的一个话题,而是在所有话题上的分布。


    选择模型参数(Selecting model parameters)

    本文描述了如何选择模型参数,比如tuning过程(密集的计算)产生话题的数量,以便找到合适的参数使模型perplexity最小。

    这个案例的代码是example-5-lda-select.scala

    这个脚本将文档分成两部分,一部分用来训练模型,另一部分用来评估不可见数据(unseen data)的混乱度(perplexity)。

    评价文档的混乱度首先要把文档分成两部分。每个文档的话题分布由单词的第一部分推测,然后工具箱用第二部分计算这一分布“意外”程度( how surprised it was)的一个平均值,意外由等概率单词选择的数量计算而来。这个值被写入控制台,数值越小意味着模型越可靠。

    混乱度得分不可用于比较文库,因为他们很容易被不同的单词量影响。但是他们可以用来在相同的数据集上比较训练的模型(比如示例脚本)。但是要清楚,有更好混乱度得分的模型并不总是产生更易懂的话题或者更适合特别任务的话题。由于没有更好的方案,混乱度得分被用作在选择中挑选的稳定措施。通常,我们希望随着话题数量的增多,混乱度得分会下降,但是混乱度的不断下降幅度会越来越小。一个好的经验法则是,挑选产生一些产生合理输出的话题(通过检查summary.txt),然后混乱度会开始下降

    一些非参数话题模型在自己的话题训练过程中可以自动选择话题数量。但是这些模型(比如 Hierarchical Dirichlet Process)目前还没有用在工具箱里。即使在这些模型中,一些参数也必须调整,比如话题平滑和词项平滑参数。

    训练一个带标签LDA模型(Training a Labeled LDA model)

    Labeled LDA is a supervised topic model for credit attribution in multi-labeled corpora [pdfbib]. If one of the columns in your input text file contains labels or tags that apply to the document, you can use Labeled LDA to discover which parts of each document go with each label, and to learn accurate models of the words best associated with each label globally.

    带标签的LDA是一个对于多标签可信属性文库的有监督话题模型。如果在你输入的文件中,一列包含了适用于此文档的标签或者标记,你就可以用带标记的LDA发现文档的某个部分属于哪个标记,还可以学习单词联系最紧密的标记的精确的模型。

    这个案例的代码是example-6-llda-learn.scala

    这个案例和训练一个常规的LDA模型非常相似,除了少数改变。首先,要指定一个带标签LDA数据集,我们需要告诉工具箱文本和标签从哪儿来。通常,带标签的LDA只有当每个文档包含一个以上标签时才有用(否则这个模型等价于朴素贝叶斯)。但是在例子中,我们会用“year”列作为标签。要注意,因为每个文档只有一个year,这个模型实际上在训练一次迭代之后就会收敛,但是这个案例是为了工作于在一个源文件中一列包含多个标签或者标记、空间分隔。

    01.val source = CSVFile("pubmed-oa-subset.csv") ~> IDColumn(1);
    02. 
    03.val tokenizer = {
    04.SimpleEnglishTokenizer() ~>            // tokenize on space and punctuation
    05.CaseFolder() ~>                        // lowercase everything
    06.WordsAndNumbersOnlyFilter() ~>         // ignore non-words and non-numbers
    07.MinimumLengthFilter(3)                 // take terms with >=3 characters
    08.}
    09. 
    10.val text = {
    11.source ~>                              // read from the source file
    12.Column(4) ~>                           // select column containing text
    13.TokenizeWith(tokenizer) ~>             // tokenize with tokenizer above
    14.TermCounter() ~>                       // collect counts (needed below)
    15.TermMinimumDocumentCountFilter(4) ~>   // filter terms in <4 docs
    16.TermDynamicStopListFilter(30) ~>       // filter out 30 most common terms
    17.DocumentMinimumLengthFilter(5)         // take only docs with >=5 terms
    18.}
    19. 
    20.// define fields from the dataset we are going to slice against
    21.val labels = {
    22.source ~>                              // read from the source file
    23.Column(2) ~>                           // take column two, the year
    24.TokenizeWith(WhitespaceTokenizer()) ~> // turns label field into an array
    25.TermCounter() ~>                       // collect label counts
    26.TermMinimumDocumentCountFilter(10)     // filter labels in < 10 docs
    27.}
    28. 
    29.val dataset = LabeledLDADataset(text, labels);


    标记LDA假设每个文档只能用标签集中有名字的话题。这里每个文档只参与了一个标签(year)。Year并不是特别有趣的标签(比如相比于包含了多个描述不同文章标记的域),但是在这个例子中已经足够了。

    训练一个GibbsLabeledLDA或者CVB0LabeledLDA模型类似于训练一个LDA模型。

    01.// define the model parameters
    02.val modelParams = LabeledLDAModelParams(dataset);
    03. 
    04.// Name of the output model folder to generate
    05.val modelPath = file("llda-cvb0-"+dataset.signature+"-"+modelParams.signature);
    06. 
    07.// Trains the model, writing to the givne output path
    08.TrainCVB0LabeledLDA(modelParams, dataset, output = modelPath, maxIterations = 1000);
    09.// or could use TrainGibbsLabeledLDA(modelParams, dataset, output = modelPath, maxIterations = 1500);

    The LabeledLDA model can be used analogously to an LDA model by adapting the previous examples to the labeled setting, as appropriate.

    训练一个PLDA模型(Training a PLDA model)

    Partially Labeled Dirchlet Allocation (PLDA) [paper] is a topic model that extends and generalizes both LDA and Labeled LDA. The model is analogous to Labeled LDA except that it allows more than one latent topic per label and a set of background labels. Learning and inference in the model is much like the example above for Labeled LDA, but you must additionally specify the number of topics associated with each label.

    部分标签 Dirchlet 分布(PLDA)是一个扩展并且概括了LDA和带标签LDA的话题模型。这个模型类似于带标签LDA,除了它允许每个标签含有一个以上的潜在话题和一系列背景标签。这个模型的学习并且推测更像上面的带标签LDA,但是你必须额外的指定每个标签相关的话题数量。

    这个例子的代码是example-7-plda-learn.scala



    展开全文
  • 由于工作需要自己翻译的,能力有限,翻译不佳,不喜勿喷。 绘图工具箱(Mapping Toolbox)提供的工具和实用程序,用于分析地理数据和创建地图显示。您可以从Shapefile文件,GeoTIFF格式,SDTS DEM和其他格式的文件...
  • Camera Calibration Toolbox for Matlab 英文原文链接:http://www.vision.caltech.edu/bouguetj/calib_doc/   (待续。。。。。。今后几天将陆续推出)

    Camera Calibration Toolbox for Matlab

    英文原文链接:http://www.vision.caltech.edu/bouguetj/calib_doc/

     

    (待续。。。。。。今后几天将陆续推出)

    展开全文
  • %lesson 2 rigidBodyTree % 刚体树是刚体与关节连接性的一种表示。使用这个类在MATLAB?中建立机器人机械手模型。如果您有一个使用统一机器人描述格式(URDF)指定的机器人模型,请使用importrobot来导入您的机器人模型...

    bdc7e982543030e53601a44cf70b7e4d.png
    %lesson 2 rigidBodyTree
    % 刚体树是刚体与关节连接性的一种表示。使用这个类在MATLAB?中建立机器人机械手模型。如果您有一个使用统一机器人描述格式(URDF)指定的机器人模型,请使用importrobot来导入您的机器人模型。
    % 刚体树模型由刚体作为刚体对象组成。每个刚体都有一个与之相关的rigidBodyJoint对象,该对象定义了如何相对于其父体进行移动。使用setFixedTransform来定义关节的框架与相邻物体的框架之间的固定转换。
    % 您可以使用RigidBodyTree类的方法从模型中添加、替换或删除刚体。
    % 机器人动力学计算也是可能的。指定机器人模型中每个刚体的质量、重心和惯性特性。你可以计算有或没有外力的正向和反向动力学,并计算给定机器人关节运动和关节输入的动力学量。
    % 要使用与动态相关的函数,请将DataFormat属性设置为“row”或“column”。
    % 对于给定的刚体树模型,还可以使用机器人逆运动学算法使用机器人模型计算所需末端执行器位置的关节角。当使用逆运动学或广义逆运动学时,指定你的刚体树模型。
    % 显示方法支持体网格的可视化。网格被指定为.stl文件,可以使用addVisual添加到单独的刚体中。另外,默认情况下,importrobot函数将加载URDF机器人模型中指定的所有可访问的.stl文件。
    % 创建一个树形结构的机器人对象。使用addBody添加刚体。
    % robot = rigidBodyTree("MaxNumBodies",N,"DataFormat", DataFormat)指定在生成代码时机器人允许的body数量的上限。您还必须将DataFormat属性指定为名称-值对。
    
    % 例程
    % 在刚体树中加入刚体和相应的关节。每个rigidBody对象都包含一个rigidBodyJoint对象,必须使用addBody将其添加到rigidBodyTree中。
    % 更改现有的rigidBodyTree对象。你可以在刚体树中替换关节,物体和子树。加载lesson1示例机器人作为rigidBodyTree对象。
    % 获取一个特定的主体来检查属性。L3体的唯一子元素是L4体。您也可以复制特定的主体。
    clear
    load exampleRobots.mat
    showdetails(puma1)
    % 获取rigidtree中名字为L3刚体句柄
    body3 = getBody(puma1,'L3'); 
    % 获取一个特定的主体来检查属性。L3体的唯一子元素是L4体。您也可以复制特定的主体。
    childBody = body3.Children{1} 
    body3Copy = copy(body3) %虽然是复制L3但是不复制他的子父属性
    % 更换L3的关节属性不改变其他。您必须创建一个新的关节对象,并使用replaceJoint来确保下游的人体几何形状不受影响。
    % 如果需要定义主体之间的转换而不是使用默认的标识矩阵,可以调用setFixedTransform。
    newJoint = rigidBodyJoint('prismatic');%移动关节
    replaceJoint(puma1,'L3',newJoint);%替换L3的关节为新关节
    
    showdetails(puma1)
    %删除整个body并使用removeBody获得结果子树。删除的主体包含在子树中。
    subtree = removeBody(puma1,'L4')
    
    %移除修改后的L3刚体。将原始复制的L3刚体添加到L2刚体,然后返回子树。
    %机器人模型保持不变。通过showdetails查看详细的比较。
    removeBody(puma1,'L3');
    addBody(puma1,body3Copy,'L2')%L2是父
    addSubtree(puma1,'L3',subtree)%加载之前子树,父是L3
    
    showdetails(puma1)
    
    % 指定刚体树的动力学特性
    % 要使用动力学函数来计算关节扭矩和加速度,请指定rigidBodyTree对象和rigidBody的动力学特性。
    % 创建一个刚体树模型。创造两个刚体附着在它上面。
    clear
    robot = rigidBodyTree('DataFormat','row');
    body1 = rigidBody('body1');
    body2 = rigidBody('body2');
    % 指定连接到主体上的关节。将body2的固定转换设置为body1。这个变换在x方向上是1m。
    joint1 = rigidBodyJoint('joint1','revolute');
    joint2 = rigidBodyJoint('joint2');
    setFixedTransform(joint2,trvec2tform([1 0 0]))
    body1.Joint = joint1;
    body2.Joint = joint2;
    % 指定两个物体的动力学特性。将身体添加到机器人模型中。
    % 对于本例,给出了带有附加球形质量(body2)的杆(body1)的基本值。
    
    body1.Mass = 2;
    body1.CenterOfMass = [0.5 0 0];
    body1.Inertia = [0.167 0.001 0.167 0 0 0];
    
    body2.Mass = 1;
    body2.CenterOfMass = [0 0 0];
    body2.Inertia = 0.0001*[4 4 4 0 0 0];
    
    addBody(robot,body1,'base');
    addBody(robot,body2,'body1');
    
    %计算整个机器人的质心位置。画出机器人的位置。将视图移动到xy平面。
    comPos = centerOfMass(robot);
    
    show(robot);
    hold on
    plot(comPos(1),comPos(2),'or')
    view(2)
    
    %改变第二个物体的质量。注意重心的变化。
    body2.Mass = 20;
    replaceBody(robot,'body2',body2) %注意这里是直接替换刚体
    
    comPos2 = centerOfMass(robot);
    plot(comPos2(1),comPos2(2),'*g')
    hold off
    
    %在刚体树模型上计算由于外力引起的正向动力学(已知力矩求位置)
    %一个扳手被应用到一个特定的身体与重力是指定为整个机器人。加载预定义的KUKA LBR机器人模型,该模型指定为RigidBodyTree对象。
    clear
    load exampleRobots.mat lbr
    lbr.DataFormat = 'row';
    lbr.Gravity = [0 0 -9.81];
    q = homeConfiguration(lbr);
    q(2)=pi/4
    % 指定表示机器人所经历的外力的扳手向量。利用外力函数生成外力矩阵。
    % 指定机器人模型、体验扳手的末端执行器、扳手矢量和当前机器人配置。
    % 扳手是相对于“tool0”车身框架给出的,也就是在tool0坐标系施加的,它要求你指定机器人的配置,q。
    wrench = [0 0 0.5 0 0 0.3];
    %externalForce(robot,bodyname,wrench)组成了外力矩阵,您可以使用该矩阵作为反向动力学和正向动力学的输入,
    %向bodyname指定的刚体施加一个外力扳手。假定扳手输入在基础框架内,力矩阵fext在基坐标系中给出。
    % 施加在物体上的力矩和力,指定为[Tx Ty Tz Fx Fy Fz]矢量。扳手的前三个要素对应于xyz轴周围的力矩。
    % 最后三个元素是沿同一轴的线性力。除非你指定了机器人的配置,第四个元素q,否则扳手力矩是相对于base。
    fext = externalForce(lbr,'tool0',wrench,q);
    % 计算当lbr处于主构型时,末端执行器“tool0”所受的外力在重力作用下产生的关节加速度。
    % 假设关节速度和关节力矩为零(输入为空向量[])。
    qddot = forwardDynamics(lbr,q,[],[],fext);
    
    
    %计算关节扭矩以对抗外力
    % 利用外力函数生成力矩阵,应用于刚体树模型。力矩阵是一个m×6的向量,对于机器人上的每个关节都有一行来应用一个六元扳手。
    % 使用外力函数,指定末端执行器,正确地将扳手分配到矩阵的正确行。你可以将多个力矩阵加在一起来对一个机器人施加多个力。
    % 要计算抵消这些外力的关节扭矩,可以使用反动力学函数。
    % 加载一个预定义的KUKA LBR机器人模型,它被指定为RigidBodyTree
    clear
    load exampleRobots.mat lbr
    lbr.DataFormat = 'row';
    lbr.Gravity = [0 0 -9.81];
    q = homeConfiguration(lbr);
    %在link1上设置外力。输入的扳手向量在基坐标系中表示。
    fext1 = externalForce(lbr,'link_1',[0 0 0.0 0.1 0 0]);
    %在末端执行器上设置外力,tool0。输入的扳手向量在tool0中表示。
    fext2 = externalForce(lbr,'tool0',[0 0 0.0 0.1 0 0],q);
    %fext1 fext2返回基于全局坐标系的力,然后显示是哪个坐标系中的力作用,数值是基于全局的。
    %计算平衡外力所需的关节力矩。要组合这些力,将力矩阵相加。假设关节速度和加速度为零(输入为[])。
    tau = inverseDynamics(lbr,q,[],[],fext1+fext2);
    %jointTorq = inverseDynamics(robot) 反动力学(机器人)计算机器人在不施加外力的情况下静止保持自身结构所需的关节力矩。
    展开全文
  • %SerialLink.IKINE Inverse manipulator kinematics %SerialLink.IKINE 机械手逆运动学函数 % % Q = R.ikine(T) is the joint coordinates corresponding to the robot % end-effector pose T which is a ...

    %SerialLink.IKINE Inverse manipulator kinematics
    %SerialLink.IKINE 机械手逆运动学函数
    %
    % Q = R.ikine(T) is the joint coordinates corresponding to the robot
    % end-effector pose T which is a homogenenous transform.
    %Q =R.ikine(T) 能够求解机器人R的在齐次矩阵T表示下,对应的关节空间的解 Q
    %
    %Q = R.ikine(T, Q0, OPTIONS) specifies the initial estimate of the joint
    % coordinates.
    %Q = R.ikine(T, Q0, OPTIONS) 指定了在初始的关节状态Q0下,实现机器人R的
    %齐次矩阵表示的姿态T 所应对的关节解Q
    %
    %Q = R.ikine(T, Q0, M, OPTIONS) specifies the initial estimate of the joint
    % coordinates and a mask matrix. For the case where the manipulator
    % has fewer than 6 DOF the solution space has more dimensions than can
    % be spanned by the manipulator joint coordinates. In this case
    % the mask matrix M specifies the Cartesian DOF (in the wrist coordinate >
    % frame) that will be ignored in reaching a solution. The mask matrix
    % has six elements that correspond to translation in X, Y and Z, and rotation
    % about X, Y and Z respectively. The value should be 0 (for ignore) or 1.
    % The number of non-zero elements should equal the number of manipulator DOF.
    %Q = R.ikine(T, Q0, M, OPTIONS) 指定了初始关节状态和一个蒙版矩阵M。
    %这种情况适用于机械手自由度少于6的情况,因为在这种情况下解空间具有比关节空间更大
    %的尺度,所以蒙版矩阵M用于将无关的解空间维度屏蔽。
    %蒙版矩阵M应该具有如下性质:
    %1、有6个元素分别对应笛卡尔空间中沿着X,Y,Z轴的平移和旋转。
    %2、这些元素只能是0或者1,0表示将对应维度屏蔽
    %3、蒙版矩阵M中的非零元素,应该等于机器手的自由度
    % For example when using a 5 DOF manipulator rotation about the wrist z-axis
    % might be unimportant in which case M = [1 1 1 1 1 0].
    %例如对于一个5自由度机械手来说,腕部Z轴的旋转或许是不必要的,因此M可以赋值为
    %M = [1 1 1 1 1 0]
    %
    % In all cases if T is 4x4xM it is taken as a homogeneous transform sequence
    % and R.ikine() returns the joint coordinates corresponding to each of the
    % transforms in the sequence. Q is MxN where N is the number of robot joints.
    % The initial estimate of Q for each time step is taken as the solution
    % from the previous time step.
    %在输入的T是一个4X4XM的齐次矩阵序列的情况下,R.ikine()会返回序列中对应每个齐次矩
    %阵的关节变量解,形式为MXN
    %在每一步的计算中,前一时刻的Q值会作为下一个时刻的初始Q0
    %
    % Options::
    % ‘pinv’ use pseudo-inverse instead of Jacobian transpose
    % ‘ilimit’,L set the maximum iteration count (default 1000)
    % ‘tol’,T set the tolerance on error norm (default 1e-6)
    % ‘alpha’,A set step size gain (default 1)
    % ‘novarstep’ disable variable step size
    % ‘verbose’ show number of iterations for each point
    % ‘verbose=2’ show state at each iteration
    % ‘plot’ plot iteration state versus time
    %“Options”可选的参数
    % ‘pinv’ 用伪逆矩阵而不是雅克比矩阵的转置
    % ‘ilimit’,L 设置最大的迭代步数为L,默认情况下是1000
    % ‘tol’,T 设置最大的平方误差为T ,默认情况下是1e-6
    % ‘alpha’,A 设置最大的步长为A,默认情况下是1
    % ‘novarstep’ 设置为步长不可变
    % ‘verbose’ 显示每个点的迭代次数
    % ‘verbose=2’ 在每次迭代的时候显示状态
    % ‘plot’ 绘制迭代状态随时间的变化图
    %
    % Notes::
    %注意事项:
    % - Solution is computed iteratively.
    %- 运动学逆解是通过迭代实现的
    % - Solution is sensitive to choice of initial gain. The variable
    % step size logic (enabled by default) does its best to find a balance
    % between speed of convergence and divergence.
    % - 解的结果对初始增益的选择很敏感。可变步长逻辑(默认是使能的)会尽力去平
    % 衡解发散和收敛的速度
    % - Some experimentation might be required to find the right values of
    % tol, ilimit and alpha.
    %- 会需要一些实验来找到合适的允许误差、最大迭代步数和最大步长
    % - The pinv option sometimes leads to much faster convergence.
    % - 伪逆选项有时候会带来快非常多的收敛速度
    % - The tolerance is computed on the norm of the error between current
    % and desired tool pose. This norm is computed from distances
    % and angles without any kind of weighting.
    %- 误差的计算是根据当前位姿与目标位姿的平方差来的。而且在位置误差和
    % 姿态误差在误差计算中所占的比重相同
    % - The inverse kinematic solution is generally not unique, and
    % depends on the initial guess Q0 (defaults to 0).
    % - 运动学逆解一般来说都不是唯一的,并且会与初始姿态Q0有关,初始姿态
    % 在不指定的情况下默认是所有关节值都为0
    % - The default value of Q0 is zero which is a poor choice for most
    % manipulators (eg. puma560, twolink) since it corresponds to a kinematic
    % singularity.
    % - Q0的默认值对于大多数机械手来说都是一个不好的选择,例如puma560和两连
    % 杆模型,因为它会知道运动学奇异的发生。
    % - Such a solution is completely general, though much less efficient
    % than specific inverse kinematic solutions derived symbolically, like
    % ikine6s or ikine3.
    %- 这个函数提供的解决方案是完全具有通用型的,尽管比起特定的机械构型的逆运动
    % 学求解方案要低效得多
    % - This approach allows a solution to obtained at a singularity, but
    % the joint angles within the null space are arbitrarily assigned.
    % 这个函数允许在奇异位点处也能够获得解,但是因为奇异位点而无解(或者是耦合的关节)
    % 它们的解是任意分配的
    % - Joint offsets, if defined, are added to the inverse kinematics to
    % generate Q.
    % 如果定义了关节偏置的话, 它们会被加到逆运动学中来产生合适的关节解Q
    %
    % 欢迎讨论学习的小伙伴,将问题发到邮箱 cheungk.roc@foxmail.com一起共同学习。
    % See also SerialLink.fkine, tr2delta, SerialLink.jacob0, SerialLink.ikine6s.

    展开全文
  • 本篇文章主要介绍几个大家应该熟练掌握的ASM工具。 asmcmd - command line interface to ASM ASM最初发布时,asmcmd的功能还很弱。从11gR2版本开始,asmcmd已经成为一个功能非常强大且常用的工具。...
  • 原作者:Bane Radulovic 译者: 庄培培 审核: 魏兴华 本篇文章主要介绍几个大家应该熟练掌握的ASM工具。 asmcmd - command line interface...
  • DockerToolbox-1.10.0

    2018-04-09 14:41:41
    本文翻译自Docker官方博客。 过去我们总听到有人说,在开发中很难使用入手使用Docker,尤其是你已经根据Compose定义过了你的应用程序 ,然后接下来要去单独安装Compose的情况。随着Compose、Kitematic 以及Boot2...
  • matlab toolbox proxy error

    2020-07-22 09:46:52
    安装toolbox出现以下问题和提示 reset matlab proxy setting in web preferences error:ERR_PROXY_CONNECTION_FAILED 翻译:网页的代理服务器设置 2.寻求度娘的帮助 发现是“浏览页”的问题 3.考虑到代理...
  • linkage 凝聚层次聚类树 语法  Z = linkage(X)  Z = linkage(X,method)  Z = linkage(X,method,metric)  Z = linkage(X,method,pdist_inputs)  Z = linkage(X,metric,'savememory',... Z = linkag...
  • Robot toolbox for MATLAB 9.10.docx对应机器人工具箱9.10版本的word文档格式,方便翻译,转换准确率非常高,格式也保存得非常完美
  • ECCV2020 TIDE: A General Toolbox for Identifying Object Detection Errors论文翻译摘要1.介绍2.工具2.1 计算mAP2.2 定义错误类型2.3计算错误的限制3.分析3.1验证设计选择3.2 比较目标属性进行精细分析3.3 不同...
  • 最近常用Curve Fitting Toolbox(以下简称CFT)处理数据,在直观的比较各种参数配置下拟合结果的时候,也常常会好奇各种统计数据的含义。今天无意中找到一些用户手册中的详细解释,觉得有用,特分享给各位亲。以下...
  • 常用工具:时间戳转换、URL编码、BASE64编码、加解密、二维码生成、ip地址查询、DNS/Whois查询、JSON解析、翻译、万年历、色彩查询等。 【插件更新】 2020-12-17 14:25:47 【插件版本】 3.1.6 【插件标签...
  • GPS状态和工具箱 显示您曾经感兴趣的所有GPS和传感器数据:卫星的位置和信号...翻译更新 目标Android 9 PRO版本的画中画模式(在Android 7及更高版本上,点击主页按钮进行测试) Android 8及更高版本需要新的通知插件
  • 1、前记:在继Robotics System Toolbox中的机器人运动(1),和具有逆运动学的2维轨迹跟踪(翻译--个人学习记录)这俩篇博客后,细细的研究了Robotics System Toolbox工具箱中的逆运动求解函数,发现必须要有足够的...
  • 安装之前先了解下关键概念: 在linux上安装Docker,你的机器即使localhost也是docker主机;在网络中,localhost是指您的计算机。...说白了就是直接安装在linux上,英文翻译真蛋疼。 在Windows安装
  • 转载翻译自:Did you know... You can drag and drop code onto the Toolbox General tab? - #191 今天的小提示很有意思,特别是如果你在给别人做演示的时候。所有的人都看到你没有写任何代码,但是实际上代码已经...
  • 原网页翻译如下: 密歇根图像重建工具箱(MIRT)是一组用Mathwork的Matlab语言编写的图像重建(和相关的图像问题)的开源算法。这个软件是由杰夫·费斯勒和他的团队在密歇根大学开发的。工具箱包括以下内容。 迭代和非...
  • 如有翻译错误请批评指正!所有代码经自己运行测试通过。转载请注明链接 :http://blog.csdn.NET/kaspar1992 The PLY Format Matlab视觉工具箱点云只支持XYZ坐标及颜色属性。 1. File Header PLY文件
  • 本系列博客将介绍Matlab...如有翻译错误请批评指正!所有代码经自己运行测试通过。转载请注明链接 :http://blog.csdn.net/kaspar1992 1. Hide and Show 3-D Point Cloud Figure - 显示和隐藏3D图 player=pcplayer
  • MATLAB MA TLAB 主程序模块 Simulink 动态仿真模块 Aerospace Blockset 航空模块集 Bioinformatics Toolbox 生物信息学工具箱 CDMA Reference Blockset CDMA 参考模块集 Communications Blockset 通信模块集 ...
  • 来源:...翻译过来就是:matlab会不知道你到底要保存哪个,毕竟我们save可以完全不给参数比如:save('./'test) 所以,需要单独写一个...
  • 本系列博客将介绍Matlab中机器...如有翻译错误请批评指正!所有代码经自己运行测试通过。 1. Create 3-D Stereo Display -创建3D立体图 >> load('webcamsSceneReconstruction.mat'); //导入双目标定的结果文件 >> I

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 151
精华内容 60
关键字:

toolbox翻译