PyTorch為何如此高效好用?來探尋深度學習框架的內部架構

2021-01-16 機器之心Pro

作為 Facebook 人工智慧團隊(FAIR)提供支持的深度學習框架,PyTorch 自 2017 年 1 月推出以來立即成為了一種流行開發工具。其在調試、編譯等方面的優勢使其受到了學界研究者們的普遍歡迎。本文中,來自蒙特婁綜合理工學院的研究員 Christian S. Perone 將為我們介紹這種神經網絡框架的內部架構,揭開 PyTorch 方便好用的真正原因。

前言

本文主要介紹了 PyTorch 代碼庫,旨在為 PyTorch 及其內部架構設計提供指導,核心目標是為那些想了解 API 知識之外的人提供有益的幫助,並給出之前教程所沒有的新內容。注意:PyTorch 構建系統需要大量使用代碼設置,因此其他人的描述我將不再重複。如果你感興趣,請參考原文提供的擴展資料。

C/C++中 Python 擴展對象的簡介

你可能知道可以藉助 C/C++擴展 Python,並開發所謂的「擴展」。PyTorch 的所有繁重工作由 C/C++實現,而不是純 Python。為了定義 C/C++中一個新的 Python 對象類型,你需要定義如下實例的一個類似結構:

// Python object that backs torch.autograd.Variablestruct THPVariable {PyObject_HEAD torch::autograd::Variable cdata; PyObject* backward_hooks;};

如上,在定義的開始有一個稱之為 PyObject_HEAD 的宏,其目標是標準化 Python 對象,並擴展至另一個結構,該結構包含一個指向類型對象的指針,以及一個帶有引用計數的欄位。

Python API 中有兩個額外的宏,分別稱為 Py_INCREF() 和 Py_DECREF(),可用於增加和減少 Python 對象的引用計數。多實體可以借用或擁有其他對象的引用(因此引用計數被增加),而只有當引用計數達到零,Python 才會自動刪除那個對象的內存。想了解更多有關 Python C/++擴展的知識,請參見:https://docs.python.org/3/extending/newtypes.html。

有趣的事實:使用小的整數作為索引、計數等在很多應用中非常見。為了提高效率,官方 CPython 解釋器緩存從-5 到 256 的整數。正由於此,聲明 a = 200; b = 200; a is b 為真,而聲明 a = 300; b = 300; a is b 為假。

Zero-copy PyTorch 張量到 Numpy,反之亦然

PyTorch 有專屬的張量表徵,分離 PyTorch 的內部表徵和外部表徵。但是,由於 Numpy 數組的使用非常普遍,尤其是當數據加載源不同時,我們確實需要在 Numpy 和 PyTorch 張量之間做轉換。正由於此,PyTorch 給出了兩個方法(from_numpy() 和 numpy()),從而把 Numpy 數組轉化為 PyTorch 數組,反之亦然。如果我們查看把 Numpy 數組轉化為 PyTorch 張量的調用代碼,就可以獲得有關 PyTorch 內部表徵的更多洞見:

at::Tensor tensor_from_numpy(PyObject* obj) {if (!PyArray_Check(obj)) { throw TypeError("expected np.ndarray (got %s)", Py_TYPE(obj)->tp_name); } auto array = (PyArrayObject*)obj; int ndim = PyArray_NDIM(array); auto sizes = to_aten_shape(ndim, PyArray_DIMS(array)); auto strides = to_aten_shape(ndim, PyArray_STRIDES(array)); // NumPy strides use bytes. Torch strides use element counts. auto element_size_in_bytes = PyArray_ITEMSIZE(array); for (auto& stride : strides) { stride /= element_size_in_bytes; } // (...) - omitted for brevity void* data_ptr = PyArray_DATA(array); auto& type = CPU(dtype_to_aten(PyArray_TYPE(array))); Py_INCREF(obj); return type.tensorFromBlob(data_ptr, sizes, strides, [obj](void* data) { AutoGIL gil; Py_DECREF(obj); });}

代碼摘自(tensor_numpy.cpp:https://github.com/pytorch/pytorch/blob/master/torch/csrc/utils/tensor_numpy.cpp#L88)

正如你在這段代碼中看到的,PyTorch 從 Numpy 表徵中獲取所有信息(數組元數據),並創建自己的張量。但是,正如你從被標註的第 18 行所看到的,PyTorch 保留一個指向內部 Numpy 數組原始數據的指針,而不是複製它。這意味著 PyTorch 將擁有這一數據,並與 Numpy 數組對象共享同一內存區域。

還有一點很重要:當 Numpy 數組對象越出範圍並獲得零引用(zero reference)計數,它將被當作垃圾回收並銷毀,這就是為什麼 Numpy 數組對象的引用計數在第 20 行有增加。該行之後,PyTorch 將從這一 Numpy 數據 blob 中創建一個新的張量對象,並且在創建這一新張量的過程中,PyTorch 將會傳遞內存數據指針,連同內存大小、步幅以及稍後張量存儲將會使用的函數(我們將會在下節討論),從而通過減少 Numpy 數組對象的引用計數並使 Python 關心這一對象內存管理而釋放數據。

tensorFromBlob() 方法將創建一個新張量,但只有在為這一張量創建一個新「存儲」之後。存儲是指存儲數據指針的地方,它並不在張量結構內部。張量存儲正是我們下一節要討論的內容。

張量存儲

張量的實際原始數據並不是立即保存在張量結構中,而是保存在我們稱之為「存儲(Storage)」的地方,它是張量結構的一部分。

正如我們前面在 tensor_from_numpy() 中看到的代碼,它調用了 tensorFromBlob() 函數以從原始數據 Blob 中創建一個張量。tensorFromBlob() 函數在內部會調用另一個名為 storageFromBlob() 函數,該函數主要根據類型為數據創建一個存儲。例如在 CPU 浮點型的情況下,它會返回一個新的 CPUFloatStorage 實例。

CPUFloatStorage 基本上是包含 utility 函數的包裝類(wrapper),且實際存儲結構如下所示稱為 THFloatStorage:

typedef struct THStorage{real *data; ptrdiff_t size; int refcount; char flag; THAllocator *allocator; void *allocatorContext; struct THStorage *view;} THStorage;

如上所示,THStorage 有一個指向原始數據、原始數據大小、flags 和 allocator 的指針,我們會在後面詳細地討論它們。值得注意的是,THStorage 不包含如何解釋內部數據的元數據,這是因為存儲對保存的內容「無處理信息的能力」,只有張量才知道如何「查看」數據。

因此,你可能已經意識到多個張量可以指向相同的存儲,而僅僅對數據採用不同的解析。這也就是為什麼我們以不同的形狀或維度,查看相同元素數量的張量會有很高的效率。下面的 Python 代碼表明,在改變張量的形狀後,存儲中的數據指針將得到共享。

>>> tensor_a = torch.ones((3, 3))>>> tensor_b = tensor_a.view(9)>>> tensor_a.storage().data_ptr() == tensor_b.storage().data_ptr()True

如 THFloatStorage 結構中的第七行代碼所示,它有一個指向 THAllocator 結構的指針。它因為給分配器(allocator)帶來靈活性而顯得十分重要,其中 allocator 可以用來分配存儲數據。

typedef struct THAllocator{void* (*malloc)(void*, ptrdiff_t); void* (*realloc)(void*, void*, ptrdiff_t); void (*free)(void*, void*);} THAllocator;

代碼摘自(THAllocator.h:https://github.com/pytorch/pytorch/blob/master/aten/src/TH/THAllocator.h#L16)

如上所述,該結構有三個函數指針欄位來定義分配器的意義:malloc、realloc 和 free。對於分配給 CPU 的內存,這些函數當然與傳統的 malloc/realloc/free POSIX 函數相關。然而當我們希望分配存儲給 GPU,我們最終會使用如 cudaMallocHost() 那樣的 CUDA 分配器,我們可以在下面的 THCudaHostAllocator malloc 函數中看到這一點。

static void *THCudaHostAllocator_malloc(void* ctx, ptrdiff_t size) {void* ptr; if (size < 0) THError("Invalid memory size: %ld", size); if (size == 0) return NULL; THCudaCheck(cudaMallocHost(&ptr, size)); return ptr;}

代碼摘自(THCAllocator.c:https://github.com/pytorch/pytorch/blob/master/aten/src/THC/THCAllocator.c#L3)

如上所示,分配器調用了一個 cudaMallocHost() 函數。你可能已經注意到版本庫組織中有縮寫的表示模式,在瀏覽版本庫時記住這些約定非常重要,它們在 PyTorch README 文件中有所總結:

TH = TorcHTHC = TorcH CudaTHCS = TorcH Cuda SparseTHCUNN = TorcH CUda Neural NetworkTHD = TorcH DistributedTHNN = TorcH Neural NetworkTHS = TorcH Sparse

該約定同樣存在於函數/類別名和其它對象中,因此了解它們十分重要。你可以在 TH 代碼中找到 CPU 分配器,在 THC 代碼中找到 CUDA 分配器。最後,我們可以看到主張量 THTensor 結構的組成:

typedef struct THTensor{int64_t *size; int64_t *stride; int nDimension; THStorage *storage; ptrdiff_t storageOffset; int refcount; char flag;} THTensor;

如上,THTensor 的主要結構為張量數據保留了 size/strides/dimensions/offsets/等,同時還有存儲 THStorage。我們可以將所有這些結構總結為以下圖表:

現在,如果我們有多重處理的需求,且希望在多個不同的進程中共享張量數據,那麼我們需要一個共享內存的方法。否則每次另一個進程需要張量或我們希望實現 Hogwild 訓練過程以將所有不同的進程寫入相同的內存區域時,我們就需要在進程間創建副本,這是非常低效的。因此,我們將在下一節討論共享內存的特定存儲方法。

共享內存

共享內存可以用很多種不同的方法實現(依賴於支持的平臺)。PyTorch 支持部分方法,但為了簡單起見,我將討論在 MacOS 上使用 CPU(而不是 GPU)的情況。由於 PyTorch 支持多種共享內存的方法,由於代碼中包含很多級的間接性,這部分會有點困難。

PyTorch 為 Python multiprocessing 模塊提供了一個封裝器,可以從 torch.multiprocessing 導入。他們對該封裝器中的實現做出了一些變動,以確保每當一個 Tensor 被放在隊列上或和其它進程共享時,PyTorch 可以確保僅有一個句柄的共享內存會被共享,而不會共享 Tensor 的完整新副本。現在,很多人都不知道 PyTorch 中的 Tensor 方法是 share_memory_(),然而,該函數正好可以觸發那個特定 Tensor 的保存內存的完整重建。該方法的執行過程是創建共享內存的一個區域,其可以在不同的進程中使用。最終,該函數可以調用以下的函數:

static THStorage* THPStorage_(newFilenameStorage)(ptrdiff_t size){int flags = TH_ALLOCATOR_MAPPED_SHAREDMEM | TH_ALLOCATOR_MAPPED_EXCLUSIVE; std::string handle = THPStorage_(__newHandle)(); auto ctx = libshm_context_new(NULL, handle.c_str(), flags); return THStorage_(newWithAllocator)(size, &THManagedSharedAllocator, (void*)ctx);}

如上所示,該函數使用了一個特殊的分類器 THManagedSharedAllocator 來創建另一個存儲。它首先定義了一些 flags,然後創建了一個格式為 /torch_ [process id] _ [random number] 的字符串句柄,最後在使用特殊的 THManagedSharedAllocator 創建新的存儲。該分配器有一個指向 PyTorch 內部庫 libshm 的函數指針,它將實現名為 Unix Domain Socket 的通信以共享特定 quyu 的內存句柄。這種分配器實際上是「smart allocator」的特例,因為它包含通信控制邏輯單元,並使用了另一個稱之為 THRefcountedMapAllocator 的分配器,它將創建市級共享內存區域並調用 mmp() 以將該區域映射到進程虛擬地址空間。

現在我們可以通過手動交換共享內存句柄而將分配給另一個進程的張量分配給一個進程,如下為 Python 示例:

>>> import torch>>> tensor_a = torch.ones((5, 5))>>> tensor_a1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1[torch.FloatTensor of size 5x5]>>> tensor_a.is_shared()False>>> tensor_a = tensor_a.share_memory_()>>> tensor_a.is_shared()True>>> tensor_a_storage = tensor_a.storage()>>> tensor_a_storage._share_filename_()(b'/var/tmp/tmp.0.yowqlr', b'/torch_31258_1218748506', 25)

在這段代碼中,執行進程 A,我們就創建了一個 5×5,被 1 所填充的張量。在此之後,我們將其共享,並列印 Unix Domain Socket 地址和句柄的元組。現在我們可以從另一個進程 B 中接入這一內存區域了:

進程 B 執行代碼:

>>> import torch>>> tensor_a = torch.Tensor()>>> tuple_info = (b'/var/tmp/tmp.0.yowqlr', b'/torch_31258_1218748506', 25)>>> storage = torch.Storage._new_shared_filename(*tuple_info)>>> tensor_a = torch.Tensor(storage).view((5, 5))1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1[torch.FloatTensor of size 5x5]

如你所見,使用 Unix Domain Socket 地址和句柄的元組信息,我們可以接入另一個進程的張量存儲內容。如果你在進程 B 改變張量,你會看到改動也會反映在進程 A 中,因為張量之間共享著同樣的存儲區域。

DLPack:深度學習框架 Babel 的希望

現在讓我們來看看 PyTorch 代碼庫最新的一些內容——DLPack(https://github.com/dmlc/dlpack)。DLPack 是一個內存張量結構的開放標準,允許張量數據在框架之間交換。非常有趣的是,這種內存表示是標準化的——與大多數框架已經在使用的內存表示方法非常類似,這就允許我們可以在框架之間共享,且完全無需複製數據。鑑於目前我們還沒有內部通信的工具,DLPack 是一個非常了不起的創造。

它無疑會幫助我們解決今天存在於 MXNet、PyTorch 等框架上「孤島」一樣的張量表示,並允許開發者在多個深度學習框架之間自由操作,享受標準化為框架帶來的優勢。

DLPack 的核心結構 DLTensor 非常簡單,如下所示:

/*!* \brief Plain C Tensor object, does not manage memory. */typedef struct { /*! * \brief The opaque data pointer points to the allocated data. * This will be CUDA device pointer or cl_mem handle in OpenCL. * This pointer is always aligns to 256 bytes as in CUDA. */ void* data; /*! \brief The device context of the tensor */ DLContext ctx; /*! \brief Number of dimensions */ int ndim; /*! \brief The data type of the pointer*/ DLDataType dtype; /*! \brief The shape of the tensor */ int64_t* shape; /*! * \brief strides of the tensor, * can be NULL, indicating tensor is compact. */ int64_t* strides; /*! \brief The offset in bytes to the beginning pointer to data */ uint64_t byte_offset;} DLTensor;

代碼來自 https://github.com/dmlc/dlpack/blob/master/include/dlpack/dlpack.h

如你所見,這裡有一個未加工數據的數據指針,以及形態/步幅/偏移/GPU 或 CPU,以及其他 DLTensor 指向的元信息。

這裡還有一個被稱為 DLManagedTensor 的受管理版本,其中框架可以提供一個環境,以及「刪除」函數,後者可以從借用張量來通知其他框架不再需要資源。

在 PyTorch 中,如果你想要轉換到 DLTensor 格式,或從 DLTensor 格式轉換,你可以找到 C/C++的方法,甚至 Python 方法來做這件事:

import torchfrom torch.utils import dlpackt = torch.ones((5, 5))dl = dlpack.to_dlpack(t)

這個 Python 函數會從 ATen 調用 toDLPack 函數,如下所示:

DLManagedTensor* toDLPack(const Tensor& src) {ATenDLMTensor * atDLMTensor(new ATenDLMTensor); atDLMTensor->handle = src; atDLMTensor->tensor.manager_ctx = atDLMTensor; atDLMTensor->tensor.deleter = &deleter; atDLMTensor->tensor.dl_tensor.data = src.data_ptr(); int64_t device_id = 0; if (src.type().is_cuda()) { device_id = src.get_device(); } atDLMTensor->tensor.dl_tensor.ctx = getDLContext(src.type(), device_id); atDLMTensor->tensor.dl_tensor.ndim = src.dim(); atDLMTensor->tensor.dl_tensor.dtype = getDLDataType(src.type()); atDLMTensor->tensor.dl_tensor.shape = const_cast<int64_t*>(src.sizes().data()); atDLMTensor->tensor.dl_tensor.strides = const_cast<int64_t*>(src.strides().data()); atDLMTensor->tensor.dl_tensor.byte_offset = 0; return &(atDLMTensor->tensor);}

如上所示,這是一個非常簡單的轉換,它可以將元數據的 PyTorch 格式轉換為 DLPack 格式,並將指針指向內部張量的數據表示。

我們都希望更多的深度學習框架可以學習這種標準,這會讓整個生態系統受益。希望本文能夠對你有所幫助。

相關焦點

  • 深度學習框架 PyTorch 為何值得學
    我們今天就來看看其中一位明星 PyTorch,看看它為何值得學。簡單介紹2018 年 10 月,PyTorch V 1.0.0 發布,融合 PyTorch 自身靈活性、研究優勢與 Caffe2 的後端與應用能力、ONNX 的框架轉換能力於一體;同時 FastAI V1.0 發布,可用單一 API 玩轉常見深度學習應用,大大降低了深度學習的學習門檻。
  • Keras vs PyTorch:誰是第一深度學習框架?
    兩大框架的連結:  Keras:https://github.com/keras-team/keras (https://keras.io/)  PyTorch:https://github.com/pytorch/pytorch  你想學習深度學習嗎?
  • 深度學習-Pytorch框架及常用代碼段學習
    前言:之前一直用的是tensorflow和keras,沒有接觸過Pytorch,但是最近因為項目需求,必須要使用Pytorch,於是從娃娃抓起,從頭學習下Pytorch,做點筆記以便日後查詢。對於筆者而言,學習某個深度學習框架,最好的資料是官方所給文檔,pytorch也是如此,官方文檔連結如下:https://pytorch.org/docs/stable/index.html一、基本設置篇主要包括一些版本號查詢,基本包的導入,顯卡設置等,如有遺漏之處,煩請指出。
  • TensorFlow與PyTorch之爭,哪個框架最適合深度學習
    選自builtin作者:Vihar Kurama機器之心編譯參與:吳攀、杜偉谷歌的 Tensorflow 與 Facebook 的 PyTorch 一直是頗受社區歡迎的兩種深度學習框架。那麼究竟哪種框架最適宜自己手邊的深度學習項目呢?
  • Torch7 開源 PyTorch:Python 優先深度學習框架
    據官網介紹,PyTorch 是一個 Python 優先的深度學習框架,能夠在強大的 GPU 加速基礎上實現張量和動態神經網絡。PyTorch 是一個 Python 軟體包,其提供了兩種高層面的功能:如有需要,你也可以復用你最喜歡的 Python 軟體包(如 numpy、scipy 和 Cython)來擴展 PyTorch。
  • pytorch深度學習一
    pytorch最近正在學習深度學習相關的課程,近幾年深度學習可謂十分火熱,不論是在工業界還是學術界都想往深度學習上靠一靠,甚至是在隔壁的機械學院都有很多實驗室研究深度學習,近期也是實驗室的要求,我也要完成學習pytorch
  • 掌握深度學習,為什麼要用 PyTorch、TensorFlow 框架?
    如果你需要深度學習模型,那麼 PyTorch 和 TensorFlow 都是不錯的選擇。作者 | Martin Heller譯者 | 彎月,責編 | 屠敏以下為譯文:並非每個回歸或分類問題都需要通過深度學習來解決。甚至可以說,並非每個回歸或分類問題都需要通過機器學習來解決。
  • 重磅| Torch7團隊開源PyTorch:Python優先的深度學習框架
    據官網介紹,PyTorch 是一個 Python 優先的深度學習框架,能夠在強大的 GPU 加速基礎上實現張量和動態神經網絡。PyTorch 介紹在粒度層面(granular level)上,PyTorch 庫包含了以下組件:使用 PyTorch 的原因通常有二:作為 numpy 的替代,以便使用強大的 GPU;將其作為一個能提供最大的靈活性和速度的深度學習研究平臺。
  • OpenAI高調站隊:深度學習框架以後主要用PyTorch
    乾明 發自 凹非寺量子位 報導 | 公眾號 QbitAIOpenAI發布最新消息,不再在各大AI框架中「搖擺」,而是支持PyTorch。這家馬斯克參與創辦、微軟10億美元投資的頂級AI研究機構表示,正在PyTorch上標準化自家深度學習框架。
  • 深度學習-Pytorch框架學習之模型訓練和測試
    前言前面四篇文章,介紹了模型搭建、數據準備及pytorch中常用的計算方法等,有了上述基礎後就可以訓練模型了,下面這篇文章會簡單介紹下在pytorch框架下如何訓練深度學習模型,以及一些常用代碼。模型訓練
  • 用PyTorch做深度學習實驗!Facebook新框架Ax和BoTorch雙雙開源
    在現代機器學習應用中,對實驗到生產的流程進行簡化是最難實現的任務之一。在已經市場化深度學習框架中,Facebook的PyTorch因其高度靈活性成為數據科學界的最愛,PyTorch能夠實現快速建模和實驗。但是,深度學習應用中的許多實驗面臨的挑戰已經超出了特定框架的能力範圍。
  • 迎來PyTorch,告別 Theano,2017 深度學習框架發展大盤點
    深度學習是機器學習中一種基於對數據進行表徵學習的方法,作為當下最熱門的話題,谷歌、Facebook、微軟等巨頭紛紛圍繞深度學習做了一系列研究,一直在支持開源深度學習框架的建設。過去一年間,在這些巨頭的加持下,深度學習框架格局發生了極大改變:新框架橫空出世,舊的框架也逐漸退出歷史舞臺,而框架與框架之間的聯繫也更加緊密,生態更為開放。
  • Caffe2代碼全部併入PyTorch:深度學習框架格局劇震
    昨日,Caffe2 的 Github 頁面突然出現了一個「巨大的改動」:Caffe2 開原始碼正式併入 PyTorch,至此,Facebook 主力支持的兩大深度學習框架已合二為一。這兩大框架,在整個深度學習框架格局中都極受關注。
  • 在Linux系統中安裝深度學習框架Pytorch
    使用Python作為開發語言,是一個以Python優先的深度學習框架。本質上是Numpy的替代者。下載好anaconda2.出錯原因:pytorch和torchvision下載失敗,主要是下載慢,延遲過高導致。
  • Caffe2 代碼全部併入 PyTorch:深度學習框架格局劇震
    昨日,Caffe2 的 Github 頁面突然出現了一個「巨大的改動」:Caffe2 開原始碼正式併入 PyTorch,至此,Facebook 主力支持的兩大深度學習框架已合二為一。
  • TensorFlow VS PyTorch的深度學習框架之爭
    前言對於廣大深度學習行業從業者而言,熟練掌握一種或多種深度學習框架,是日常煉丹的必備技能之一。深度學習框架市場經歷了早期的混亂之後,逐漸形成了以 TensorFlow 和 PyTorch 兩家獨大的市場格局。
  • 「2017深度學習框架大事記」PyTorch成TensorFlow最大競爭對手...
    已經有其他一些不太知名的深度學習框架使用動態計算圖,例如Chainer。動態圖的優點在於,圖(graph)是由run定義(「define by run」),而不是傳統的「define and run」。特別是,在輸入可以變化的情況下,例如文本這樣的非結構化數據,這非常有用而且高效。
  • 清華自研深度學習框架「計圖」開源!多項任務性能超過PyTorch
    乾明 發自 凹非寺量子位 報導 | 公眾號 QbitAIAI框架,又來重磅中國玩家。剛剛,清華自研的深度學習框架,正式對外開源。「貴系」計算機系的圖形實驗室出品,取名Jittor,中文名計圖。值得一提的是,這也是首個來自中國高校科研機構的開源深度學習框架,之前,業內來自「高校」的還有加拿大蒙特婁大學的Theano,UC伯克利的Caffe。與主流的深度學習框架TensorFlow、Pytorch不同,Jittor是一個完全基於動態編譯(Just-in-time)、使用元算子和統一計算圖的深度學習框架。
  • 深度學習:盤點全球的深度學習框架「Tensorflow、Pytorch」勝出
    深度學習在人工智慧技中的表現尤為的突出,想要學習深度學習,首先需要掌握一個有效的深度學習框架,這篇文章將盤點目前全球流行的深度學習框架,從框架的流行程度、應用場景出發,來提高大家對深度學習框架的認識。我們可以把「張量」想像成一個N維數組,而「流」直觀地表達張量之間通過計算來相互轉換的過程。深度學習的一系列任務,其實都是在給定輸入和輸出下,探索其內部函數映射的過程。張量與流通俗易懂地解釋了深度學習算法的運行過程,即張量之間通過計算相互轉換。TensorFlow的運行原理為:用張量定義數據模型,把數據模型和操作定義在計算圖中,使用會話運行計算。
  • 寫給純小白的深度學習環境搭建寶典:pytorch+tensorflow
    每天給小編五分鐘,小編用自己的代碼,讓你輕鬆學習人工智慧。本文將手把手帶你快速搭建你自己的深度學習環境,然後實現自己的第一個深度學習程序。野蠻智能,小白也能看懂的人工智慧。如果你對循環神經網絡的基本原理還不了解,可以通過小編的精講深度學習RNN三大核心點,三分鐘掌握循環神經網絡進行簡單了解。下面進入實戰環節。