天天看點

[翻譯] NumSharp的數組切片功能 [:]

原文位址:https://medium.com/scisharp/slicing-in-numsharp-e56c46826630

翻譯初稿(英文水準有限,請多包涵):

由于Numsharp新推出了數組切片這個牛逼的功能,是以.NET社群距離擁有強大的開源機器學習平台又近了一步。  

Python之是以是機器學習的首選語言,部分原因就是因為它擁有一些牛逼的庫,例如NumPy和Tensorflow。與此同時,C#開發人員也迫切需要用于機器學習和資料科學的強大開源庫。而NumSharp,這個由 SciSharp STACK這個開源組織全力推動的,要把NumPy移植到C#的這個項目,由于其最近全面實作了切片技術,進而向該目标邁進了一大步。該技術允許對n維數組随意的建立子集,并将其作為對原始資料的高效視圖。因為這些,使得它與TensorFlow.net一起成為了C#中機器學習的有用工具。  

如果你沒用過NumPy,你可能不知道切片技術有多好用, Python數組允許通過對一定範圍對元素進行索引來傳回數組的一個切片,其索引操作是這樣的:a[start:end:step]。但是,隻有使用NumPy複雜巧妙的數組實作,切片才成為一種真正強大的資料操作技術,若沒有這種技術,機器學習或資料科學就無法想象了。  

對于那些不能或不想因為機器學習就轉換到Python語言的人來說,幸運的事情發生了,我對此也很羨慕, NumSharp将這種能力帶入了.NET世界裡。作為NumSharp的開發人員之一,我将向您展示幾個重要的切片用例,并附有C#的示例代碼段。首先請注意,由于語言文法的不同,在C#中無法以與Python相同的方式進行索引。但是,我們決定保留Python裡切片定義的文法,是以在C#裡,我們使用字元串來索引切片。   

[翻譯] NumSharp的數組切片功能 [:]
[翻譯] NumSharp的數組切片功能 [:]

而使用NumSharp寫出的C#代碼也是差不多一樣的。但請注意,這裡有一個細微的差别是,這裡的切片使用的是字元串作為索引器的參數進行的索引。 

[翻譯] NumSharp的數組切片功能 [:]
[翻譯] NumSharp的數組切片功能 [:]

正如您所看到的,NumSharp團隊花了很多的精力來保證代碼盡可能的與Python相似。 這非常重要,因為這樣的話,現有的依賴于NumPy的代碼就可以很輕松的移植到C#上去了。 

[翻譯] NumSharp的數組切片功能 [:]

對于運作時性能,尤其是對于大規模的資料集而言,能夠在不進行複制的情況下僅對函數傳入和傳出原始資料的本地部分(例如:一張大圖檔中的一部分)是至關重要的。切片使用局部坐标進行索引的,是以您的算法無需了解資料的全局結構,這樣就有效地簡化了您的工作,并確定盡可能高的性能,因為避免了不必要的複制。 

除了對切片的範圍指定start和end之外,再通過指定它的步長,就可以建立數組的稀疏視圖了。這是一個連C# 8.0新的數組切片文法都沒有的功能(據我所知)。在使用交錯資料時,此功能變得非常重要。您可以通過設計算法來讓它們處理連的續資料并為它們提供模拟連續資料源的稀疏切片,進而盡可能降低算法的複雜性。 

[翻譯] NumSharp的數組切片功能 [:]

切片可以進一步切片,如果您使用高維資料的話,這也将是一個非常重要的功能。同時這也有助于減少算法的複雜性,因為通過遞歸切片減少了資料的維數。 

[翻譯] NumSharp的數組切片功能 [:]

如果您需要将資料數組視為一個卷,并在不需要進行令人煩躁的坐标轉換計算的情況下使用其中的某些部分,那麼.reshape()方法就是您的朋友。 

所有由.reshape()或切片操作建立的數組都隻是原始資料的視圖。當您對視圖的元素進行疊代、讀取或寫入時,其實您通路的是原始的資料數組。很顯然,NumSharp為您做了相應的索引變換,是以您可以使用相對的坐标對切片進行索引。 

使用值為負數的步長可以高效的反轉切片的順序。它的優點是不需要複制或列舉資料就可以完成此操作,就像IEnumerable.Reverse() 一樣。差別在于,視圖(就是指a["::-1"]的操作結果)以相反的順序顯示資料,此外您無需對其進行列舉就可以索引到該反轉序列。 

當處理高維資料時,該資料的算法也會變得非常複雜。在處理NumSharp的NDArray的.ToString() 方法時(這個方法可以列印出任意高維卷)我注意到該算法通過系統地和遞歸地将(N-1)D卷切出ND-卷等諸如此類的方式簡單而優雅的取得了結果。 

通過在可傳回低維子卷的範圍符号上使用NumSharp的索引符号進行切片,才使這種分而治之的方法變得可行。 

範圍符号[“start:stop:step”]允許您通路具有相同次元給定卷的子範圍。是以即使隻劃出二維矩陣的一列,仍然可以得到隻有一列的二維矩陣。下面這一小段C#代碼就展示了這一點: 

[翻譯] NumSharp的數組切片功能 [:]

數組字元索引重載可以實作在一個N維數組裡從特定位置建立視圖。是以,用索引符号從二維矩陣中分割出一個列,可以得到一個一維向量: 

[翻譯] NumSharp的數組切片功能 [:]
[翻譯] NumSharp的數組切片功能 [:]

如果您一眼也沒有發現差異,那麼下面這兩個切片定義, ange [":,2:3"] vs index [":,2"],它們的結果是大不相同的。NumSharp wiki提供了新切片表示法的完整參考。 

在實作N維視圖的切片時,我得出這樣一個結論,對于.NET中的許多其他領域來說它可能很有趣,是以我将它分解出一個自己的獨立庫SliceAndDice。它裡面有個東西叫做ArraySlice <T>,它是對所有索引的C#資料結構(如T[]或IList<T>)的一個輕量級包裝,此外它還允許您使用相同的塑形,切片和視圖機制,并且無需進行任何其他的重度數值計算。它隻使用了幾百行代碼就漂亮簡潔的完成了切片的壯舉。 

NumSharp最近被賦予了切片和視圖機制,同樣就是這些機制讓NumPy成為Python機器學習生态最重要的庫之一。SciSharp Stack作為一個開源組織,目前隻有少數技術娴熟的開發人員,但他們卻非常努力地要為.NET世界帶來同樣的魔力。NumSharp最近的這次改進就是實作這一目标的重要基石。 

[翻譯] NumSharp的數組切片功能 [:]