Stanford - CS224U, Natural Language Understanding
Spring 2020
CS224U: Natural Language Understanding is the first course I took in the Stanford AI Certification Program. This blog is a short summary of the material and what I took away from it.
The instructors for recent terms have been Prof. Christopher Potts and Bill MacCartney, and this year was no exception. Both are major figures in the field; Apple’s Siri is one of the products Bill led. Because of COVID-19, the course went fully online for remote students and Stanford on-campus students alike, taught over Zoom. Combined enrollment was around 120+. I teamed with a Stanford undergrad on the homework. The final project was me, that undergrad, and a CS PhD at Northwestern. The final project became optional because of the pandemic.
Lecture 1, Introduction and course overview
NLP VS. NLU
In the first lecture the instructors gave a short intro and then contrasted NLP (Natural Language Processing) with NLU (Natural Language Understanding). My take is that NLU is a sub-area of NLP: NLU focuses on machine understanding of language, NLP on processing it. The course covers Grounded Language Understanding, a classic NLU problem. They used the Pragmatic Color Describer to introduce Grounding. When you describe a color in language, the words you pick depend on the surrounding context. Enter our orange cats:


When describing the two orange cats we can distinguish them as the lighter orange cat vs the darker one. If the comparison cat is not orange, we do not need to specify the shade; we just say orange cat. For example:

When we use contrastive language we assume the listener shares our understanding of color shades. That shared understanding is Grounding. More on the Pragmatic Color Describer later.
A brief history of NLU
The instructors gave a short history of NLU
- 1966: Eliza
- 1988: Latent Semantic Analysis
- January 2011: IBM Watson beats Jeopardy! Champions
- October 2011: Apple Siri launches in beta
- April 2014: Microsoft Cortana demoed
- May 2016: Google Assistant
CS224u topics
They then listed the NLU topics for the term: eight topics, two lectures each. Plenty of material.
- Vector-space models
- Sentiment analysis
- Relation extraction
- Natural Language Inference
- Grounding
- Contextual word representations
- Adversarial testing
- Methods and metrics
The professor then sketched progress in each area and recommended SUPERINTELLIGENCE - NICK BOSTROM. I found it worthwhile: it is about the future of AI and the social issues that might follow. Little technical content, simple language. A decent English-practice read if you have time.
Finally they pointed to a few starter tutorials: setting up the course virtualenv, intro to PyTorch and NumPy, etc. Strongly recommend following the setup tutorial and cloning the course GitHub; there is a lot of useful material.
CS224U virtual environment setup tutorial
Lecture 2, Distributed word representations
This lecture covers the most basic but still central idea in NLP: word vectors. Prof. Potts started from co-occurrence matrices and went through GloVe, Word2Vec, and related methods.
Vector representations are a core idea in deep learning; the running joke is “everything can be an embedding.” In retail, every product and every store can be a high-dimensional vector. You can study product relationships the same way. Alibaba, Walmart, and Amazon have all done substantial work here. A Product2Vec paper if you want to dig in ( Studying Product Competition Using Representation Learning).
Word vector representations are now the default effective method in the field, but they rest on a deep linguistic idea. It goes back to the question: what defines the meaning of a word? The answer here is that the other words that appear with it in a sentence define its meaning.
You shall know a word by the company it keeps. - Firth (1957)
“distributional statements can cover all of the material of a language without requiring support from other types of information. - Firth (1957)
The simplest co-occurrence matrix captures meaning by counting how often words appear together.
How to build a co-occurrence matrix
Building a co-occurrence matrix has two main parameters.
- Window Size: the range around a center word in which co-occurrence is counted
- Scaling: used to adjust the co-occurrence values
Example from a line of Shakespeare: “For thy sweet love remembered such wealth brings That then I scorn to change my state with kings.”

Choice of these two parameters follows this logic
- Larger window size and smoother scaling capture more semantic information
- Smaller window size and heavier scaling capture more syntactic information
Compute the co-occurrence matrix over a huge collection of sentences and documents; the counts of how often each word appears with every other word give the simplest word vectors. Each row in the figure below can be treated as a word embedding. Raw counts are not enough; next we look at statistical methods that improve vector quality. Window-based co-occurrence has an obvious flaw: words like the, and, or, is co-occur with almost everything but carry little meaning. Later we cover reweighting methods such as PMI and PPMI that mitigate this.

How to compare two vectors
Once words are vectors we need systematic ways to compare them. The course covers:
- Euclidean distance
- Euclidean distance with L-2
- Cosine distance
- Matching-based methods
- KL divergence
Euclidean distance
Distance between n-dimensional vectors u, v:
\[{euclidean(u, v)=\sqrt{\sum_{i=1}^{n}{|u_i - v_i|^2}}}\]Euclidean distance is the straight-line distance between two points. If two vectors point the same way but have different magnitudes, the Euclidean distance is still large. For word vectors direction usually matters more than magnitude; vectors that point the same way tend to have similar meaning, so Euclidean distance is not a good comparison method.
Euclidean distance with L-2 norm
If we L2-normalize the vectors, every vector has magnitude 1. Euclidean distance then ignores magnitude and only reflects direction.
Cosine distance
Cosine distance measures only the angle between vectors; magnitude is irrelevant. It is one of the most common ways to compare word vectors in NLP.

One thing worth noting: ranking by Euclidean distance after L2 normalization is the same as ranking by cosine distance. The numeric values differ, but the order when comparing multiple vectors is identical. In word-vector applications they can be treated as equivalent.
Matching-based methods
Matching-based methods are not used much in NLU. The course only mentioned them briefly; I just list the formulas here.

KL divergence
KL divergence is a way to compare two probability distributions. For a deeper dive see KL divergence.
\[D(p || q) = \sum_{i=1}^{n} {p_ilog(\frac{p_i}{q_i})}\]In NLU, to compare two word vectors we first turn each vector into a probability distribution that sums to 1, then apply KL divergence. The lecture gave this example. A, B, and C have already been turned into distributions that sum to 1. The method only works if the vectors can be interpreted as distributions; negative values make it inapplicable.

Normalizing the co-occurrence matrix
We have covered how to build a co-occurrence matrix and how it yields word vectors. Frequency-based vectors have a serious problem: raw frequency is not very meaningful for language understanding. A simple example: 妖魔鬼怪 vs 魑魅魍魉. The two idioms mean essentially the same thing, but 妖魔鬼怪 appears far more often in student essays because 魑魅魍魉 is hard to write and you lose points if you get it wrong. Frequency is therefore a poor signal; we can reduce its effect with normalization. L2 normalization and converting the vector to a probability distribution are two options. Next is a common method: Observed/Expected.
Observed/Expected is

How should we interpret the expected count? It is the expected frequency if the row word and column word were independent. In the figure, keep appears 60 times and tabs 21 times. If they were independent, the probability they co-occur would be P(keep) * P(tabs) = 60/101 * 21/101. Observed/Expected compares the actual count with that independence assumption.
From Observed/Expected we also get Pointwise Mutual Information (PMI) and Positive PMI (PPMI). PMI is log(Observed/Expected); PPMI sets every negative PMI (from the log) to 0. Note that log(0) is undefined in math, but in this setting we take log(0)=0.
TF-IDF
TF: Term frequency: P(word | document) IDF: Inverse document frequency (IDF)
The professor also mentioned t-test weighting, pairwise distance matrices, etc., but they are not used much in this course so I will not expand on them.
Dimensionality reduction
Co-occurrence matrices are huge; a word representation can easily have thousands or tens of thousands of dimensions. Using them raw does not extract meaning well, so we need dimensionality reduction. The course covers four families of methods:
- Latent Semantic Analysis
- Singular value decomposition (SVD)
- Principal Components Analysis (PCA)
- Non-negative Matrix Factorization (NMF)
- Probabilistic LSA (PLSA; Hofmann 1999)
- Latent Dirichlet Allocation (LDA; Blei et al. 2003)
- t-SNE (van der Maaten and Hinton 2008)
- Autoencoders
- GloVe
- Word2Vec
The methods under LSA are less common in NLP today, and SVD and PCA are basic dimensionality-reduction techniques, so I will not go into them. We focus on Autoencoder, GloVe, and Word2Vec.
Autoencoder
An autoencoder is a deep neural architecture used for dimensionality reduction. The lecture showed a simple autoencoder:

The main difference from a usual network is that a standard net needs an input X and a target Y. Training an autoencoder only needs X, because the input and the target are both X. The objective is to make the output X_hat equal the input X. The code below is the autoencoder in the figure; input_dim_ and output_dim_ are equal (the dimension of X).
import torch
import torch.nn as nn
def define_graph(self):
return nn.Sequential(
nn.Linear(self.input_dim_, self.hidden_dim),
nn.Tanh(),
nn.Linear(self.hidden_dim, self.output_dim_))
GloVe
GloVe is a landmark result in NLP; almost every NLP course covers it. Here is a short look at how it works. The GloVe objective is to learn word vectors whose dot products are proportional to their co-occurrence probabilities.
Before GloVe there were two main families of word-vector methods: 1. Matrix Factorization Methods based on the co-occurrence matrix (everything we discussed above). 2. Shallow window-based methods that use a local context window. That family includes the skip-gram model and the continuous bag-of-words model. Both families have clear weaknesses. In the first, high-frequency words such as the, is, and do not represent meaning well. The second family only sees a local window, so it cannot fully exploit a large corpus.
CS224U: Natural Language Understanding 是我在Stanford AI Certification Program 里的第一节课。 这篇Blog对知识点和学习心得做一个简单的总结。
最近几学期这门课的教授一直是Prof. Christopher Potts和Bill MacCartney,今年也不例外。两位都是真*巨佬,苹果的Siri就是Bill领导的产品之一。这学期因为COVID-19疫情的原因,无论是我们Online的学生还是Stanford的在校学生,课程都变成Online了,通过Zoom授课。这学期Online+在校学生大概有120+人。我这学期作业是跟一个Stanford本科的白人小哥一组,final project 是我跟白人小哥哥加一个在 Northwestern 的CS PhD。然而个final project因为疫情也变成optional的了。
Lecture 1, Introduction and course overview
NLP VS. NLU
第一节课,老师简单做了一些自我介绍,然后介绍了一个NLP(Natural Language Processing) 和NLU(Natural Language Understanding)的不同。我的理解是NLU是NLP下的一个小分支, NLU强调的机器对语言的理解,而NLP则强调对语言的处理。门课会涉及到Grounded Language Understanding,是一个典型的NLU问题。这门课用 Pragmatic Color Describer 来简单介绍了Grounding的概念。 当我用语言描述一个颜色的时候,我们所用的描述性词汇取决于周围的环境。有请我们的橘猫登场:


我们描述两只橘猫的时候,就可以用浅一点的那个只橘猫VS深色的橘猫来作区分。然而当对比的猫不是橘色的话,我们就需要描述橘色的深浅,只需要说橘猫即可。比如这样:

当我们使用对比描述语言的时候,我们假设说话对象对颜色深浅有跟我们一样的理解。这个理解就是Grounding。 有关Pragmatic Color Describer的具体内容后面会详细讲。
A brief history of NLU
这部分老师简单介绍了一下NLU的发展历史
- 1966: Eliza
- 1988: Latent Semantic Analysis
- 2011年1月: IBM Watson beats Jeopardy! Champions
- 2011年10月: Apple Siri launches in beta
- 2014年4月: Microsoft Cortana demoed
- 2016年5月: Google Assistant
CS224u topics
随后介绍了一下这学期会cover的NLU topics,八个topic,每个topic两个lecture。内容还是相当丰富的。
- Vector-space models
- Sentiment analysis
- Relation extraction
- Natural Language Inference
- Grounding
- Contextual word representations
- Adversarial testing
- Methods and metrics
随后教授介绍了各个方向的发展,并且介绍了一个本书SUPERINTELLIGENCE - NICK BOSTROM, 我读着觉得不错,主要讲的就是对AI的未来发展,和可能带来的相应的社会问题。没什么技术内容,用词简单, 有时间的朋友可以读读,当做练习英文也不错。
最后教授介绍了一下几个入门教程,包括设置课程的虚拟环境,PyTorch和Numpy的入门,等。强烈建议跟着教程设置一下虚拟环境,并克隆这门课的Github,有很多有用的东西。
Lecture 2, Distributed word representations
这节课讲的就是NLP里面最基础,但相当重要的Word Vector。 Prof. Potts从最开始的Co-occurrence矩阵,讲到到GloVe和Word2Vec等方法。
Vector representation的思想,是深度学习里的一个核心思想,我们就经常开玩笑说,“万物皆可Embedding”。比如在零售业,每一个商品,每一个门店,都可以用一个高维向量来表示。同理我们也可以通过这种向量来研究商品之间的关系。中国零售大佬阿里巴巴,和美国零售Walmart,Amazon都在这方面有深入的研究,这里附上一篇有关Product2Vec的论文,有兴趣的同学可以读一下( Studying Product Competition Using Representation Learning)。
现在Word vector representation已经是学术界默认的有效方法,然而其背后有着对语言学深刻的理解。这要追溯到这个语言学问题:什么定义了一个词的意思? 在这里的理解是,与这个词一同出现在一个句子的其他词定义了这个词的意义。
You shall know a word by the company it keeps. - Firth (1957)
“distributional statements can cover all of the material of a language without requiring support from other types of information. - Firth (1957)
最简单的Co-occurrence矩阵通过计算词汇同时出现的次数来反应词义信息。
如何构建Co-occurrence矩阵
Co-occurrence矩阵的构建有两个主要参数。
- Window Size: 以一个单词为中心,前后考虑co-occurrence的范围
- Scaling: 用于调整co-occurrence的数值
这里用莎士比亚的一句诗来举例: “For thy sweet love remembered such wealth brings That then I scorn to change my state with kings.”

这两个参数的选取,主要遵循以下逻辑
- 更大的window size和更平滑的scaling能获取更多的semantic information(语义信息)
- 更小的window size和更多的scaling能获取更多的syntactic information(句子结构信息)
用海量的句子,文章来计算co-occurrence矩阵,每个词与其他词一起出现的次数就能构成最简单的word vector。下图的每一行都可以看做一个word embedding。当然简单的计数并不能达到我们想要的效果,接下来会讲如何通过统计方法提高word vector的质量。然而基于窗口构建的co-occurrence有一个明显的缺点,像the, and, or, is等词汇跟其他词co-occurrence的频率非常高,但是包含词义的信息却非常少。后面会讲到一些reweighting的方法,比如PMI,PPMI,来改善这个情况。

如何比较两个向量
单词变成向量之后,我们需要系统的比较两个向量的方法。这门课介绍了以下几个方法:
- Euclidean distance
- Euclidean distance with L-2
- Cosine distance
- Matching-based methods
- KL divergence
Euclidean distance(欧几里得距离)
n维向量u, v之间的距离:
\[{euclidean(u, v)=\sqrt{\sum_{i=1}^{n}{|u_i - v_i|^2}}}\]Euclidean distance描述的是两点之间的直线距离。如果两个向量方向一致,大小不同的话,欧式距离也会非常大。通常word vector的方向比大小更重要,方向一致的word vector通常有着相近的词意,所以Euclidean distance不是比较word vector的合适方法。
Euclidean distance with L-2 norm
如果我们对向量进行归一化,那么向量大小都会变为1,这是用在用Euclidean distance就能排除向量大小的影响,从而只考虑向量方向的影响。
Cosine distance
Cosine distance只测量向量角度,向量大小完全无关。Cosine distance是NLP界最常用的word vector比较方法之一。

这里有点值得注意的是, euclidean distance + L-2 Normalization的排序是等同于cosine distance的。这两种方法的数值不完全相同,但是用来比较多个向量距离的时候排序是一样的。在word vector应用领域,可以认为是等价的。
Matching-based methods
Matching based在NLU领域用的并不多,这门课只是简单 提了一下,我在这就简单列一下公式。

KL divergence
KL divergence本身是一种比较两个概率分部的方法。想具体了解KL divergence的同学可以看这篇KL divergence。
\[D(p || q) = \sum_{i=1}^{n} {p_ilog(\frac{p_i}{q_i})}\]在NLU的运用中,如果我们要比较两个word vector我们首先要吧word vector变成一个和为1的概率分布,然后用KL divergence来比较距离。课上给出了这么一个例子。A, B, C都是变成和为1的概率分布了。使用KL的前提是,向量能被理解为概率分布,如果向量里面有负值,那么这个方法就不适用。

标准化Co-occurrence矩阵
我们已经简单讲了如何构建co-occurrence矩阵,并且通过co-occurrence矩阵引申出word vector的概念。然而靠词出现的频率产生的word vector有一个很严重的问题,就是词出现频率在语言理解里的意义并不大。举一个很简单的例子,妖魔鬼怪VS魑魅魍魉。这两个成语的意思基本一样,但是大家写作文的时候可能妖魔鬼怪出现的频率会高很多,因为魑魅魍魉实在太难写了,写错还要扣分不是。所以频率并不是一个非常好的方法,我们可以通过标准化的方法来减弱频率的影响。L-2 normalization和把向量转化为概率的方法。下面会讲一个常用的方法Observe/Expected。
Observed/Expected公式如下

这里该怎么理解这这个expected的计算呢?expected可以理解为在行和列的词都是独立事件的时候,这个词出现频率的期望值。在这张图给出的例子中,keep这个词出现了60次,tabs出现了21次。如果这两个词出现是独立事件的话,那么keep, tabs一起出现的概率应该是P(keep) * P(tabs) = 60/101 * 21/101。Observed/Expected是在比较实际情况和假设为独立事件的时候的不同。
在Observed/Expected的基础上,我们还可以得到Pointwise Mutual Information(PMI)和Positive PMI(PPMI)。PMI是log(Observed/Expected),而PPMI则是把所有PMI中因为log产生的负数改为0。值得注意的是数学上log(0)是没有定义的,但是在这个应用场景下log(0)=0。
TF-IDF
TF: Term frequency: P(word | document) IDF: Inverse document frequency (IDF)
教授还提到了t-test weighting,pairwise distance matrices等,但这些在这门课中用到的并不多,就不在这展开了。
Dimensionality reduction
Co-occurrence矩阵非常大,一个word representation可能会高达上千,上万维度,如果直接用的话并不能很好的提取词义信息,所以这里要用到降维的方法。这门课介绍了四种方法:
- Latent Semantic Analysis
- Singular value decomposition (SVD)
- Principal Components Analysis (PCA)
- Non-negative Matrix Factorization (NMF)
- Probabilistic LSA (PLSA; Hofmann 1999)
- Latent Dirichlet Allocation (LDA; Blei et al. 2003)
- t-SNE (van der Maaten and Hinton 2008)
- Autoencoders
- GloVe
- Word2Vec
这里LSA下面的方法在如今的NLP领域已经不那么常用了,而且SVD和PCA是比较基础的降维方法,这里就不展开讲。我们主要看看Autoencoder, GloVe, 和Word2Vec。
Autoencoder
Autoencoder是一类用来降维结构的深度神经网络结构。老师在lecture中给出了一个简单的Autoencoder模型的结构

Autoencoder结构与其他神经网络不一样的地方主要是,训练寻常的神经网络,我们需要一个输入X,和输出Y。但是训练Autoencoder, 我们只需要输入X即可,因为这里的输入和输出都是X。优化的目的是让输出层的X_hat等于输入层的X。以下就是图中描述的Autoencoder,这里的input_dim_和output_dim_是相等的都是X向量的维度。
import torch
import torch.nn as nn
def define_graph(self):
return nn.Sequential(
nn.Linear(self.input_dim_, self.hidden_dim),
nn.Tanh(),
nn.Linear(self.hidden_dim, self.output_dim_))
GloVe
GloVe是NLP界一个里程碑级别的成就,基本上所有NLP相关的课程都会讲到这个,我们就来简单看看GloVe就是怎么实现的。GloVe的优化目标是学习一组word vector使其点乘和他们co-occurrence的概率成正比。
在GloVe之前,生成word vector两大类方法是: 1. 基于co-occurrence矩阵的Matrix Factorization Methods,咱之前讨论的都是这一类方法。2: 基于local context window的Shallow Window-Based Methods。这类方法包括skip-gram model和continuous bag-of-words model。然而这两类方法都有明显的缺陷。第一类中有些高频的词汇,例如the, is, and等并不能很好的代表词意。第二类方法是我是基于local window,所以无法完全利用庞大的语料数据。
Comments