-
1 # IT人劉俊明
-
2 # SOWORD科技言
機器學習程式語言有很多種,我們常用的有C語言,C++,java,python,在過去幾年,人工智慧還在發展階段,而在前兩年人工智慧爆發,Python再次被人熟知,熱度一度上升超過java,為什麼Python能成為機器學習的首選語言?
第一,從學習角度分析python語法簡單,學習成本低。
第二,python免費庫眾多,特別是科學演算法擴充套件庫,免費,易學、嚴謹的程式設計語言。
第三,Python是完全面向物件的語言。易維護,易開發。
第四,容易與他人程式語言結合,比如C語言,C++,java都可以,可嵌入性,可擴充套件性。
-
3 # 臥蠶uncle46
就因為python相比於其他程式語言簡單,不用太注重語法,你可以想一下那些做機器學習的人,人家真正搞的是演算法,好不容易把演算法搞出來還要花一大堆時間去程式設計實現,花無謂的時間在程式設計語法上不值得。
-
4 # 機器之心Pro
隨著機器學習的興起,Python 逐步成為了「最受歡迎」的語言。它簡單易用、邏輯明確並擁有海量的擴充套件包,因此其不僅成為機器學習與資料科學的首選語言,同時在網頁、資料爬取可科學研究等方面成為不二選擇。此外,很多入門級的機器學習開發者都是跟隨大流選擇 Python,但到底為什麼要選擇 Python 就是本文的核心內容。
本教程的目的是讓你相信兩件事:首先,Python 是一種非常棒的程式語言;其次,如果你是一名科學家,Python 很可能值得你去學習。本教程並非想要說明 Python 是一種萬能的語言;相反,作者明確討論了在幾種情況下,Python 並不是一種明智的選擇。本教程的目的只是提供對 Python 一些核心特徵的評論,並闡述作為一種通用的科學計算語言,它比其他常用的替代方案(最著名的是 R 和 Matlab)更有優勢。
本教程的其餘部分假定你已經有了一些程式設計經驗,如果你非常精通其他以資料為中心的語言(如 R 或 Matlab),理解本教程就會非常容易。本教程不能算作一份關於 Python 的介紹,且文章重點在於為什麼應該學習 Python 而不是怎樣寫 Python 程式碼(儘管其他地方有大量的優秀教程)。
概述Python(相對來說)易於學習程式設計很難,因此從絕對意義上來說,除非你已經擁有程式設計經驗,否則程式語言難以學習。但是,相對而言,Python 的高階屬性(見下一節)、語法可讀性和語義直白性使得它比其他語言更容易學習。例如,這是一個簡單 Python 函式的定義(故意未註釋),它將一串英語單詞轉換為
(crummy)Pig Latin:def pig_latin(text): """ Takes in a sequence of words and converts it to (imperfect) pig latin. """ word_list = text.split(" ") output_list = [] for word in word_list: word = word.lower() if word.isalpha(): first_char = word[0] if first_char in "aeiou": word = word + "ay" else: word = word[1:] + first_char + "yay" output_list.append(word) pygged = " ".join(output_list) return pygged以上函式事實上無法生成完全有效的 Pig Latin(假設存在「有效 Pig Latin」),但這沒有關係。有些情況下它是可行的:
test1 = pig_latin("let us see if this works")print(test1)拋開 Pig Latin 不說,這裡的重點只是,出於幾個原因,程式碼是很容易閱讀的。首先,程式碼是在高階抽象中編寫的(下面將詳細介紹),因此每行程式碼都會對映到一個相當直觀的操作。這些操作可以是「取這個單詞的第一個字元」,而不是對映到一個沒那麼直觀的低階操作,例如「為一個字元預留一個位元組的記憶體,稍後我會傳入一個字元」。其次,控制結構(如,for—loops,if—then 條件等)使用諸如「in」,「and」和「not」的簡單單詞,其語義相對接近其自然英語含義。第三,Python 對縮排的嚴格控制強加了一種使程式碼可讀的規範,同時防止了某些常見的錯誤。第四,Python 社群非常強調遵循樣式規定和編寫「Python 式的」程式碼,這意味著相比使用其他語言的程式設計師而言,Python 程式設計師更傾向於使用一致的命名規定、行的長度、程式設計習慣和其他許多類似特徵,它們共同使別人的程式碼更易閱讀(儘管這可以說是社群的一個特徵而不是語言本身)。
Python 是一種高階語言與其他許多語言相比,Python 是一種相對「高階」的語言:它不需要(並且在許多情況下,不允許)使用者擔心太多底層細節,而這是其他許多語言需要去處理的。例如,假設我們想建立一個名為「my_box_of_things」的變數當作我們所用東西的容器。我們事先不知道我們想在盒子中保留多少物件,同時我們希望在新增或刪除物件時,物件數量可以自動增減。所以這個盒子需要佔據一個可變的空間:在某個時間點,它可能包含 8 個物件(或「元素」),而在另一個時間點,它可能包含 257 個物件。在像 C 這樣的底層語言中,這個簡單的要求就已經給我們的程式帶來了一些複雜性,因為我們需要提前宣告盒子需要佔據多少空間,然後每次我們想要增加盒子需要的空間時,我麼需要明確建立一個佔據更多空間的全新的盒子,然後將所有東西複製到其中。
# Create a box (really, a "list") with 5 things# Create my_box_of_things = ["Davenport", "kettle drum", "swallow-tail coat", "table cloth", "patent leather shoes"]print(my_box_of_things)["Davenport", "kettle drum", "swallow-tail coat", "table cloth", "patent leather shoes"]# Add a few more thingsmy_box_of_things += ["bathing suit", "bowling ball", "clarinet", "ring"]# Maybe add one last thingmy_box_of_things.append("radio that only needs a fuse")# Let"s see what we have...print(my_box_of_things)更一般來說,Python(以及根據定義的其他所有高階語言)傾向於隱藏需要在底層語言中明確表達的各種死記硬背的宣告。這使得我們可以編寫非常緊湊、清晰的程式碼(儘管它通常以降低效能為代價,因為內部不再可訪問,因此最佳化變得更加困難)。
例如,考慮從檔案中讀取純文字這樣看似簡單的行為。對於與檔案系統直接接觸而傷痕累累的開發者來說,從概念上看似乎只需要兩個簡單的操作就可以完成:首先開啟一個檔案,然後從其中讀取。實際過程遠不止這些,並且比 Python 更底層的語言通常強制(或至少是鼓勵)我們去承認這一點。例如,這是在 Java 中從檔案中讀取內容的規範(儘管肯定不是最簡潔的)方法:
import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;public class ReadFile { public static void main(String[] args) throws IOException{ String fileContents = readEntireFile("./foo.txt"); } private static String readEntireFile(String filename) throws IOException { FileReader in = new FileReader(filename); StringBuilder contents = new StringBuilder(); char[] buffer = new char[4096]; int read = 0; do { contents.append(buffer, 0, read); read = in.read(buffer); } while (read >= 0); return contents.toString(); }}你可以看到我們不得不做一些令人苦惱的事,例如匯入檔案讀取器、為檔案中的內容建立一個快取,以塊的形式讀取檔案塊並將它們分配到快取中等等。相比之下,在 Python 中,讀取檔案中的全部內容只需要如下程式碼:
# Read the contents of "hello_world.txt"text = open("hello_world.txt").read()當然,這種簡潔性並不是 Python 獨有的;還有其他許多高階語言同樣隱藏了簡單請求所暗含的大部分令人討厭的內部過程(如,Ruby,R,Haskell 等)。但是,相對來說比較少有其他語言能與接下來探討的 Python 特徵相媲美。
Python 是一種通用語言根據設計,Python 是一種通用的語言。也就是說,它旨在允許程式設計師在任何領域編寫幾乎所有型別的應用,而不是專注於一類特定的問題。在這方面,Python 可以與(相對)特定領域的語言進行對比,如 R 或 PHP。這些語言原則上可用於很多情形,但仍針對特定用例進行了明確最佳化(在這兩個示例中,分別用於統計和網路後端開發)。
Python 通常被親切地成為「所有事物的第二個最好的語言」,它很好地捕捉到了這樣的情緒,儘管在很多情況下 Python 並不是用於特定問題的最佳語言,但它通常具有足夠的靈活性和良好的支援性,使得人們仍然可以相對有效地解決問題。事實上,Python 可以有效地應用於許多不同的應用中,這使得學習 Python 成為一件相當有價值的事。因為作為一個軟體開發人員,能夠使用單一語言實現所有事情,而不是必須根據所執行的專案在不同語言和環境間進行切換,是一件非常棒的事。
標準庫
透過瀏覽標準庫中可用的眾多模組列表,即 Python 直譯器自帶的工具集(沒有安裝第三方軟體包),這可能是最容易理解 Python 通用性的方式。若考慮以下幾個示例:
os: 系統操作工具
re:正則表達
collections:有用的資料結構
multiprocessing:簡單的並行化工具
pickle:簡單的序列化
json:讀和寫 JSON
argparse:命令列引數解析
functools:函式化程式設計工具
datetime:日期和時間函式
cProfile:分析程式碼的基本工具
這張列表乍一看並不令人印象深刻,但對於 Python 開發者來說,使用它們是一個相對常見的經歷。很多時候用谷歌搜尋一個看似重要甚至有點深奧的問題,我們很可能找到隱藏在標準庫模組內的內建解決方案。
JSON,簡單的方法
例如,假設你想從 web.JSON 中讀取一些 JSON 資料,如下所示:
data_string = """[ { "_id": "59ad8f86450c9ec2a4760fae", "name": "Dyer Kirby", "registered": "2016-11-28T03:41:29 +08:00", "latitude": -67.170365, "longitude": 130.932548, "favoriteFruit": "durian" }, { "_id": "59ad8f8670df8b164021818d", "name": "Kelly Dean", "registered": "2016-12-01T09:39:35 +08:00", "latitude": -82.227537, "longitude": -175.053135, "favoriteFruit": "durian" }]"""我們可以花一些時間自己編寫 json 解析器,或試著去找一個有效讀取 json 的第三方包。但我們很可能是在浪費時間,因為 Python 內建的 json 模組已經能完全滿足我們的需要:
import jsondata = json.loads(data_string)print(data)"""[{"_id": "59ad8f86450c9ec2a4760fae", "name": "Dyer Kirby", "registered": "2016-11-28T03:41:29 +08:00", "latitude": -67.170365, "longitude": 130.932548, "favoriteFruit": "durian"}, {"_id": "59ad8f8670df8b164021818d", "name": "Kelly Dean", "registered": "2016-12-01T09:39:35 +08:00", "latitude": -82.227537, "longitude": -175.053135, "favoriteFruit": "durian"}]請注意,在我們能於 json 模組內使用 loads 函式前,我們必須匯入 json 模組。這種必須將幾乎所有功能模組明確地匯入名稱空間的模式在 Python 中相當重要,且基本名稱空間中可用的內建函式列表非常有限。許多用過 R 或 Matlab 的開發者會在剛接觸時感到惱火,因為這兩個包的全域性名稱空間包含數百甚至上千的內建函式。但是,一旦你習慣於輸入一些額外字元,它就會使程式碼更易於讀取和管理,同時命名衝突的風險(R 語言中經常出現)被大大降低。
優異的外部支援
當然,Python 提供大量內建工具來執行大量操作並不意味著總需要去使用這些工具。可以說比 Python 豐富的標準庫更大的賣點是龐大的 Python 開發者社群。多年來,Python 一直是世界上最流行的動態程式語言,開發者社群也貢獻了眾多高質量的安裝包。
Web 和 API 開發:flask,Django,Falcon,hug
爬取資料和解析文字/標記: requests,beautifulsoup,scrapy
自然語言處理(NLP):nltk,gensim,textblob
數值計算和資料分析:numpy,scipy,pandas,xarray
機器學習:scikit-learn,Theano,Tensorflow,keras
影象處理:pillow,scikit-image,OpenCV
作圖:matplotlib,seaborn,ggplot,Bokeh
等等
Python 的一個優點是有出色的軟體包管理生態系統。雖然在 Python 中安裝包通常比在 R 或 Matlab 中更難,這主要是因為 Python 包往往具有高度的模組化和/或更多依賴於系統庫。但原則上至少大多數 Python 的包可以使用 pip 包管理器透過命令提示符安裝。更復雜的安裝程式和包管理器,如 Anaconda 也大大減少了配置新 Python 環境時產生的痛苦。
Python 是一種(相對)快速的語言這可能令人有點驚訝:從表面上看,Python 是一種快速語言的說法看起來很愚蠢。因為在標準測試時,和 C 或 Java 這樣的編譯語言相比,Python 通常會卡頓。毫無疑問,如果速度至關重要(例如,你正在編寫 3D 圖形引擎或執行大規模的流體動力學模擬實驗),Python 可能不會成為你最優選擇的語言,甚至不會是第二好的語言。但在實際中,許多科學家工作流程中的限制因素不是執行時間而是開發時間。一個花費一個小時執行但只需要 5 分鐘編寫的指令碼通常比一個花費 5 秒鐘執行但是需要一個禮拜編寫和除錯的指令碼更合意。此外,正如我們將在下面看到的,即使我們所用的程式碼都用 Python 編寫,一些最佳化操作通常可以使其執行速度幾乎與基於 C 的解決方案一樣快。實際上,對大多數科學家家來說,基於 Python 的解決方案不夠快的情況並不是很多,而且隨著工具的改進,這種情況的數量正在急劇減少。
不要重複做功
軟體開發的一般原則是應該儘可能避免做重複工作。當然,有時候是沒法避免的,並且在很多情況下,為問題編寫自己的解決方案或建立一個全新的工具是有意義的。但一般來說,你自己編寫的 Python 程式碼越少,效能就越好。有以下幾個原因:
Python 是一種成熟的語言,所以許多現有的包有大量的使用者基礎並且經過大量最佳化。例如,對 Python 中大多數核心科學庫(numpy,scipy,pandas 等)來說都是如此。
大多數 Python 包實際上是用 C 語言編寫的,而不是用 Python 編寫的。對於大多數標準庫,當你呼叫一個 Python 函式時,實際上很大可能你是在執行具有 Python 介面的 C 程式碼。這意味著無論你解決問題的演算法有多精妙,如果你完全用 Python 編寫,而內建的解決方案是用 C 語言編寫的,那你的效能可能不如內建的方案。例如,以下是執行內建的 sum 函式(用 C 編寫):
# Create a list of random floatsimport randommy_list = [random.random() for i in range(10000)]# Python"s built-in sum() function is pretty fast%timeit sum(my_list)47.7 µs ± 4.5 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)從演算法上來說,你沒有太多辦法來加速任意數值列表的加和計算。所以你可能會想這是什麼鬼,你也許可以用 Python 自己寫加和函式,也許這樣可以封裝內建 sum 函式的開銷,以防它進行任何內部驗證。嗯……並非如此。
def ill_write_my_own_sum_thank_you_very_much(l): s = 0 for elem in my_list: s += elem return s%timeit ill_write_my_own_sum_thank_you_very_much(my_list)331 µs ± 50.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)至少在這個例子中,執行你自己簡單的程式碼很可能不是一個好的解決方案。但這不意味著你必須使用內建 sum 函式作為 Python 中的效能上限!由於 Python 沒有針對涉及大型輸入的數值運算進行最佳化,因此內建方法在加和大型列表時是表現次優。在這種情況下我們應該做的是提問:「是否有其他一些 Python 庫可用於對潛在的大型輸入進行數值分析?」正如你可能想的那樣,答案是肯定的:NumPy 包是 Python 的科學生態系統中的主要成分,Python 中的絕大多數科學計算包都以某種方式構建在 NumPy 上,它包含各種能幫助我們的計算函式。
在這種情況下,新的解決方案是非常簡單的:如果我們將純 Python 列表轉化為 NumPy 陣列,我們就可以立即呼叫 NumPy 的 sum 方法,我們可能期望它應該比核心的 Python 實現更快(技術上講,我們可以傳入一個 Python 列表到 numpy.sum 中,它會隱式地將其轉換為陣列,但如果我們打算複用該 NumPy 陣列,最好明確地轉化它)。
import numpy as npmy_arr = np.array(my_list)%timeit np.sum(my_arr)7.92 µs ± 1.15 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)因此簡單地切換到 NumPy 可加快一個數量級的列表加和速度,而不需要自己去實現任何東西。
需要更快的速度?
當然,有時候即使使用所有基於 C 的擴充套件包和高度最佳化的實現,你現有的 Python 程式碼也無法快速削減時間。在這種情況下,你的下意識反應可能是放棄並轉化到一個「真正」的語言。並且通常,這是一種完全合理的本能。但是在你開始使用 C 或 Java 移植程式碼前,你需要考慮一些不那麼費力的方法。
使用 Python 編寫 C 程式碼
首先,你可以嘗試編寫 Cython 程式碼。Cython 是 Python 的一個超集(superset),它允許你將(某些)C 程式碼直接嵌入到 Python 程式碼中。Cython 不以編譯的方式執行,相反你的 Python 檔案(或其中特定的某部分)將在執行前被編譯為 C 程式碼。實際的結果是你可以繼續編寫看起來幾乎完全和 Python 一樣的程式碼,但仍然可以從 C 程式碼的合理引入中獲得性能提升。特別是簡單地提供 C 型別的宣告通常可以顯著提高效能。
以下是我們簡單加和程式碼的 Cython 版本:
# Jupyter extension that allows us to run Cython cell magics%load_ext CythonThe Cython extension is already loaded. To reload it, use: %reload_ext Cython%%%%cythoncython defdef ill_write_my_own_cython_sum_thank_you_very_muchill_write (list arr): cdef int N = len(arr) cdef float x = arr[0] cdef int i for i in range(1 ,N): x += arr[i] return x%timeit ill_write_my_own_cython_sum_thank_you_very_much(my_list)227 µs ± 48.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)關於 Cython 版本有幾點需要注意一下。首先,在你第一次執行定義該方法的單元時,需要很少的(但值得注意的)時間來編譯。那是因為,與純粹的 Python 不同,程式碼在執行時不是逐行解譯的;相反,Cython 式的函式必須先編譯成 C 程式碼才能呼叫。
其次,雖然 Cython 式的加和函式比我們上面寫的簡單的 Python 加和函式要快,但仍然比內建求和方法和 NumPy 實現慢得多。然而,這個結果更有力地說明了我們特定的實現過程和問題的本質,而不是 Cython 的一般好處;在許多情況下,一個有效的 Cython 實現可以輕易地將執行時間提升一到兩個數量級。
使用 NUMBA 進行清理
Cython 並不是提升 Python 內部效能的唯一方法。從開發的角度來看,另一種更簡單的方法是依賴於即時編譯,其中一段 Python 程式碼在第一次呼叫時被編譯成最佳化的 C 程式碼。近年來,在 Python 即時編譯器上取得了很大進展。也許最成熟的實現可以在 numba 包中找到,它提供了一個簡單的 jit 修飾器,可以輕易地結合其他任何方法。
我們之前的示例並沒有強調 JITs 可以產生多大的影響,所以我們轉向一個稍微複雜點的問題。這裡我們定義一個被稱為 multiply_randomly 的新函式,它將一個一維浮點數陣列作為輸入,並將陣列中的每個元素與其他任意一個隨機選擇的元素相乘。然後它返回所有隨機相乘的元素和。
讓我們從定義一個簡單的實現開始,我們甚至都不採用向量化來代替隨機相乘操作。相反,我們簡單地遍歷陣列中的每個元素,從中隨機挑選一個其他元素,將兩個元素相乘並將結果分配給一個特定的索引。如果我們用基準問題測試這個函式,我們會發現它執行得相當慢。
import numpy as npdef multiply_randomly_naive(l): n = l.shape[0] result = np.zeros(shape=n) for i in range(n): ind = np.random.randint(0, n) result[i] = l[i] * l[ind] return np.sum(result)%timeit multiply_randomly_naive(my_arr)25.7 ms ± 4.61 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)在我們即時編譯之前,我們應該首先自問是否上述函式可以用更加符合 NumPy 形式的方法編寫。NumPy 針對基於陣列的操作進行了最佳化,因此應該不惜一切代價地避免使用迴圈操作,因為它們會非常慢。幸運的是,我們的程式碼非常容易向量化(並且易於閱讀):
def multiply_randomly_vectorized(l): n = len(l) inds = np.random.randint(0, n, size=n) result = l * l[inds] return np.sum(result)%timeit multiply_randomly_vectorized(my_arr)234 µs ± 50.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)在作者的機器上,向量化版本的執行速度比迴圈版本的程式碼快大約 100 倍。迴圈和陣列操作之間的這種效能差異對於 NumPy 來說是非常典型的,因此我們要在演算法上思考你所做的事的重要性。
假設我們不是花時間重構我們樸素的、緩慢的實現,而是簡單地在我們的函式上加一個修飾器去告訴 numba 庫我們要在第一次呼叫它時將函式編譯為 C。字面上,下面的函式 multiply_randomly_naive_jit 與上面定義的函式 multiply_randomly_naive 之間的唯一區別是 @jit 修飾器。當然,4 個小字元是沒法造成那麼大的差異的。對吧?
import numpy as npfrom numba import jit@jitdef multiply_randomly_naive_jit(l): n = l.shape[0] result = np.zeros(shape=n) for i in range(n): ind = np.random.randint(0, n) result[i] = l[i] * l[ind] return np.sum(result)%timeit multiply_randomly_naive_jit(my_arr)135 µs ± 22.4 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)令人驚訝的是,JIT 編譯版本的樸素函式事實上比向量化的版本跑得更快。
有趣的是,將 @jit 修飾器應用於函式的向量化版本(將其作為聯絡留給讀者)並不能提供更多幫助。在 numba JIT 編譯器用於我們的程式碼之後,Python 實現的兩個版本都以同樣的速度執行。因此,至少在這個例子中,即時編譯不僅可以毫不費力地為我們提供類似 C 的速度,而且可以避免以 Python 式地去最佳化程式碼。
這可能是一個相當有力的結論,因為(a)現在 numba 的 JIT 編譯器只覆蓋了 NumPy 特徵的一部分,(b)不能保證編譯的程式碼一定比解譯的程式碼執行地更快(儘管這通常是一個有效的假設)。這個例子真正的目的是提醒你,在你宣稱它慢到無法去實現你想要做的事之前,其實你在 Python 中有許多可用的選擇。值得注意的是,如 C 整合和即時編譯,這些效能特徵都不是 Python 獨有的。Matlab 最近的版本自動使用即時編譯,同時 R 支援 JIT 編譯(透過外部庫)和 C ++ 整合(Rcpp)。
Python 是天生面向物件的即使你正在做的只是編寫一些簡短的指令碼去解析文字或挖掘一些資料,Python 的許多好處也很容易領會到。在你開始編寫相對大型的程式碼片段前,Python 的最佳功能之一可能並不明顯:Python 具有設計非常優雅的基於物件的資料模型。事實上,如果你檢視底層,你會發現 Python 中的一切都是物件。甚至函式也是物件。當你呼叫一個函式的時候,你事實上正在呼叫 Python 中每個物件都執行的 __call__ 方法:
def double(x): return x*2# Lists all object attributesdir(double)["__annotations__", "__call__", "__class__", "__closure__", "__code__", "__defaults__", "__delattr__", "__dict__", "__dir__", "__doc__", "__eq__", "__format__", "__ge__", "__get__", "__getattribute__", "__globals__", "__gt__", "__hash__", "__init__", "__init_subclass__", "__kwdefaults__", "__le__", "__lt__", "__module__", "__name__", "__ne__", "__new__", "__qualname__", "__reduce__", "__reduce_ex__", "__repr__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__"]事實上,因為 Python 中的一切都是物件,Python 中的所有內容遵循相同的核心邏輯,實現相同的基本 API,並以類似的方式進行擴充套件。物件模型也恰好非常靈活:可以很容易地定義新的物件去實現有意思的事,同時仍然表現得相對可預測。也許並不奇怪,Python 也是編寫特定領域語言(DSLs)的一個絕佳選擇,因為它允許使用者在很大程度上過載和重新定義現有的功能。
魔術方法
Python 物件模型的核心部分是它使用「魔術」方法。這些在物件上實現的特殊方法可以更改 Python 物件的行為——通常以重要的方式。魔術方法(Magic methods)通常以雙下劃線開始和結束,一般來說,除非你知道自己在做什麼,否則不要輕易篡改它們。但一旦你真的開始改了,你就可以做些相當了不起的事。
舉個簡單的例子,我們來定義一個新的 Brain 物件。首先,Barin 不會進行任何操作,它只會待在那兒禮貌地發呆。
class Brain(object): def __init__(self, owner, age, status): self.owner = owner self.age = age self.status = status def __getattr__(self, attr): if attr.startswith("get_"): attr_name = attr.split("_")[1] if hasattr(self, attr_name): return lambda: getattr(self, attr_name) raise AttributeError在 Python 中,__init__ 方法是物件的初始化方法——當我們嘗試建立一個新的 Brain 例項時,它會被呼叫。通常你需要在編寫新類時自己實現__init__,所以如果你之前看過 Python 程式碼,那__init__ 可能看起來就比較熟悉了,本文就不再贅述。
相比之下,大多數使用者很少明確地實現__getattr__方法。但它控制著 Python 物件行為的一個非常重要的部分。具體來說,當用戶試圖透過點語法(如 brain.owner)訪問類屬性,同時這個屬性實際上並不存在時,__getattr__方法將會被呼叫。此方法的預設操作僅是引發一個錯誤:
# Create a new Brain instancebrain = Brain(owner="Sue", age="62", status="hanging out in a jar")print(brain.owner)---------------------------------------------------------------------------sueprint(brain.gender)---------------------------------------------------------------------------AttributeError Traceback (most recent call last)<ipython-input-136-52813a6b3567> in <module>()----> 1 print(brain.gender)<ipython-input-133-afe64c3e086d> in __getattr__(self, attr) 12 if hasattr(self, attr_name): 13 return lambda: getattr(self, attr_name)---> 14 raise AttributeErrorAttributeError:重要的是,我們不用忍受這種行為。假設我們想建立一個替代介面用於透過以「get」開頭的 getter 方法從 Brain 類的內部檢索資料(這是許多其他語言中的常見做法),我們當然可以透過名字(如 get_owner、get_age 等)顯式地實現 getter 方法。但假設我們很懶,並且不想為每個屬性編寫一個顯式的 getter。此外,我們可能想要為已經建立的 Brains 類新增新的屬性(如,brain.foo = 4),在這種情況下,我們不需要提前為那些未知屬性建立 getter 方法(請注意,在現實世界中,這些是為什麼我們接下來要這麼做的可怕理由;當然這裡完全是為了舉例說明)。我們可以做的是,當用戶請求任意屬性時,透過指示 Brain 類的操作去改變它的行為。
在上面的程式碼片段中,我們的 __getattr__ 實現首先檢查了傳入屬性的名稱。如果名稱以 get_ 開頭,我們將檢查物件內是否存在期望屬性的名稱。如果確實存在,則返回該物件。否則,我們會引發錯誤的預設操作。這讓我們可以做一些看似瘋狂的事,比如:
print(brain.get_owner())其他不可思議的方法允許你動態地控制物件行為的其他各種方面,而這在其他許多語言中你沒法做到。事實上,因為 Python 中的一切都是物件,甚至數學運算子實際上也是對物件的秘密方法呼叫。例如,當你用 Python 編寫表示式 4 + 5 時,你實際上是在整數物件 4 上呼叫 __add__,其引數為 5。如果我們願意(並且我們應該小心謹慎地行使這項權利!),我們能做的是建立新的特定領域的「迷你語言」,為通用運算子注入全新的語義。
舉個簡單的例子,我們來實現一個表示單一 Nifti 容積的新類。我們將依靠繼承來實現大部分工作;只需從 nibabel 包中繼承 NiftierImage 類。我們要做的就是定義 __and__ 和 __or__ 方法,它們分別對映到 & 和 | 運算子。看看在執行以下幾個單元前你是否搞懂了這段程式碼的作用(可能你需要安裝一些包,如 nibabel 和 nilearn)。
from nibabel import Nifti1Imagefrom nilearn.image import new_img_likefrom nilearn.plotting import plot_stat_mapimport numpy as npimport matplotlib.pyplot as plt%matplotlib inlineclass LazyMask(Nifti1Image): """ A wrapper for the Nifti1Image class that overloads the & and | operators to do logical conjunction and disjunction on the image data. """ def __and__(self, other): if self.shape != other.shape: raise ValueError("Mismatch in image dimensions: %s vs. %s" % (self.shape, other.shape)) data = np.logical_and(self.get_data(), other.get_data()) return new_img_like(self, data, self.affine) def __or__(self, other): if self.shape != other.shape: raise ValueError("Mismatch in image dimensions: %s vs. %s" % (self.shape, other.shape)) data = np.logical_or(self.get_data(), other.get_data()) return new_img_like(self, data, self.affine)img1 = LazyMask.load("image1.nii.gz")img2 = LazyMask.load("image2.nii.gz")result = img1 & img2fig, axes = plt.subplots(3, 1, figsize=(15, 6))p = plot_stat_map(img1, cut_coords=12, display_mode="z",, axes=axes[0], vmax=3)plot_stat_map(img2, cut_coords=p.cut_coords, display_mode="z",, axes=axes[1], vmax=3)p = plot_stat_map(result, cut_coords=p.cut_coords, display_mode="z",, axes=axes[2], vmax=3)Python 社群我在這裡提到的 Python 的最後一個特徵就是它優秀的社群。當然,每種主要的程式語言都有一個大型的社群致力於該語言的開發、應用和推廣;關鍵是社群內的人是誰。一般來說,圍繞程式語言的社群更能反映使用者的興趣和專業基礎。對於像 R 和 Matlab 這樣相對特定領域的語言來說,這意味著為語言貢獻新工具的人中很大一部分不是軟體開發人員,更可能是統計學家、工程師和科學家等等。當然,統計學家和工程師沒什麼不好。例如,與其他語言相比,統計學家較多的 R 生態系統的優勢之一就是 R 具有一系列統計軟體包。
然而,由統計或科學背景使用者所主導的社群存在缺點,即這些使用者通常未受過軟體開發方面的訓練。因此,他們編寫的程式碼質量往往比較低(從軟體的角度看)。專業的軟體工程師普遍採用的最佳實踐和習慣在這種未經培訓的社群中並不出眾。例如,CRAN 提供的許多 R 包缺少類似自動化測試的東西——除了最小的 Python 軟體包之外,這幾乎是聞所未聞的。另外在風格上,R 和 Matlab 程式設計師編寫的程式碼往往在人與人之間的一致性方面要低一些。結果是,在其他條件相同的情況下,用 Python 編寫軟體往往比用 R 編寫的程式碼具備更高的穩健性。雖然 Python 的這種優勢無疑與語言本身的內在特徵無關(一個人可以使用任何語言(包括 R、Matlab 等)編寫出極高質量的程式碼),但仍然存在這樣的情況,強調共同慣例和最佳實踐規範的開發人員社群往往會使大家編寫出更清晰、更規範、更高質量的程式碼。
結論Python 太棒了。
-
5 # 小肥崔
Python高度封裝,很多功能都有現成的庫。而機器學習模型迭代快,而且經常需要多種模型對照實驗,所以開發效率高的python成為了首選。但當實驗有結論後,並滿足一段時間內被選定的模型不會作大改動和高吞吐這兩個條件,模型往往就會用效能遠勝於Python的C++重寫。
-
6 # 菜菜菜鳥
首先人工智慧和python並沒有什麼必然聯絡,python也只是實現人工智慧的一個工具,任何程式語言都可以開發人工智慧,比如C語言、c++、java等。python與這幾種需要想比:執行速度不如這幾個快,但學習成本低,開發速度快,開發週期短,不用造輪子,各種模組和類庫可以直接拿來使用。
Python不僅容易上手,而且具有豐富和強大的庫(包括官方類庫和各種第三方庫),並且能夠把用其他語言製作的各種模組(尤其是C/C++)很輕鬆地聯結在一起。
即便是不懂人工智知識和原理的人也能使用相關的類庫處理要處理的資料,建立模型,對資料進行分析和預測。
因此當下作為普通人也可以學習一下Python和機器學習,即便不是專業的程式猿也能輕易的開發一些小工具供自己使用,提高工作效率。
-
7 # DKink
Python原來誕生之初就是為了配合C語言做快速開發的,在開發過程中發現效能瓶頸時,可以把Python指令碼用C重寫最佳化效能。像AI這種要不停地修改的程式,使用這種指令碼寫是很方便的。
-
8 # 散居獵人
為什麼會提這麼不靠譜的問題?誰說的開發人工智慧非要用PYTHON?人工智慧是演算法,什麼計算機語言都可以描述。任何語言都自帶類庫或函式如DLL,還有作業系統提供API,不需要所有計算模組都自己做。各種語言寫的程式模組,生成類似DLL函式模組,開放介面後都是可以相互呼叫的。PYTHON只是一門計算機語言,沒有能力凌駕於其他語言之上。
-
9 # 壯志山河
本人是跨專業轉行至人工智慧網際網路行業,目前是人工智慧演算法工程師,所用語言為GO、Python和R等。在業務開發體驗中,用的最爽滑的還是Python,現將使用Python的一些心得體會總結如下。
1.Python的語法較為簡單。作為一門高階語言,Python的很多功能均已被封裝,在程式設計時直接拿來用就行,不用像C++或Java那麼底層,許多功能還需要自己動手實現,即使是程式設計零基礎的同學,只要方法得當,只需一兩個星期入門Python就足夠了。
2.Python的開發庫非常多。在Python的整合開發工具anaconda裡給資料工作者已經預先安裝很多開發庫,用conda命令可以很方便地管理Python庫的安裝和使用,並且只要你想到的功能,在Python庫中基本都已收錄,這樣極大的提高了開發效率,避免了重複開發。
3.Python是解釋型語言,程式設計過程體驗良好。Python的整合編輯器中,可以寫一步命令執行一步命令,做到隨編寫,隨改錯,這樣的互動性是Java和GO等編譯型語言無法比擬的。
4.人工智慧本身演算法複雜,精通人工智慧演算法已經非常傷腦筋,如果再用實現過程較複雜的語言,估計資料科學家們要瘋掉。畢竟,演算法科學家們還有很多更重要的事情要做。
-
10 # 中公優就業
在所有程式語言裡,Python並不算萌新,從1991年釋出第一個版本,至今已經快30年了。近年隨著人工智慧的火爆,Python迅速升溫,成為眾多AI從業者的首選語言。
今天小U就和大家說說為什麼要想成為人工智慧領域的領頭羊,就一定要入門Python?
首先,Python是一種說人話的語言
什麼叫“說人話”?Python這門語言具備以下幾個特點:
開發者不需要關注底層
語法簡單直觀
表達形式一致
For 個例子:
C 語言Hello World 程式碼:
Java語言Hello World 程式碼
Python語言Hello World 程式碼
僅僅是一個Hello World程式,就能看出區別了,是不是?
編譯 VS 解釋
當然,僅僅是一個Hello World的話,C和Java的程式碼也多不了幾行。但是C和Java的程式碼要執行都必須要先經過編譯的環節。
對於C語言來說,在不同的作業系統上使用什麼樣的編譯器,也是一個需要斟酌的問題。一旦程式碼被copy到新的機器,執行環境和之前不同,還需要重新編譯……
想執行別人寫的程式,想copy別人的程式碼,那是不可能滴!
而Python則不用編譯,直接執行。而且都可以不用寫檔案,一條條語句可以直接作為命令列執行。
強大的AI支援庫
Python內建的math和random庫。結合NumPy支援維度陣列與矩陣運算,堪稱AI資料神器!再加上Python這種語法簡潔明瞭、風格統一;不需要關注底層實現;連矩陣元素都可以像在紙上寫公式一樣;寫完公式還能自動計算出結果的程式語言,開發者就可以把工作重心放在模型和演算法上啦。
如今,Python在AI領域的霸主地位已經奠定。
想學人工智慧,舍Python其誰?
-
11 # 千鋒武漢
人工智慧掀起了世界的新一波科技浪潮,如今,你要是不懂點AI、機器學習和Python都不好意思說你是現代人。那麼為什麼Python是入行人工智慧的首選語言?Python究竟和人工智慧什麼關係?為什麼人工智慧把Python也給帶火了?今天就給大家簡單介紹下。
先來上兩張圖人工智慧和Python的圖。
從上圖可以看出,人工智慧包含常用機器學習和深度學習兩個很重要的模組,而下圖中Python擁有matplotlib、Numpy、sklearn、keras等大量的庫,像pandas、sklearn、matplotlib這些庫都是做資料處理、資料分析、資料建模和繪圖的庫,基本上機器學習中對資料的爬取(scrapy)、對資料的處理和分析(pandas)、對資料的繪圖(matplotlib)和對資料的建模(sklearn)在Python中全都能找到對應的庫來進行處理。
所以,要想學習AI而不懂Python,那就相當於想學英語而不認識單詞,所以,Python學起來吧。
那要想學人工智慧,想學Python,哪些東西要學習呢?下面給大家簡單介紹下:
爬蟲:requests、scrapy、selenium、beautifulSoup,這些庫都是寫網路爬蟲需要使用到的,好好掌握這些東西,資料就有了。
然後,有了資料就可以進行資料處理和分析了,這個時候,你需要用到資料處理的一些庫。
資料處理:Numpy、scipy、pandas、matplotlib,這些庫分別可以進行矩陣計算、科學計算、資料處理、繪圖等操作,有了這些庫,你就可以一步步開始把資料處理成你需要的格式。
接著,資料符合你的格式以後,你就需要利用這些資料進行建模了,這個時候你用到的庫也有很多。
建模:nltk、keras、sklearn,這些庫主要是用於自然語言處理、深度學習和機器學習的,把這些用好了,你的模型就構建出來了。
最後,如果你的專案是基於Python開發的線上系統,你還可以學一學Python的Web開發,這樣,你做的模型還能直接用在線上系統。
Web開發:django、flask、tornado,這些庫搞明白了,你Web開發也就搞定了。
以上只是你入門要學習人工智慧所要掌握的一些基本的庫,要想真正使用起來,你可能需要花費很多時間去研究和學習這裡面的每一個細節。
不過,有句話叫“人生苦短,我用Python”,之所以這麼說是因為Python在實現各個功能的時候要遠比其他語言簡練的多,很多功能在Python中只需要一行程式碼搞定,但是在Java中你可能需要寫好多好多程式碼才能實現。
就拿一個簡單的例子,讀寫檔案來說吧:
Python讀寫檔案:
Java讀寫檔案:
各位學習人工智慧的同胞們,你們看到了吧,就是一個簡單的讀寫檔案,Java的操作要比Python複雜太多太多!
在真實的工作中,我們需要做的事情是把大量的精力集中在資料上、資料分析和理解上,而不是花費30%-50%的時間去寫程式碼,Python不光是提供了機器學習所需要的一切工具庫,還能讓你專注在資料處理和分析上,所以,要學習和進入人工智慧行業的話,好好學習Python吧,騷年!
最後,附上一張今年語言排行榜。
如果你想在AI這個行業混,就要用Python。人生苦短,趕快讓Python來點亮你的高薪人生吧!
-
12 # 人工智慧學者
Python是入行人工智慧的首先語言有些言過其實。它只是簡單易學罷了。其實真正實用的演算法是用C語言寫的。更重要的是,機器學習不能代替人工智慧,它只是人工智慧的一部分,只是最近比較火罷了。人工智慧的核心是可解釋,是推理。真正能稱得上人工智慧語言的是prolog和LISP。其它都是過程性語言,比較的只是易用性和速度。
-
13 # 老好學IT
Python是一種工具性語言,學習Python主要是用來解決自己工作中的問題,提升工作效率。並不一定非要做人工智慧。說Python是入行人工智慧的首選語言,主要是Python的工具屬性及存在大量現成的工具是Python語言編寫的,另外就是主流的人功能智慧框架都支援Python語言介面。辨證看待,吹上天就是炒作了。
-
14 # 剁椒魚頭看電影
做人工智慧研究最多的人不是普通的軟體工程師; 他們不關心記憶體管理,const引用和多重繼承。他們想要的工具允許他們視覺化他們的資料,只需幾行程式碼就可以進行實驗,並與他們的資料和模型進行互動,無需重新編譯和重新執行每一個微小的變化。
Python允許他們完成所有這些,而C ++則不然。
也就是說,機器學習模型也大量使用底層硬體,如用於快速矩陣操作的GPU。為此,像C或C ++這樣的語言是必不可少的。事實上,像Tensorflow [1]這樣暴露Python介面的大多數庫都有用C編寫的子模組,這些子模組可以執行很多效能關鍵的工作。
我們既可以利用像Python這樣的語言的表達性和簡單性,也可以利用像C ++這樣的語言的效能和低階整合。
-
15 # 軟體開發與運維
是,python已經是AI時代事實上的標準語言。做系統/中間層等的開發,Java依然有市場。
對於新人,建議一定要學好python,無論你未來做什麼或者用什麼語言,python都會用到,並且會很用。同時建議學習C/C++,對計算機底層會有更深入的理解。
-
16 # IoT數字科技時代
在過去幾年中,Python已經成為機器學習和AI的主要開發語言。由於對於數值計算來說,人工記憶體管理非常重要,CPython為低級別的擴充套件提供了一種高效、實用的API。對於Web程式設計而言,Python不需要使用JSON,XML解析,影象處理和資料庫連線的快速庫。 但是,大多數Python使用者不喜歡這些本機擴充套件。本機擴充套件反而造成一些不便,更容易導致出錯。
Python社群應該接受必要的本機擴充套件。透過投入更好的工具來強化其優勢,Python語言將變得更強大。個人開發人員將受益於Cython,並瞭解如何閱讀和構建本機庫。這尤其適用於機器學習和人工智慧領——當前軟體開發中發展最快的領域。
Python 對於AI來說是最好的語言——但它可以更好。
Python在資料科學和AI中佔據主導地位
比R更具有通用性和實用性
比Java和C ++更有生產力和靈活性
比Ruby和JavaScript擁有更好的生態系統
Python是一個很全面的語言,尤其對於資料科學,機器學習和AI
Python為何擁有最好的生態系統?
某一語言獲得“勝利”,不僅由於它足夠好,而且天時地利
2004年之前Java和C ++的生產力不足
C擴充套件對於Perl和Ruby來說相對較難
我們應該怎麼做?
個人開發人員應該習慣寫Cython
社群應該投入更多資源,使其更簡單明瞭
效能是Python程式碼的一個大問題
1、在AI研究中,你最常使用的是什麼程式語言?
Python 78%
Python 55%
Python 的生態系統使其成為AI的最佳選擇
“真正使Python和Ruby兩種語言區分開來的是它們的框架和庫的環境”
“scikit學習:Python機器學習是用於此目的的最簡單、最先進的庫之一。”
“由於其軟體包庫的成熟度和廣度”
-
17 # 加米穀大資料
原因1:Python是一種說人話的語言
所謂“說人話”,是指這種語言:
開發者不需要關注底層語法簡單直觀表達形式一致原因2:強大的AI支援庫
矩陣運算
NumPy由資料科學家Travis Oliphant創作,支援維度陣列與矩陣運算。結合Python內建的math和random庫,堪稱AI資料神器
原因3:規模效應
語言簡單易學,支援庫豐富強大,這兩大支柱從早期就奠定了Python的江湖地位
相關:
人工智慧和資料科學的七大 Python 庫
https://www.toutiao.com/i6644719988944929293/
-
18 # sunjiahao1
Python由於其簡潔優美和極高的開發效率,得到了越來越多公司的青睞,人工智慧已經成為了當下最熱門的話題了,未來可以說就是人工智慧的天下了,公司選用Python進行網站Web、搜尋引擎(Google)、雲計算(OpenStack)、大資料、人工智慧、科學計算等方向的開發。Python將成為繼C++和Java之後的第三個主流程式語言,Python結合人工智慧也是尚 矽谷的優勢課程,python的人才就業優勢也是比較明顯的。
-
19 # 凌雲義
此問題應該反過來看,是人工智慧發展一定程度上促進了python程式語言的發展。早期這門語言被大量用在系統運維,科學計算領域。目前由於大資料,人工智慧的發展,使得其成為新寵。目前兩者相輔相成發展,但是語言只是工具,人工智慧是技術和思想。需要可以使用的比較多,世界上程式語言已經無法全部精通,況且這門需要也只是使用在某些方面,人工智慧的底層很多還是會用到其他的程式語言。
-
20 # 小黑同學
python 面嚮物件語言
可讀性強
庫非常廣範
容易學習
原始碼容易理解
多數學術研究人員他們都在使用
機器學習 主要是強調演算法 而並不太注重用什麼語言實現,於是就有了python版本的tensorflow框架 有了阿爾法機器人之後 這個框架被谷歌開源,廣為流傳。既然有人造了車的底盤和輪子那為什麼還要重新造呢,許多公司 開發者 就都紛紛轉去學習tensorflow 框架,發現是python 寫的 於是。。。 python 火了。
我是程式設計師,純手寫回復
求贊。提前感謝。
回覆列表
人工智慧是我的研究方向之一,我目前也在使用Python做智慧診療方面的落地應用,我就以我的切身經歷談一談Python在人工智慧方面的應用。
我研究人工智慧是從機器學習開始的,因為我之前一直在做大資料相關的研發,而從大資料進入機器學習則是順理成章的事情。機器學習要做的事情就是從雜亂無章的資料中找到規律,透過資料的蒐集和整理來訓練演算法,達到最終應用的目的。
由於我使用Java語言的時間比較長,所以在剛開始做機器學習演算法實現的時候,我首選的語言就是Java,因為程式語言畢竟只是工具,哪個工具使用的順手就用那個,所以一直使用Java實現。直到有一次我參加一個機器學習的交流會,一個同行向我推薦使用Python來做機器學習,他跟我說Python做機器學習非常簡單,不用過多考慮語言實現方面的事情,可以把精力放在演算法上。
我用了一週左右的時間就完成了Python的學習,然後就開始一邊使用一邊熟悉Python。現在使用Python也有幾年時間了,可以說Python非常適合做演算法實現。一方面語法簡單,另一方面可使用的演算法庫非常豐富,程式調整起來也很快,所以使用Python做機器學習讓我感覺輕鬆了不少。
目前我的落地專案也在使用Python完成,雖然在速度上沒有Java快,但是從程式開發的角度來說,使用Python確實有一定的樂趣。
如果有Python、Java、大資料、人工智慧等方面的問題,也可以諮詢我。