# 4.2. 特征提取
校驗者:
[@if only](https://github.com/apachecn/scikit-learn-doc-zh)
翻譯者:
[@片刻](https://github.com/apachecn/scikit-learn-doc-zh)
模塊 [`sklearn.feature_extraction`](classes.html#module-sklearn.feature_extraction "sklearn.feature_extraction") 可用于提取符合機器學習算法支持的特征,比如文本和圖片。
Note
特征特征提取與 特征選擇 有很大的不同:前者包括將任意數據(如文本或圖像)轉換為可用于機器學習的數值特征。后者是將這些特征應用到機器學習中。
## 4.2.1. 從字典類型加載特征
類 [`DictVectorizer`](generated/sklearn.feature_extraction.DictVectorizer.html#sklearn.feature_extraction.DictVectorizer "sklearn.feature_extraction.DictVectorizer") 可用于將標準的Python字典(dict)對象列表的要素數組轉換為 scikit-learn 估計器使用的 NumPy/SciPy 表示形式。
雖然 Python 的處理速度不是特別快,但 Python 的 `dict` 優點是使用方便,稀疏(不需要存儲的特征),并且除了值之外還存儲特征名稱。
類 [`DictVectorizer`](generated/sklearn.feature_extraction.DictVectorizer.html#sklearn.feature_extraction.DictVectorizer "sklearn.feature_extraction.DictVectorizer") 實現了 “one-of-K” 或 “one-hot” 編碼,用于分類(也稱為標稱,離散)特征。分類功能是 “屬性值” 對,其中該值被限制為不排序的可能性的離散列表(例如主題標識符,對象類型,標簽,名稱…)。
在下面的例子,”城市” 是一個分類屬性,而 “溫度” 是傳統的數字特征:
```
>>> measurements = [
... {'city': 'Dubai', 'temperature': 33.},
... {'city': 'London', 'temperature': 12.},
... {'city': 'San Francisco', 'temperature': 18.},
... ]
>>> from sklearn.feature_extraction import DictVectorizer
>>> vec = DictVectorizer()
>>> vec.fit_transform(measurements).toarray()
array([[ 1., 0., 0., 33.],
[ 0., 1., 0., 12.],
[ 0., 0., 1., 18.]])
>>> vec.get_feature_names()
['city=Dubai', 'city=London', 'city=San Francisco', 'temperature']
```
類 [`DictVectorizer`](generated/sklearn.feature_extraction.DictVectorizer.html#sklearn.feature_extraction.DictVectorizer "sklearn.feature_extraction.DictVectorizer") 也是對自然語言處理模型中訓練序列分類器的有用的表示變換,通常通過提取圍繞感興趣的特定的詞的特征窗口來工作。
例如,假設我們具有提取我們想要用作訓練序列分類器(例如:塊)的互補標簽的部分語音(PoS)標簽的第一算法。以下 dict 可以是在 “坐在墊子上的貓” 的句子,圍繞 “sat” 一詞提取的這樣一個特征窗口:
```
>>> pos_window = [
... {
... 'word-2': 'the',
... 'pos-2': 'DT',
... 'word-1': 'cat',
... 'pos-1': 'NN',
... 'word+1': 'on',
... 'pos+1': 'PP',
... },
... # in a real application one would extract many such dictionaries
... ]
```
該描述可以被矢量化為適合于呈遞分類器的稀疏二維矩陣(可能在被管道 [`text.TfidfTransformer`](generated/sklearn.feature_extraction.text.TfidfTransformer.html#sklearn.feature_extraction.text.TfidfTransformer "sklearn.feature_extraction.text.TfidfTransformer") 進行歸一化之后):
```
>>> vec = DictVectorizer()
>>> pos_vectorized = vec.fit_transform(pos_window)
>>> pos_vectorized
<1x6 sparse matrix of type '<... 'numpy.float64'>'
with 6 stored elements in Compressed Sparse ... format>
>>> pos_vectorized.toarray()
array([[ 1., 1., 1., 1., 1., 1.]])
>>> vec.get_feature_names()
['pos+1=PP', 'pos-1=NN', 'pos-2=DT', 'word+1=on', 'word-1=cat', 'word-2=the']
```
你可以想象,如果一個文本語料庫的每一個單詞都提取了這樣一個上下文,那么所得的矩陣將會非常寬(許多 one-hot-features),其中大部分通常將會是0。 為了使結果數據結構能夠適應內存,該類``DictVectorizer`` 的 `scipy.sparse` 默認使用一個矩陣而不是一個 `numpy.ndarray`。
## 4.2.2. 特征哈希(相當于一種降維技巧)
類 [`FeatureHasher`](generated/sklearn.feature_extraction.FeatureHasher.html#sklearn.feature_extraction.FeatureHasher "sklearn.feature_extraction.FeatureHasher") 是一種高速,低內存消耗的向量化方法,它使用了`特征散列 feature hashing <[https://en.wikipedia.org/wiki/Feature\_hashing](https://en.wikipedia.org/wiki/Feature_hashing)>`\_ 技術 ,或可稱為 “散列法” (hashing trick)的技術。 代替在構建訓練中遇到的特征的哈希表,如向量化所做的那樣 [`FeatureHasher`](generated/sklearn.feature_extraction.FeatureHasher.html#sklearn.feature_extraction.FeatureHasher "sklearn.feature_extraction.FeatureHasher") 將哈希函數應用于特征,以便直接在樣本矩陣中確定它們的列索引。 結果是以犧牲可檢測性為代價,提高速度和減少內存的使用; 哈希表不記得輸入特性是什么樣的,沒有 `inverse_transform` 辦法。
由于散列函數可能導致(不相關)特征之間的沖突,因此使用帶符號散列函數,并且散列值的符號確定存儲在特征的輸出矩陣中的值的符號。 這樣,碰撞可能會抵消而不是累積錯誤,并且任何輸出要素的值的預期平均值為零。默認情況下,此機制將使用 `alternate_sign=True` 啟用,對于小型哈希表大小(`n_features < 10000`)特別有用。 對于大的哈希表大小,可以禁用它,以便將輸出傳遞給估計器,如 [`sklearn.naive_bayes.MultinomialNB`](generated/sklearn.naive_bayes.MultinomialNB.html#sklearn.naive_bayes.MultinomialNB "sklearn.naive_bayes.MultinomialNB") 或 [`sklearn.feature_selection.chi2`](generated/sklearn.feature_selection.chi2.html#sklearn.feature_selection.chi2 "sklearn.feature_selection.chi2") 特征選擇器,這些特征選項器可以使用非負輸入。
類 [`FeatureHasher`](generated/sklearn.feature_extraction.FeatureHasher.html#sklearn.feature_extraction.FeatureHasher "sklearn.feature_extraction.FeatureHasher") 接受映射(如 Python 的 `dict` 及其在 `collections` 模塊中的變體),使用鍵值對 `(feature, value)` 或字符串,具體取決于構造函數參數 `input_type`。 映射被視為 `(feature, value)` 對的列表,而單個字符串的隱含值為1,因此 `['feat1', 'feat2', 'feat3']` 被解釋為 `[('feat1', 1), ('feat2', 1), ('feat3', 1)]`。 如果單個特征在樣本中多次出現,相關值將被求和(所以 `('feat', 2)` 和 `('feat', 3.5)` 變為 `('feat', 5.5)`)。 [`FeatureHasher`](generated/sklearn.feature_extraction.FeatureHasher.html#sklearn.feature_extraction.FeatureHasher "sklearn.feature_extraction.FeatureHasher") 的輸出始終是 CSR 格式的 `scipy.sparse` 矩陣。
特征散列可以在文檔分類中使用,但與 [`text.CountVectorizer`](generated/sklearn.feature_extraction.text.CountVectorizer.html#sklearn.feature_extraction.text.CountVectorizer "sklearn.feature_extraction.text.CountVectorizer") 不同,[`FeatureHasher`](generated/sklearn.feature_extraction.FeatureHasher.html#sklearn.feature_extraction.FeatureHasher "sklearn.feature_extraction.FeatureHasher") 不執行除 Unicode 或 UTF-8 編碼之外的任何其他預處理; 請參閱下面的哈希技巧向量化大文本語料庫,用于組合的 tokenizer/hasher。
例如,有一個詞級別的自然語言處理任務,需要從 `(token, part_of_speech)` 鍵值對中提取特征。可以使用 Python 生成器函數來提取功能:
```
def token_features(token, part_of_speech):
if token.isdigit():
yield "numeric"
else:
yield "token={}".format(token.lower())
yield "token,pos={},{}".format(token, part_of_speech)
if token[0].isupper():
yield "uppercase_initial"
if token.isupper():
yield "all_uppercase"
yield "pos={}".format(part_of_speech)
```
然后, `raw_X` 為了可以傳入 `FeatureHasher.transform` 可以通過如下方式構造:
```
raw_X = (token_features(tok, pos_tagger(tok)) for tok in corpus)
```
并傳入一個 hasher:
```
hasher = FeatureHasher(input_type='string')
X = hasher.transform(raw_X)
```
得到一個 `scipy.sparse` 類型的矩陣 `X`。
注意使用發生器的理解,它將懶惰引入到特征提取中:詞令牌(token)只能根據需要從哈希值進行處理。
### 4.2.2.1. 實現細節
類 [`FeatureHasher`](generated/sklearn.feature_extraction.FeatureHasher.html#sklearn.feature_extraction.FeatureHasher "sklearn.feature_extraction.FeatureHasher") 使用簽名的 32-bit 變體的 MurmurHash3。 因此導致(并且由于限制 `scipy.sparse`),當前支持的功能的最大數量 .
特征哈希的原始形式源于Weinberger et al,使用兩個單獨的哈希函數, 和  分別確定特征的列索引和符號。 現有的實現是基于假設:MurmurHash3的符號位與其他位獨立。
由于使用簡單的模數將哈希函數轉換為列索引,建議使用2次冪作為 `n_features` 參數; 否則特征不會均勻的分布到列中。
參考文獻: Kilian Weinberger,Anirban Dasgupta,John Langford,Alex Smola和Josh Attenberg(2009)。用于大規模多任務學習的特征散列。PROC。ICML。 MurmurHash3。
參考文獻:
- Kilian Weinberger, Anirban Dasgupta, John Langford, Alex Smola and Josh Attenberg (2009). [用于大規模多任務學習的特征散列](http://alex.smola.org/papers/2009/Weinbergeretal09.pdf). Proc. ICML.
- [MurmurHash3](https://github.com/aappleby/smhasher).
## 4.2.3. 文本特征提取
### 4.2.3.1. 話語表示
文本分析是機器學習算法的主要應用領域。 然而,原始數據,符號文字序列不能直接傳遞給算法,因為它們大多數要求具有固定長度的數字矩陣特征向量,而不是具有可變長度的原始文本文檔。
為解決這個問題,scikit-learn提供了從文本內容中提取數字特征的最常見方法,即:
- **令牌化(tokenizing)** 對每個可能的詞令牌分成字符串并賦予整數形的id,例如通過使用空格和標點符號作為令牌分隔符。
- **統計(counting)** 每個詞令牌在文檔中的出現次數。
- **標準化(normalizing)** 在大多數的文檔 / 樣本中,可以減少重要的次令牌的出現次數的權重。。
在該方案中,特征和樣本定義如下:
- 每個\*\*單獨的令牌發生頻率\*\*(歸一化或不歸零)被視為一個\*\*特征\*\*。
- 給定\*\*文檔\*\*中所有的令牌頻率向量被看做一個多元sample\*\*樣本\*\*。
因此,文本的集合可被表示為矩陣形式,每行對應一條文本,每列對應每個文本中出現的詞令牌(如單個詞)。
我們稱\*\*向量化\*\*是將文本文檔集合轉換為數字集合特征向量的普通方法。 這種特殊思想(令牌化,計數和歸一化)被稱為 **Bag of Words** 或 “Bag of n-grams” 模型。 文檔由單詞出現來描述,同時完全忽略文檔中單詞的相對位置信息。
### 4.2.3.2. 稀疏
由于大多數文本文檔通常只使用文本詞向量全集中的一個小子集,所以得到的矩陣將具有許多特征值為零(通常大于99%)。
例如,10,000 個短文本文檔(如電子郵件)的集合將使用總共100,000個獨特詞的大小的詞匯,而每個文檔將單獨使用100到1000個獨特的單詞。
為了能夠將這樣的矩陣存儲在存儲器中,并且還可以加速代數的矩陣/向量運算,實現通常將使用諸如 `scipy.sparse` 包中的稀疏實現。
### 4.2.3.3. 常用 Vectorizer 使用
類 [`CountVectorizer`](generated/sklearn.feature_extraction.text.CountVectorizer.html#sklearn.feature_extraction.text.CountVectorizer "sklearn.feature_extraction.text.CountVectorizer") 在單個類中實現了令牌化和出現頻數統計:
```
>>> from sklearn.feature_extraction.text import CountVectorizer
```
這個模型有很多參數,但參數的默認初始值是相當合理的(請參閱 [參考文檔](classes.html#text-feature-extraction-ref) 了解詳細信息):
```
>>> vectorizer = CountVectorizer()
>>> vectorizer
CountVectorizer(analyzer=...'word', binary=False, decode_error=...'strict',
dtype=<... 'numpy.int64'>, encoding=...'utf-8', input=...'content',
lowercase=True, max_df=1.0, max_features=None, min_df=1,
ngram_range=(1, 1), preprocessor=None, stop_words=None,
strip_accents=None, token_pattern=...'(?u)\\b\\w\\w+\\b',
tokenizer=None, vocabulary=None)
```
讓我們使用它來進行簡單文本全集令牌化,并統計詞頻:
```
>>> corpus = [
... 'This is the first document.',
... 'This is the second second document.',
... 'And the third one.',
... 'Is this the first document?',
... ]
>>> X = vectorizer.fit_transform(corpus)
>>> X
<4x9 sparse matrix of type '<... 'numpy.int64'>'
with 19 stored elements in Compressed Sparse ... format>
```
初始設定是,令牌化字符串,提取至少兩個字母的詞默認配置,做這一步的函數可以顯式的被調用:
```
>>> analyze = vectorizer.build_analyzer()
>>> analyze("This is a text document to analyze.") == (
... ['this', 'is', 'text', 'document', 'to', 'analyze'])
True
```
analyzer 在擬合期間發現的每個項都被分配一個與所得矩陣中的列對應的唯一整數索引。列的這種解釋可以檢索如下:
```
>>> vectorizer.get_feature_names() == (
... ['and', 'document', 'first', 'is', 'one',
... 'second', 'the', 'third', 'this'])
True
>>> X.toarray()
array([[0, 1, 1, 1, 0, 0, 1, 0, 1],
[0, 1, 0, 1, 0, 2, 1, 0, 1],
[1, 0, 0, 0, 1, 0, 1, 1, 0],
[0, 1, 1, 1, 0, 0, 1, 0, 1]]...)
```
從列標到特征名的反轉映射儲存在向量化類 vectorizer 的屬性 `vocabulary_` 中:
```
>>> vectorizer.vocabulary_.get('document')
1
```
因此,在將來的調用轉換方法中,在訓練語料庫中未出現的詞將被完全忽略:
```
>>> vectorizer.transform(['Something completely new.']).toarray()
...
array([[0, 0, 0, 0, 0, 0, 0, 0, 0]]...)
```
請注意,在上一個語料庫中,第一個和最后一個文檔具有完全相同的單詞,因此被編碼成相同的向量。 特別是最后一個字符是詢問形式時我們丟失了他的信息。為了防止詞組順序顛倒,除了提取一元模型 1-grams(個別詞)之外,我們還可以提取 2-grams 的單詞:
```
>>> bigram_vectorizer = CountVectorizer(ngram_range=(1, 2),
... token_pattern=r'\b\w+\b', min_df=1)
>>> analyze = bigram_vectorizer.build_analyzer()
>>> analyze('Bi-grams are cool!') == (
... ['bi', 'grams', 'are', 'cool', 'bi grams', 'grams are', 'are cool'])
True
```
矢量化提取的詞因此變得很大,同時可以在定位模式時消歧義:
```
>>> X_2 = bigram_vectorizer.fit_transform(corpus).toarray()
>>> X_2
...
array([[0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0],
[0, 0, 1, 0, 0, 1, 1, 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0],
[1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1]]...)
```
特別是 “Is this” 的疑問形式只出現在最后一個文檔中:
```
>>> feature_index = bigram_vectorizer.vocabulary_.get('is this')
>>> X_2[:, feature_index]
array([0, 0, 0, 1]...)
```
### 4.2.3.4. Tf–idf 項加權
在一個大的文本語料庫中,一些單詞將出現很多次(例如 “the”, “a”, “is” 是英文),因此對文檔的實際內容沒有什么有意義的信息。 如果我們將直接計數數據直接提供給分類器,那么這些頻繁詞組會掩蓋住那些我們關注但很少出現的詞。
為了為了重新計算特征權重,并將其轉化為適合分類器使用的浮點值,因此使用 tf-idf 變換是非常常見的。
Tf表示\*\*術語頻率\*\*,而 tf-idf 表示術語頻率乘以\*\*轉制文檔頻率\*\*: .
使用 `TfidfTransformer` 的默認設置,`TfidfTransformer(norm='l2', use_idf=True, smooth_idf=True, sublinear_tf=False)` 術語頻率,一個術語在給定文檔中出現的次數乘以 idf 組件, 計算為
,
其中  是文檔的總數, 是包含術語  的文檔數。 然后,所得到的 tf-idf 向量通過歐幾里得范數歸一化:
.
它源于一個詞權重的信息檢索方式(作為搜索引擎結果的評級函數),同時也在文檔分類和聚類中表現良好。
以下部分包含進一步說明和示例,說明如何精確計算 tf-idfs 以及如何在 scikit-learn 中計算 tf-idfs, [`TfidfTransformer`](generated/sklearn.feature_extraction.text.TfidfTransformer.html#sklearn.feature_extraction.text.TfidfTransformer "sklearn.feature_extraction.text.TfidfTransformer") 并 [`TfidfVectorizer`](generated/sklearn.feature_extraction.text.TfidfVectorizer.html#sklearn.feature_extraction.text.TfidfVectorizer "sklearn.feature_extraction.text.TfidfVectorizer") 與定義 idf 的標準教科書符號略有不同

在 [`TfidfTransformer`](generated/sklearn.feature_extraction.text.TfidfTransformer.html#sklearn.feature_extraction.text.TfidfTransformer "sklearn.feature_extraction.text.TfidfTransformer") 和 [`TfidfVectorizer`](generated/sklearn.feature_extraction.text.TfidfVectorizer.html#sklearn.feature_extraction.text.TfidfVectorizer "sklearn.feature_extraction.text.TfidfVectorizer") 中 `smooth_idf=False`,將 “1” 計數添加到 idf 而不是 idf 的分母:

該歸一化由類 [`TfidfTransformer`](generated/sklearn.feature_extraction.text.TfidfTransformer.html#sklearn.feature_extraction.text.TfidfTransformer "sklearn.feature_extraction.text.TfidfTransformer") 實現:
```
>>> from sklearn.feature_extraction.text import TfidfTransformer
>>> transformer = TfidfTransformer(smooth_idf=False)
>>> transformer
TfidfTransformer(norm=...'l2', smooth_idf=False, sublinear_tf=False,
use_idf=True)
```
有關所有參數的詳細信息,請參閱 [參考文檔](classes.html#text-feature-extraction-ref)。
讓我們以下方的詞頻為例。第一個次在任何時間都是100%出現,因此不是很有重要。另外兩個特征只占不到50%的比例,因此可能更具有代表性:
```
>>> counts = [[3, 0, 1],
... [2, 0, 0],
... [3, 0, 0],
... [4, 0, 0],
... [3, 2, 0],
... [3, 0, 2]]
...
>>> tfidf = transformer.fit_transform(counts)
>>> tfidf
<6x3 sparse matrix of type '<... 'numpy.float64'>'
with 9 stored elements in Compressed Sparse ... format>
>>> tfidf.toarray()
array([[ 0.81940995, 0. , 0.57320793],
[ 1. , 0. , 0. ],
[ 1. , 0. , 0. ],
[ 1. , 0. , 0. ],
[ 0.47330339, 0.88089948, 0. ],
[ 0.58149261, 0. , 0.81355169]])
```
每行都被正則化,使其適應歐幾里得標準:

例如,我們可以計算`計數`數組中第一個文檔中第一個項的 tf-idf ,如下所示:




現在,如果我們對文檔中剩下的2個術語重復這個計算,我們得到:


和原始 tf-idfs 的向量:
![\text{tf-idf}_raw = [3, 0, 2.0986].](https://box.kancloud.cn/f7baaba2868b146232496322ac2e67d7_190x18.jpg)
然后,應用歐幾里德(L2)規范,我們獲得文檔1的以下 tf-idfs:
![\frac{[3, 0, 2.0986]}{\sqrt{\big(3^2 + 0^2 + 2.0986^2\big)}} = [ 0.819, 0, 0.573].](https://box.kancloud.cn/4655ebd7d24920201b011de93bd11667_264x45.jpg)
此外,默認參數 `smooth_idf=True` 將 “1” 添加到分子和分母,就好像一個額外的文檔被看到一樣包含集合中的每個術語,這樣可以避免零分割:

使用此修改,文檔1中第三項的 tf-idf 更改為 1.8473:

而 L2 標準化的 tf-idf 變為
![\frac{[3, 0, 1.8473]}{\sqrt{\big(3^2 + 0^2 + 1.8473^2\big)}} = [0.8515, 0, 0.5243]](https://box.kancloud.cn/a19cab771e80fef8c6ebd1dee79e78c8_276x45.jpg):
```
>>> transformer = TfidfTransformer()
>>> transformer.fit_transform(counts).toarray()
array([[ 0.85151335, 0. , 0.52433293],
[ 1. , 0. , 0. ],
[ 1. , 0. , 0. ],
[ 1. , 0. , 0. ],
[ 0.55422893, 0.83236428, 0. ],
[ 0.63035731, 0. , 0.77630514]])
```
通過 `擬合` 方法調用計算的每個特征的權重存儲在模型屬性中:
```
>>> transformer.idf_
array([ 1. ..., 2.25..., 1.84...])
```
由于 tf-idf 經常用于文本特征,所以還有一個類 [`TfidfVectorizer`](generated/sklearn.feature_extraction.text.TfidfVectorizer.html#sklearn.feature_extraction.text.TfidfVectorizer "sklearn.feature_extraction.text.TfidfVectorizer") ,它將 [`CountVectorizer`](generated/sklearn.feature_extraction.text.CountVectorizer.html#sklearn.feature_extraction.text.CountVectorizer "sklearn.feature_extraction.text.CountVectorizer")和 [`TfidfTransformer`](generated/sklearn.feature_extraction.text.TfidfTransformer.html#sklearn.feature_extraction.text.TfidfTransformer "sklearn.feature_extraction.text.TfidfTransformer") 的所有選項組合在一個單例模型中:
```
>>> from sklearn.feature_extraction.text import TfidfVectorizer
>>> vectorizer = TfidfVectorizer()
>>> vectorizer.fit_transform(corpus)
...
<4x9 sparse matrix of type '<... 'numpy.float64'>'
with 19 stored elements in Compressed Sparse ... format>
```
雖然tf-idf標準化通常非常有用,但是可能有一種情況是二元變量顯示會提供更好的特征。 這可以使用類 [`CountVectorizer`](generated/sklearn.feature_extraction.text.CountVectorizer.html#sklearn.feature_extraction.text.CountVectorizer "sklearn.feature_extraction.text.CountVectorizer") 的 `二進制` 參數來實現。 特別地,一些估計器,諸如 [伯努利樸素貝葉斯](naive_bayes.html#bernoulli-naive-bayes) 顯式的使用離散的布爾隨機變量。 而且,非常短的文本很可能影響 tf-idf 值,而二進制出現信息更穩定。
通常情況下,調整特征提取參數的最佳方法是使用基于網格搜索的交叉驗證,例如通過將特征提取器與分類器進行流水線化:
> - 用于文本特征提取和評估的樣本管道 [Sample pipeline for text feature extraction and evaluation](../auto_examples/model_selection/grid_search_text_feature_extraction.html#sphx-glr-auto-examples-model-selection-grid-search-text-feature-extraction-py)
### 4.2.3.5. 解碼文本文件
文本由字符組成,但文件由字節組成。字節轉化成字符依照一定的編碼(encoding)方式。 為了在Python中的使用文本文檔,這些字節必須被 *解碼* 為 Unicode 的字符集。 常用的編碼方式有 ASCII,Latin-1(西歐),KOI8-R(俄語)和通用編碼 UTF-8 和 UTF-16。還有許多其他的編碼存在
Note
編碼也可以稱為 ‘字符集’, 但是這個術語不太準確: 單個字符集可能存在多個編碼。
scikit-learn 中的文本提取器知道如何解碼文本文件, 但只有當您告訴他們文件的編碼的情況下才行, [`CountVectorizer`](generated/sklearn.feature_extraction.text.CountVectorizer.html#sklearn.feature_extraction.text.CountVectorizer "sklearn.feature_extraction.text.CountVectorizer") 才需要一個 `encoding` 參數。 對于現代文本文件,正確的編碼可能是 UTF-8,因此它也是默認解碼方式 (`encoding="utf-8"`).
如果正在加載的文本不是使用UTF-8進行編碼,則會得到 `UnicodeDecodeError`. 矢量化的方式可以通過設定 `decode_error` 參數設置為 `"ignore"` 或
```
"replace"``來避免拋出解碼錯誤。
有關詳細信息,請參閱Python函數 ``bytes.decode
```
的文檔(在Python提示符下鍵入 `help(bytes.decode)` )。
如果您在解碼文本時遇到問題,請嘗試以下操作:
- 了解文本的實際編碼方式。該文件可能帶有標題或 README,告訴您編碼,或者可能有一些標準編碼,您可以根據文本的來源來推斷編碼方式。
- 您可能可以使用 UNIX 命令 `file` 找出它一般使用什么樣的編碼。 Python `chardet` 模塊附帶一個名為 `chardetect.py` 的腳本,它會猜測具體的編碼,盡管你不能依靠它的猜測是正確的。
- 你可以嘗試 UTF-8 并忽略錯誤。您可以使用 `bytes.decode(errors='replace')` 對字節字符串進行解碼,用無意義字符替換所有解碼錯誤,或在向量化器中設置 `decode_error='replace'`. 這可能會損壞您的功能的有用性。
- 真實文本可能來自各種使用不同編碼的來源,或者甚至以與編碼的編碼不同的編碼進行粗略解碼。這在從 Web 檢索的文本中是常見的。Python 包 [ftfy](https://github.com/LuminosoInsight/python-ftfy) 可以自動排序一些解碼錯誤類,所以您可以嘗試將未知文本解碼為 `latin-1`,然后使用 `ftfy` 修復錯誤。
- 如果文本的編碼的混合,那么它很難整理分類(20個新聞組數據集的情況),您可以把它們回到簡單的單字節編碼,如 `latin-1`。某些文本可能顯示不正確,但至少相同的字節序列將始終代表相同的功能。
例如,以下代碼段使用 `chardet` (未附帶 scikit-learn,必須單獨安裝)來計算出編碼方式。然后,它將文本向量化并打印學習的詞匯(特征)。輸出在下方給出。
```
>>> import chardet
>>> text1 = b"Sei mir gegr\xc3\xbc\xc3\x9ft mein Sauerkraut"
>>> text2 = b"holdselig sind deine Ger\xfcche"
>>> text3 = b"\xff\xfeA\x00u\x00f\x00 \x00F\x00l\x00\xfc\x00g\x00e\x00l\x00n\x00 \x00d\x00e\x00s\x00 \x00G\x00e\x00s\x00a\x00n\x00g\x00e\x00s\x00,\x00 \x00H\x00e\x00r\x00z\x00l\x00i\x00e\x00b\x00c\x00h\x00e\x00n\x00,\x00 \x00t\x00r\x00a\x00g\x00 \x00i\x00c\x00h\x00 \x00d\x00i\x00c\x00h\x00 \x00f\x00o\x00r\x00t\x00"
>>> decoded = [x.decode(chardet.detect(x)['encoding'])
... for x in (text1, text2, text3)]
>>> v = CountVectorizer().fit(decoded).vocabulary_
>>> for term in v: print(v)
```
(根據 `chardet` 的版本,可能會返回第一個值錯誤的結果。) 有關 Unicode 和字符編碼的一般介紹,請參閱Joel Spolsky的 [絕對最小每個軟件開發人員必須了解 Unicode](http://www.joelonsoftware.com/articles/Unicode.html).
### 4.2.3.6. 應用和實例
詞匯表達方式相當簡單,但在實踐中卻非常有用。
特別是在 **監督學習的設置** 中,它能夠把快速和可擴展的線性模型組合來訓練 **文檔分類器**, 例如:
> - 使用稀疏特征對文本文檔進行分類 [Classification of text documents using sparse features](../auto_examples/text/document_classification_20newsgroups.html#sphx-glr-auto-examples-text-document-classification-20newsgroups-py)
在 **無監督的設置** 中,可以通過應用諸如 [K-means](clustering.html#k-means) 的聚類算法來將相似文檔分組在一起:
> - 使用k-means聚類文本文檔 [Clustering text documents using k-means](../auto_examples/text/document_clustering.html#sphx-glr-auto-examples-text-document-clustering-py)
最后,通過松弛聚類的約束條件,可以通過使用非負矩陣分解( [非負矩陣分解(NMF 或 NNMF)](decomposition.html#nmf) 或NNMF)來發現語料庫的主要主題:
> - 主題提取與非負矩陣分解和潛在Dirichlet分配 [Topic extraction with Non-negative Matrix Factorization and Latent Dirichlet Allocation](../auto_examples/applications/plot_topics_extraction_with_nmf_lda.html#sphx-glr-auto-examples-applications-plot-topics-extraction-with-nmf-lda-py)
### 4.2.3.7. 詞語表示的限制
一組單詞(什么是單詞)無法捕獲短語和多字表達,有效地忽略任何單詞順序依賴。另外,這個單詞模型不包含潛在的拼寫錯誤或詞匯導出。
N克搶救!而不是構建一個簡單的unigrams集合 (n=1),可能更喜歡一組二進制 (n=2),其中計算連續字對。
還可以考慮一個字符 n-gram 的集合,這是一種對拼寫錯誤和派生有彈性的表示。
例如,假設我們正在處理兩個文檔的語料庫: `['words', 'wprds']`. 第二個文件包含 ‘words’ 一詞的拼寫錯誤。 一個簡單的單詞表示將把這兩個視為非常不同的文檔,兩個可能的特征都是不同的。 然而,一個字符 2-gram 的表示可以找到匹配的文檔中的8個特征中的4個,這可能有助于優選的分類器更好地決定:
```
>>> ngram_vectorizer = CountVectorizer(analyzer='char_wb', ngram_range=(2, 2))
>>> counts = ngram_vectorizer.fit_transform(['words', 'wprds'])
>>> ngram_vectorizer.get_feature_names() == (
... [' w', 'ds', 'or', 'pr', 'rd', 's ', 'wo', 'wp'])
True
>>> counts.toarray().astype(int)
array([[1, 1, 1, 0, 1, 1, 1, 0],
[1, 1, 0, 1, 1, 1, 0, 1]])
```
在上面的例子中,使用 `'char_wb` 分析器’,它只能從字邊界內的字符(每側填充空格)創建 n-gram。 `'char'` 分析器可以創建跨越單詞的 n-gram:
```
>>> ngram_vectorizer = CountVectorizer(analyzer='char_wb', ngram_range=(5, 5))
>>> ngram_vectorizer.fit_transform(['jumpy fox'])
...
<1x4 sparse matrix of type '<... 'numpy.int64'>'
with 4 stored elements in Compressed Sparse ... format>
>>> ngram_vectorizer.get_feature_names() == (
... [' fox ', ' jump', 'jumpy', 'umpy '])
True
>>> ngram_vectorizer = CountVectorizer(analyzer='char', ngram_range=(5, 5))
>>> ngram_vectorizer.fit_transform(['jumpy fox'])
...
<1x5 sparse matrix of type '<... 'numpy.int64'>'
with 5 stored elements in Compressed Sparse ... format>
>>> ngram_vectorizer.get_feature_names() == (
... ['jumpy', 'mpy f', 'py fo', 'umpy ', 'y fox'])
True
```
對于使用白色空格進行單詞分離的語言,對于語言邊界感知變體 `char_wb` 尤其有趣,因為在這種情況下,它會產生比原始 `char` 變體顯著更少的噪音特征。 對于這樣的語言,它可以增加使用這些特征訓練的分類器的預測精度和收斂速度,同時保持關于拼寫錯誤和詞導出的穩健性。
雖然可以通過提取 n-gram 而不是單獨的單詞來保存一些本地定位信息,但是包含 n-gram 的單詞和袋子可以破壞文檔的大部分內部結構,因此破壞了該內部結構的大部分含義。
為了處理自然語言理解的更廣泛的任務,因此應考慮到句子和段落的地方結構。因此,許多這樣的模型將被稱為 “結構化輸出” 問題,這些問題目前不在 scikit-learn 的范圍之內。
### 4.2.3.8. 用哈希技巧矢量化大文本語料庫
上述向量化方案是簡單的,但是它存在 **從字符串令牌到整數特征索引的內存映射** ( `vocabulary_` 屬性),在處理 **大型數據集時會引起幾個問題** :
- 語料庫越大,詞匯量越大,使用的內存也越大.
- 擬合(fitting)需要根據原始數據集的大小等比例分配中間數據結構的大小.
- 構建詞映射需要完整的傳遞數據集,因此不可能以嚴格在線的方式擬合文本分類器.
- pickling和un-pickling vocabulary 很大的向量器會非常慢(通常比pickling/un-pickling單純數據的結構,比如同等大小的Numpy數組).
- 將向量化任務分隔成并行的子任務很不容易實現,因為 `vocabulary_` 屬性要共享狀態有一個細顆粒度的同步障礙:從標記字符串中映射特征索引與每個標記的首次出現順序是獨立的,因此應該被共享,在這點上并行worker的性能收到了損害,使他們比串行更慢。
通過組合由 [`sklearn.feature_extraction.FeatureHasher`](generated/sklearn.feature_extraction.FeatureHasher.html#sklearn.feature_extraction.FeatureHasher "sklearn.feature_extraction.FeatureHasher") 類實現的 “散列技巧” ([特征哈希(相當于一種降維技巧)](#feature-hashing)) 和 [`CountVectorizer`](generated/sklearn.feature_extraction.text.CountVectorizer.html#sklearn.feature_extraction.text.CountVectorizer "sklearn.feature_extraction.text.CountVectorizer") 的文本預處理和標記化功能,可以克服這些限制。
這種組合是在 [`HashingVectorizer`](generated/sklearn.feature_extraction.text.HashingVectorizer.html#sklearn.feature_extraction.text.HashingVectorizer "sklearn.feature_extraction.text.HashingVectorizer") 中實現的,該類是與 [`CountVectorizer`](generated/sklearn.feature_extraction.text.CountVectorizer.html#sklearn.feature_extraction.text.CountVectorizer "sklearn.feature_extraction.text.CountVectorizer") 大部分 API 兼容的變壓器類。 [`HashingVectorizer`](generated/sklearn.feature_extraction.text.HashingVectorizer.html#sklearn.feature_extraction.text.HashingVectorizer "sklearn.feature_extraction.text.HashingVectorizer") 是無狀態的,這意味著您不需要 `fit` 它:
```
>>> from sklearn.feature_extraction.text import HashingVectorizer
>>> hv = HashingVectorizer(n_features=10)
>>> hv.transform(corpus)
...
<4x10 sparse matrix of type '<... 'numpy.float64'>'
with 16 stored elements in Compressed Sparse ... format>
```
你可以看到從向量輸出中抽取了16個非0特征標記:與之前由CountVectorizer在同一個樣本語料庫抽取的19個非0特征要少。差異來自哈希方法的沖突,因為較低的n\_features參數的值。
在真實世界的環境下,n\_features參數可以使用默認值2 \*\* 20(將近100萬可能的特征)。如果內存或者下游模型的大小是一個問題,那么選擇一個較小的值比如2 \*\* 18可能有一些幫助,而不需要為典型的文本分類任務引入太多額外的沖突。
注意維度并不影響CPU的算法訓練時間,這部分是在操作CSR指標(LinearSVC(dual=True), Perceptron, SGDClassifier, PassiveAggressive),但是,它對CSC matrices (LinearSVC(dual=False), Lasso(), etc)算法有效。
讓我們再次嘗試使用默認設置:
```
>>> hv = HashingVectorizer()
>>> hv.transform(corpus)
...
<4x1048576 sparse matrix of type '<... 'numpy.float64'>'
with 19 stored elements in Compressed Sparse ... format>
```
沖突沒有再出現,但是,代價是輸出空間的維度值非常大。當然,這里使用的19詞以外的其他詞之前仍會有沖突。
類 [`HashingVectorizer`](generated/sklearn.feature_extraction.text.HashingVectorizer.html#sklearn.feature_extraction.text.HashingVectorizer "sklearn.feature_extraction.text.HashingVectorizer") 還具有以下限制:
- 不能反轉模型(沒有inverse\_transform方法),也無法訪問原始的字符串表征,因為,進行mapping的哈希方法是單向本性。
- 沒有提供了IDF權重,因為這需要在模型中引入狀態。如果需要的話,可以在管道中添加 [`TfidfTransformer`](generated/sklearn.feature_extraction.text.TfidfTransformer.html#sklearn.feature_extraction.text.TfidfTransformer "sklearn.feature_extraction.text.TfidfTransformer") 。
### 4.2.3.9. 使用 HashingVectorizer 執行外核縮放
使用 [`HashingVectorizer`](generated/sklearn.feature_extraction.text.HashingVectorizer.html#sklearn.feature_extraction.text.HashingVectorizer "sklearn.feature_extraction.text.HashingVectorizer") 的一個有趣的開發是執行外核 [out-of-core](https://en.wikipedia.org/wiki/Out-of-core_algorithm) 縮放的能力。 這意味著我們可以從無法放入電腦主內存的數據中進行學習。
實現核外擴展的一個策略是將數據以流的方式以一小批提交給評估器。每批的向量化都是用HashingVectorizer這樣來保證評估器的輸入空間的維度是相等的。因此任何時間使用的內存數都限定在小頻次的大小。 盡管用這種方法可以處理的數據沒有限制,但是從實用角度學習時間受到想要在這個任務上花費的CPU時間的限制。
對于文本分類任務中的外核縮放的完整示例,請參閱文本文檔的外核分類 [Out-of-core classification of text documents](../auto_examples/applications/plot_out_of_core_classification.html#sphx-glr-auto-examples-applications-plot-out-of-core-classification-py).
### 4.2.3.10. 自定義矢量化器類
通過將可調用傳遞給向量化程序構造函數可以定制行為:
```
>>> def my_tokenizer(s):
... return s.split()
...
>>> vectorizer = CountVectorizer(tokenizer=my_tokenizer)
>>> vectorizer.build_analyzer()(u"Some... punctuation!") == (
... ['some...', 'punctuation!'])
True
```
特別是我們命名:
> - `預處理器`: 可以將整個文檔作為輸入(作為單個字符串)的可調用,并返回文檔的可能轉換的版本,仍然是整個字符串。這可以用于刪除HTML標簽,小寫整個文檔等。
> - `tokenizer`: 一個可從預處理器接收輸出并將其分成標記的可調用函數,然后返回這些列表。
> - `分析器`: 一個可替代預處理程序和標記器的可調用程序。默認分析儀都會調用預處理器和刻錄機,但是自定義分析儀將會跳過這個。 N-gram提取和停止字過濾在分析器級進行,因此定制分析器可能必須重現這些步驟。
(Lucene 用戶可能會識別這些名稱,但請注意,scikit-learn 概念可能無法一對一映射到 Lucene 概念上。)
為了使預處理器,標記器和分析器了解模型參數,可以從類派生并覆蓋 `build_preprocessor`, `build_tokenizer`` 和 `build_analyzer` 工廠方法,而不是傳遞自定義函數。
一些提示和技巧:
> - 如果文檔由外部包進行預先標記,則將它們存儲在文件(或字符串)中,令牌由空格分隔,并通過 `analyzer=str.split`
> - Fancy 令牌級分析,如詞干,詞法,復合分割,基于詞性的過濾等不包括在 scikit-learn 代碼庫中,但可以通過定制分詞器或分析器來添加。
>
> 這是一個 `CountVectorizer`, 使用 [NLTK](http://www.nltk.org) 的 tokenizer 和 lemmatizer:
>
>
> ```
> >>> from nltk import word_tokenize # doctest: +SKIP
> >>> from nltk.stem import WordNetLemmatizer # doctest: +SKIP
> >>> class LemmaTokenizer(object):
> ... def __init__(self):
> ... self.wnl = WordNetLemmatizer()
> ... def __call__(self, doc):
> ... return [self.wnl.lemmatize(t) for t in word_tokenize(doc)]
> ...
> >>> vect = CountVectorizer(tokenizer=LemmaTokenizer()) # doctest: +SKIP
>
> (請注意,這不會過濾標點符號。)
> 例如,以下例子將英國的一些拼寫變成美國拼寫::
>
> >>> import re
> >>> def to_british(tokens):
> ... for t in tokens:
> ... t = re.sub(r"(...)our$", r"\1or", t)
> ... t = re.sub(r"([bt])re$", r"\1er", t)
> ... t = re.sub(r"([iy])s(e$|ing|ation)", r"\1z\2", t)
> ... t = re.sub(r"ogue$", "og", t)
> ... yield t
> ...
> >>> class CustomVectorizer(CountVectorizer):
> ... def build_tokenizer(self):
> ... tokenize = super(CustomVectorizer, self).build_tokenizer()
> ... return lambda doc: list(to_british(tokenize(doc)))
> ...
> >>> print(CustomVectorizer().build_analyzer()(u"color colour")) # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
> [...'color', ...'color']
>
> 用于其他樣式的預處理; 例子包括 stemming, lemmatization, 或 normalizing numerical tokens, 后者說明如下:
>
> * :ref:`sphx_glr_auto_examples_bicluster_plot_bicluster_newsgroups.py`
>
> ```
在處理不使用顯式字分隔符(例如空格)的亞洲語言時,自定義向量化器也是有用的。
## 4.2.4. 圖像特征提取
### 4.2.4.1. 補丁提取
[`extract_patches_2d`](generated/sklearn.feature_extraction.image.extract_patches_2d.html#sklearn.feature_extraction.image.extract_patches_2d "sklearn.feature_extraction.image.extract_patches_2d") 函數從存儲為二維數組的圖像或沿著第三軸的顏色信息三維提取修補程序。 要從其所有補丁重建圖像,請使用 [`reconstruct_from_patches_2d`](generated/sklearn.feature_extraction.image.reconstruct_from_patches_2d.html#sklearn.feature_extraction.image.reconstruct_from_patches_2d "sklearn.feature_extraction.image.reconstruct_from_patches_2d"). 例如讓我們使用3個彩色通道(例如 RGB 格式)生成一個 4x4 像素的圖像:
```
>>> import numpy as np
>>> from sklearn.feature_extraction import image
>>> one_image = np.arange(4 * 4 * 3).reshape((4, 4, 3))
>>> one_image[:, :, 0] # R channel of a fake RGB picture
array([[ 0, 3, 6, 9],
[12, 15, 18, 21],
[24, 27, 30, 33],
[36, 39, 42, 45]])
>>> patches = image.extract_patches_2d(one_image, (2, 2), max_patches=2,
... random_state=0)
>>> patches.shape
(2, 2, 2, 3)
>>> patches[:, :, :, 0]
array([[[ 0, 3],
[12, 15]],
[[15, 18],
[27, 30]]])
>>> patches = image.extract_patches_2d(one_image, (2, 2))
>>> patches.shape
(9, 2, 2, 3)
>>> patches[4, :, :, 0]
array([[15, 18],
[27, 30]])
```
現在讓我們嘗試通過在重疊區域進行平均來從補丁重建原始圖像:
```
>>> reconstructed = image.reconstruct_from_patches_2d(patches, (4, 4, 3))
>>> np.testing.assert_array_equal(one_image, reconstructed)
```
在 [`PatchExtractor`](generated/sklearn.feature_extraction.image.PatchExtractor.html#sklearn.feature_extraction.image.PatchExtractor "sklearn.feature_extraction.image.PatchExtractor") 以同樣的方式類作品 [`extract_patches_2d`](generated/sklearn.feature_extraction.image.extract_patches_2d.html#sklearn.feature_extraction.image.extract_patches_2d "sklearn.feature_extraction.image.extract_patches_2d"), 只是它支持多種圖像作為輸入。它被實現為一個估計器,因此它可以在管道中使用。看到:
```
>>> five_images = np.arange(5 * 4 * 4 * 3).reshape(5, 4, 4, 3)
>>> patches = image.PatchExtractor((2, 2)).transform(five_images)
>>> patches.shape
(45, 2, 2, 3)
```
### 4.2.4.2. 圖像的連接圖
scikit-learn 中的幾個估計可以使用特征或樣本之間的連接信息。 例如,Ward聚類(層次聚類 [層次聚類](clustering.html#hierarchical-clustering) )可以聚集在一起,只有圖像的相鄰像素,從而形成連續的斑塊:
[](../auto_examples/cluster/plot_face_ward_segmentation.html)
為此,估計器使用 ‘連接性’ 矩陣,給出連接的樣本。
該函數 [`img_to_graph`](generated/sklearn.feature_extraction.image.img_to_graph.html#sklearn.feature_extraction.image.img_to_graph "sklearn.feature_extraction.image.img_to_graph") 從2D或3D圖像返回這樣一個矩陣。類似地,[`grid_to_graph`](generated/sklearn.feature_extraction.image.grid_to_graph.html#sklearn.feature_extraction.image.grid_to_graph "sklearn.feature_extraction.image.grid_to_graph") 為給定這些圖像的形狀的圖像構建連接矩陣。
這些矩陣可用于在使用連接信息的估計器中強加連接,如 Ward 聚類(層次聚類 [層次聚類](clustering.html#hierarchical-clustering) ),而且還要構建預計算的內核或相似矩陣。
Note
**示例**
- [A demo of structured Ward hierarchical clustering on a raccoon face image](../auto_examples/cluster/plot_face_ward_segmentation.html#sphx-glr-auto-examples-cluster-plot-face-ward-segmentation-py)
- [Spectral clustering for image segmentation](../auto_examples/cluster/plot_segmentation_toy.html#sphx-glr-auto-examples-cluster-plot-segmentation-toy-py)
- [Feature agglomeration vs. univariate selection](../auto_examples/cluster/plot_feature_agglomeration_vs_univariate_selection.html#sphx-glr-auto-examples-cluster-plot-feature-agglomeration-vs-univariate-selection-py)
- scikit-learn 0.19 中文文檔
- 用戶指南
- 1. 監督學習
- 1.1. 廣義線性模型
- 1.2. 線性和二次判別分析
- 1.3. 內核嶺回歸
- 1.4. 支持向量機
- 1.5. 隨機梯度下降
- 1.6. 最近鄰
- 1.7. 高斯過程
- 1.8. 交叉分解
- 1.9. 樸素貝葉斯
- 1.10. 決策樹
- 1.11. 集成方法
- 1.12. 多類和多標簽算法
- 1.13. 特征選擇
- 1.14. 半監督學習
- 1.15. 等式回歸
- 1.16. 概率校準
- 1.17. 神經網絡模型(有監督)
- 2. 無監督學習
- 2.1. 高斯混合模型
- 2.2. 流形學習
- 2.3. 聚類
- 2.4. 雙聚類
- 2.5. 分解成分中的信號(矩陣分解問題)
- 2.6. 協方差估計
- 2.7. 經驗協方差
- 2.8. 收斂協方差
- 2.9. 稀疏逆協方差
- 2.10. Robust 協方差估計
- 2.11. 新奇和異常值檢測
- 2.12. 密度估計
- 2.13. 神經網絡模型(無監督)
- 3. 模型選擇和評估
- 3.1. 交叉驗證:評估估算器的表現
- 3.2. 調整估計器的超參數
- 3.3. 模型評估: 量化預測的質量
- 3.4. 模型持久化
- 3.5. 驗證曲線: 繪制分數以評估模型
- 4. 數據集轉換
- 4.1. Pipeline(管道)和 FeatureUnion(特征聯合): 合并的評估器
- 4.2. 特征提取
- 4.3. 預處理數據
- 4.4. 無監督降維
- 4.5. 隨機投影
- 4.6. 內核近似
- 4.7. 成對的矩陣, 類別和核函數
- 4.8. 預測目標 (y) 的轉換
- 5. 數據集加載工具
- 6. 大規模計算的策略: 更大量的數據
- 7. 計算性能
- 教程
- 使用 scikit-learn 介紹機器學習
- 關于科學數據處理的統計學習教程
- 機器學習: scikit-learn 中的設置以及預估對象
- 監督學習:從高維觀察預測輸出變量
- 模型選擇:選擇估計量及其參數
- 無監督學習: 尋求數據表示
- 把它們放在一起
- 尋求幫助
- 處理文本數據
- 選擇正確的評估器(estimator)
- 外部資源,視頻和談話