from tensorflow.keras import models, layers, utils, backend as K
import matplotlib.pyplot as plt
import shap
ANN由具有輸入和輸出維度的層組成。后者由神經(jīng)元(也稱(chēng)為“節(jié)點(diǎn)”)的數(shù)量決定,神經(jīng)元是一個(gè)計(jì)算單元,通過(guò)激活函數(shù)連接加權(quán)輸入(幫助神經(jīng)元打開(kāi)/關(guān)閉)。
與大多數(shù)機(jī)器學(xué)習(xí)算法一樣,權(quán)重在訓(xùn)練期間隨機(jī)初始化和優(yōu)化,以最小化損失函數(shù)。
圖層可以分組為:
輸入層具有將輸入向量傳遞給神經(jīng)網(wǎng)絡(luò)的工作。如果我們有一個(gè)包含 3 個(gè)特征的矩陣(形狀 N x 3),則該層將 3 個(gè)數(shù)字作為輸入,并將相同的 3 個(gè)數(shù)字傳遞給下一層。
隱藏層代表中間節(jié)點(diǎn),它們對(duì)數(shù)字進(jìn)行多次轉(zhuǎn)換以提高最終結(jié)果的準(zhǔn)確性,輸出由神經(jīng)元的數(shù)量定義。
返回神經(jīng)網(wǎng)絡(luò)最終輸出的輸出層。如果我們?cè)谧鲆粋€(gè)簡(jiǎn)單的二元分類(lèi)或回歸,輸出層應(yīng)該只有 1 個(gè)神經(jīng)元(因此它只返回 1 個(gè)數(shù)字)。
在具有 5 個(gè)不同類(lèi)的多類(lèi)分類(lèi)的情況下,輸出層應(yīng)具有 5 個(gè)神經(jīng)元。
ANN最簡(jiǎn)單的形式是感知器,一個(gè)只有一層的模型,與線(xiàn)性回歸模型非常相似。詢(xún)問(wèn)感知器內(nèi)部發(fā)生了什么,相當(dāng)于詢(xún)問(wèn)多層神經(jīng)網(wǎng)絡(luò)的單個(gè)節(jié)點(diǎn)內(nèi)部發(fā)生了什么......讓我們分解一下。
假設(shè)我們有一個(gè)包含 N 行、3 個(gè)特征和 1 個(gè)目標(biāo)變量(即二進(jìn)制 1/0)的數(shù)據(jù)集:
我在 0 到 1 之間放置了一些隨機(jī)數(shù)數(shù)據(jù)在輸入神經(jīng)網(wǎng)絡(luò)之前應(yīng)始終縮放。
就像在所有其他機(jī)器學(xué)習(xí)用例中一樣,我們將訓(xùn)練一個(gè)模型來(lái)逐行使用特征預(yù)測(cè)目標(biāo)。讓我們從第一行開(kāi)始:
在數(shù)學(xué)公式中搜索最佳參數(shù),以最大程度地減少預(yù)測(cè)誤差。在回歸模型,即線(xiàn)性回歸中,您必須找到最佳權(quán)重,在基于樹(shù)的模型(即隨機(jī)森林)中,這是關(guān)于找到最佳拆分點(diǎn)......
通常,權(quán)重是隨機(jī)初始化的,然后隨著學(xué)習(xí)的進(jìn)行進(jìn)行調(diào)整。在這里,我將它們?nèi)吭O(shè)置為 1:
到目前為止,我們還沒(méi)有做任何與線(xiàn)性回歸不同的事情。對(duì)于業(yè)務(wù)來(lái)說(shuō),這很簡(jiǎn)單。
現(xiàn)在,這里是從線(xiàn)性模型 Σ(xiwi)=Y 到非線(xiàn)性模型 f ( Σ(xiwi)=Y 的升級(jí)...輸入激活函數(shù)。
激活函數(shù)定義該節(jié)點(diǎn)的輸出。
有很多,甚至可以創(chuàng)建一些自定義函數(shù),您可以在官方文檔中找到詳細(xì)信息并查看此備忘單。如果我們?cè)谑纠性O(shè)置一個(gè)簡(jiǎn)單的線(xiàn)性函數(shù),那么我們與線(xiàn)性回歸模型沒(méi)有區(qū)別。
我將使用僅返回 1 或 0 的二進(jìn)制步驟激活函數(shù):
圖片來(lái)源:作者
我們有感知器的輸出,這是一個(gè)單層神經(jīng)網(wǎng)絡(luò),它接受一些輸入并返回 1 個(gè)輸出。現(xiàn)在,模型的訓(xùn)練將繼續(xù),將輸出與目標(biāo)進(jìn)行比較,計(jì)算誤差并優(yōu)化權(quán)重,一次又一次地重復(fù)整個(gè)過(guò)程。
圖片來(lái)源:作者 這是神經(jīng)元的常見(jiàn)表示形式:
圖片來(lái)源:作者
可以說(shuō)所有的深度學(xué)習(xí)模型都是神經(jīng)網(wǎng)絡(luò),但并非所有的神經(jīng)網(wǎng)絡(luò)都是深度學(xué)習(xí)模型。一般來(lái)說(shuō),“深度”學(xué)習(xí)適用于算法至少有 2 個(gè)隱藏層(因此總共 4 層,包括輸入和輸出)的情況。
想象一下同時(shí)復(fù)制神經(jīng)元進(jìn)程3次:由于每個(gè)節(jié)點(diǎn)(加權(quán)和和激活函數(shù))返回一個(gè)值,我們將擁有具有3個(gè)輸出的第一個(gè)隱藏層。
現(xiàn)在讓我們?cè)俅问褂眠@ 3 個(gè)輸出作為第二個(gè)隱藏層的輸入,該隱藏層返回 3 個(gè)新數(shù)字。
最后,我們將添加一個(gè)輸出層(僅 1 個(gè)節(jié)點(diǎn))以獲得模型的最終預(yù)測(cè)。
請(qǐng)記住,這些層可以具有不同數(shù)量的神經(jīng)元和不同的激活函數(shù),并且在每個(gè)節(jié)點(diǎn)中,權(quán)重被訓(xùn)練以?xún)?yōu)化最終結(jié)果。這就是為什么添加的層越多,可訓(xùn)練參數(shù)的數(shù)量就越多。
現(xiàn)在,您可以查看神經(jīng)網(wǎng)絡(luò)的全貌:
為了盡可能簡(jiǎn)單,我沒(méi)有提到業(yè)務(wù)部門(mén)可能不感興趣的某些細(xì)節(jié),但數(shù)據(jù)科學(xué)家絕對(duì)應(yīng)該意識(shí)到這一點(diǎn)。特別:
偏差:在每個(gè)神經(jīng)元內(nèi)部,輸入和權(quán)重的線(xiàn)性組合還包括一個(gè)偏差,類(lèi)似于線(xiàn)性方程中的常數(shù),因此神經(jīng)元的完整公式為
f( Σ(Xi * Wi ) + 偏置 )
梯度下降:用于訓(xùn)練神經(jīng)網(wǎng)絡(luò)的優(yōu)化算法,
通過(guò)在最陡下降的方向上重復(fù)步驟來(lái)找到損失函數(shù)的局部最小值。
source: 3Blue1Brown (Youtube)
Model Design
The easiest way to build a Neural Network with TensorFlow is with the Sequential class of Keras. Let’s use it to make the Perceptron from our previous example, so a model with only one Dense layer. It is the most basic layer as it feeds all its inputs to all the neurons, each neuron providing one output.
model = models.Sequential(name='Perceptron', layers=[
layers.Dense( #a fully connected layer
name='dense',
input_dim=3, #with 3 features as the input
units=1, #and 1 node because we want 1 output
activation='linear' #f(x)=x
)
])
model.summary()
摘要函數(shù)提供結(jié)構(gòu)和大小的快照(就要訓(xùn)練的參數(shù)而言)。在這種情況下,我們只有 4 個(gè)(3 個(gè)權(quán)重和 1 個(gè)偏差),所以它非常輕巧。
如果你想使用Keras中尚未包含的激活函數(shù),就像我在可視化示例中展示的二進(jìn)制步驟函數(shù)一樣,你必須弄臟原始TensorFlow:
# define the function
import tensorflow as tf
def binary_step_activation(x):
##return 1 if x>0 else 0
return K.switch(x>0, tf.math.divide(x,x), tf.math.multiply(x,0))
# build the model
model = models.Sequential(name='Perceptron', layers=[
layers.Dense(
name='dense',
input_dim=3,
units=1,
activation=binary_step_activation
)
])
現(xiàn)在讓我們嘗試從感知器轉(zhuǎn)向深度神經(jīng)網(wǎng)絡(luò)??赡苣銜?huì)問(wèn)自己一些問(wèn)題:
多少層?
正確的答案是“嘗試不同的變體,看看什么有效”。
我通常使用 Dropout 處理 2 個(gè)密集隱藏層,這是一種通過(guò)將輸入隨機(jī)設(shè)置為 0 來(lái)減少過(guò)度擬合的技術(shù)。
隱藏層對(duì)于克服數(shù)據(jù)的非線(xiàn)性很有用,因此如果您不需要非線(xiàn)性,則可以避免隱藏層。過(guò)多的隱藏層會(huì)導(dǎo)致過(guò)度擬合。
有多少神經(jīng)元?
什么是激活功能?
有很多,我們不能說(shuō)一個(gè)絕對(duì)更好。無(wú)論如何,最常用的是 ReLU,這是一個(gè)分段線(xiàn)性函數(shù),只有在為正時(shí)才返回輸出,并且主要用于隱藏層。
此外,輸出層必須具有與預(yù)期輸出兼容的激活。例如,線(xiàn)性函數(shù)適用于回歸問(wèn)題,而 Sigmoid 通常用于分類(lèi)。
n_features = 10
model = models.Sequential(name='DeepNN', layers=[
### hidden layer 1
layers.Dense(name='h1', input_dim=n_features,
units=int(round((n_features+1)/2)),
activation='relu'),
layers.Dropout(name='drop1', rate=0.2),
### hidden layer 2
layers.Dense(name='h2', units=int(round((n_features+1)/4)),
activation='relu'),
layers.Dropout(name='drop2', rate=0.2),
### layer output
layers.Dense(name='output', units=1, activation='sigmoid')
])
model.summary()
請(qǐng)注意,順序類(lèi)并不是使用 Keras 構(gòu)建神經(jīng)網(wǎng)絡(luò)的唯一方法。Model 類(lèi)提供了對(duì)層的更大靈活性和控制,可用于構(gòu)建具有多個(gè)輸入/輸出的更復(fù)雜的模型。有兩個(gè)主要區(qū)別:
在順序類(lèi)中,需要指定輸入層,它隱含在第一個(gè)密集層的輸入維度中。這些圖層像對(duì)象一樣保存,可以應(yīng)用于其他圖層的輸出,
例如:輸出 = layer(...)(輸入) 這就是如何使用 Model 類(lèi)來(lái)構(gòu)建我們的感知器和 DeepNN:
# Perceptron
inputs = layers.Input(name='input', shape=(3,))
outputs = layers.Dense(name='output', units=1,
activation='linear')(inputs)
model = models.Model(inputs=inputs, outputs=outputs,
name='Perceptron')
# DeepNN
### layer input
inputs = layers.Input(name='input', shape=(n_features,))
### hidden layer 1
h1 = layers.Dense(name='h1', units=int(round((n_features+1)/2)), activation='relu')(inputs)
h1 = layers.Dropout(name='drop1', rate=0.2)(h1)
### hidden layer 2
h2 = layers.Dense(name='h2', units=int(round((n_features+1)/4)), activation='relu')(h1)
h2 = layers.Dropout(name='drop2', rate=0.2)(h2)
### layer output
outputs = layers.Dense(name='output', units=1, activation='sigmoid')(h2)
model = models.Model(inputs=inputs, outputs=outputs, name='DeepNN')
始終可以檢查模型摘要中的參數(shù)數(shù)量是否與順序中的參數(shù)數(shù)量相同。
請(qǐng)記住,我們正在向企業(yè)講述一個(gè)故事,可視化是我們最好的盟友。
我準(zhǔn)備了一個(gè)函數(shù)來(lái)繪制人工神經(jīng)網(wǎng)絡(luò)的 TensorFlow 模型的結(jié)構(gòu),這是完整的代碼:
'''
Extract info for each layer in a keras model.
'''
def utils_nn_config(model):
lst_layers = []
if 'Sequential' in str(model): #-> Sequential doesn't show the input layer
layer = model.layers[0]
lst_layers.append({'name':'input', 'in':int(layer.input.shape[-1]), 'neurons':0,
'out':int(layer.input.shape[-1]), 'activation':None,
'params':0, 'bias':0})
for layer in model.layers:
try:
dic_layer = {'name':layer.name, 'in':int(layer.input.shape[-1]), 'neurons':layer.units,
'out':int(layer.output.shape[-1]), 'activation':layer.get_config()['activation'],
'params':layer.get_weights()[0], 'bias':layer.get_weights()[1]}
except:
dic_layer = {'name':layer.name, 'in':int(layer.input.shape[-1]), 'neurons':0,
'out':int(layer.output.shape[-1]), 'activation':None,
'params':0, 'bias':0}
lst_layers.append(dic_layer)
return lst_layers
'''
Plot the structure of a keras neural network.
'''
def visualize_nn(model, description=False, figsize=(10,8)):
## get layers info
lst_layers = utils_nn_config(model)
layer_sizes = [layer['out'] for layer in lst_layers]
## fig setup
fig = plt.figure(figsize=figsize)
ax = fig.gca()
ax.set(title=model.name)
ax.axis('off')
left, right, bottom, top = 0.1, 0.9, 0.1, 0.9
x_space = (right-left) / float(len(layer_sizes)-1)
y_space = (top-bottom) / float(max(layer_sizes))
p = 0.025
## nodes
for i,n in enumerate(layer_sizes):
top_on_layer = y_space*(n-1)/2.0 + (top+bottom)/2.0
layer = lst_layers[i]
color = 'green' if i in [0, len(layer_sizes)-1] else 'blue'
color = 'red' if (layer['neurons'] == 0) and (i > 0) else color
### add description
if (description is True):
d = i if i == 0 else i-0.5
if layer['activation'] is None:
plt.text(x=left+d*x_space, y=top, fontsize=10, color=color, s=layer['name'].upper())
else:
plt.text(x=left+d*x_space, y=top, fontsize=10, color=color, s=layer['name'].upper())
plt.text(x=left+d*x_space, y=top-p, fontsize=10, color=color, s=layer['activation']+' (')
plt.text(x=left+d*x_space, y=top-2*p, fontsize=10, color=color, s='Σ'+str(layer['in'])+'[X*w]+b')
out = ' Y' if i == len(layer_sizes)-1 else ' out'
plt.text(x=left+d*x_space, y=top-3*p, fontsize=10, color=color, s=') = '+str(layer['neurons'])+out)
### circles
for m in range(n):
color = 'limegreen' if color == 'green' else color
circle = plt.Circle(xy=(left+i*x_space, top_on_layer-m*y_space-4*p), radius=y_space/4.0, color=color, ec='k', zorder=4)
ax.add_artist(circle)
### add text
if i == 0:
plt.text(x=left-4*p, y=top_on_layer-m*y_space-4*p, fontsize=10, s=r'$X_{'+str(m+1)+'}$')
elif i == len(layer_sizes)-1:
plt.text(x=right+4*p, y=top_on_layer-m*y_space-4*p, fontsize=10, s=r'$y_{'+str(m+1)+'}$')
else:
plt.text(x=left+i*x_space+p, y=top_on_layer-m*y_space+(y_space/8.+0.01*y_space)-4*p, fontsize=10, s=r'$H_{'+str(m+1)+'}$')
## links
for i, (n_a, n_b) in enumerate(zip(layer_sizes[:-1], layer_sizes[1:])):
layer = lst_layers[i+1]
color = 'green' if i == len(layer_sizes)-2 else 'blue'
color = 'red' if layer['neurons'] == 0 else color
layer_top_a = y_space*(n_a-1)/2. + (top+bottom)/2. -4*p
layer_top_b = y_space*(n_b-1)/2. + (top+bottom)/2. -4*p
for m in range(n_a):
for o in range(n_b):
line = plt.Line2D([i*x_space+left, (i+1)*x_space+left],
[layer_top_a-m*y_space, layer_top_b-o*y_space],
c=color, alpha=0.5)
if layer['activation'] is None:
if o == m:
ax.add_artist(line)
else:
ax.add_artist(line)
plt.show()
讓我們?cè)谖覀兊?2 個(gè)模型上嘗試一下,
首先是感知器:
visualize_nn(model, description=True, figsize=(10,8))
圖片來(lái)源:作者
圖片來(lái)源:作者
TensorFlow也提供了一個(gè)繪制模型結(jié)構(gòu)的工具,你可能希望將其用于具有更復(fù)雜層(CNN,RNN等)的更復(fù)雜的神經(jīng)網(wǎng)絡(luò)。
有時(shí)設(shè)置起來(lái)有點(diǎn)棘手,如果您有問(wèn)題,這篇文章可能會(huì)有所幫助。
utils.plot_model(model, to_file='model.png', show_shapes=True, show_layer_names=True)
這會(huì)將此圖像保存在筆記本電腦上,因此,如果您只想將其繪制在筆記本上,只需運(yùn)行以下命令即可刪除該文件:
import os
os.remove('model.png')
最后,是時(shí)候訓(xùn)練我們的深度學(xué)習(xí)模型了。為了使它運(yùn)行,我們必須“編譯”,或者換句話(huà)說(shuō),我們需要定義優(yōu)化器、損失函數(shù)和指標(biāo)。
我通常使用 Adam 優(yōu)化器,這是一種梯度下降的替代優(yōu)化算法(自適應(yīng)優(yōu)化器中最好的)。其他參數(shù)取決于用例。
在(二元)分類(lèi)問(wèn)題中,您應(yīng)該使用(二元)交叉熵?fù)p失,它將每個(gè)預(yù)測(cè)概率與實(shí)際類(lèi)輸出進(jìn)行比較。
至于指標(biāo),我喜歡監(jiān)控準(zhǔn)確性和 F1 分?jǐn)?shù),這是一個(gè)結(jié)合了精度和召回率的指標(biāo)(后者必須實(shí)現(xiàn),因?yàn)樗形窗?TensorFlow 中)。
# define metrics
def Recall(y_true, y_pred):
true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
recall = true_positives / (possible_positives + K.epsilon())
return recall
def Precision(y_true, y_pred):
true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
precision = true_positives / (predicted_positives + K.epsilon())
return precision
def F1(y_true, y_pred):
precision = Precision(y_true, y_pred)
recall = Recall(y_true, y_pred)
return 2*((precision*recall)/(precision+recall+K.epsilon()))
# compile the neural network
model.compile(optimizer='adam', loss='binary_crossentropy',
metrics=['accuracy',F1])
另一方面,在回歸問(wèn)題中,我通常將 MAE 設(shè)置為損失,將 R 平方設(shè)置為度量。
# define metrics
def R2(y, y_hat):
ss_res = K.sum(K.square(y - y_hat))
ss_tot = K.sum(K.square(y - K.mean(y)))
return ( 1 - ss_res/(ss_tot + K.epsilon()) )
# compile the neural network
model.compile(optimizer='adam', loss='mean_absolute_error',
metrics=[R2])
在開(kāi)始訓(xùn)練之前,我們還需要確定 Epochs 和 Batches:
由于數(shù)據(jù)集可能太大而無(wú)法一次全部處理,因此將其拆分為多個(gè)批次(批處理大小越大,需要的內(nèi)存空間就越多)。
反向傳播和隨后的參數(shù)更新每批發(fā)生一次,是整個(gè)訓(xùn)練集的一次傳遞。
因此,如果您有 100 個(gè)觀測(cè)值,并且批大小為 20,則需要 5 個(gè)批次才能完成 1 個(gè) epoch。批大小應(yīng)為 2 的倍數(shù)(常見(jiàn):32、64、128、256),因?yàn)橛?jì)算機(jī)通常以 2 的冪組織內(nèi)存。
我傾向于從 100 個(gè) epoch 開(kāi)始,批大小為 32。
在訓(xùn)練期間,我們希望看到指標(biāo)得到改善,損失逐個(gè)時(shí)期減少。此外,最好保留一部分?jǐn)?shù)據(jù) (20%-30%) 進(jìn)行驗(yàn)證。
換句話(huà)說(shuō),模型將分離這部分?jǐn)?shù)據(jù),以評(píng)估訓(xùn)練之外的每個(gè)紀(jì)元結(jié)束時(shí)的損失和指標(biāo)。
假設(shè)你已經(jīng)把你的數(shù)據(jù)準(zhǔn)備好到一些 X 和 y 數(shù)組中(如果沒(méi)有,你可以簡(jiǎn)單地生成隨機(jī)數(shù)據(jù),如
import numpy as np
X = np.random.rand(1000,10)
y = np.random.choice([1,0], size=1000)
),您可以按如下方式啟動(dòng)和可視化訓(xùn)練:
# train/validation
training = model.fit(x=X, y=y, batch_size=32, epochs=100, shuffle=True, verbose=0, validation_split=0.3)
# plot
metrics = [k for k in training.history.keys() if ('loss' not in k) and ('val' not in k)]
fig, ax = plt.subplots(nrows=1, ncols=2, sharey=True, figsize=(15,3))
## training
ax[0].set(title='Training')
ax11 = ax[0].twinx()
ax[0].plot(training.history['loss'], color='black') ax[0].set_xlabel('Epochs')
ax[0].set_ylabel('Loss', color='black')
for metric in metrics:
ax11.plot(training.history[metric], label=metric) ax11.set_ylabel('Score', color='steelblue')
ax11.legend()
## validation
ax[1].set(title='Validation')
ax22 = ax[1].twinx()
ax[1].plot(training.history['val_loss'], color='black') ax[1].set_xlabel('Epochs')
ax[1].set_ylabel('Loss', color='black')
for metric in metrics:
ax22.plot(training.history['val_'+metric], label=metric) ax22.set_ylabel('Score', color='steelblue')
plt.show()
圖片由作者提供?;貧w示例,此處為筆記本 這些圖取自?xún)蓚€(gè)實(shí)際用例,這兩個(gè)用例將標(biāo)準(zhǔn)機(jī)器學(xué)習(xí)算法與神經(jīng)網(wǎng)絡(luò)進(jìn)行比較(每個(gè)圖像下的鏈接)。
我們訓(xùn)練并測(cè)試了我們的模型,但我們?nèi)匀粵](méi)有說(shuō)服業(yè)務(wù)部門(mén)相信結(jié)果......我們能做什么?很簡(jiǎn)單,我們構(gòu)建了一個(gè)解釋器來(lái)證明我們的深度學(xué)習(xí)模型不是一個(gè)黑匣子。
我發(fā)現(xiàn)Shap與神經(jīng)網(wǎng)絡(luò)配合得很好:對(duì)于每個(gè)預(yù)測(cè),它能夠估計(jì)每個(gè)特征對(duì)模型預(yù)測(cè)值的貢獻(xiàn)。
基本上,它回答了“為什么模型說(shuō)這是 1 而不是 0?”的問(wèn)題。
您可以使用以下代碼:
請(qǐng)注意,您也可以在其他機(jī)器學(xué)習(xí)模型(即線(xiàn)性回歸、隨機(jī)森林)上使用此功能,而不僅僅是神經(jīng)網(wǎng)絡(luò)。
正如您可以從代碼中讀到的那樣,如果X_train參數(shù)保留為 None,我的函數(shù)假定它不是深度學(xué)習(xí)。
讓我們?cè)诜诸?lèi)和回歸示例中對(duì)其進(jìn)行測(cè)試:
i = 1
explainer_shap(model,
X_names=list_feature_names,
X_instance=X[i],
X_train=X,
task='classification', #task='regression'
top=10)
分類(lèi)示例,泰坦尼克號(hào)數(shù)據(jù)集中,預(yù)測(cè)是“幸存”主要是因?yàn)樘摂M變量_male=0,所以乘客是女性。
回歸示例房?jī)r(jià)數(shù)據(jù)集
這個(gè)房?jī)r(jià)的主要驅(qū)動(dòng)力是一個(gè)大地下室。
結(jié)論
本文是一個(gè)教程,演示如何設(shè)計(jì)和構(gòu)建人工神經(jīng)網(wǎng)絡(luò),無(wú)論是深度的還是非深度的。一步一步地分解了單個(gè)神經(jīng)元內(nèi)部發(fā)生的事情,更普遍地說(shuō)是層內(nèi)發(fā)生的事情。故事變得簡(jiǎn)單,就好像我們正在向業(yè)務(wù)部門(mén)解釋深度學(xué)習(xí)一樣,使用了大量的可視化。
一篇非常詳細(xì)和翔實(shí)的文章,概括了量子計(jì)算如何推進(jìn)數(shù)據(jù)科學(xué)的發(fā)展,以及數(shù)據(jù)科學(xué)如何推進(jìn)量子計(jì)算的發(fā)展。
聯(lián)系客服