習(xí)路線:從環(huán)境搭建到模型實(shí)戰(zhàn)的完整路徑)
這個(gè)系列寫到第十篇正好是個(gè)適合回望的節(jié)點(diǎn)。后臺(tái)的私信和評(píng)論區(qū)里問(wèn)得最多的其實(shí)已經(jīng)不是“什么是梯度下降”“反向傳播怎么寫”這類概念問(wèn)題而是特別樸素的一類Python裝不上、庫(kù)裝不上、環(huán)境變量配不好、跑模型報(bào)一堆看不懂的錯(cuò)。這說(shuō)明大多數(shù)人卡住的位置不是算法不夠聰明而是環(huán)境和基礎(chǔ)工具鏈這一關(guān)沒(méi)過(guò)好。作為一門需要長(zhǎng)期投入的領(lǐng)域“Python 人工智能編程”的難點(diǎn)從來(lái)不在某一節(jié)課而在于如何把零散的知識(shí)點(diǎn)串成一條能走下去的路線。這一篇我不打算堆新概念而是想結(jié)合這些年見過(guò)的、踩過(guò)的問(wèn)題把“從零到精通”里最容易讓人放棄的幾個(gè)關(guān)口逐個(gè)拆開講講環(huán)境怎么搭才不折騰、語(yǔ)法哪些是必須刻進(jìn)肌肉記憶的、數(shù)學(xué)題和矩陣練的是什么、以及從編程過(guò)渡到AI該朝哪個(gè)方向使勁。不管你是剛下載Python還沒(méi)跑通第一個(gè)print的新手還是已經(jīng)會(huì)寫函數(shù)但面對(duì)機(jī)器學(xué)習(xí)庫(kù)一頭霧水的進(jìn)階者這篇都能幫你找到自己堵在哪兒了。1. 先看清楚自己的位置Python人工智能編程的學(xué)習(xí)地圖1.1 從熱搜詞看新手真實(shí)卡點(diǎn)每次寫這個(gè)系列我都會(huì)去看一下當(dāng)下搜索欄里和Python相關(guān)的熱門詞。很有意思的是“python安裝”“python環(huán)境變量配置”“python下載cv2”“VS Code安裝python”這類詞常年霸榜熱度遠(yuǎn)遠(yuǎn)超過(guò)“神經(jīng)網(wǎng)絡(luò)”“模型訓(xùn)練”這說(shuō)明真正的痛點(diǎn)其實(shí)比想象中基礎(chǔ)得多。你去任何一個(gè)Python技術(shù)群待上一周就會(huì)發(fā)現(xiàn)永遠(yuǎn)有人在問(wèn)為什么我在命令行敲python沒(méi)反應(yīng)為什么pip install numpy報(bào)錯(cuò)為什么VS Code里寫代碼不提示這些問(wèn)題聽起來(lái)小但足以讓一個(gè)零基礎(chǔ)的人懷疑自己是不是不適合學(xué)編程。事實(shí)上絕大多數(shù)人都不是不適合而是沒(méi)人告訴他們先把環(huán)境搞到“無(wú)腦可用”的狀態(tài)再開始學(xué)語(yǔ)法效率會(huì)高得多。正因?yàn)槿绱诉@篇系列文章我不打算一上來(lái)就講 keras 或者 PyTorch而是要把這條路上最容易忽略的地基部分重新捋一遍。地基踩實(shí)了后面學(xué)NumPy、Pandas、爬蟲、量化策略甚至自己訓(xùn)練小模型都會(huì)順暢得多。1.2 Python并不是人工智能學(xué)習(xí)的全部很多人把“Python人工智能編程”理解成“學(xué)會(huì)了Python就等于會(huì)了AI”這是一個(gè)天大的誤會(huì)。Python只是工具和你手上的螺絲刀一樣真正值錢的是用螺絲刀擰出什么。人工智能編程這條路線本質(zhì)上由三塊拼圖組成第一塊是編程能力本身變量、類型、函數(shù)、文件操作、裝飾器、迭代器這些語(yǔ)法層面的東西必須熟練到不假思索。第二塊是數(shù)學(xué)和算法視野包括線性代數(shù)里的矩陣、概率論里的分布、微積分里的梯度概念不一定需要你推到每個(gè)公式但至少要懂它們?cè)诖a里長(zhǎng)什么樣子。第三塊才是模型框架比如sklearn、PyTorch、TensorFlow這些框架能幫你用幾十行代碼實(shí)現(xiàn)一個(gè)分類器或一個(gè)回歸模型。合理的路徑應(yīng)該是“語(yǔ)法 → 數(shù)據(jù)結(jié)構(gòu)和算法 → 數(shù)學(xué) 工具庫(kù) → 模型框架”。很多人反著來(lái)裝好Python就直奔深度學(xué)習(xí)教程三天后發(fā)現(xiàn)自己連“訓(xùn)練集”和“測(cè)試集”為什么要分開都答不上來(lái)然后沮喪棄坑。1.3 系列第十篇的承上啟下邏輯為什么第十篇適合做一次這樣的盤點(diǎn)因?yàn)榘凑5倪B載節(jié)奏第一篇到第三篇講環(huán)境、語(yǔ)法、基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)第四篇到第六篇講NumPy、Pandas、數(shù)據(jù)可視化第七篇到第九篇開始涉及爬蟲、并發(fā)和模型入門。到了第十篇讀者群里既有跟著一路走下來(lái)的老讀者也有中途跳進(jìn)來(lái)看兩眼的新朋友這個(gè)時(shí)候如果不停下來(lái)把知識(shí)串一遍后面講深度學(xué)習(xí)的時(shí)候基礎(chǔ)不牢的人會(huì)跟得很辛苦。我也會(huì)借這一篇把隱藏在許多熱搜詞背后的真實(shí)問(wèn)題攤開比如“python構(gòu)建鄰接矩陣”背后是圖算法的基礎(chǔ)“李白打酒python”背后是典型的遞歸和枚舉思維“python協(xié)程”背后是IO密集任務(wù)的性能瓶頸。你看著是一個(gè)個(gè)零散的小問(wèn)題放在學(xué)習(xí)地圖里其實(shí)都有明確的位置。2. 環(huán)境與工具鏈為什么是第一道分水嶺——版本、虛擬環(huán)境和常用依賴環(huán)境這一關(guān)卡掉的人比算法卡掉的還多。我第一次教朋友搭環(huán)境的時(shí)候就發(fā)現(xiàn)大多數(shù)人缺的不是動(dòng)手能力而是沒(méi)人告訴他們“哪種選擇最省事”。這里我把幾個(gè)最典型的決策點(diǎn)掰開揉碎講清楚。2.1 版本選擇的現(xiàn)實(shí)問(wèn)題要不要死守Python 3.8熱搜里“python 3.8”的詞條常年居高不下這不是偶然。很多第三方庫(kù)尤其是帶編譯組件的庫(kù)在Python 3.8上兼容性最穩(wěn)。我自己也曾在3.9和3.10上遇到過(guò)一個(gè)老版本庫(kù)不兼容的情況最后只能降回3.8解決。但另一方面新版Python在性能和語(yǔ)法糖上有實(shí)打?qū)嵉奶嵘N医o新手的原則是如果不是公司老項(xiàng)目約束直接裝最新穩(wěn)定版當(dāng)前大多數(shù)教程已支持3.11、3.12讓寫代碼時(shí)能體驗(yàn)到新語(yǔ)法避免一開始就被兼容性問(wèn)題澆滅熱情。但如果你是在Linux服務(wù)器上部署項(xiàng)目系統(tǒng)自帶的版本往往是3.x系列的老版本千萬(wàn)別手動(dòng)卸掉系統(tǒng)Python去裝新的那會(huì)把依賴系統(tǒng)Python的軟件拆壞。正確做法是裝一個(gè)獨(dú)立的Python版本通過(guò)軟鏈或者包管理器管理。我剛接觸Linux的時(shí)候傻乎乎地下載了源碼編譯安裝了Python 3.11然后發(fā)現(xiàn)系統(tǒng)自帶的yum直接罷工了因?yàn)閥um依賴的還是系統(tǒng)老版本Python。后來(lái)學(xué)聰明了所有額外版本都放到/usr/local/bin/python3.11這樣的獨(dú)立路徑不和系統(tǒng)版本搶位子。這個(gè)教訓(xùn)值一次重啟服務(wù)器。2.2 虛擬環(huán)境為什么不要直接pip install到全局很多新手喜歡裝完P(guān)ython就開始pip install numpy直接裝到全局環(huán)境。短時(shí)間看沒(méi)什么問(wèn)題但一旦你同時(shí)搞兩個(gè)項(xiàng)目一個(gè)需要numpy 1.x一個(gè)需要numpy 2.x就會(huì)開始打架。更麻煩的是有些庫(kù)升級(jí)后API變了你昨天能跑的代碼今天突然報(bào)錯(cuò)你卻想不起是什么時(shí)候動(dòng)了環(huán)境。虛擬環(huán)境就是給每個(gè)項(xiàng)目一個(gè)獨(dú)立的Python環(huán)境相當(dāng)于每個(gè)項(xiàng)目有自己的“工具箱”互不干擾。Python自帶的venv就夠用# Windows python -m venv myenv myenv\Scripts\activate # macOS / Linux python -m venv myenv source myenv/bin/activate激活之后命令行開頭會(huì)出現(xiàn)(myenv)字樣這時(shí)候再用pip install所有包都只裝進(jìn)這個(gè)環(huán)境不會(huì)污染全局。新手不用急著上conda先把這個(gè)流程跑順已經(jīng)能少踩一半的坑。等以后做數(shù)據(jù)科學(xué)或者需要一個(gè)專門的Python環(huán)境時(shí)再換conda不遲。2.3 常用AI依賴安裝演練numpy、cv2、pandas的坑先說(shuō)結(jié)論如果你能用pip install裝成功是最好的因?yàn)槭∈?。但?shí)際過(guò)程中最常遇到的報(bào)錯(cuò)有兩種。第一種是pip install numpy報(bào)錯(cuò)“Microsoft Visual C 14.0 is required”。這是因?yàn)閚umpy的某些輪子在Windows上需要C編譯環(huán)境。解決辦法不是去官網(wǎng)下載Visual Studio而是升級(jí)pip之后再用預(yù)編譯的wheel安裝python -m pip install --upgrade pip pip install numpy升級(jí)pip之后pip會(huì)自動(dòng)找到帶.whl后綴的預(yù)編譯文件沒(méi)必要從源碼編譯。第二種是pip install opencv-python后導(dǎo)入報(bào)錯(cuò)說(shuō)找不到DLL。這通常是opencv官方包在Windows上依賴VC運(yùn)行庫(kù)去微軟官網(wǎng)裝一個(gè)最新的VC Redistributable就能解決。如果還不行換個(gè)鏡像源試試pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple鏡像源只解決下載慢和連接不上的問(wèn)題不解決DLL缺失所以裝完后先跑一句import cv2驗(yàn)證。安裝好之后記得驗(yàn)證導(dǎo)入import numpy as np import pandas as pd import cv2 print(np.__version__, pd.__version__, cv2.__version__)一行代碼能跑通說(shuō)明環(huán)境基本沒(méi)問(wèn)題可以放心繼續(xù)學(xué)習(xí)。2.4 編輯器與調(diào)試VS Code怎么配置Python解釋器編輯器不是越復(fù)雜越好VS Code搭配官方Python插件是我推薦給所有人的組合免費(fèi)、輕量、夠用。你可能踩過(guò)這個(gè)坑裝完VS Code寫Python右下角沒(méi)有解釋器選項(xiàng)代碼一運(yùn)行就用錯(cuò)環(huán)境。配置邏輯很簡(jiǎn)單安裝“Python”擴(kuò)展然后按CtrlShiftP打開命令面板輸入“Python: Select Interpreter”選擇你虛擬環(huán)境里的python.exe。這一步做完你的終端和新文件都會(huì)自動(dòng)使用這個(gè)環(huán)境不會(huì)再出現(xiàn)“明明pip裝了這個(gè)庫(kù)運(yùn)行卻說(shuō)找不到”的問(wèn)題。順帶說(shuō)一句熱搜詞里還有“emacs配置python”這類詞。我理解折騰編輯器的樂(lè)趣但真的別在入門前三個(gè)月花太多時(shí)間配置編輯器。工具是為你服務(wù)的不是讓你服務(wù)工具的。VS Code默認(rèn)配置就能覆蓋九成場(chǎng)景。3. Python基礎(chǔ)語(yǔ)法還缺哪幾塊從變量、類型轉(zhuǎn)換到函數(shù)與文件操作環(huán)境搭好了接下來(lái)就是語(yǔ)法。很多人會(huì)去看那種幾百集的視頻教程看著看著就忘了前面其實(shí)沒(méi)必要?;A(chǔ)語(yǔ)法里真正要反復(fù)練的就那么幾個(gè)核心點(diǎn)練熟它們你就能看懂絕大多數(shù)項(xiàng)目代碼。3.1 安裝好之后需要刻進(jìn)肌肉記憶的5個(gè)語(yǔ)法點(diǎn)一個(gè)合格的人工智能方向程序員基礎(chǔ)語(yǔ)法過(guò)關(guān)的標(biāo)準(zhǔn)不是會(huì)寫課本習(xí)題而是看到一段陌生代碼能快速反應(yīng)過(guò)來(lái)它在干什么。我認(rèn)為以下五個(gè)點(diǎn)最重要變量和類型Python是動(dòng)態(tài)類型語(yǔ)言同一個(gè)變量名可以先后指向整數(shù)、字符串、列表。這個(gè)特性讓入門很爽但也容易讓人忽略類型問(wèn)題。做AI項(xiàng)目時(shí)數(shù)據(jù)量大、類型雜type()查看類型和isinstance()做類型判斷要常用。類型轉(zhuǎn)換int(123)、float(3.14)、str(42)是最基礎(chǔ)的顯式轉(zhuǎn)換。列表轉(zhuǎn)字符串用.join(list)字符串轉(zhuǎn)列表用str.split(,)這幾對(duì)操作在做數(shù)據(jù)處理時(shí)幾乎天天見。條件與循環(huán)if-elif-else、for、while誰(shuí)都會(huì)寫但重要的是理解遍歷的邏輯。數(shù)據(jù)清洗時(shí)那種“遇到空值就跳過(guò)”的循環(huán)本質(zhì)上就是條件分支加循環(huán)的排列組合。函數(shù)定義函數(shù)不只是把代碼包起來(lái)更重要的是參數(shù)設(shè)計(jì)和返回值設(shè)計(jì)。用def定義一個(gè)多參數(shù)函數(shù)時(shí)默認(rèn)參數(shù)要放在必選參數(shù)之后關(guān)鍵字參數(shù)**kwargs是擴(kuò)展功能的利器。文件操作AI項(xiàng)目離不開讀數(shù)據(jù)、存模型文件。用with open(...) as f上下文管理器可以保證文件用完自動(dòng)關(guān)閉避免資源泄漏。數(shù)據(jù)量一大文件指針沒(méi)關(guān)會(huì)導(dǎo)致后續(xù)讀取失敗這是新手經(jīng)常忽略的坑。3.2 數(shù)組切片與矩陣思維為什么numpy比list好用熱搜詞里“python數(shù)組切片命令”“python矩陣0”這類詞說(shuō)明大家在數(shù)據(jù)處理上遇到了障礙。Python自帶的list也能切片比如lst[1:4]但一旦涉及矩陣運(yùn)算list的效率就完全不夠看。NumPy的核心是ndarray它支持按行、按列切片還能做四則運(yùn)算和矩陣乘法。用自然語(yǔ)言說(shuō)就是list像一排盒子你只能逐個(gè)拿東西numpy像一整塊數(shù)據(jù)板你可以橫著切、豎著切、對(duì)角線切甚至整塊板同時(shí)做運(yùn)算。舉個(gè)最直接的例子假設(shè)你有5個(gè)學(xué)生每人考了3門課成績(jī)數(shù)據(jù)是一個(gè)5行3列的矩陣import numpy as np scores np.array([ [85, 90, 78], [92, 88, 85], [76, 95, 80], [88, 82, 93], [97, 85, 79] ]) # 查看第2個(gè)學(xué)生的成績(jī) print(scores[1, :]) # 查看所有學(xué)生的第3門課成績(jī) print(scores[:, 2]) # 計(jì)算每門課的平均分 print(scores.mean(axis0))這段代碼如果用list實(shí)現(xiàn)你得寫好幾層循環(huán)用numpy一行搞定而且底層是C語(yǔ)言優(yōu)化過(guò)的數(shù)據(jù)量大時(shí)速度差距是幾十倍甚至更多。練習(xí)切片的時(shí)候建議自己動(dòng)手創(chuàng)建一個(gè)二維數(shù)組把[:, 1]、[1, :]、[::2]這些寫法都試一遍在腦子里建立“軸”的概念后面學(xué)矩陣運(yùn)算、圖像處理cv2里的OpenCV圖像本質(zhì)就是三維數(shù)組都會(huì)順很多。3.3 類型轉(zhuǎn)換、列表推導(dǎo)式和函數(shù)設(shè)計(jì)的常見誤區(qū)很多新手學(xué)了一堆語(yǔ)法寫代碼時(shí)依然拖拖拉拉原因是缺少“組合運(yùn)用”的習(xí)慣。以類型轉(zhuǎn)換為例實(shí)際數(shù)據(jù)處理中經(jīng)常遇到這樣的情況從CSV文件讀出來(lái)的是字符串要轉(zhuǎn)成整數(shù)才能算平均值。正確的組合是列表推導(dǎo)式加類型轉(zhuǎn)換data_str [12, 34, 56] data_int [int(x) for x in data_str] print(sum(data_int) / len(data_int)) # 34.0這里[int(x) for x in data_str]是Python里最常用的列表推導(dǎo)式一句頂三行循環(huán)。函數(shù)設(shè)計(jì)的常見誤區(qū)是“一個(gè)函數(shù)什么都干”控制不好參數(shù)數(shù)量。實(shí)際經(jīng)驗(yàn)是一個(gè)函數(shù)最好只干一件事參數(shù)控制在3到5個(gè)以內(nèi)復(fù)雜邏輯拆成多個(gè)小函數(shù)調(diào)試的時(shí)候能快速定位到出錯(cuò)環(huán)節(jié)。如果函數(shù)超過(guò)二十行就要考慮是不是該拆了。另外熱搜詞里還有“python變量的類型練習(xí)題”“python定義函數(shù)”這類搜索其實(shí)都是同一個(gè)信號(hào)缺動(dòng)手量。語(yǔ)法學(xué)習(xí)沒(méi)有捷徑你可以在交互式環(huán)境里一遍一遍輸入type(123)、type(abc)、int(3.8)看輸出結(jié)果。踩過(guò)幾個(gè)TypeError和ValueError的坑比背十遍教程都管用。4. 用數(shù)學(xué)題和矩陣把“算法直覺(jué)”練出來(lái)李白打酒、鄰接矩陣與結(jié)構(gòu)化思維到了這一章要反復(fù)提醒自己人工智能編程不是只寫業(yè)務(wù)邏輯它和算法思維、數(shù)學(xué)抽象密不可分。這一章不做枯燥的公式推導(dǎo)而是用兩個(gè)經(jīng)典編程題和一個(gè)數(shù)據(jù)抽象概念把“算法感覺(jué)”講出來(lái)。4.1 李白打酒刷題循環(huán)、遞歸和逆推的經(jīng)典練習(xí)“李白街上走提壺去買酒。遇店加一倍見花喝一斗。三遇店和花喝光壺中酒。試問(wèn)壺中原有多少酒”這是一道非常古老的數(shù)學(xué)題但放在Python里它是一個(gè)極其適合練遞歸和枚舉的題目。常見版本是李白總共遇到店和花若干次店的順序和花的順序可以排列最后見過(guò)一次花壺中酒剛好喝光。用代碼枚舉所有可能的序列再倒推初始酒量是否大于0就是標(biāo)準(zhǔn)解法。這里用一個(gè)簡(jiǎn)化版本說(shuō)明假設(shè)酒壺容量不限初始酒量未知。每遇到一次“店”酒量翻倍每遇到一次“花”酒量減1?,F(xiàn)在有n次遇店、m次見花總共遇到nm次最后一次是花。求滿足條件的初始酒量數(shù)值??梢杂眠f歸搜索def dfs(shop_left, flower_left, wine, path): # 遞歸出口店和花都用完了 if shop_left 0 and flower_left 0: if wine 0: print(path, 初酒 , start) return # 保證過(guò)程中酒量不為負(fù)數(shù) if wine 0 and shop_left 0: return # 遇店加一倍 if shop_left 0: dfs(shop_left - 1, flower_left, wine * 2, path 店) # 見花喝一斗且最后一站必須是花 if flower_left 0 and (shop_left 0 or flower_left 1): if wine 0: dfs(shop_left, flower_left - 1, wine - 1, path 花)這道題練的不是什么高深算法而是兩個(gè)關(guān)鍵思維一是逆推從最后剩余0反推初始值二是狀態(tài)搜索每一步的狀態(tài)由店、花、酒量決定。和AI里的遞歸、動(dòng)態(tài)規(guī)劃、狀態(tài)轉(zhuǎn)移一脈相承。刷這類題的時(shí)候我建議你在紙上畫狀態(tài)樹不要只在腦子里轉(zhuǎn)畫著畫著就明白了。4.2 鄰接矩陣從數(shù)據(jù)結(jié)構(gòu)到圖算法“python構(gòu)建鄰接矩陣”也是經(jīng)常被搜的詞。鄰接矩陣是圖論里最基礎(chǔ)的存儲(chǔ)結(jié)構(gòu)也是很多圖算法比如最短路徑、聚類、圖神經(jīng)網(wǎng)絡(luò)的地基。它的思想特別樸素假設(shè)你有N個(gè)節(jié)點(diǎn)就建立一個(gè)N行N列的矩陣矩陣第i行第j列的值表示節(jié)點(diǎn)i和節(jié)點(diǎn)j是否有邊相連。無(wú)向圖是對(duì)稱矩陣有向圖則不是。用Python表達(dá)出來(lái)并不難import numpy as np # 節(jié)點(diǎn)0-節(jié)點(diǎn)1有邊節(jié)點(diǎn)1-節(jié)點(diǎn)2有邊節(jié)點(diǎn)2-節(jié)點(diǎn)0有邊 edges [(0, 1), (1, 2), (2, 0)] n 3 adj np.zeros((n, n), dtypeint) for i, j in edges: adj[i, j] 1 adj[j, i] 1 # 無(wú)向圖 print(adj)運(yùn)行結(jié)果是一個(gè)3x3的矩陣。這個(gè)矩陣有什么用它的意義在于把“節(jié)點(diǎn)之間的關(guān)系”變成了“可以進(jìn)行矩陣運(yùn)算的數(shù)據(jù)”。學(xué)過(guò)numpy后你還可以通過(guò)矩陣乘法計(jì)算兩點(diǎn)之間長(zhǎng)度為2的路徑數(shù)量這正是很多圖算法的基礎(chǔ)。等以后接觸到圖神經(jīng)網(wǎng)絡(luò)你會(huì)發(fā)現(xiàn)節(jié)點(diǎn)特征被算進(jìn)鄰接矩陣?yán)锏倪^(guò)程和這個(gè)例子是一脈相承的。4.3 結(jié)構(gòu)化數(shù)據(jù)與類型設(shè)計(jì)臟數(shù)據(jù)也會(huì)變成金礦“python結(jié)構(gòu)化數(shù)據(jù)”這個(gè)熱搜詞很有意思。在AI場(chǎng)景里結(jié)構(gòu)化數(shù)據(jù)指的是像表格一樣規(guī)規(guī)矩矩的數(shù)據(jù)每一行一個(gè)樣本每一列一個(gè)特征。Pandas的核心數(shù)據(jù)結(jié)構(gòu)DataFrame就是干這個(gè)的import pandas as pd df pd.DataFrame({ age: [18, 25, 30], income: [5000, 8000, 12000] }) # 問(wèn)題age是字符串轉(zhuǎn)成整數(shù) df[age] df[age].astype(int) print(df.dtypes)這也是數(shù)據(jù)處理里最典型的操作讀進(jìn)來(lái)的數(shù)據(jù)可能類型不對(duì)、有缺失、有重復(fù)你得先清洗成“結(jié)構(gòu)化”的樣子模型才有東西可學(xué)。熱搜里“python篩選一樣的”說(shuō)的就是去重和篩選Pandas天然支持df.drop_duplicates(inplaceTrue)在我看來(lái)“結(jié)構(gòu)化數(shù)據(jù) → 類型設(shè)計(jì) → 清洗 → 建?!笔且粭l完整的生產(chǎn)線。會(huì)用Excel整理表格的人學(xué)Pandas會(huì)特別快因?yàn)槟X子里的表格思維直接遷移過(guò)來(lái)了。這一塊練熟了后面做量化策略、用戶畫像、甚至做個(gè)小推薦系統(tǒng)都不會(huì)出現(xiàn)拿到數(shù)據(jù)不知道從哪下手的問(wèn)題。5. 從Python到人工智能爬蟲、異步與量化策略的過(guò)渡基礎(chǔ)語(yǔ)法和算法思維有底子之后就該考慮怎么和“人工智能”本身接軌了。很多人的第一個(gè)真實(shí)項(xiàng)目不是跑模型而是寫爬蟲——從網(wǎng)上抓數(shù)據(jù)再清洗分析。這個(gè)過(guò)程能讓你真正體會(huì)“數(shù)據(jù)是燃料”這句話。5.1 爬蟲第一批AI應(yīng)用的數(shù)據(jù)來(lái)源爬蟲是Python最受歡迎的用途之一。寫一個(gè)爬蟲不難但寫一個(gè)“有分寸”的爬蟲并不容易?;舅悸肥窍全@取頁(yè)面再解析內(nèi)容最后存儲(chǔ)。用requests加BeautifulSoup就夠了不用專門上Scrapy。舉個(gè)例子import requests from bs4 import BeautifulSoup url https://example.com/list resp requests.get(url) soup BeautifulSoup(resp.text, html.parser) for item in soup.select(.item-title): print(item.text.strip())這里的.select用的是CSS選擇器如果你會(huì)前端幾乎零成本上手。需要提醒的是爬蟲只能抓公開數(shù)據(jù)要尊重目標(biāo)網(wǎng)站的robots協(xié)議控制請(qǐng)求頻率不要給對(duì)方服務(wù)器造成壓力。很多免費(fèi)源碼網(wǎng)站提供的爬蟲例子代碼本身沒(méi)問(wèn)題但實(shí)際使用時(shí)很容易踩到請(qǐng)求頭缺失導(dǎo)致反爬攔截的坑加個(gè)“User-Agent”會(huì)好很多headers {User-Agent: Mozilla/5.0 ...} resp requests.get(url, headersheaders)爬蟲練好了你就能為AI項(xiàng)目找到第一批真實(shí)數(shù)據(jù)而不是永遠(yuǎn)用教程里的鳶尾花數(shù)據(jù)集。5.2 協(xié)程與queue不堵塞吞吐量的關(guān)鍵熱搜詞里“python協(xié)程”“python隊(duì)列queue不堵塞”放在一起看特別有畫面感。單線程爬蟲抓幾百個(gè)頁(yè)面可能得幾十秒甚至幾分鐘而異步協(xié)程的抓取速度能快一個(gè)數(shù)量級(jí)。因?yàn)榈却W(wǎng)絡(luò)響應(yīng)的時(shí)間其實(shí)是空閑的協(xié)程就是利用這段空閑去干別的事。Python自帶的asyncio加上aiohttp是異步爬蟲的標(biāo)準(zhǔn)組合import asyncio import aiohttp async def fetch(session, url): async with session.get(url) as resp: return await resp.text() async def main(): async with aiohttp.ClientSession() as session: html await fetch(session, https://example.com) print(len(html)) asyncio.run(main())這里await的意思是“我暫時(shí)把控制權(quán)交出去等結(jié)果回來(lái)再繼續(xù)”多個(gè)協(xié)程交替執(zhí)行總耗時(shí)接近最慢的那個(gè)請(qǐng)求而不是所有請(qǐng)求之和?!皅ueue不堵塞”的常見場(chǎng)景是生產(chǎn)者-消費(fèi)者模型爬蟲作為生產(chǎn)者往隊(duì)列里丟鏈接多個(gè)消費(fèi)者從隊(duì)列里取任務(wù)。用queue.Queue注意設(shè)置合適的maxsize否則生產(chǎn)太快消費(fèi)太慢會(huì)把內(nèi)存撐爆。異步場(chǎng)景則要用asyncio.Queue同步隊(duì)列在事件循環(huán)里會(huì)阻塞整個(gè)循環(huán)這是個(gè)經(jīng)典坑。5.3 量化交易策略代碼別急著上模型先把指標(biāo)回測(cè)寫清楚“python量化交易策略代碼”是技術(shù)社區(qū)里非常活躍的話題。廣告里宣傳的“AI炒股”大多夸大了但量化本身是一種極佳的Python綜合練習(xí)。量化策略的基本流程是取歷史行情數(shù)據(jù) → 計(jì)算指標(biāo) → 生成買入賣出信號(hào) → 回測(cè)計(jì)算收益和回撤。新手最常犯的錯(cuò)誤是一上來(lái)就想套深度學(xué)習(xí)模型預(yù)測(cè)漲跌結(jié)果模型倒是跑起來(lái)了數(shù)據(jù)泄露和過(guò)擬合的坑一個(gè)都躲不掉。我的建議是先做最樸素的“雙均線策略”短期均線上穿長(zhǎng)期均線時(shí)買入下穿時(shí)賣出。用pandas就能寫import pandas as pd data pd.read_csv(history.csv) data[ma_fast] data[close].rolling(5).mean() data[ma_slow] data[close].rolling(20).mean() data[signal] 0 data.loc[data[ma_fast] data[ma_slow], signal] 1 data[position] data[signal].diff().fillna(0)這一段代碼已經(jīng)能讓行情數(shù)據(jù)變成一列交易信號(hào)。然后再算資金曲線和回撤率理解“過(guò)擬合”是怎么發(fā)生的。這個(gè)項(xiàng)目做完你對(duì)“數(shù)據(jù)→特征→策略→評(píng)估”這條價(jià)值鏈的理解會(huì)超過(guò)很多空談AI的教程。5.4 人工智能方向的三個(gè)銜接動(dòng)作到了這個(gè)階段如果你想接著往AI模型方向深入有件事必須做把NumPy、Pandas、Matplotlib這三個(gè)庫(kù)練熟。它們?nèi)齻€(gè)是數(shù)據(jù)科學(xué)的基本盤也是銜接機(jī)器學(xué)習(xí)模型的橋梁。NumPy管張量多維數(shù)組Pandas管表格數(shù)據(jù)Matplotlib管可視化——三個(gè)拼在一起你就能完成“讀取數(shù)據(jù)、清洗數(shù)據(jù)、觀察數(shù)據(jù)”全套動(dòng)作了。然后可以接觸scikit-learn先跑一個(gè)k近鄰或邏輯回歸的分類小項(xiàng)目體會(huì)模型訓(xùn)練和評(píng)估的完整流程。有了這個(gè)基礎(chǔ)再上手PyTorch或TensorFlow就會(huì)踏實(shí)很多不會(huì)因?yàn)椤発折交叉驗(yàn)證”或者“訓(xùn)練集測(cè)試集切分”這樣的概念卡殼。記住在AI領(lǐng)域Python只是第一艘渡船你真正需要提升的是數(shù)據(jù)和模型的直覺(jué)而這兩樣都得靠一遍一遍親手跑數(shù)據(jù)、畫圖、調(diào)參去培養(yǎng)。6. 常見問(wèn)題排查實(shí)錄——把搜索框里的報(bào)錯(cuò)一次性清干凈最后一章專門解決大家搜索頻率最高的幾個(gè)環(huán)境報(bào)錯(cuò)問(wèn)題。我把它們整理成一個(gè)速查表遇到問(wèn)題直接對(duì)照排查可以少走很多彎路。現(xiàn)象常見原因解決建議Windows安裝Python報(bào)0x80070643已安裝的舊版本殘留/系統(tǒng)組件更新失敗卸載舊版、清理安裝目錄用官方安裝包以管理員身份重裝pip install numpy報(bào)MSVC編譯錯(cuò)誤本地沒(méi)有C編譯器pip未匹配到wheel先升級(jí)pippython -m pip install --upgrade pip再裝一次import cv2報(bào)DLL找不到缺少VC運(yùn)行庫(kù)安裝微軟Visual C Redistributable再驗(yàn)證import cv2VS Code運(yùn)行代碼但找不到自己的Python環(huán)境沒(méi)有選擇正確的解釋器CtrlShiftP→ “Python: Select Interpreter”選虛擬環(huán)境敲python沒(méi)反應(yīng)Windows環(huán)境變量PATH未配置安裝時(shí)勾選“Add Python to PATH”或手動(dòng)把Python安裝目錄加入PATHpandas讀取中文CSV亂碼文件編碼不是UTF-8pd.read_csv(... , encodinggbk)根據(jù)文件實(shí)際編碼修改排查環(huán)境問(wèn)題有一個(gè)基本原則一次只改一個(gè)變量。比如你同時(shí)升級(jí)了pip、換了鏡像源、重裝了Python最后成功了但你不知道是哪個(gè)動(dòng)作起了作用。下次遇到類似問(wèn)題還是兩眼一抹黑。正確做法是先確認(rèn)報(bào)錯(cuò)信息里的關(guān)鍵詞再有針對(duì)性地操作每改一步跑一次驗(yàn)證命令。關(guān)于提問(wèn)我也多說(shuō)一句。在技術(shù)社區(qū)提問(wèn)時(shí)不要只發(fā)一句“報(bào)錯(cuò)了求解”那樣誰(shuí)也幫不了你。要把完整的報(bào)錯(cuò)信息、操作系統(tǒng)版本、Python版本、你執(zhí)行過(guò)的命令都貼出來(lái)。我見過(guò)太多人問(wèn)“python安裝numpy庫(kù)的方法”底下的回答寫得再詳細(xì)提問(wèn)者連自己的Python版本都沒(méi)說(shuō)——這就像去看病只說(shuō)“難受”不給醫(yī)生任何具體癥狀。會(huì)提問(wèn)也是一種技能把問(wèn)題描述清楚你離答案就走完了一半的路。另外那些“免費(fèi)python源碼大全”“python的mc代碼免費(fèi)復(fù)制”之類的東西我的態(tài)度是看看無(wú)妨但千萬(wàn)別當(dāng)成學(xué)習(xí)捷徑。把來(lái)歷不明的代碼直接復(fù)制運(yùn)行輕則報(bào)錯(cuò)重則帶來(lái)安全問(wèn)題。真正值得你花時(shí)間的是自己動(dòng)手把一份代碼逐行讀明白再改造它這才是編程能力增長(zhǎng)的唯一路徑。跑通了不驕傲報(bào)錯(cuò)了不慌張把每個(gè)報(bào)錯(cuò)都當(dāng)成一次免費(fèi)的教學(xué)機(jī)會(huì)這個(gè)心態(tài)比所有語(yǔ)法技巧都重要。最后再分享一個(gè)我自己的小體會(huì)學(xué)Python人工智能這條路大多數(shù)人放棄都不是因?yàn)殡y度而是因?yàn)椤皼](méi)反饋”——寫了幾十行代碼不知道對(duì)不對(duì)跑半天模型不知道訓(xùn)練得好不好。所以不管學(xué)到哪個(gè)階段一定要定期做一個(gè)小項(xiàng)目哪怕是用水管工思維寫一個(gè)爬蟲、根據(jù)天氣數(shù)據(jù)預(yù)測(cè)明天的溫度也好過(guò)漫無(wú)目的地刷教程。做一個(gè)完整的小項(xiàng)目你會(huì)在收尾的那一刻突然發(fā)現(xiàn)原來(lái)自己已經(jīng)會(huì)用代碼解決真實(shí)問(wèn)題了。這個(gè)成就感就是撐著你走到“精通”的那口氣。