當前位置:
首頁 > 知識 > 獨家 一文讀懂TensorFlow

獨家 一文讀懂TensorFlow

(點擊可查看大圖)

人工智慧、機器學習和深度學習

在介紹TensorFlow(以下簡稱為TF)之前,我們首先了解一下相關背景。

TF是一種機器學習框架,而機器學習經常和人工智慧,深度學習聯繫在一起,那麼三者到底是什麼關係呢?

簡單來講三者可以理解為包含於被包含的關係。其中最大的是人工智慧(以下簡稱為AI),AI最早起源於1956年的達特茅斯會議,當時AI的幾位先驅在會上展示了最早的AI程序:Logic Theorist,能夠自動推導數學原理第二章前52個定理中的38個,甚至其中一個定理的證明過程比書中給出的還要優雅,他們甚至曾嘗試要發表這一新的證明方式(不過後來被拒了)。總之,簡單來說,AI就是賦予機器以人的智能,讓機器具有學習和認知的能力。

機器學習(以下簡稱為ML)則是實現AI的一種方法。舉個簡單的垃圾郵件過濾的例子,我們人類判斷一個郵件是否是垃圾郵件很簡單,通過標題或內容很快就可以辨別。但是讓機器完成這樣的任務就沒這麼簡單。對於經典的ML演算法,首先需要從原始數據(郵件)中提取特徵,比如發信人地址、郵件標題、郵件內容關鍵詞等,從而將文字的郵件轉換成包含多個特徵的向量,然後利用邏輯回歸演算法在已經標定的數據集上進行訓練,得到每個特徵的權重。這些權重構成我們的預測模型,對於一封新的郵件,就可以用這個模型判斷其是否是垃圾郵件。

傳統的ML最大的問題就是特徵提取。比如讓機器識別照片中的動物是貓還是狗,如何設計特徵?深度學習(以下簡稱為DL)正是為了解決特徵提取的問題,我們不再需要人工設計特徵,而是讓演算法從數據中自動學習特徵,將簡單的特徵組合形成複雜的特徵來解決這些問題,所以DL可以說是實現ML的一種技術。

TensorFlow簡介

TensorFlow是什麼

Tensorflow是一個Google開發的第二代機器學習系統,克服了第一代系統DistBelief僅能開發神經網路演算法、難以配置、依賴Google內部硬體等局限性,應用更加廣泛,並且提高了靈活性和可移植性,速度和擴展性也有了大幅提高。字面上理解,TensorFlow就是以張量(Tensor)在計算圖(Graph)上流動(Flow)的方式的實現和執行機器學習演算法的框架。具有以下特點:

靈活性。TensorFlow不是一個嚴格的「神經網路」庫。只要可以將計算表示成數據流圖,就可以使用TensorFlow,比如科學計算中的偏微分求解等。(實際上其官網的介紹中對TF的定位就是基於數據流圖的科學計算庫,而非僅僅是機器學習庫)

可移植性。同一份代碼幾乎不經過修改既可以部署到有任意數量CPU、GPU或TPU(Tensor Processing Unit,Google專門為機器學習開發的處理器)的PC、伺服器或移動設備上。

自動求微分。同Theano一樣,TensorFlow也支持自動求微分,用戶不需要再通過反向傳播求解梯度。

多語言支持。TensorFlow官方支持Python、C++、Go和Java介面,用戶可以在硬體配置較好的機器中用Python進行實驗,在資源較緊張或需要低延遲的環境中用C++進行部署。

性能。雖然TensorFlow最開始發布時僅支持單機,在性能評測上並不出色,但是憑藉Google強大的開發實力,TensorFlow性能已經追上了其他框架。

Google為什麼開源Tensorflow

Google第一代分散式機器學習框架DistBelief在內部大規模使用後沒有選擇開源,而第二代TensorFlow於2015年11月在GitHub上開源,並在持續快速開發迭代中。TensorFlow最早由Google Brain的工程師開發,設計初衷是加速機器學習的研究,並快速地將研究原型轉化為產品。Google選擇開源TensorFlow的原因很簡單:第一是希望藉助社區的力量,大家一起完善TensorFlow。第二是回饋社區,Google希望讓這個優秀的工具得到更多的應用,提高學術界和工業界使用機器學習的效率。

自從2015年11月開源以來,TensorFlow迅速在眾多的機器學習框架中脫穎而出,在Github上獲得了最多的Star。下圖統計了Github上流行的機器學習框架的Star數量:

TensorFlow大事記

2015年11月9日,Google Research 發布了文章:TensorFlow - Google』s latest machine learning system, open sourced for everyone,正式宣布其新一代機器學習系統開源。

2016年4月13日,TensorFlow v0.8發布,提供分散式計算支持。

2016年4月29日,開發AlphaGo的DeepMind宣布從Torch7平台轉向TensorFlow。

2016年4月12日,基於TensorFlow的世界最準確的語法解析器SyntaxNet宣布開源。

2016年6月27日,TensorFlow v0.9發布,提高對移動設備的支持。

2016年8月30日,TF-Slim——TensorFlow的高層庫發布,用戶可以更簡單快速地定義模型。

2017年2月15日,TensorFlow v1.0發布,提高了速度和靈活性,並且承諾提供穩定的Python API。

TensorFlow架構

TF的系統構架分為兩部分:

前端:提供編程模型,負責構造計算圖,提供Python,C++,Java,Go等多種語言支持。

後端:提供運行時環境,負責執行計算圖,採用C++實現。

用戶在搭建演算法時,可以根據個人喜好和實際需求採用合適的前端語言來構建計算圖。圖搭建完成後,以Session為橋樑連接TF的後端,啟動並執行圖的計算過程。TF的後端根據當前硬體環境調用Operation的Kernal(Operation在某種硬體設備的特定實現)完成具體的計算。

註:後文對Session,Operation有具體解釋

TensorFlow編程模式

符號式編程 vs 命令式編程

和我們一般常用的命令式(Imperative)編程模式不同,TF採用的是符號式(Symbolic)編程。我們先認識一下兩種編程模式:

命令式編程是很常見的編程模式,大多數Python或C++程序都採用命令式編程。命令式編程明確輸入變數,根據程序邏輯逐步運算。下面是一段命令式編程的Python代碼:

import numpy as np

a = np.ones(10)

b = np.ones(10) * 2

c = b * a

d = c + 1

執行完第一步a = np.ones(10)後,程序得到了輸入變數a,第二句後得到了b,當執行c = b * a時,程序通過乘法計算而得到了c。

符號式編程則將計算過程抽象為計算圖,所有輸入節點、運算節點和輸出節點均符號化處理。將上述命令式編程代碼轉換為符號式編程:

A = Variable( A )

B = Variable( B )

C = B * AD = C + Constant(1)

# compiles the function

f = compile(D)

d = f(A=np.ones(10), B=np.ones(10)*2)

當前四步執行後,程序並沒有A、B、C、D的值,僅僅是構建了由這四個符號構成的計算圖,如下圖所示:

大多數符號式編程的程序中都或顯式或隱式地包含編譯的步驟,將前面定義的計算圖打包成可以調用的函數,而實際的計算則發生在編譯後。

Theano和TensorFlow屬於典型的符號式編程模式,而Torch則是命令式編程模式。在靈活性上,命令式編程模式更優,而在內存和計算上,符號式編程效率更高。

TensorFlow基本概念

要使用TensorFlow,我們必須理解TensorFlow:

使用圖(Graph)表示計算流程

在會話(Session)中執行圖

使用張量(Tensor)表示數據

使用變數(Variable)維護狀態

使用feed和fetch為任意的操作賦值或從中獲取數據

TF使用graph表示計算流程。圖中的節點稱為操作(Operation,以下簡稱OP)。每個OP接受0到多個Tensor,執行計算,輸出0到多個Tensor。圖是對計算流程的描述,需要在Session中運行。Session將計算圖的OP分配到CPU或GPU等計算單元,並提供相關的計算方法,並且會返回OP的結果。

張量(Tensor)

TF使用Tensor表示所有數據,相當於Numpy中的ndarray,0維的數值、一維的矢量、二維的矩陣到n維數組都是Tensor。相對於Numpy,TensorFlow提供了創建張量函數的方法,以及導數的自動計算。下表對比了Numpy和TensorFlow的基本用法。

變數(Variable)

在訓練模型時,Variable被用來存儲和更新參數。Variable包含張量儲存在內存的緩衝區中,必須顯式地進行初始化,在訓練後可以寫入磁碟。下面代碼中的Variable充當了一個簡單的計數器角色:

# Create a Variable, that will be initialized to the scalar value 0.

state = tf.Variable(0, name="counter")

# Create an Op to add one to `state`.

one = tf.constant(1)

new_value = tf.add(state, one)

update = tf.assign(state, new_value)

# Variables must be initialized by running an `init` Op after having

# launched the graph. We first have to add the `init` Op to the graph.

init_op = tf.initialize_all_variables()

# Launch the graph and run the ops.

with tf.Session() as sess:

# Run the init op

sess.run(init_op)

# Print the initial value of state

print(sess.run(state))

# Run the op that updates state and print state .

for _ in range(3):

sess.run(update)

print(sess.run(state))

# output:

# 0

# 1

# 2

# 3

上述代碼中assign()操作同add()一樣,都是在構建計算圖而沒有執行實際的計算。直到run()函數才會真正執行賦值等計算操作。

一般來說,用戶使用一系列Variable來表示一個統計模型,在訓練過程中運行圖計算來不斷更新,訓練完成後可以使用這些Variable構成的模型進行預測。

Feed

TensorFlow除了可以使用Variable和Constant引入數據外,還提供了Feed機制實現從外部導入數據。一般Feed總是與佔位符placeholder一起使用。

input1 = tf.placeholder(tf.float32)

input2 = tf.placeholder(tf.float32)

output = tf.mul(input1, input2)

with tf.Session() as sess:

print(sess.run([output], feed_dict=))

# output:

# [array([ 14.], dtype=float32)]

Fetch

要獲取操作的輸出,需要執行會話的run()函數,並且提供需要提取的OP。下面是獲取輸出的典型例子:

input1 = tf.constant([3.0])

input2 = tf.constant([2.0])

input3 = tf.constant([5.0])

intermed = tf.add(input2, input3)

mul = tf.mul(input1, intermed)

with tf.Session() as sess:

result = sess.run([mul, intermed])

print(result)

# output:

# [array([ 21.], dtype=float32), array([ 7.], dtype=float32)]

圖和會話

由於TF採用符號式編程模式,所以TF程序通常可以分為兩部分:圖的構建和圖的執行。

GIF/303K

圖的構建

構建圖的第一步,是創建源OP(source op),源操作不需要任何輸入,例如常量(constant),源操作的輸出被傳遞給其它操作做運算。

Python庫中,OP構造器的返回值代表被構造出的OP的輸出,這些返回值可以傳遞給其它OP構造器作為輸入。

TensorFlow Python庫有一個默認圖 (default graph),OP構造器可以為其增加節點。這個默認圖對許多程序來說已經足夠用了。

import tensorflow as tf

# Create a Constant op that produces a 1x2 matrix. The op is

# added as a node to the default graph.

#

# The value returned by the constructor represents the output

# of the Constant op.

matrix1 = tf.constant([[3., 3.]])

# Create another Constant that produces a 2x1 matrix.

matrix2 = tf.constant([[2.],[2.]])

# Create a Matmul op that takes matrix1 and matrix2 as inputs.

# The returned value, product , represents the result of the matrix

# multiplication.

product = tf.matmul(matrix1, matrix2)

上面使用TensorFlow提供的默認圖構建了包含三個節點的計算圖:兩個constant()操作和一個matmul()操作。要實際執行矩陣乘法,必須在Session中運行該計算圖。

圖的執行

要執行計算圖,首先需要創建Session對象,如果不提供參數,Session構造器將運行默認圖。

# Launch the default graph.

sess = tf.Session()

# To run the matmul op we call the session run() method, passing product

# which represents the output of the matmul op. This indicates to the call

# that we want to get the output of the matmul op back.

#

# All inputs needed by the op are run automatically by the session. They

# typically are run in parallel.

#

# The call run(product) thus causes the execution of three ops in the

# graph: the two constants and matmul.

#

# The output of the op is returned in result as a numpy `ndarray` object.

result = sess.run(product)

print(result)

# ==> [[ 12.]]

# Close the Session when we re done.

sess.close()

Session結束後,需要關閉以釋放資源。用戶也可以使用with控制語句自動關閉會話。

with tf.Session() as sess:

result = sess.run([product])

print(result)

TensorFlow簡單入門--MNIST字元識別

MNIST是一個簡單的計算機視覺數據集,包含共7萬個手寫數字字元,以灰度圖表示:

MNIST同時包含每個手寫字元對應的數字,稱為標籤(label)。上圖對應的標籤為5,0,4,1。

接下來,我們將使用TensorFlow訓練一個字元識別的多分類器,通過字元圖片預測對應的數字,這裡我們使用最簡單的多分類器--Softmax回歸。

MNIST數據集

首先讀取MNIST數據集:

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

MNIST數據集被讀入mnist對象中,分為三部分:55000行的訓練集(mnist.train)、10000行的測試集(mnist.test)和5000行的驗證集(mnist.validation)。這樣的切分很重要,在機器學習模型設計時必須有一個單獨的測試數據集不用於訓練而是用來評估這個模型的性能,從而更加容易把設計的模型推廣到其他數據集上(泛化)。

每個MNIST數據都包含一個字元圖片和對應的label,分別用「x」和「y」表示。每個圖片「x」由2828個像素構成,展開得到長度為784的向量。最後,我們得到的訓練數據集即形狀為[55000, 784]的二維數組以及對應的標籤(0-9)。

Softmax回歸

Softmax回歸是二分類器logistic回歸的推廣,是一種最簡單的多分類器。Softmax回歸分為兩步,首先通過加權求和得到一張給定圖片屬於特定數字類的證據(evidence),如果這個像素具有很強的證據說明這張圖片不屬於該類,那麼相應的權值為負數,相反如果這個像素擁有有利的證據支持這張圖片屬於這個類,那麼權值是正數。

下面的圖片顯示了一個模型學習到的圖片上每個像素對於特定數字類的權值。紅色代表負數權值,藍色代表正數權值。

我們也需要加入一個額外的偏置量(bias),因為輸入往往會帶有一些無關的干擾量。因此對於給定的輸入圖片 x 它代表的是數字 i 的證據可以表示為

其中Wij為 i 像素對 j字元的權重,bi為數字類 i 的偏置量,j 代表給定圖片 x 的像素索引用於像素求和。然後用softmax函數可以把這些證據轉換成概率 y:

這裡的softmax可以看成是一個激勵(activation)函數或者鏈接(link)函數,把我們定義的線性函數的輸出轉換成我們想要的格式,也就是關於10個數字類的概率分布。因此,給定一張圖片,它對於每一個數字的吻合度可以被softmax函數轉換成為一個概率值。softmax函數可以定義為:

用矩陣來表示:

實現回歸模型

TF程序可以分為圖的構建和圖的執行兩部分,而圖的構建又可細分為輸入圖、推斷圖、訓練圖和評估圖四部分。

使用TF之前,首先導入它:

import tensorflow as tf

輸入圖

x = tf.placeholder("float", [None, 784])

y_ = tf.placeholder("float", [None, 10])

這裡的x和y不是一個特定的值,而是兩個佔位符(placeholder),我們在TF運行計算時輸入這個值。我們希望能夠輸入任意數量的MNIST圖像,每一張圖展平成784維的向量。我們用2維的浮點數張量來表示這些圖片,這個張量的形狀是[None,784]。(這裡的None表示此張量的第一個維度可以是任何長度的。)

推斷圖

W = tf.Variable(tf.zeros([784,10]))

b = tf.Variable(tf.zeros([10]))

對於模型中的權重和偏置量這些參數,我們使用Variable來表示。初始化模型參數,這裡我們用全為零的張量來初始化W和b。因為我們要學習W和b的值,它們的初值可以隨意設置。注意,W的維度是[784,10],因為我們想要用784維的圖片向量乘以它以得到一個10維的證據值向量,每一位對應不同數字類。b的形狀是[10],所以我們可以直接把它加到輸出上面。

訓練圖

計算圖的第三個要素是訓練圖。為了訓練我們的模型,我們首先需要定義一個指標來評估這個模型是好的。其實,在機器學習,我們通常定義指標來表示一個模型是壞的,這個指標稱為代價(cost)或損失(loss),然後盡量最小化這個指標。

一個非常常見的代價函數是「交叉熵」(cross-entropy)。交叉熵產生於資訊理論裡面的信息壓縮編碼技術,但是它後來演變成為從博弈論到機器學習等其他領域裡的重要技術手段。它的定義如下:

是我們預測的概率分布,是實際的分布(我們輸入的one-hot vector)。比較粗糙的理解是,交叉熵是用來衡量我們的預測用於描述真相的低效性。

實現交叉熵:

cross_entropy = -tf.reduce_sum(y_*tf.log(y))

首先,用tf.log計算y的每個元素的對數。接下來,我們把y_的每一個元素和tf.log(y_)的對應元素相乘。最後,用tf.reduce_sum計算張量的所有元素的總和。(注意,這裡的交叉熵不僅僅用來衡量單一的一對預測和真實值,而是所有100幅圖片的交叉熵的總和。對於100個數據點的預測表現比單一數據點的表現能更好地描述我們的模型的性能。

現在我們知道我們需要我們的模型做什麼啦,用TensorFlow來訓練它是非常容易的。因為TensorFlow擁有一張描述你各個計算單元的圖,它可以自動地使用反向傳播演算法(backpropagation algorithm)來有效地確定你的變數是如何影響你想要最小化的那個代價函數的。然後,TensorFlow會用你選擇的優化演算法來不斷地修改變數以降低代價函數。

train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

在這裡,我們要求TF用梯度下降演算法(gradient descent algorithm)以0.5的學習速率最小化交叉熵。梯度下降演算法(gradient descent algorithm)是一個簡單的學習過程,TF只需將每個變數一點點地往使代價不斷降低的方向移動。當然TF也提供了其他許多優化演算法:只要簡單地調整一行代碼就可以使用其他的演算法。

TF在這裡實際上所做的是,它會在後台給描述你的計算的那張圖裡面增加一系列新的計算操作單元用於實現反向傳播演算法和梯度下降演算法。然後,它返回給你的只是一個單一的操作,當運行這個操作時,它用梯度下降演算法訓練你的模型,微調你的變數,不斷減少代價。

我們現在可以創建一個Session來運行模型,

sess = tf.InteractiveSession()

首先我們需要初始化所有變數,

tf.global_variables_initializer().run()

然後開始訓練模型,這裡我們讓模型循環訓練1000次!

for _ in range(1000):

sess.run(train_step, feed_dict=)

該循環的每個步驟中,我們都會隨機抓取訓練數據中的100個批處理數據點,然後我們用這些數據點作為參數替換之前的佔位符來運行train_step。

使用一小部分的隨機數據來進行訓練被稱為隨機訓練(stochastic training)- 在這裡更確切的說是隨機梯度下降訓練。在理想情況下,我們希望用我們所有的數據來進行每一步的訓練,因為這能給我們更好的訓練結果,但顯然這需要很大的計算開銷。所以,每一次訓練我們可以使用不同的數據子集,這樣做既可以減少計算開銷,又可以最大化地學習到數據集的總體特性。

評估圖

最後,我們要評估模型的性能,還需要構建評估圖。

首先讓我們找出那些預測正確的標籤。tf.argmax 是一個非常有用的函數,它能給出某個tensor對象在某一維上的其數據最大值所在的索引值。由於標籤向量是由0,1組成,因此最大值1所在的索引位置就是類別標籤,比如tf.argmax(y,1)返回的是模型對於任一輸入x預測到的標籤值,而 tf.argmax(y_,1) 代表正確的標籤,我們可以用 tf.equal 來檢測我們的預測是否真實標籤匹配(索引位置一樣表示匹配)。

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))

這行代碼會給我們一組布爾值。為了確定正確預測項的比例,我們可以把布爾值轉換成浮點數,然後取平均值。例如,[True, False, True, True] 會變成 [1,0,1,1] ,取平均值後得到 0.75.

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

最後,我們計算所學習到的模型在測試數據集上面的正確率。

print(sess.run(accuracy, feed_dict=))

這個最終結果值應該大約是92%。

其他機器學習框架

Caffe

Caffe全稱為Convolutional Architecture for Fast Feature Embedding,目前由BVLC(Berkeley Vision and Learning Center)進行維護。其創始人是加州大學伯克利的Ph.D.賈楊清,後來曾在Google Brain工作,開發TensorFlow。

Caffe優點在於使用配置文件方式定義網路,容易上手。訓練速度快,而且有大量訓練好的經典模型。組件模塊化,方便拓展到新的模型上。

Caffe最開始設計是只是針對圖像,沒有考慮文本、語音或者時間序列的數據,因此對卷積神經網路的支持很好,但是時間序列RNN、LSTM等支持不是很充分。要實現新的神經網路模塊(Layer)時,需要用戶自己寫C++或CUDA代碼實現正向和反向演算法,對新用戶有一定的難度。Caffe沒有原生的分散式支持,官方僅支持單機多CPU的訓練,不過有些第三方的支持,如雅虎開源的CaffeOnSpark,可藉助Spark的分散式框架實現Caffe的大規模分散式訓練。

Torch

Torch的定位是LuaJIT上的高效的科學計算庫,其歷史非常悠久,但真正發揚光大是在Facebook開源了其深度學習的組件之後。Torch與TensorFlow一樣,採用了底層C++加腳本語言調用的方式,不過Torch使用的是Lua,其性能非常優秀,常見的代碼通過JIT優化可以到C的性能的80%,但是相對Python並不是那麼主流,對多數用戶有學習成本。另外,Torch與Theano和TensorFlow採用符號編程模式不同,其採用命令式編程模式,所以實現某些複雜操作以及debug時更方便。

Keras

Keras是一個崇尚極簡、高度模塊化的神經網路庫,使用Python實現,可以運行在TensorFlow或Theano上,旨在讓用戶進行最快速的原型實驗。不同於Theano、TensorFlow等支持通用的數值計算,Keras專註於深度學習,它提供了目前為止最方便的API,用戶只需要將高級的模塊拼在一起,就可以搭建神經網路,大大降低了編程開銷、Keras所有模塊都是簡潔、易懂、完全可配置、可任意插拔的,基本沒有使用限制,神經網路、損失函數、優化器、初始化方法、激活函數和正則化等模塊都可以自由組合。使用Keras,只需要幾行就可以實現一個MLP,十幾行就可以實現一個AlexNet。如果Theano和TensorFlow是深度學習領域的Numpy,那麼Keras就是這個領域的scikit-learn。Keras最大的問題就是目前無法直接使用多GPU,所以對大規模的數據處理速度沒有其他支持多GPU和分散式的框架快。

參考資料

官網

TensorFlow Website(最權威、詳細的文檔)

(https://www.tensorflow.org)

視頻教程

TF開發者Sherry Moore的教程

(https://www.youtube.com/watch?v=Ejec3ID_h0w&t=2117s)

周莫煩的TF教程

(https://www.youtube.com/watch?v=2FmcHiLCwTU&list=PL2-dafEMk2A7EEME489DsI468AB0wQsMV)

Siraj的TF教程

(https://www.youtube.com/watch?v=Se9ByBnKb0o&list=PLXO45tsB95cJHXaDKpbwr5fC_CCYylw1f)

文章

深入淺出Tensorflow(一):深度學習及TensorFlow簡介

(http://www.infoq.com/cn/articles/introduction-of-tensorflow-part01)

Programming Models for Deep Learning

(http://mxnet.io/architecture/program_model.html#symbolic-and-imperative-programs)

TensorFlow學習筆記1:入門

(http://www.jeyzhang.com/tensorflow-learning-notes.html)

圖解TensorFlow架構與設計

(https://mp.weixin.qq.com/s?__biz=MzAwNDI4ODcxNA==&mid=2652244394&idx=1&sn=8c66795bc0e0d262f8defd18c07165a3)

編輯:黃繼彥

李選選,清華大學工程物理系博士研究生,專業是面向計算生物學的數據分析和演算法開發,對機器學習和大數據很感興趣,希望在「數據派」結交更多的朋友,互相學習,提高自己的水平。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 數據派THU 的精彩文章:

一文讀懂自然語言處理NLP
300+門編程計算機科學免費新課大集合
帶你訓練一個簡單的音頻識別網路
第四範式程曉澄:機器學習如何優化推薦系統
李飛飛:物體識別之後,計算機視覺的進展、目標和前景何在?

TAG:數據派THU |