譯者:飛龍
協(xié)議:CC BY-NC-SA 4.0
自豪地采用谷歌翻譯
聚類和 KMeans
我們現(xiàn)在冒險(xiǎn)進(jìn)入我們的第一個應(yīng)用罗售,即使用 k-means 算法進(jìn)行聚類景醇。 聚類是一種數(shù)據(jù)挖掘練習(xí),我們獲取大量數(shù)據(jù)并找到彼此相似的點(diǎn)的分組疫粥。 K-means 是一種非常善于在許多類型的數(shù)據(jù)集中查找簇的算法。
對于簇和 k-means的 更多信息箫柳,請參閱 k-means 算法的 scikit-learn 文檔或觀看此視頻手形。
生成樣本
首先啥供,我們需要生成一些樣本悯恍。 我們可以隨機(jī)生成樣本,但這可能會給我們提供非常稀疏的點(diǎn)伙狐,或者只是一個大分組 - 對于聚類來說并不是非常令人興奮涮毫。
相反,我們將從生成三個質(zhì)心開始贷屎,然后在該點(diǎn)周圍隨機(jī)選擇(具有正態(tài)分布)罢防。 首先,這是一個執(zhí)行此操作的方法
import tensorflow as tf
import numpy as np
def create_samples(n_clusters, n_samples_per_cluster, n_features, embiggen_factor, seed):
np.random.seed(seed)
slices = []
centroids = []
# 為每個簇創(chuàng)建樣本
for i in range(n_clusters):
samples = tf.random_normal((n_samples_per_cluster, n_features),
mean=0.0, stddev=5.0, dtype=tf.float32, seed=seed, name="cluster_{}".format(i))
current_centroid = (np.random.random((1, n_features)) * embiggen_factor) - (embiggen_factor/2)
centroids.append(current_centroid)
samples += current_centroid
slices.append(samples)
# 創(chuàng)建一個大的“樣本”數(shù)據(jù)集
samples = tf.concat(slices, 0, name='samples')
centroids = tf.concat(centroids, 0, name='centroids')
return centroids, samples
這種方法的工作方式是隨機(jī)創(chuàng)建n_clusters
個不同的質(zhì)心(使用np.random.random((1, n_features))
)并將它們用作tf.random_normal
的質(zhì)心唉侄。 tf.random_normal
函數(shù)生成正態(tài)分布的隨機(jī)值咒吐,然后我們將其添加到當(dāng)前質(zhì)心。 這會在該形心周圍創(chuàng)建一些點(diǎn)属划。 然后我們記錄質(zhì)心(centroids.append
)和生成的樣本(slices.append(samples)
)恬叹。 最后,我們使用tf.concat
創(chuàng)建“一個大樣本列表”同眯,并使用tf.concat
將質(zhì)心轉(zhuǎn)換為 TensorFlow 變量绽昼。
將create_samples
方法保存在名為functions.py
的文件中,允許我們?yōu)檫@個(以及下一個P胛稀)課程硅确,將這些方法導(dǎo)入到我們的腳本中目溉。 創(chuàng)建一個名為generate_samples.py
的新文件,其中包含以下代碼:
import tensorflow as tf
import numpy as np
from functions import create_samples
n_features = 2
n_clusters = 3
n_samples_per_cluster = 500
seed = 700
embiggen_factor = 70
np.random.seed(seed)
centroids, samples = create_samples(n_clusters, n_samples_per_cluster, n_features, embiggen_factor, seed)
model = tf.global_variables_initializer()
with tf.Session() as session:
sample_values = session.run(samples)
centroid_values = session.run(centroids)
這只是設(shè)置了簇和特征的數(shù)量(我建議將特征的數(shù)量保持為 2菱农,以便我們以后可以可視化它們)缭付,以及要生成的樣本數(shù)。 增加embiggen_factor
將增加簇的“散度”或大小循未。 我在這里選擇了一個提供良好學(xué)習(xí)機(jī)會的值蛉腌,因?yàn)樗梢陨梢曈X上可識別的集群。
為了使結(jié)果可視化只厘,我們使用matplotlib
創(chuàng)建繪圖函數(shù)烙丛。 將此代碼添加到functions.py
:
def plot_clusters(all_samples, centroids, n_samples_per_cluster):
import matplotlib.pyplot as plt
# 繪制出不同的簇
# 為每個簇選擇不同的顏色
colour = plt.cm.rainbow(np.linspace(0,1,len(centroids)))
for i, centroid in enumerate(centroids):
# 為給定簇抓取樣本,并用新顏色繪制出來
samples = all_samples[i*n_samples_per_cluster:(i+1)*n_samples_per_cluster]
plt.scatter(samples[:,0], samples[:,1], c=colour[i])
# 還繪制質(zhì)心
plt.plot(centroid[0], centroid[1], markersize=35, marker="x", color='k', mew=10)
plt.plot(centroid[0], centroid[1], markersize=30, marker="x", color='m', mew=5)
plt.show()
所有這些代碼都是使用不同的顏色繪制每個簇的樣本羔味,并在質(zhì)心位置創(chuàng)建一個大的紅色X
河咽。 質(zhì)心提供為參數(shù),稍后會很方便赋元。
更新generate_samples.py
忘蟹,通過將import plot_clusters
添加到文件頂部來導(dǎo)入此函數(shù)。 然后搁凸,將這行代碼添加到底部:
plot_clusters(sample_values, centroid_values, n_samples_per_cluster)
運(yùn)行generate_samples.py
現(xiàn)在應(yīng)該提供以下繪圖:
初始化
k-means 算法從初始質(zhì)心的選擇開始媚值,初始質(zhì)心只是數(shù)據(jù)中實(shí)際質(zhì)心的隨機(jī)猜測。 以下函數(shù)將從數(shù)據(jù)集中隨機(jī)選擇多個樣本作為此初始猜測:
def choose_random_centroids(samples, n_clusters):
# 第 0 步:初始化:選擇 n_clusters 個隨機(jī)點(diǎn)
n_samples = tf.shape(samples)[0]
random_indices = tf.random_shuffle(tf.range(0, n_samples))
begin = [0,]
size = [n_clusters,]
size[0] = n_clusters
centroid_indices = tf.slice(random_indices, begin, size)
initial_centroids = tf.gather(samples, centroid_indices)
return initial_centroids
這段代碼首先為每個樣本創(chuàng)建一個索引(使用tf.range(0, n_samples)
护糖,然后隨機(jī)打亂它褥芒。從那里,我們使用tf.slice
選擇固定數(shù)量(n_clusters
)的索引嫡良。這些索引與我們的初始質(zhì)心相關(guān)锰扶,然后使用tf.gather
組合在一起形成我們的初始質(zhì)心數(shù)組。
將這個新的choose_random_centorids
函數(shù)添加到functions.py
中寝受,并創(chuàng)建一個新腳本(或更新前一個腳本)坷牛,寫入以下內(nèi)容:
import tensorflow as tf
import numpy as np
from functions import create_samples, choose_random_centroids, plot_clusters
n_features = 2
n_clusters = 3
n_samples_per_cluster = 500
seed = 700
embiggen_factor = 70
centroids, samples = create_samples(n_clusters, n_samples_per_cluster, n_features, embiggen_factor, seed)
initial_centroids = choose_random_centroids(samples, n_clusters)
model = tf.global_variables_initializer()
with tf.Session() as session:
sample_values = session.run(samples)
updated_centroid_value = session.run(initial_centroids)
plot_clusters(sample_values, updated_centroid_value, n_samples_per_cluster)
這里的主要變化是我們?yōu)檫@些初始質(zhì)心創(chuàng)建變量,并在會話中計(jì)算其值很澄。 然后京闰,我們將初始猜測繪制到plot_cluster
,而不是用于生成數(shù)據(jù)的實(shí)際質(zhì)心甩苛。
運(yùn)行此操作會將得到與上面類似的圖像蹂楣,但質(zhì)心將處于隨機(jī)位置。 嘗試運(yùn)行此腳本幾次浪藻,注意質(zhì)心移動了很多捐迫。
更新質(zhì)心
在開始對質(zhì)心位置進(jìn)行一些猜測之后,然后 k-means 算法基于數(shù)據(jù)更新那些猜測爱葵。 該過程是為每個樣本分配一個簇號施戴,表示它最接近的質(zhì)心反浓。 之后,將質(zhì)心更新為分配給該簇的所有樣本的平均值赞哗。 以下代碼處理分配到最近的簇的步驟:
def assign_to_nearest(samples, centroids):
# 為每個樣本查找最近的質(zhì)心
# START from http://esciencegroup.com/2016/01/05/an-encounter-with-googles-tensorflow/
expanded_vectors = tf.expand_dims(samples, 0)
expanded_centroids = tf.expand_dims(centroids, 1)
distances = tf.reduce_sum( tf.square(
tf.subtract(expanded_vectors, expanded_centroids)), 2)
mins = tf.argmin(distances, 0)
# END from http://esciencegroup.com/2016/01/05/an-encounter-with-googles-tensorflow/
nearest_indices = mins
return nearest_indices
請注意雷则,我從這個頁面借用了一些代碼,這些代碼具有不同類型的 k-means 算法肪笋,以及許多其他有用的信息月劈。
這種方法的工作方式是計(jì)算每個樣本和每個質(zhì)心之間的距離,這通過distances =
那行來實(shí)現(xiàn)藤乙。 這里的距離計(jì)算是歐幾里德距離猜揪。 這里重要的一點(diǎn)是tf.subtract
會自動擴(kuò)展兩個參數(shù)的大小。 這意味著將我們作為矩陣的樣本坛梁,和作為列向量的質(zhì)心將在它們之間產(chǎn)生成對減法而姐。 為了實(shí)現(xiàn),我們使用tf.expand_dims
為樣本和質(zhì)心創(chuàng)建一個額外的維度划咐,強(qiáng)制tf.subtract
的這種行為拴念。
下一步代碼處理質(zhì)心更新:
def update_centroids(samples, nearest_indices, n_clusters):
# 將質(zhì)心更新為與其相關(guān)的所有樣本的平均值。
nearest_indices = tf.to_int32(nearest_indices)
partitions = tf.dynamic_partition(samples, nearest_indices, n_clusters)
new_centroids = tf.concat([tf.expand_dims(tf.reduce_mean(partition, 0), 0) for partition in partitions], 0)
return new_centroids
此代碼選取每個樣本的最近索引褐缠,并使用tf.dynamic_partition
將這些索引分到單獨(dú)的組中政鼠。 從這里開始,我們在一個組中使用tf.reduce_mean
來查找該組的平均值队魏,從而形成新的質(zhì)心公般。 我們只需將它們連接起來形成我們的新質(zhì)心。
現(xiàn)在我們有了這個部分器躏,我們可以將這些調(diào)用添加到我們的腳本中(或者創(chuàng)建一個新腳本):
import tensorflow as tf
import numpy as np
from functions import *
n_features = 2
n_clusters = 3
n_samples_per_cluster = 500
seed = 700
embiggen_factor = 70
data_centroids, samples = create_samples(n_clusters, n_samples_per_cluster, n_features, embiggen_factor, seed)
initial_centroids = choose_random_centroids(samples, n_clusters)
nearest_indices = assign_to_nearest(samples, initial_centroids)
updated_centroids = update_centroids(samples, nearest_indices, n_clusters)
model = tf.global_variables_initializer()
with tf.Session() as session:
sample_values = session.run(samples)
updated_centroid_value = session.run(updated_centroids)
print(updated_centroid_value)
plot_clusters(sample_values, updated_centroid_value, n_samples_per_cluster)
此代碼將:
- 從初始質(zhì)心生成樣本
- 隨機(jī)選擇初始質(zhì)心
- 關(guān)聯(lián)每個樣本和最近的質(zhì)心
- 將每個質(zhì)心更新為與關(guān)聯(lián)的樣本的平均值
這是 k-means 的單次迭代俐载! 我鼓勵你們練習(xí)一下蟹略,把它變成一個迭代版本登失。
1)傳遞給generate_samples
的種子選項(xiàng)可確保每次運(yùn)行腳本時(shí),“隨機(jī)”生成的樣本都是一致的挖炬。 我們沒有將種子傳遞給choose_random_centroids
函數(shù)揽浙,這意味著每次運(yùn)行腳本時(shí)這些初始質(zhì)心都不同。 更新腳本來為隨機(jī)質(zhì)心包含新的種子意敛。
2)迭代地執(zhí)行 k 均值算法馅巷,其中來自之前迭代的更新的質(zhì)心用于分配簇,然后用于更新質(zhì)心草姻,等等钓猬。 換句話說,算法交替調(diào)用assign_to_nearest
和update_centroids
撩独。 在停止之前敞曹,更新代碼來執(zhí)行此迭代 10 次账月。 你會發(fā)現(xiàn),隨著 k-means 的更多迭代澳迫,得到的質(zhì)心平均上更接近局齿。 (對于那些對 k-means 有經(jīng)驗(yàn)的人,未來的教程將研究收斂函數(shù)和其他停止標(biāo)準(zhǔn)橄登。)
訓(xùn)練和收斂
大多數(shù)人工智能和機(jī)器學(xué)習(xí)的關(guān)鍵組成部分是循環(huán)抓歼,即系統(tǒng)在多次訓(xùn)練迭代中得到改善。 以這種方式訓(xùn)練的一種非常簡單的方法拢锹,就是在for
循環(huán)中執(zhí)行更新谣妻。 我們在第 2 課中看到了這種方式的一個例子:
import tensorflow as tf
x = tf.Variable(0, name='x')
model = tf.global_variables_initializer()
with tf.Session() as session:
for i in range(5):
session.run(model)
x = x + 1
print(session.run(x))
我們可以改變此工作流,使用變量來收斂循環(huán)卒稳,如下所示:
import tensorflow as tf
x = tf.Variable(0., name='x')
threshold = tf.constant(5.)
model = tf.global_variables_initializer()
with tf.Session() as session:
session.run(model)
while session.run(tf.less(x, threshold)):
x = x + 1
x_value = session.run(x)
print(x_value)
這里的主要變化是拌禾,循環(huán)現(xiàn)在是一個while
循環(huán),測試(tf.less
用于小于測試)為真時(shí)繼續(xù)循環(huán)展哭。 在這里湃窍,我們測試x
是否小于給定閾值(存儲在常量中),如果是匪傍,我們繼續(xù)循環(huán)您市。
梯度下降
任何機(jī)器學(xué)習(xí)庫都必須具有梯度下降算法。 我認(rèn)為這是一個定律役衡。 無論如何茵休,Tensorflow 在主題上有一些變化,它們可以直接使用手蝎。
梯度下降是一種學(xué)習(xí)算法榕莺,嘗試最小化某些誤差。 你問哪個誤差棵介? 嗯钉鸯,這取決于我們,雖然有一些常用的方法邮辽。
讓我們從一個基本的例子開始:
import tensorflow as tf
import numpy as np
# x 和 y 是我們的訓(xùn)練數(shù)據(jù)的占位符
x = tf.placeholder("float")
y = tf.placeholder("float")
# w 是存儲我們的值的變量唠雕。 它使用“猜測”來初始化
# w[0] 是我們方程中的“a”,w[1] 是“b”
w = tf.Variable([1.0, 2.0], name="w")
# 我們的模型是 y = a*x + b
y_model = tf.multiply(x, w[0]) + w[1]
# 我們的誤差定義為差異的平方
error = tf.square(y - y_model)
# GradientDescentOptimizer 完成繁重的工作
train_op = tf.train.GradientDescentOptimizer(0.01).minimize(error)
# TensorFlow 常規(guī) - 初始化值吨述,創(chuàng)建會話并運(yùn)行模型
model = tf.global_variables_initializer()
with tf.Session() as session:
session.run(model)
for i in range(1000):
x_value = np.random.rand()
y_value = x_value * 2 + 6
session.run(train_op, feed_dict={x: x_value, y: y_value})
w_value = session.run(w)
print("Predicted model: {a:.3f}x + {b:.3f}".format(a=w_value[0], b=w_value[1]))
這里的主要興趣點(diǎn)是train_op = tf.train.GradientDescentOptimizer(0.01).minimize(error)
岩睁,其中定義了訓(xùn)練步長。 它旨在最小化誤差變量的值揣云,該變量先前被定義為差的平方(常見的誤差函數(shù))捕儒。 0.01 是嘗試學(xué)習(xí)更好的值所需的步長。
其它優(yōu)化器
TensorFlow 有一整套優(yōu)化器邓夕,并且你也可以定義自己的優(yōu)化器(如果你對這類事情感興趣)刘莹。 如何使用它們的 API亿笤,請參閱此頁面。 列表如下:
GradientDescentOptimizer
AdagradOptimizer
MomentumOptimizer
AdamOptimizer
FtrlOptimizer
RMSPropOptimizer
其他優(yōu)化方法可能會出現(xiàn)在 TensorFlow 的未來版本或第三方代碼中栋猖。 也就是說净薛,上述優(yōu)化對于大多數(shù)深度學(xué)習(xí)技術(shù)來說已經(jīng)足夠了。 如果你不確定要使用哪一個蒲拉,請使用AdamOptimizer
肃拜,除非失敗。
譯者注:原文推薦隨機(jī)梯度優(yōu)化器雌团,在所有優(yōu)化器里是最爛的燃领,已更改。
這里一個重要的注意事項(xiàng)是锦援,我們只優(yōu)化了一個值猛蔽,但該值可以是一個數(shù)組。 這就是為什么我們使用w
作為變量灵寺,而不是兩個單獨(dú)的變量a
和b
曼库。
繪制誤差
這個代碼是上面的一個小改動。 首先略板,我們創(chuàng)建一個列表來存儲誤差毁枯。然后,在循環(huán)內(nèi)部叮称,我們顯式地計(jì)算train_op
和誤差种玛。 我們在一行中執(zhí)行此操作,因此誤差僅計(jì)算一次瓤檐。 如果我們在單獨(dú)的行中這樣做赂韵,它將計(jì)算誤差,然后是訓(xùn)練步驟挠蛉,并且在這樣做時(shí)祭示,它將需要重新計(jì)算誤差。
下面我把代碼放在上一個程序的tf.global_variables_initializer()
行下面 - 這一行上面的所有內(nèi)容都是一樣的碌秸。
errors = []
with tf.Session() as session:
session.run(model)
for i in range(1000):
x_train = tf.random_normal((1,), mean=5, stddev=2.0)
y_train = x_train * 2 + 6
x_value, y_value = session.run([x_train, y_train])
_, error_value = session.run([train_op, error], feed_dict={x: x_value, y: y_value})
errors.append(error_value)
w_value = session.run(w)
print("Predicted model: {a:.3f}x + {b:.3f}".format(a=w_value[0], b=w_value[1]))
import matplotlib.pyplot as plt
plt.plot([np.mean(errors[i-50:i]) for i in range(len(errors))])
plt.show()
plt.savefig("errors.png")
你可能已經(jīng)注意到我在這里采用窗口平均值 - 使用np.mean(errors[i-50:i])
而不是僅使用errors[i]
绍移。 這樣做的原因是我們只在循環(huán)中測試一次,所以雖然誤差會減小讥电,但它會反彈很多。 采用這個窗口平均值可以平滑一點(diǎn)轧抗,但正如你在上面所看到的恩敌,它仍然會跳躍。
1)創(chuàng)建第 6 課中的 k-means 示例的收斂函數(shù)横媚,如果舊質(zhì)心與新質(zhì)心之間的距離小于給定的epsilon
值纠炮,則停止訓(xùn)練月趟。
2)嘗試從梯度下降示例(w
)中分離a
和b
值。
3)我們的例子一次只訓(xùn)練一個示例恢口,這是低效的孝宗。 擴(kuò)展它來一次使用多個(例如 50 個)訓(xùn)練樣本來學(xué)習(xí)。
TFLearn
已更新到最新的 TFLearn API耕肩。
這些教程主要關(guān)注 TensorFlow 的機(jī)制因妇,但真正的用例是機(jī)器學(xué)習(xí)。 TensorFlow 有許多用于構(gòu)建機(jī)器學(xué)習(xí)模型的方法猿诸,其中許多可以在官方 API 頁面上找到婚被。 這些函數(shù)允許你從頭開始構(gòu)建模型,包括自定義層面梳虽,例如如何構(gòu)建神經(jīng)網(wǎng)絡(luò)中的層址芯。
在本教程中,我們將查看 TensorFlow Learn窜觉,它是名為skflow
的軟件包的新名稱谷炸。 TensorFlow Learn(以下簡稱:TFLearn)是一個機(jī)器學(xué)習(xí)包裝器,基于 scikit-learn API禀挫,允許你輕松執(zhí)行數(shù)據(jù)挖掘淑廊。 這意味著什么? 讓我們一步一步地完成它:
機(jī)器學(xué)習(xí)
機(jī)器學(xué)習(xí)是一種概念特咆,構(gòu)建從數(shù)據(jù)中學(xué)習(xí)的算法季惩,以便對新數(shù)據(jù)執(zhí)行操作。 在這種情況下腻格,這意味著我們有一些輸入的訓(xùn)練數(shù)據(jù)和預(yù)期結(jié)果 - 訓(xùn)練目標(biāo)画拾。 我們將看看著名的數(shù)字?jǐn)?shù)據(jù)集,這是一堆手繪數(shù)字的圖像菜职。 我們的輸入訓(xùn)練數(shù)據(jù)是幾千個這些圖像青抛,我們的訓(xùn)練目標(biāo)是預(yù)期的數(shù)字。
任務(wù)是學(xué)習(xí)一個模型酬核,可以回答“這是什么數(shù)字蜜另?”,對于這樣的輸入:
這是一個分類任務(wù)嫡意,是數(shù)據(jù)挖掘最常見的應(yīng)用之一举瑰。 還有一些稱為回歸和聚類的變體(以及許多其他變體),但在本課中我們不會涉及它們蔬螟。
如果你想了解數(shù)據(jù)挖掘的更多信息此迅,請查看我的書“Python 數(shù)據(jù)挖掘”。
Scikit-Learn API
Scikit-learn 是一個用于數(shù)據(jù)挖掘和分析的 Python 包,它非常受歡迎耸序。 這是因?yàn)樗鼜V泛支持不同的算法忍些,令人驚嘆的文檔,以及龐大而活躍的社區(qū)坎怪。 其他一個因素是它的一致接口罢坝,它的 API,允許人們構(gòu)建可以使用 scikit-learn 輔助函數(shù)訓(xùn)練的模型搅窿,并允許人們非常容易地測試不同的模型嘁酿。
我們來看看 scikit-learn 的 API,但首先我們需要一些數(shù)據(jù)戈钢。 以下代碼加載了一組可以使用matplotlib.pyplot
顯示的數(shù)字圖像:
from sklearn.datasets import load_digits
from matplotlib import pyplot as plt
digits = load_digits()
我們可以使用pyplot.imshow
顯示其中一個圖像痹仙。 在這里,我設(shè)置interpolation ='none'
來完全按原樣查看數(shù)據(jù)殉了,但是如果你刪除這個屬性开仰,它會變得更清晰(也嘗試減小數(shù)字大小)薪铜。
fig = plt.figure(figsize=(3, 3))
plt.imshow(digits['images'][66], cmap="gray", interpolation='none')
plt.show()
在 scikit-learn 中众弓,我們可以構(gòu)建一個簡單的分類器,訓(xùn)練它隔箍,然后使用它來預(yù)測圖像的數(shù)字谓娃,只需使用四行代碼:
from sklearn import svm
classifier = svm.SVC(gamma=0.001)
classifier.fit(digits.data, digits.target)
predicted = classifier.predict(digits.data)
第一行只是導(dǎo)入支持向量機(jī)模型,這是一種流行的機(jī)器學(xué)習(xí)方法蜒滩。
第二行構(gòu)建“空白”分類器滨达,gamma
設(shè)置為 0.001。
第三行使用數(shù)據(jù)來訓(xùn)練模型俯艰。 在這一行(這是該代碼的大部分“工作”)中捡遍,調(diào)整 SVM 模型的內(nèi)部狀態(tài)來擬合訓(xùn)練數(shù)據(jù)。 我們還傳遞digits.data
竹握,因?yàn)檫@是一個展開的數(shù)組画株,是該算法的可接受輸入。
最后啦辐,最后一行使用這個訓(xùn)練好的分類器來預(yù)測某些數(shù)據(jù)的類谓传,在這種情況下再次是原始數(shù)據(jù)集。
要了解這是多么準(zhǔn)確芹关,我們可以使用 NumPy 計(jì)算準(zhǔn)確度:
import numpy as np
print(np.mean(digits.target == predicted))
結(jié)果非常令人印象深刻(近乎完美)续挟,但這些有點(diǎn)誤導(dǎo)。 在數(shù)據(jù)挖掘中充边,你永遠(yuǎn)不應(yīng)該在用于訓(xùn)練的相同數(shù)據(jù)上評估你的模型庸推。 潛在的問題被稱為“過擬合”常侦,其中模型準(zhǔn)確地學(xué)習(xí)了訓(xùn)練數(shù)據(jù)所需的內(nèi)容浇冰,但是無法很好地預(yù)測新的沒見過的數(shù)據(jù)贬媒。 為解決這個問題,我們需要拆分我們的訓(xùn)練和測試數(shù)據(jù):
from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(digits.data, digits.target)
結(jié)果仍然非常好肘习,大約 98%际乘,但這個數(shù)據(jù)集在數(shù)據(jù)挖掘中是眾所周知的,其特征已有詳細(xì)記錄漂佩。 無論如何脖含,我們現(xiàn)在知道我們要做什么,讓我們在 TFLearn 中實(shí)現(xiàn)它投蝉!
TFLearn
TensorFlow Learn 接口距離 scikit-learn 的接口只有一小步之遙:
from tensorflow.contrib import learn
n_classes = len(set(y_train))
classifier = learn.LinearClassifier(feature_columns=[tf.contrib.layers.real_valued_column("", dimension=X_train.shape[1])],
n_classes=n_classes)
classifier.fit(X_train, y_train, steps=10)
y_pred = classifier.predict(X_test)
唯一真正的變化是import
語句和模型养葵,它來自不同的可用算法列表。 一個區(qū)別是分類器需要知道它將預(yù)測多少個類瘩缆,可以使用len(set(y_train))
找到关拒,或者換句話說,訓(xùn)練數(shù)據(jù)中有多少個唯一值庸娱。
另一個區(qū)別是着绊,需要告知分類器預(yù)期的特征類型。 對于這個例子熟尉,我們有真正重要的連續(xù)特征归露,所以我們可以簡單地指定feature_columns
值(它需要在列表中)。 如果你使用類別特征斤儿,則需要單獨(dú)說明剧包。 這方面的更多信息,請查看 TFLearn 示例的文檔往果。
可以像以前一樣評估結(jié)果疆液,來計(jì)算準(zhǔn)確性,但 scikit-learn 有 classification_report棚放,它提供了更深入的了解:
from sklearn import metrics
print(metrics.classification_report(y_true=y_test, y_pred=y_pred))
結(jié)果顯示每個類的召回率和精度枚粘,以及總體值和 f 度量。這些分?jǐn)?shù)比準(zhǔn)確性更可靠飘蚯,更多信息請參閱維基百科上的此頁面馍迄。
這是 TFLearn 的高級概述。你可以定義自定義分類器局骤,你將在練習(xí) 3 中看到它們攀圈,并將分類器組合到流水線中(對此的支持很小,但正在改進(jìn))峦甩。該軟件包有可能成為工業(yè)和學(xué)術(shù)界廣泛使用的數(shù)據(jù)挖掘軟件包赘来。
1)將分類器更改為DNNClassifier
并重新運(yùn)行现喳。隨意告訴所有朋友你現(xiàn)在使用深度學(xué)習(xí)來做數(shù)據(jù)分析。
2)DNNClassifier
的默認(rèn)參數(shù)是好的犬辰,但不完美嗦篱。嘗試更改參數(shù)來獲得更高的分?jǐn)?shù)。
3)從 TFLearn 的文檔中查看此示例并下載 CIFAR 10 數(shù)據(jù)集幌缝。構(gòu)建一個使用卷積神經(jīng)網(wǎng)絡(luò)預(yù)測圖像的分類器灸促。你可以使用此代碼加載數(shù)據(jù):
def load_cifar(file):
import pickle
import numpy as np
with open(file, 'rb') as inf:
cifar = pickle.load(inf, encoding='latin1')
data = cifar['data'].reshape((10000, 3, 32, 32))
data = np.rollaxis(data, 3, 1)
data = np.rollaxis(data, 3, 1)
y = np.array(cifar['labels'])
# 最開始只需 2 和 9
# 如果要構(gòu)建大型模型,請刪除這些行
mask = (y == 2) | (y == 9)
data = data[mask]
y = y[mask]
return data, y