1. 自然语言处理简介

自然语言处理 (Natural Language Processing, NLP) 是人工智能领域最火热的研究方向之一,NLP 为计算机真正理解人类语言提供了基础。NLP 已成为现代计算机程序系统的重要组成部分,广泛用于搜索引擎、语音助手、文档处理等应用中。机器可以很好地处理结构化数据,但在处理非结构化的文本时,就变得相对困难了。NLP 的目标是开发使计算机能够理解非结构化文本及语言的算法。
处理非结构化自然语言最具挑战性的事情之一就是语言存在多变复杂的上下文,上下文在如何理解语言时起着非常重要的作用。虽然,人类善于理解语言,但仍尚不清楚人类为何能够非常容易地理解语言。即使没有明确是上下文,我们也可以使用过去的知识和经验来理解对话。
为了解决这一问题,研究人员使用机器学习方法开发各种算法模型,利用大量的文本语料库,然后根据这些数据训练算法以执行各种任务,例如文本分类、情绪分析和主题建模等。简单而言,NLP 算法经过训练以检测输入文本数据中的模式并从中获得所需信息。

2. 自然语言处理相关库

2.1 NLTK

NLTK 是构建 Python 程序以处理自然语言的库。它为 50 多个语料库和词汇资源(如 WordNet )提供了易于使用的接口,以及一套用于分类、分词、词干、标记、解析和语义推理的文本处理库、工业级 NLP 库的包装器,可以使用以下命令安装:

pip install nltk

安装完成后,可以使用以下语句下载相关数据:

import nltk
nltk.download()

2.2 Gensim

Gensim 能够将文档根据 TF-IDFLDALSI 等模型转换成向量模式,Gensim 同样还实现了 word2vec,能够将单词转换为词向量,可以用于处理大型语料库,使用以下命令进行安装:

pip install gensim

2.3 Pattern

Pattern 是一个多用途的Python库,可以用于不同的任务,如分词、情感分析等,同时它的语法简单易懂,对需要处理文本数据的开发人员而言加油良好的学习曲线,使用以下命令进行安装:

pip install pattern

3. 自然语言处理基础

本节中,我们将介绍用于分析文本和构建 NLP 应用程序的基础概念。

3.1 文本分词

当我们处理文本时,我们需要将其分解成更小的部分进行分析。为此,需要使用分词 (Tokenizing) 技术,分词是将文本划分为一组片段(例如单词或句子)的过程,分离出的每一单词或句子称为 token,根据需要,我们可以不同分词技术将文本分成多个 token,接下来,我们使用 NLTK 对输入文本进行分词。首先,导入以下包:

from nltk.tokenize import sent_tokenize, word_tokenize, WordPunctTokenizer

定义将用于分词的输入文本:

input_text = "If the implementation is hard to explain, it's a bad idea. \If the implementation is easy to explain, it may be a good idea."

将输入文本划分为句子 token

print("Sentence tokenizer:")
print(sent_tokenize(input_text))

将输入文本划分为单词 token

print("Word tokenizer:")
print(word_tokenize(input_text))

使用 WordPunct 分词器将输入文本划分为单词 token

print("Word punct tokenizer:")
print(WordPunctTokenizer().tokenize(input_text))

运行代码,得到的输出结果如下:

3.2 词干提取

文本数据通常包括大量变化,处理文本需要能够处理大量变化的文本数据。例如,我们需要处理同一个词的不同形式,并使计算机能够理解这些不同的词具有相同的基本形式。如 swim 这个词可以出现多种形式,包括:swimsswamswumswiming 等,这组词具有相似的含义,将不同形式的单词转换为其基本形式的过程称为词干提取 (stemming),词干提取是一种产生词根或基本词的形态转换方法。
在分析文本时,提取这些词根非常有用,这样做可以从输入文本中提取有用的统计数据。词干提取器 (stemmer) 的目标是将单词从它们的不同形式转换为共同的基本形式,简单的词干提取是一个启发式过程,通过截断单词的末端来提取它们的基本形式。接下来,我们使用 NLTK 进行词干提取。
首先,导入以下包:

from nltk.stem.porter import PorterStemmer
from nltk.stem.lancaster import LancasterStemmer
from nltk.stem.snowball import SnowballStemmer

定义一些输入词:

input_words = ['are', 'be', 'begins', 'reading', 'swims', 'goes', 'done', 'had', 'reduced', 'horse', 'normalize', 'worked','terribly', 'move','operation', 'noisy', 'capital', 'swam']

实例化 PorterLancasterSnowball 词干提取器对象:

porter = PorterStemmer()
lancaster = LancasterStemmer()
snowball = SnowballStemmer('english')

为输出显示创建一个名称列表并相应地格式化输出文本:

stemmer_names = ['PORTER', 'LANCASTER', 'SNOWBALL']
formatted_text = '{:>20}' * (len(stemmer_names) + 1)
print('\n', formatted_text.format('INPUT WORD', *stemmer_names), '\n', '='*90)

遍历单词并使用三个词干提取器获取这些单词的词干:

for word in input_words:output = [word, porter.stem(word), lancaster.stem(word), snowball.stem(word)]print(formatted_text.format(*output))

运行代码,输出结果如下所示:

从上图可以看出,三种词干提取算法基本上能够实现目标,它们之间的区别在于词干提取的严格程度。Porter 词干提取器是最不严格的,而 Lancaster 是最严格的,仔细观察输出,可以看到它们之间的差异。当输入单词为 terriblyoperation 之类的词时,词干提取得到的结果会有所不同。从 Lancaster 词干提取器获得的词干输出较为混乱,因为它会在最大程度上减少单词。通常情况下我们可以选择 Snowball 词干提取器,因为它可以在速度和严格性之间取得良好权衡。

3.3 词形还原

词形还原 (Lemmatization) 是另一种将单词简化为基本形式的方法。上一节的词干提取器中获得的一些单词基本形式没有任何意义,词形还原则是将单词的不同变形形式组合在一起的过程,以便可以将它们作为单个单词进行分析。词形还原类似词干提取,但它为单词赋予了上下文意义。因此,它可以具有相似含义的单词链接到同一个单词。例如,三个词干提取器都将 leaves 的转换为 leav,但 leav 并非真实的单词。词形还原采用更结构化的方法来解决这一问题。
词形还原过程使用单词的词汇和形态分析。它通过删除诸如 inged 之类的后缀来获得其基本形式。如果将 leaves 这个词进行词形还原,可以得到输出 leaf。需要注意的是,词形还原的输出取决于单词是动词还是名词。接下来,我们使用 NLTK 进行词形还原。
首先,导入以下包:

from nltk.stem import WordNetLemmatizer

定义一些输入词,我们使用与上一节中相同输入单词集,以便比较输出:

input_words = ['are', 'be', 'begins', 'reading', 'swims', 'goes', 'done', 'had', 'reduced', 'horse', 'normalize', 'worked','terribly', 'move','operation', 'noisy', 'capital', 'swam']

创建一个词形还原器对象:

lemmatizer = WordNetLemmatizer()

为输出显示创建一个名称列表并相应地格式化输出文本:

lemmatizer_names = ['NOUN LEMMATIZER', 'VERB LEMMATIZER']
formatted_text = '{:>25}' * (len(lemmatizer_names) + 1)
print('\n', formatted_text.format('INPUT WORD', *lemmatizer_names), '\n', '='*90)

遍历单词并使用名词和动词词形还原器对单词进行词形还原:

for word in input_words:output = [word, lemmatizer.lemmatize(word, pos='n'), lemmatizer.lemmatize(word, pos='v')]print(formatted_text.format(*output))

运行以上代码,可以得到如下输出结果:


可以看到,当涉及到诸如 swamhorse 等词时,名词词形还原器与动词词形还原器的工作方式不同,将这些输出与词干提取器输出进行比较,可以发现它们之间的差异。词形还原器得到的输出都是有意义的,而词干提取器的输出可能有意义,也可能没有意义。
需要注意的是,执行以上程序,必须首先执行以下代码:

import nltk
nltk.download()

否则会报类似如下错误:

During handling of the above exception, another exception occurred:Traceback (most recent call last):File "/python3.7/lib/python3.7/runpy.py", line 193, in _run_module_as_main
....File "/python3.7/lib/python3.7/site-packages/nltk/data.py", line 583, in findraise LookupError(resource_not_found)
LookupError:
**********************************************************************Resource omw-1.4 not found.Please use the NLTK Downloader to obtain the resource:

3.4 文本分块

文本数据通常需要分成几部分进行进一步分析,这一过程称为分块 (Chunking)。将文本分块的条件可能根据不同问题而有所不同,在分块期间,除了需要保证输出块具有意义外,不需要遵守任何其它约束。当我们处理大型文本文档时,将文本分块以提取有意义的信息就变得十分重要了。本节中,我们使用 NLTK 将输入文本划分为多个块。
首先,导入以下所需包:

import numpy as np
from nltk.corpus import cmudict

定义函数 chunker 用于将输入文本分块,其中第一个参数是文本,第二个参数是每个块的单词数:

def chunker(input_data, n):input_words = input_data.split(' ')output = []

遍历文本并使用输入参数将它们分块,函数返回一个列表:

    cur_chunk = []count = 0for word in input_words:cur_chunk.append(word)count += 1if count == n:output.append(' '.join(cur_chunk))count, cur_chunk = 0, []output.append(' '.join(cur_chunk))return output

本节使用 cmudict 语料库读取输入数据:

input_data = ' '.join(cmudict.words())

定义每个块中的单词数 chunk_size

# 定义每个区块中的单词数
chunk_size = 700

将输入文本分块并显示输出:

chunks = chunker(input_data, chunk_size)
print('\nNumber of text chunks =', len(chunks), '\n')
for i, chunk in enumerate(chunks):print('Chunk', i+1, '==>', chunk[:80])

运行以上代码,可以得到以下输出结果:


我们已经学习了对文本进行分割和分块的技术,接下来,我们综合应用以上技术研究如何执行文本分析。

4. 自然语言处理应用

4.1 使用词袋模型获取单词总数

使用词袋模型进行文本分析的主要目标之一是将非结构化的文本数据转换为计算机可以识别的数值形式,以便我们使用机器学习算法对其进行进一步分析。假设我们需要分析的文本文档中包含数百万个单词的,为了分析这些文档,我们需要提取文本并将其转换为数值表示形式。
机器学习算法通常需要使用数值数据作为输入,以便可以分析数据并提取有意义的信息,这就是词袋模型的用途所在。该模型能够从文档中的所有单词中提取不同单词,并使用文档矩阵 (Term-Document Matrix) 构建模型,将每个文档表示为一个词袋 (Bag of Words)。我们只需要记录单词数量,而忽略语法细节和单词顺序。
接下里,我们将具体介绍文档矩阵。文档矩阵本质上是一个表格,它提供了文档中出现的各种单词的计数。因此,文本文档可以表示为各种单词的加权组合,我们可以设置阈值并选择更有意义的单词。或者说,词袋模型可以构建文档中所有单词数量的频率直方图,并用作特征向量。我们考虑以下句子:

  • The teacher assigned each of the children a different task
  • They worked hard to give their children a good start in life
  • The task was a formidable one

在以上三个句子中,我们可以得到以下 22 个不同的词:

the
teacher
assigned
each
of
children
a
different
task
they
worked
hard
to
give
their
good
start
in
life
was
formidable
one

接下来,我们使用每个句子中的单词数量为每个句子构建一个频率直方图,每个特征向量都是 22 维的,因为我们有 22 个不同的单词:

[2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0]
[1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1]

使用词袋模型提取到句子的特征,即文档矩阵后,我们就可以使用机器学习算法来分析这些数据。接下来,我们使用 NLTK 构建词袋模型。
首先,导入所需包,同时我们还将重用上节中定义的分块函数 chunker

import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from nltk.corpus import movie_reviewsdef chunker(input_data, n):input_words = input_data.split(' ')output = []cur_chunk = []count = 0for word in input_words:cur_chunk.append(word)count += 1if count == n:output.append(' '.join(cur_chunk))count, cur_chunk = 0, []output.append(' '.join(cur_chunk))return output

movie_reviews 语料库中读取输入数据,为了便于观察,我们仅使用前 5400 个单词:

input_data = ' '.join(movie_reviews.words()[:5400])

定义每个块中的单词数:

# 定义每个区块中的单词数
chunk_size = 800

使用 chunker 函数将输入文本分成块,并将块转换为字典项:

text_chunks = chunker(input_data, chunk_size)
# 将块转换为字典项
chunks = []
for count, chunk in enumerate(text_chunks):d = {'index': count, 'text': chunk}chunks.append(d)

提取文档矩阵,我们每个块中获得每个单词的计数,可以使用 CountVectorizer 方法来完成这一任务,该方法接受两个输入参数,第一个参数是最小文档频率,第二个参数是最大文档频率,这里的频率是指一个词在文本中出现的次数:

count_vectorizer = CountVectorizer(min_df=7, max_df=20)
document_term_matrix = count_vectorizer.fit_transform([chunk['text'] for chunk in chunks])

使用词袋模型提取词汇表并显示,词汇表是指在上一步中提取的单词列表:

vocabulary = np.array(count_vectorizer.get_feature_names())
print("\nVocabulary:\n", vocabulary)

为了便于观察,为每个块生成一个名称:

# 为每个分块编号
chunk_names = []
for i in range(len(text_chunks)):chunk_names.append('Chunk-' + str(i+1))

打印文档矩阵:

# 打印文档矩阵
print("\nDocument term matrix:")
formatted_text = '{:>12}' * (len(chunk_names) + 1)
print('\n', formatted_text.format('Word', *chunk_names), '\n')
for word, item in zip(vocabulary, document_term_matrix.T):output = [word] + [str(freq) for freq in item.data]print(formatted_text.format(*output))

运行以上代码,可以得到以下输出结果:


文本中出现的所有单词都可以在词袋模型文档矩阵中看到,同时可以观察到每个块中的不同单词出现的次数。我们已经完成了单词的计数,接下来,就可以在此基础上根据单词的频率使用机器学习算法完成一些预测任务。

4.2 文本分类

文本类别预测可以用于预测给定文本所属的类别,文本分类经常用于对文本文档进行分类。搜索引擎经常使用此工具按相关性对搜索结果进行排序。例如,假设我们要预测给定的句子是属于体育、娱乐还是科学等。为此,我们可以构建数据语料库并训练了机器学习算法,然后用训练完成的算法推断未知数据。
为了构建文本预测模型,我们将使用词频-逆文本频率 (Term Frequency - Inverse Document Frequency, TF-IDF) 指标。在一组文档中,TF-IDF 指标可以帮助我们了解给定单词对于一个文件集或一个语料库中的其中一个文件的重要程度,单词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。
TF-IDF 指标的第一部分是词频 (Term Frequency, TF),其衡量每个单词在给定文档中出现的频率,由于不同的文档有不同数量的单词,直方图中的确切数字会有所不同。为了使这些直方图具有可比性,我们需要标准化直方图。因此,我们将每个单词的计数除以给定文档中的单词总数,以获得词频。
TF-IDF 指标的第二部分是逆文本频率 (Inverse Document Frequency, IDF),它衡量一个词在给定文档集中对文档的独特性。当我们计算词频时,假设所有词都同等重要,但是我们不能仅仅依赖于每个单词的出现频率,因为诸如 andorthe 之类的单词出现了很多。为了平衡这些常用词的频率,我们需要降低它们的权重并增加稀有词的权重,这也有助于我们识别每个文档所独有的单词。
为了计算这个统计量,我们需要计算文档数量与给定单词的比率,然后将其除以文档总数。这个比率本质上是包含给定单词的文档的分数,然后通过利用该比率计算逆文档频率。
我们可以结合词频和逆文本频率来生成特征向量对文档进行分类,这是对文本进行更深入分析以获得更深层含义的基础,例如情感分析或主题分析等。接下来,我们使用 Scikit-learn 构建文本类别预测模型。
首先,我们导入以下所需包:

from sklearn.datasets import fetch_20newsgroups
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer

定义将用于训练数据集的类别字典映射,我们使用五个类别。此字典对象中的键使用 Scikit-learn 数据集中的名称:

# 定义类别映射
category_map = {'talk.politics.misc': 'Politics', 'rec.autos': 'Autos', 'rec.sport.hockey': 'Hockey', 'sci.electronics': 'Electronics', 'sci.med': 'Medicine'}

使用 fetch_20newsgroups 获取训练数据集:

training_data = fetch_20newsgroups(subset='train', categories=category_map.keys(), shuffle=True, random_state=5)

使用 CountVectorizer 对象提取单词计数:

count_vectorizer = CountVectorizer()
train_tc = count_vectorizer.fit_transform(training_data.data)
print("\nDimensions of training data:", train_tc.shape)

创建 TfidfTransformer 实例计算 TF-IDF 并使用数据对其进行训练:

tfidf = TfidfTransformer()
train_tfidf = tfidf.fit_transform(train_tc)

定义用于测试的样本输入语句:

# 定义测试数据
input_data = ['You can wirelessly manipulate many devices','You must be careful when driving a slippery road','Political debate helps us understand both sides', 'Players must be careful when approaching the goal post'
]

使用训练数据训练多项式贝叶斯分类器:

classifier = MultinomialNB().fit(train_tfidf, training_data.target)

使用 CountVectorizer 对象转换输入数据:

input_tc = count_vectorizer.transform(input_data)

使用 TF-IDF 转换器转换向量数据,使其可以通过推理模型得到预测结果:

input_tfidf = tfidf.transform(input_tc)

使用 TF-IDF 变换后的向量数据预测输出:

predictions = classifier.predict(input_tfidf)

打印输入测试数据中每个样本的输出类别:

for sent, category in zip(input_data, predictions):print('\nInput:', sent, '\nPredicted category:', category_map[training_data.target_names[category]])

运行以上代码,我们可以得到以下输出,可以看到预测的类别是正确的:

4.3 情感分析

情感分析是确定一段文本所表达情感的过程。例如,它可以用来确定电影评论是积极 (positive) 的还是消极 (negative) 的,这个简单是示例是 NLP 最流行的基础教程应用之一,根据不同的任务,我们也可以添加更多类别。情感发现模型可用于了解人们对产品、品牌的感受,可以用于分析营销活动、民意调查、购物网站上的产品评论等。接下来,我们构建情感分析模型确定观众影评是积极的还是消极的。
本节,我们使用朴素贝叶斯分类器来构建情感分析模型。首先,从文本中提取所有不同单词词汇表,NLTK 分类器需要将这些数据以字典的形式排列,以便提取这些词汇。同时,我们将文本数据划分为训练和测试数据集,使用训练数据集训练朴素贝叶斯分类器将评论分为积极和消极。之后,可以计算并显示表示积极和消极信息量最高的词。接下来,我们使用 NLTK 实现上述情感分析模型。
首先,导入以下所需包:

from nltk.corpus import movie_reviews
from nltk.classify import NaiveBayesClassifier
from nltk.classify.util import accuracy as nltk_accuracy

定义函数 extract_features,根据输入的单词构造字典对象并返回:

def extract_features(words):return dict([(word, True) for word in words])

加载带标签的电影评论:

fileids_pos = movie_reviews.fileids('pos')
fileids_neg = movie_reviews.fileids('neg')

从电影评论中提取特征并为它们构建相应的 PositiveNegative 标签:

features_pos = [(extract_features(movie_reviews.words(fileids=[f])), 'Positive') for f in fileids_pos]
features_neg = [(extract_features(movie_reviews.words(fileids=[f])), 'Negative') for f in fileids_neg]

将数据集划分为训练和测试数据集,我们将 80% 用于训练和 20% 用于测试:

threshold = 0.8
num_pos = int(threshold * len(features_pos))
num_neg = int(threshold * len(features_neg))

分离训练和测试的特征向量:

features_train = features_pos[:num_pos] + features_neg[:num_neg]
features_test = features_pos[num_pos:] + features_neg[num_neg:]

打印用于训练和测试的数据样本数量:

print('\nNumber of training datapoints:', len(features_train))
print('Number of test datapoints:', len(features_test))

使用训练数据集训练 NaiveBayesClassifier 并使用 NLTK 中内置度量准确率的方法计算模型准确率:

classifier = NaiveBayesClassifier.train(features_train)
print('\nAccuracy of the classifier:', nltk_accuracy(classifier, features_test))

打印前 n 个信息量最大的单词:

n = 15
print('\nTop ' + str(n) + ' most informative words:')
for i, item in enumerate(classifier.most_informative_features()):print(str(i+1) + '. ' + item[0])if i == n - 1:break

定义用于测试的输入文本数据:

input_reviews = ['The costumes in this film are very nice', 'The story was terrible, and I think the character was very weak','The film director is said to be wonderful', ' This is such a stupid movie. I wont recommend it to anyone'
]

遍历样本数据并预测输出:

print("\nMovie review predictions:")
for review in input_reviews:print("\nReview:", review)

计算每个输入样本的属于 PositiveNegative 的类别概率:

    probabilities = classifier.prob_classify(extract_features(review.split()))

选择概率预测中的最大值:

    predicted_sentiment = probabilities.max()

打印预测的输出类别( PositiveNegative ):

    print("Predicted sentiment:", predicted_sentiment)print("Probability:", round(probabilities.prob(predicted_sentiment), 2))

执行以上代码,可以看到如下输出,可以看出模型在测试数据集上的预测是正确的:

总结

在本节中,我们了解了自然语言处理中的各种基本概念,首先介绍了分词技术以将输入文本分成多个 token,然后学习了如何使用词干提取和词形还原将单词转换为基本形式,并介绍了文本分块技术,根据预定义的条件将输入文本分成多个块。
然后,综合使用上述方法基于词袋模型构建了一个文档矩阵,学习了如何使用机器学习技术对文本进行分类,最后,我们介绍了如何识别给定文本中的主题。

系列链接

使用Scikit-learn开启机器学习之旅
一文开启深度学习之旅
一文开启计算机视觉之旅
一文开启监督学习之旅
一文开启无监督学习之旅

一文开启自然语言处理之旅相关推荐

  1. 容器开启数据服务之旅系列(二):Kubernetes如何助力Spark大数据分析

    摘要: 容器开启数据服务之旅系列(二):Kubernetes如何助力Spark大数据分析 (二):Kubernetes如何助力Spark大数据分析 概述 本文为大家介绍一种容器化的数据服务Spark ...

  2. 使用SpringBoot开启微服务之旅

    \ 本文要点 \\ 微服务可以使你的代码解耦\\t 微服务可以使不同的团队专注于更小范围的工作职责.使用独立的技术.更安全更频繁地部署\\t SpringBoot支持各种REST API的实现方式\\ ...

  3. 容器开启数据服务之旅系列(一):Kubernetes如何解自建PostgreSQL运维之痛

    摘要: 通过阿里云Kubernetes容器服务,开启你的数据服务之旅 (一)云上运维自建数据库之痛,使用容器服务自动恢复数据库postgresql实例 概述 本文为大家介绍一种容器化的数据服务 pos ...

  4. 容器开启数据服务之旅系列(二):Kubernetes如何助力Spark大数据分析 1

    摘要: 容器开启数据服务之旅系列(二):Kubernetes如何助力Spark大数据分析 (二):Kubernetes如何助力Spark大数据分析 概述 本文为大家介绍一种容器化的数据服务Spark ...

  5. 金融科技大数据产品推荐:Chinapex创略智能客户数据平台——开启智慧营销之旅

    智能.实时的客户数据平台是一个独特的解决方案,由AI和机器学习驱动,助力企业完成从多数据源采集.分析,到数据运用的闭环,支持各种客户相关的应用场景,包括营销.客户体验优化,以及运营等 官网 | www ...

  6. 容器开启数据服务之旅系列(四):Kubernetes QoS 助力在线运用与大数据离线运用的带宽控制和磁盘控制...

    容器开启数据服务之旅系列(四) Kubernetes QoS 助力在线运用与大数据离线运用的带宽控制和磁盘控制 概述 本文是2018年大数据峰会上的一些分享,关于在线业务,离线业务在ACK(阿里云容器 ...

  7. NGUI从入门到实战第1章开启NGUI学习之旅

    NGUI从入门到实战第1章开启NGUI学习之旅 NGUI是Unity最重要的插件之一.使用NGUI可以高效地为游戏添加界面.本书将带领大家学习NGUI.作为NGUI学习之旅的第一站,本章会在整体上介绍 ...

  8. 华为诺亚方舟实验室主任李航:神经符号处理开启自然语言处理新篇章

    华为诺亚方舟实验室主任李航:神经符号处理开启自然语言处理新篇章 本文作者:王金许 2017-07-26 19:29 导语:​深度学习(神经处理)给自然语言处理带来了革命性的进步,基于深度学习的机器翻译 ...

  9. 【云栖大会】与马云一起开启“飞天·进化”之旅

    与马云一起开启"飞天·进化"之旅 再过20个小时,2016杭州云栖大会就要开幕了,我们的倒计时海报也陪伴大家走过了16个日夜.相信大家会对这次大会主题"飞天·进化&quo ...

最新文章

  1. Android Studio的配置问题——Intel HAXM is required to run this AVD,VT-x is disabled in BIOS;
  2. 树形结构 —— 树与二叉树 —— 树的数据生成器
  3. GitHub上最励志的计算机自学教程,绝对牛B
  4. CUDA/CUDNN下载安装以及适配pytorch和tensorflow
  5. 财智理财7破解思路与总结
  6. 网页页面缩小放大的快捷键
  7. Office 365开启现代工作方式!协同工作保持高效率!
  8. 创建Substrate 私有网络
  9. 腾讯笔试——安排机器 【 题目描述】小 Q 的公司最近接到 m 个任务, 第 i 个任务需要 xi 的时间去完成, 难度等级为 yi。 小 Q 拥有 n 台机器, 每台机器最长工作时间 zi, 机器等
  10. ue4人物动作_ue4人物动作资源Resource Gathering Animation418
  11. 人工智能 deepface 换脸技术 学习
  12. python 庖丁科技pdflux的表格解析(精度很高)
  13. 你看到的好片子,原来藏着这么多黑科技……
  14. 使用 MoveIt 控制自己的真实机械臂【2】——编写 action server 端代码
  15. Excel 特殊分组汇总示例
  16. 高中计算机学ppt吗,1.1高中信息技术基础开学第一课.ppt
  17. 亚马逊被关联?别怕有救
  18. CREO:CREO软件之工程图界面的简介(【创建】、【布局】、【表】、【注释】、【插入页面】、【装配图出工程图】、【将视图转为绘制图元】、【工程图输入到CAD中去修改】)图文教程之详细攻略
  19. 戴尔外星人原厂系统创建带F12 SupportAssist OS Recovery恢复保姆级教程外星人出厂系统还原教程X17,X15,X14,R13,M15R7,M17R5,R14,51MR1 R2
  20. 数据库管理员道德规范

热门文章

  1. Linux和Docker常用必备指令
  2. 东南大学计算机网络实验报告三,东南大学计算机网络第三次实验报告.docx
  3. 【软件测试】集成测试和系统测试
  4. 城市轨道交通运营管理属于什么院系_城市轨道交通运营管理属于什么类型的专业...
  5. 百度知道推广敏感词汇总
  6. 计算机水平要空着吗,计算机等级考试一级考试练习题
  7. java理论知识之Redis
  8. 大二课设-基于Tcp的c/s模式的网络聊天室(c#)
  9. 群集服务器作用,使用集群服务器的必要性是什么?其优缺点是什么?
  10. 网络游戏封包基础 作者不明