TensorFlow 學習指南 二、線性模型
原文: ofollow,noindex">LearningTensorFlow.com
譯者: 飛龍
協議: CC BY-NC-SA 4.0
自豪地採用 谷歌翻譯
廣播
當我們操作不同維度的陣列時,它們可以以不同的方式組合,無論是逐元素還是通過廣播。
讓我們從頭開始,構建更復雜的例子。 在下面的示例中,我們有表示單個數字的 TensorFlow 常量。
import tensorflow as tf a = tf.constant(3, name='a') with tf.Session() as session: print(session.run(a))
這裡沒什麼驚喜! 我們也可以進行計算,例如將其加上另一個數字:
a = tf.constant(3, name='a') b = tf.constant(4, name='b') add_op = a + b with tf.Session() as session: print(session.run(add_op))
讓我們將這個概念擴充套件到一個數字列表。 首先,讓我們建立一個包含三個數字的列表,然後建立另一個數字列表:
a = tf.constant([1, 2, 3], name='a') b = tf.constant([4, 5, 6], name='b') add_op = a + b with tf.Session() as session: print(session.run(add_op))
這稱為逐元素操作,其中依次考慮每個列表中的元素,將它們相加,然後合併結果。
如果我們將這個列表和僅僅一個數字相加,會發生什麼?
a = tf.constant([1, 2, 3], name='a') b = tf.constant(4, name='b') add_op = a + b with tf.Session() as session: print(session.run(add_op))
這是你所期望的嗎? 這被稱為廣播操作。 我們的主要物件引用是 a
,它是一個數字列表,也稱為陣列或一維向量。 與單個數字(稱為標量)相加會產生廣播操作,其中標量將與列表的每個元素相加。
現在讓我們看一個擴充套件,它是一個二維陣列,也稱為矩陣。 這個額外的維度可以被認為是“列表的列表”。 換句話說,列表是標量的組合,矩陣是列表的列表。
也就是說,矩陣上的操作如何工作?
a = tf.constant([[1, 2, 3], [4, 5, 6]], name='a') b = tf.constant([[1, 2, 3], [4, 5, 6]], name='b') add_op = a + b with tf.Session() as session: print(session.run(add_op))
這是逐元素的。 如果我們加上一個標量,結果是可以預測的:
a = tf.constant([[1, 2, 3], [4, 5, 6]], name='a') b = tf.constant(100, name='b') add_op = a + b with tf.Session() as session: print(session.run(add_op))
事情開始變得棘手。 如果我們將一維陣列與二維矩陣相加會發生什麼?
a = tf.constant([[1, 2, 3], [4, 5, 6]], name='a') b = tf.constant([100, 101, 102], name='b') add_op = a + b with tf.Session() as session: print(session.run(add_op))
在這種情況下,陣列被廣播為矩陣的形狀,導致陣列與矩陣的每一行相加。 使用此術語,矩陣是行的列表。
如果我們不想要這個,而是想將矩陣的列與 b
相加呢?
a = tf.constant([[1, 2, 3], [4, 5, 6]], name='a') b = tf.constant([100, 101,], name='b') add_op = a + b with tf.Session() as session: print(session.run(add_op))
這不起作用,因為 TensorFlow 試圖按照行廣播。 它不能這樣做,因為 b
中的值的數量(2)與每行中的標量數量(3)不同。
我們可以通過從列表中建立一個新矩陣來執行此操作。
a = tf.constant([[1, 2, 3], [4, 5, 6]], name='a') b = tf.constant([[100], [101]], name='b') add_op = a + b with tf.Session() as session: print(session.run(add_op))
這裡發生了什麼? 要理解這一點,讓我們看一下矩陣形狀。
a.shape TensorShape([Dimension(2), Dimension(3)]) b.shape TensorShape([Dimension(2), Dimension(1)])
你可以從這兩個示例中看到 a
有兩個維度,第一個大小為 2,第二個大小為 3。換句話說,它有兩行,每行有三個標量。
我們的常數 b
也有兩個維度,兩行,每行一個標量。如果有一行兩個標量,這與列表不同,也與矩陣不同。
由於形狀在第一維匹配,而第二維不匹配的事實,廣播發生在列而不是行中。 廣播規則的更多資訊請參見 此處 。
建立一個三維矩陣。 如果將其與標量,陣列或矩陣相加,會發生什麼?
使用 tf.shape
(這是一個操作)在圖的操作期間獲得常量的形狀。
考慮更高維矩陣的用例。 換句話說,在哪裡你可能需要 4D 矩陣,甚至是 5D 矩陣? 提示:考慮集合而不是單個物件。
隨機性
機器學習模型是許多變數的複雜集合,但必須經過訓練才能找到好的值。這也意味著必須將這些“權重”設定為初始值。一種選擇是從所有權重為零開始。但是,這會在演算法上引起問題 - 基本上,錯誤的梯度無法修復錯誤。相反,我們經常將這些權重設定為隨機值。然後,模型學習並調整。
TensorFlow 有許多用於生成隨機數的內建方法。這包括我們熟悉的分佈,如“均勻”,以及你可能聽說過的其他分佈,如“正態”分佈。均勻分佈就像你擲骰子時得到的東西那樣 - 有一組值,它們都是等可能的。正態分佈是統計課程中教授的標準,其中資料具有更可能的平均值,以及圍繞它的“鐘形”曲線。我們將看到的,其他的也包括在內。
在本節中,我們將建立一個基本的輔助函式,它只執行一個 TensorFlow 變數。這個小函式非常有用!它建立一個會話,初始化變數併為我們執行它。它僅限於單個變數,因此對於較大的程式可能沒有用。
import tensorflow as tf def run_variable(variable): tf.initialize_all_variables() with tf.Session() as sess: return sess.run(variable)
希望現在這對你來說都很熟悉。 如果沒有,請再看看第一章,開始吧。
讓我們從一個基本的分佈開始,均勻分佈。
my_distribution = tf.random_uniform((6, 4), seed=42) uniform = run_variable(my_distribution)
這為我們提供了一個 6 乘 4 的張量(隨機值的更多資訊,請參閱上一節)。為了視覺化,我們可以使用直方圖:
from matplotlib import pyplot as plt plt.hist(uniform.flatten()) plt.show()
請注意,如果你使用的是 Jupyter 筆記本,請使用 %matplotlib inline
並刪除 plt.show()
行。
所得影象顯示了圖片,雖然還不是很清楚......

image
此直方圖顯示可能的值介於 0 和 1 之間。每個值應該是等可能的,但它看起來並不是那樣。 原因是我們只選擇了少量的值。 如果我們增加陣列的大小,它會變得更加均勻。
large_normal = tf.random_uniform((600, 400), seed=42) large_uniform = run_variable(large_normal) plt.hist(large_uniform.flatten()) plt.show()

image
更均勻了!
如果你沒有任何其他資訊,對於在機器學習模型中初始化權重,均勻分佈非常有用。 它也是一個“有界”分佈,它具有設定的最小值和最大值,隨機值不能超出該範圍。 要更改範圍,例如更改為 0 和 10,請乘以範圍並新增最小值。 在課程結束時有一個練習。
另一種常用的分佈是正態分佈,在 TensorFlow 中實現為 random_normal
函式:
distribution = tf.random_normal((600, 4), seed=42) normal = run_variable(distribution) plt.hist(normal.flatten()) plt.show()

image
預設情況下,此分佈的平均值約為 0,標準差為 1。這些值不受限制,但越來越不可能偏離平均值,標準差設定了可能性減小的速率。 在實踐中,大約 60% 的值落在距離平均值一個標準差的“半徑”內,並且 99% 落在 4 個標準差內。
均值和標準差是 random_normal
函式的引數。 例如,身高可近似建模為正態分佈,平均值約為 170cm,標準差約為 15cm。
distribution = tf.random_normal((10000,), seed=42, mean=170, stddev=15) normal = run_variable(distribution) plt.hist(normal.flatten()) plt.show()

image
到目前為止,我們的直方圖使用 matplotlib
生成。 我們也可以使用 TensorFlow 來建立它們! histogram_fixed_width
函式接受值的列表(如我們的隨機值),範圍和要計算的桶數。 然後計算每個桶的範圍內有多少個值,並將結果作為陣列返回。
import numpy as np bins = tf.histogram_fixed_width(normal, (normal.min(), normal.max()), nbins=20) histogram_bins = run_variable(bins) x_values = np.linspace(normal.min(), normal.max(), len(histogram_bins)) plt.bar(x_values, histogram_bins,)
在 plt.bar
呼叫中,我們再次手動生成 bin
值,然後使用條形圖將這些值繪製為 x
值,並使用 histogram_bins
作為高度。

image
這是正確的,但看起來不對。 直方圖的值在那裡,但寬度非常窄(我們的箱桶僅由單個值表示)。 我們來解決這個問題:
bar_width = (normal.max() - normal.min()) / len(histogram_bins) plt.bar(x_values, histogram_bins, width=bar_width)

image
- 使用均勻分佈建模單次擲骰子。 繪製結果來確保其符合你的期望
- 使用單個圖中的純 TensorFlow 呼叫替換本課程的最後一個程式碼塊。 換句話說,使用 TensorFlow 概念來替換
.min()
,.max()
和len
呼叫。 只有繪圖在沒有 TensorFlow 的情況下進行!
線性方程
通過 tf.solve
函式,TensorFlow 可以求解線性方程組。 你可能會將這些視為連線的方程,如下所示:

image
這些型別的線性方程用於數學中的許多問題,從優化工廠輸出到幾何。 你可以使用多種方法解決這些方程,但在本課中,我們將瞭解如何使用 tf.solve
為我們執行此操作。
我將專注於幾何。 這是位於二維 (x, y)
空間的兩個點, p1
和 p2
:

image
這是他們在圖上的樣子:

image
要在 TensorFlow 中執行此操作,我們首先設定線性方程組,我們的點位於中心。 首先,我們建立我們的點矩陣。 第一行對應於第一個點,第二行對應於第二個點。 同樣,第一列是 x
值,而第二列是 y
值。
import tensorflow as tf # 點 1 x1 = tf.constant(2, dtype=tf.float32) y1 = tf.constant(9, dtype=tf.float32) point1 = tf.stack([x1, y1]) # 點 2 x2 = tf.constant(-1, dtype=tf.float32) y2 = tf.constant(3, dtype=tf.float32) point2 = tf.stack([x2, y2]) # 將點組合為陣列 X = tf.transpose(tf.stack([point1, point2]))
直線的方程是:

image
重新排列方程(5),使 x
和 y
在同一側,我們得到以下結果:

image
我們的任務是在給定觀測點的情況下,找到上面的方程中的 a
和 b
的值。 我們可以通過取點陣列的逆並將其乘以一個矩陣,來輕易做到這一點。
使用矩陣(因為我們使用的是 TensorFlow),如果 X
是我們觀察點的矩陣,而 A
是我們需要學習的引數,我們設定一個系統:

image
接下來要學習的引數就是:

image
矩陣 B
很簡單,適當廣播的數字 1,它源於上面方程的右側。
矩陣 A
是上面方程 3 中的引數。
B = tf.ones((1, 2), dtype=tf.float32) parameters = tf.matmul(B, tf.matrix_inverse(X)) with tf.Session() as session: A = session.run(parameters)
最後一步是從上面的方程(5)中找到我們的 a
和 b
值,即從這些引數轉換(符合方程(7))。
b = 1 / A[0][1] a = -b * A[0][0] print("Equation: y = {a}x + {b}".format(a=a, b=b))
這個解決方案很好地包含在 tf.solve
函式中。 為了看到它,讓我們看另一個例子。 這是一個圓圈:

image
以下是圓圈上的三個觀察點:

image

image
圓的規範方程是:

image
為了求解引數 d
, e
和 f
,我們建立另一個點陣列,並用 1 填充它來建立一個方陣。 我們正在尋找三個引數,因此我們的 A
矩陣必須具有形狀 (3, 3)
。
由於這個方程的平方部分沒有引數,當我們有 x
和 y
的觀測值時,我們的方程變得有點不同:

image
因此,我們的 A
矩陣由 x
和 y
值(以及另一列 1)組成,我們的 B
矩陣是負的 x
和 y
的平方和。
import tensorflow as tf points = tf.constant([[2, 1], [0, 5], [-1, 2]], dtype=tf.float64) A = tf.constant([ [2, 1, 1], [0, 5, 1], [-1, 2, 1] ], dtype='float64') B = -tf.constant([[5], [25], [5]])
然後我們使用 tf.matrix_solve
來找到我們的 X
陣列,這是我們方程的引數。 在會話中執行它,我們得到三個值,即 D
, E
和 F
。
X = tf.matrix_solve(A, B) with tf.Session() as session: result = session.run(X) D, E, F = result.flatten() print("Equation: x**2 + y**2 + {D}x + {E}y + {F} = 0".format(**locals()))
1)求解包含以下三點的圓: P(2,1)
, Q(0,5)
, R(-1,2)
2)下面給出橢圓的一般形式。 解決以下幾點(解決這個方程需要五點):
橢圓的一般形式:

image
觀測點:

image
3D 中的 TensorFlow
TensorFlow 不僅僅是一個深度學習庫 - 它是一個但數值操作庫,因此它可以執行許多其他庫可以執行的任務。 在本課中,我們將介紹如何使用 TensorFlow 對 3D 物件執行操作。
3D 物件可以被建模為三維空間中的一系列三角形,我們通常將其稱為 (x, y, z)
。 這些名稱不是必需的,但通常使用。 從這些 3D 點中的三個建立三角形。 點本身可以表示為大小為 (3,)
的向量。 這些陣列是一個大小為 (n, 3),
的矩陣,其中 n
是我們擁有的點數。 讓我們深入去看一個基本的立方體。 我們稍後將需要此功能,所以讓我們建立一個繪製基本形狀的函式:
from mpl_toolkits.mplot3d import Axes3D import numpy as np from matplotlib import cm import matplotlib.pyplot as plt from scipy.spatial import Delaunay def plot_basic_object(points): """繪製一個基本物件,假設它是凸的而不是太複雜""" tri = Delaunay(points).convex_hull fig = plt.figure(figsize=(8, 8)) ax = fig.add_subplot(111, projection='3d') S = ax.plot_trisurf(points[:,0], points[:,1], points[:,2], triangles=tri, shade=True, cmap=cm.Blues,lw=0.5) ax.set_xlim3d(-5, 5) ax.set_ylim3d(-5, 5) ax.set_zlim3d(-5, 5) plt.show()
如果你正在使用 Jupyter 筆記本,我建議執行這一行程式碼,它為你提供了一個非常棒的互動式 3D 繪圖。 左鍵單擊並拖動來左右移動,右鍵單擊並拖動來放大或縮小。
%matplotlib notebook
現在讓我們建立一個形狀。 下面的函式將返回組成立方體的六個點。 如果你回到上一個函式,你將看到 Delaunay 線,它將這些點轉換成三角形,以便我們可以渲染它們。
import numpy as np def create_cube(bottom_lower=(0, 0, 0), side_length=5): """從給定的左下角點(最小的 x,y,z 值)開始建立一個立方體""" bottom_lower = np.array(bottom_lower) points = np.vstack([ bottom_lower, bottom_lower + [0, side_length, 0], bottom_lower + [side_length, side_length, 0], bottom_lower + [side_length, 0, 0], bottom_lower + [0, 0, side_length], bottom_lower + [0, side_length, side_length], bottom_lower + [side_length, side_length, side_length], bottom_lower + [side_length, 0, side_length], bottom_lower, ]) return points
現在讓我們把這些碎片放在一起,看看它是什麼樣的:
cube_1 = create_cube(side_length=2) plot_basic_object(cube_1)

image
我只是在這裡顯示一個影象,但是你可以看到立方體,它已被我們的程式碼變成三角形並且顏色不同(取決於 z
值)。 這很好,但現在讓我們使用 TensorFlow 對此進行一些操作。
平移
平移是一個簡單的動作:向上/向下,向左/向右,向前/向後,或這些的某種組合。 它是通過簡單地向每個點新增一個向量來建立的。 如果向所有點新增相同的向量,則整個物件將一致地移動。 檢視我們關於廣播的章節,瞭解當我們將大小為 (3,)
的平移向量新增到大小 (n, 3)
的點矩陣時會發生什麼。
import tensorflow as tf def translate(points, amount): return tf.add(points, amount) points = tf.constant(cube_1, dtype=tf.float32) # 更新此處的值來移動多維資料集。 translation_amount = tf.constant([3, -3, 0], dtype=tf.float32) translate_op = translate(points, translation_amount) with tf.Session() as session: translated_cube = session.run(translate_op) plot_basic_object(translated_cube)

image
旋轉
通過建立點積或旋轉矩陣和原點來形成旋轉。 旋轉物件首先需要你確定要旋轉的軸。 要圍繞特定軸旋轉,請將該軸的值設定為 0,相關軸中的值為 1。 你需要三個矩陣:
沿 x
軸旋轉
[[1, 0, 0], [0, cos \theta, sin \theta], [0, -sin \theta, cos \theta]]
沿 y
軸旋轉
[[cos \theta, 0, -sin \theta], [0, 1, 0], [sin \theta, 0, cos \theta]]
沿 z
軸旋轉
[[cos \theta, sin \theta, 0], [-sin \theta, cos \theta, 0], [0, 0, 1]]
def rotate_around_z(points, theta): theta = float(theta) rotation_matrix = tf.stack([[tf.cos(theta), tf.sin(theta), 0], [-tf.sin(theta), tf.cos(theta), 0], [0, 0, 1]]) return tf.matmul(tf.to_float(points), tf.to_float(rotation_matrix)) with tf.Session() as session: result = session.run(rotate_around_z(cube_1, 75)) plot_basic_object(result)

image
通過這些簡單,但是可以大規模組合的矩陣操作,你可以像這樣為 3D 物件建立一系列的變換。 此概念可以用於實現剪下,縮放,交叉等。 GPU 非常擅長進行這些轉換,這些轉換恰好與資料分析工作(如深度學習)所需的相同型別的轉換相關。 因此,TensorFlow 可以很好地配合 GPU,處理 3D 物件以及深度學習任務。
- 建立不同的物件,例如四稜錐或者六稜柱。 如果你不確定如何開始,請先從稜柱開始,然後先在2D中建立它。
- 圍繞
x
軸和y
軸旋轉物件。 - 你可以將旋轉組合到單個變換矩陣中。 為此,只需計算旋轉的點積。
- 對於問題 3,順序是否重要?
- 剪下矩陣是具有非對角線值的單位矩陣。 一個例子如下。 建立剪下矩陣並測試不同的值。
[[1, 0.5, 0], [0, 1, 0], [0, 0, 1]]
線性模型的分類
在本課中,我們將瞭解使用 TensorFlow 進行機器學習。
我們將建立自己的線性分類器,並使用 TensorFlow 的內建優化演算法來訓練它。
首先,我們將檢視資料以及我們要做的事情。 對於那些剛接觸機器學習的人來說,我們嘗試執行的任務稱為監督機器學習或分類。
任務是嘗試計算一些輸入資料和輸出值之間的關係。 實際上,輸入資料可以是測量值,例如高度或重量,輸出值可以是預期的預測值,例如“cat”或“dog”。
這裡的課程擴充套件自我們的課程“收斂”,在後面的章節中。 我建議你先完成那個課程。
讓我們建立並可視化一些資料:
from sklearn.datasets import make_blobs import numpy as np from sklearn.preprocessing import OneHotEncoder X_values, y_flat = make_blobs(n_features=2, n_samples=800, centers=3, random_state=500) y = OneHotEncoder().fit_transform(y_flat.reshape(-1, 1)).todense() y = np.array(y) %matplotlib inline from matplotlib import pyplot as plt # 可選的行:將預設數字大小設定得稍大。 plt.rcParams['figure.figsize'] = (24, 10) plt.scatter(X_values[:,0], X_values[:,1], c=y_flat, alpha=0.4, s=150)

image
在這裡,我們有三種資料,黃色,藍色和紫色。 它們繪製在兩個維度上,我們稱之為 x0x0
和 x1x1
。
這些值儲存在 X
陣列中。
當我們執行機器學習時,有必要將資料拆分為我們用於建立模型的訓練集和用於評估它的測試集。 如果我們不這樣做,那麼我們可以簡單地建立一個“作弊分類器”,只記得我們的訓練資料。 通過拆分,我們的分類器必須學習輸入(繪圖上的位置)和輸出之間的關係。
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test, y_train_flat, y_test_flat = train_test_split(X_values, y, y_flat) X_test += np.random.randn(*X_test.shape) * 1.5
現在我們繪製測試資料。 從訓練資料中學習位置和顏色之間的關係之後,將給予分類器以下幾個點,並且將評估它對點著色的準確度。
#plt.scatter(X_train[:,0], X_train[:,1], c=y_train_flat, alpha=0.3, s=150) plt.plot(X_test[:,0], X_test[:,1], 'rx', markersize=20)

image
建立模型
我們的模型將是一個簡單的線性分類器。 這意味著它將在三種顏色之間繪製直線。 一條線上方的點被賦予一種顏色,而一條線下方的點被賦予另一種顏色。 我們將這些稱為決策直線,儘管它們通常被稱為決策邊界,因為其他模型可以學習比線更復雜的形狀。
為了在數學上表示我們的模型,我們使用以下等式:
Y = XW + b
我們的權重 W
是 (n_features, n_classes)
矩陣,表示我們模型中的學習權重。 它決定了決策直線的位置。 X
是 (n_rows, n_features)
矩陣,並且是位置資料 - 給定點位於圖上。 最後, b
是 (1, n_classes)
向量,並且是偏差。 我們需要這樣,以便我們的線不必經過點 (0,0)
,使我們能夠在圖上的任何位置“繪製”直線。
X
中的點是固定的 - 這些是訓練或測試資料,稱為觀測資料。 W
和 b
的值是我們模型中的引數,我們可以控制這些值。 為這些值選擇好的值,可以為我們提供良好的決策線。
在我們的模型中為引數選擇好的值的過程,稱為訓練演算法,並且是機器學習中的“學習”。
讓我們從上面得到我們的數學模型,並將其轉換為 TensorFlow 操作。
import tensorflow as tf n_features = X_values.shape[1] n_classes = len(set(y_flat)) weights_shape = (n_features, n_classes) W = tf.Variable(dtype=tf.float32, initial_value=tf.random_normal(weights_shape))# Weights of the model X = tf.placeholder(dtype=tf.float32) Y_true = tf.placeholder(dtype=tf.float32) bias_shape = (1, n_classes) b = tf.Variable(dtype=tf.float32, initial_value=tf.random_normal(bias_shape)) Y_pred = tf.matmul(X, W)+ b
上面的 Y_pred
張量代表我們的數學模型。通過傳入觀測資料( X
),我們可以得到預期值,在我們的例子中,是給定點的預期顏色。請注意偏差使用廣播在所有預測中應用。
Y_pred
中的實際值由“似然”組成,模型將為給定點選擇每個類的似然,生成 (n_rows, n_classes)
大小的矩陣。它們不是真正的似然,但我們可以通過找到最大值,來找出我們的模型認為的最有可能的類。
接下來,我們需要定義一個函式來評估給定權重集的好壞程度。請注意,我們尚未學習權重,只是給出了隨機值。 TensorFlow 具有內建的損失函式,可以接受預測的輸出的(即模型產生的值)與實際值(我們首次建立測試集時建立的真實情況)。我們比較它們,並評估我們的模型表現如何。我們稱之為損失函式,因為我們做得越差,值越高 - 我們試圖將損失最小化。
loss_function = tf.losses.softmax_cross_entropy(Y_true, Y_pred)
最後一步是建立一個優化步驟,該步驟接受我們的損失函式,並找到給定變數的最小化損失的值。 請注意, loss
函式引用 Y_true
,後者又引用 W
和 b
。 TensorFlow 選擇此關係,並更改這些變數中的值來尋找良好的值。
learner = tf.train.GradientDescentOptimizer(0.1).minimize(loss_function)
現在開始訓練了!
我們在迴圈中遍歷學習器,來找到最佳權重。 每次迴圈中,前一迴圈的學習權重會在下一個迴圈中略有改善。 前一行程式碼中的 0.1
是學習率。 如果增加該值,演算法學得更快。 但是,較小的值通常會收斂到更好的值。 當你檢視模型的其他方面時,值為 0.1
是一個很好的起點。
每次迴圈中,我們通過佔位符將我們的訓練資料傳遞給學習器。 每隔 100 個迴圈,我們通過將測試資料直接傳遞給損失函式,來了解我們的模型是如何學習的。
with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for i in range(5000): result = sess.run(learner, {X: X_train, Y_true: y_train}) if i % 100 == 0: print("Iteration {}:\tLoss={:.6f}".format(i, sess.run(loss_function, {X: X_test, Y_true: y_test}))) y_pred = sess.run(Y_pred, {X: X_test}) W_final, b_final = sess.run([W, b]) predicted_y_values = np.argmax(y_pred, axis=1) predicted_y_values h = 1 x_min, x_max = X_values[:, 0].min() - 2 * h, X_values[:, 0].max() + 2 * h y_min, y_max = X_values[:, 1].min() - 2 * h, X_values[:, 1].max() + 2 * h x_0, x_1 = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) decision_points = np.c_[x_0.ravel(), x_1.ravel()]
有點複雜,但我們正在有效地建立一個二維網格,涵蓋 x0
和 x1
的可能值。
# 我們在 NumPy 中重建我們的模型 Z = np.argmax(decision_points @ W_final[[0,1]] + b_final, axis=1) # 建立 x_0 和 x_1 值的等高線圖 Z = Z.reshape(xx.shape) plt.contourf(x_0, x_1, Z, alpha=0.1) plt.scatter(X_train[:,0], X_train[:,1], c=y_train_flat, alpha=0.3) plt.scatter(X_test[:,0], X_test[:,1], c=predicted_y_values, marker='x', s=200) plt.xlim(x_0.min(), x_0.max()) plt.ylim(x_1.min(), x_1.max())

image
你就實現了它! 我們的模型會將黃色區域中的任何東西分類為黃色,依此類推。 如果覆蓋實際測試值(儲存在 y_test_flat
中),則可以高亮任何差異。
X
from sklearn.datasets import load_digits digits = load_digits() X = digits.data y = digits.target