The two most important days in your life are the day you were born and the day you find out why. -Mark Twain

#100 這是第 100 篇文章...

 這是第一百篇文章,不是學術理論文章,也不是工程技術說明,只是一個單純的生活回顧文.

這幾年的變化很大,對許多年輕人來說,看部落格應該不是件流行的事情.對我這個老人來說,用文字方式來表達想法,是一個比較嚴謹的方式,畢竟是腦筋思考過,文字修飾過的產物.除此之外,還能練習自己的中文寫作能力,讓自己的頭腦繼續保持對文字寫作的熱情.

從 2019 年開始,我的工作和生活有些改變,所以讓我沒有太多空餘時間能整理自己的腦袋來寫部落格的文章,特別是那種圖文並茂的技術說明文章.回顧來看,前面許多文章都是我用小畫家或是 Powerpoint 一個框一個箭頭去畫下來,然後再上傳到 Github 做儲存空間.這一路走來,我收到了一些讀者回應,大部份的人都是來謝謝我寫出那些文章,幫助他們了解背後的原理.非常感謝這些讀者們的回應.誠如第 0 篇文章所說的,這個部落格的目的就是希望把我走過的路,看到的事與物紀錄下來,我以前跌倒過的地方,我相信後面的人也很可能會遇到.如果我能留下一些蛛絲馬跡讓後面的人在 google 答案時能為他的工作或人生有一點啟發,我想這也是我為大家做出一點小小的貢獻.

2019 年開始,尤其嚴峻的工作挑戰和責任,再加上我收了一位小徒弟,當時他是一位國中二年級的學生,擁有優於常人的數學頭腦.從那時起,我平日時間幾乎都是工作 12 小時以上,星期六下午則是小徒弟的上課時間,星期日不是家庭時間就是工作時間,所以比較少有力氣和精神來寫部落格文章了.一年半後,工作上終於有個很成功的回報,同時小徒弟也考上建中.這兩件事情是我在 2020 年最值得寫在人生記錄上的事情.

小徒弟考上建中後,仍維持每個星期六下午來上課,我差不多把我知道的資料結構,演算法等大大小小都告訴他了.我會的當然是一部份而己,為了補不足,我也特別去買了許多課外書給小徒弟自己念,然後我們再一起討論.在那過程中,其實我也學了不少.這就是最典型的,教學相長.當時本來心想要鼓勵小徒弟要不要放棄課業,全力學習寫程式去拼資訊的奧林匹克獎.但是,我後來退縮了.想想我自己也沒做過的事,要我小徒弟去拼,我可能也幫不上什麼忙.打消這種想法,重心還是放在學校功課上,寫程式就當課後興趣.同時,他班上也有幾個興趣相同的同學們,常常討論一些問題的解法以及一些特別的資料結構,在這過程中,我也跟他學習了.

去年,小徒弟在學測後考上了交大資工.他的分數排不上台大資工,而清大資工和交大資工是非常有機會的,湊巧清大交大的面試考試時間又衝突,這擺明了逼高中生只能選一間,於是我建議小徒弟選擇交大資工.後來,緣份來了,交大資工考上了,果然是全村的希望.小徒弟上了大學後,我仍會詢問課程修了什麼,內容學了些什麼.從他學習的內容中,可以看到現在資工系學的東西比我們以前那年代好很多了,尤其是在寫程式這一塊.小徒弟未來想走人工智慧的相關領域,這也可想而見.這兩年來,AI 相關題材相當熱門.其實,AI 一直都在,只不過是 ChatGPT 的出現讓 AI 這個名詞有如中樂透一夜致富的感覺,就像十年寒窗無人問,一舉成名天下知的情況.這兩年來,大大小小的 AI 模型如雨後春荀般的出現,許多相關的工具也是前後相繼的出現,也因為這些 AI 模型和相關的工具鏈的出現,讓一般不是 AI 專長的軟體工程師有機會能做出一些很有趣的 AI 應用,包括我自己也是.同時,也帶來許多新的挑戰,因為你可能已經發現了,ChatGPT 寫出來的程式碼幾乎可以輕易地打敗你寫出來的程式碼了.對軟體工程師來說,這是一個警訊,也是一個機會,就看你如何讓這些 AI 工具成為你的助手,而不是害你成為失業的人.當時,Github copilot 剛問世時,我鼓勵我所有的工程師們一定要學習如何使用它,我們不需要擔心是不是會被 AI 取代,我們要擔心的是別人都會了,而你卻不會!


回首來時路,山高無坦途.

這句話是我在許多登山界的影片裡常會聽到的一句話.人生跟登山也是類似的過程,有時上坡,有時下坡,有時陽光,有時陰雨.對大部份的人來說,生活處處充滿挑戰,因為人們心中都有個夢想,所以才願意時時接受挑戰.挑戰沒成功,這是正常的事情.無論如何,生活還是要過下去,明天還是要繼續活下去,bug 還是要解的.

而我呢? 接下來,我的工作更多了,也很難擠出時間寫更多文章.我常在想,ChatGPT 知道了很多知識,我可以把部落格的文章改成我和 ChatGPT 的對話內容,透過一問一答的方式來讓讀者了解我的思路,讓 ChatGPT 來產生簡單易懂的答案,不知道讀者們會喜歡這想法嗎 ?


Share:

#99 一個特別的資料結構 K-D 樹

前陣子和團隊成員討論工作內容時,看到了一位特別的資料結構.老實說,我以前不知道這個結構,因此特別去查了資料,然後將它的內容寫在這裡.

在電腦科學中,組織數據的方式對於快速查找和使用數據至關重要。其中一種特別的數據結構稱為 K-D 樹(K-Dimension tree),主要用於在多維空間中組織點,非常適合應用於機器學習、電腦圖形和資料庫搜索等領域。現在,讓我們來看看 K-D 樹是什麼、為什麼被發明、它可以解決哪些問題,以及如何編寫 K-D 樹的程式碼。

假設你有一組在 2 維空間中的點(例如地圖上的座標),地圖是由 X, Y 軸所組成的.當你希望快速找到某個位置的最近點,K-D 樹就是一個很好的工具.K-D 樹是一種二元搜尋樹,它在具有 k 維空間中將點組織起來的能力。每一層代表一個維度,並且通過交替各個維度的分割,可以使得在空間內找到鄰近點變得更加容易。

所以, K 代表的是維度數,以地圖來說,K=2.

假設你有一組城市地標的座標,並希望快速找到離給定位置最近的地標,假設你有台北 101 的座標,要尋找附近著名的景點座標。在沒有任何其他資料結構的幫助下,每次搜尋都需要比較每一個地點,計算距離,然後依照 "附近" 的定義來決定那些景點的座標符合要求.如果一個地圖裡有成千上萬甚至數百萬個景點座標時,則尋找會非常耗時。K-D 樹就是為了解決這個問題而發明的。它的核心理念是將座標進行合理的排列,以便在搜尋時可以排除大量不相關的點。K-D 樹最早由 Jon Bentley 在 1975 年發明,並在需要快速搜尋和排序空間數據的應用中廣泛使用,例如 最近鄰搜尋(找到最近的點)。

接下來談談 K-D 樹如何建立以及如何利用它來搜尋.

1.建立過程 - 首先選擇一個維度作為 "分割" 維度。為了簡單起見,假設在 2D 空間中,所以我們有兩個維度:X 和 Y。 - 在樹的根節點上,根據 X 座標分割點。 - 找到 X 值的中位數,並將其作為 "支點" (pivot) 來劃分。把其他座標點 X 大於中位數的放在左邊,小於中位數的放在右邊。 - 接下來,在每一層上交替進行維度分割。下一層使用 Y 座標進行分割,然後再回到 x 座標,以此類推。

因此,樹的每一層就是由不同的維度來形成,以地圖為例,就是 X , Y , X , Y 以此類推,一直到把所有的資料都寫入到樹裡.

2. 尋找過程 - 若要找到最近的鄰居,將目標點與樹的每一層進行比較,根據點是更接近左子樹還是右子樹來選擇路徑。 - 當搜尋到 LEAF 節點時,檢查距離以確認它是否為目前發現的最近點。 - 通過使用樹的結構,我們不需要查看每一個點,這使得搜尋比直接比較更快。

我們將上述的想法利用程式碼來呈現時,它看起來如下:

以下是使用 KD 權的程式碼範例

K-D 樹是一種強大的資料結構,可以幫助我們在多維空間中快速找到點。通過有效組織數據,K-D 樹使得進行最近鄰搜尋和範圍搜尋變得更快。當你在地理位置相關的應用中尋找附近的選項時,K-D 樹很可能就在背後默默運作。

Share:

#98 淺談機器學習

人工智慧在電腦科學的領域不是一個新主題,已經存在很長的時間.其目的是希望電腦可以做出接近人腦一樣的決策,甚至希望比人腦更好.從以前到現在曾試過了數種不同的方式,從 90 年代開始,機器學習成為了人工智慧裡主流的方式,革新了我們處理數據分析、自動化和決策的方式。這文章將討論機器學習的基礎概念,淺談其不同類型、訓練模型等.

機器學習是近二三十年來人工智慧裡流行的方法,專注於開發能夠基於數據的了解並做出預測或決策的演算法。它涉及創建模型和使用模型,這些模型可以找到模式、做出決策,並且隨著時間的推移提高其準確性。機器學習的廣泛分類可以分為 3 大類:監督學習 (supervised learning), 非監督學習 (non-supervised learning) 和半監督學習 (semi-supervised learning)。這一區分主要基於用在開發模型的訓練數據是否包含要預測的結果的答案。

在監督學習中,模型在標籤化的數據集上訓練,也就是說每一筆訓練資料都已經附上了正確答案,也就是標籤,這也代表了每一筆訓練資料都有正確輸入和輸出配對,通常來說,這是基於人類的決策來決定是否正確,所以早期的機器學習專案都需要依賴大量人力的介入來為每個數據給予正確答案,也就是標籤化的動作。模型學習從輸入數據中預測輸出答案,並且可以根據已知結果來衡量其性能。舉個例子,你要做一個能自動辦別貓或狗的程式,你收集了許多有關狗和貓的照片,假設超過了一萬張各式各樣的貓狗照片.並且每一個照片你都給出了正確答案,如第一張是貓,第二張是狗,第三張是貓等等.機器學習裡最重要的任務就是為你的程式產生出一個數學公式 (function),公式的輸入數據就是照片, 公式的輸出結果是答案,貓或狗. 所以,機器學習就是要產生這樣的 數學公式給你的程式來使用. 我們先跳過製作數學公式的細節過程,這個數學公式的行為是從現有的一萬張照片裡 “學習” 而來的,因此,你可以想成用過去的照片,找出一個模式,然後去預測未來的照片. 因此,只要訓練時輸入的照片別太少,在預測的效果就不會太差. 預測準確率也是評估該數學公式表現好壞的重要指標,也常是用來衝量該數學公式的效果好壞. 所以,機器學習裡講的模型就是在訓練過程後產生的數學公式.因為每一張照片都搭配著正確答案,所以這種方式稱為監督學習,也就是說,每個訓練資料的輸入和輸出的關係都是由人類預先定義好.如果每張照片並沒有搭配著正確答案,這種方式則稱為非監督學習。如果訓練的數據裡有部份有標籤,而部份沒有,則這種方式稱為半監督學習。

既便你完全沒接觸過任何的機器學習演算法,單純地從上述的說明加上你對基本演算法的認識,你一定能推斷出監督學習和非監督學習是兩種完全不同的方式.監督學習的訓練資料已經有答案,所以你需要的演算法是在輸入 (照片) 和輸出 (貓狗) 之間找出關係,而非監督學習沒有答案,所以比較適合把 “類似” 的輸入聚合在一起,所謂的 "類似" 可依照功能來區別,讓人們可以很直覺地知道為何這些資料會被放一起.舉個例子,產品推薦功能,在現在許多電子商務或是影音平台網站上都會常見到這樣的功能,網站裡有許多的商品和影片,一開始沒人會知道你想買些什麼.一旦資料越來越多後,許多客戶隨著時間會建立出許多訂單,從訂單的產品裡可以整理出一套 “類似” 的規則.舉例,常買烤雞的客戶也常買牛排,常看搞笑影片的客戶比較少看知識型的影片,這些 “類似” 規則的建立就是非監督學習的成品.

從上面的說明你可以看到不論是那一種方式的機器學習方法都需要足夠多的資料,建立出來的模型也都是依照過去資料的累積而建立出來的,至少這個模型能不能拿來用在未來的預測上,這實在很難保證.舉例,貓狗照片的辦識應該沒太大問題,畢竟十年後二十年後,貓狗的長相都還是會一樣 (除非他們都成了變種貓狗了),但同一家購物商店的商品推薦功能在十年後二十年後還能用嗎? 這沒人敢保證,畢竟商品推薦的模型是用過去數年的客戶訂單資料所建立出來的,裡面都是這些客戶的行為,如果整個社區的住戶全部都換了,你覺得你還能拿一樣的模型來用嗎 ? 答案可能可以,也可能不行.

在監督學習裡所建立出來的模型基本上都是依照你給的新輸入來算出預測的答案. 一般來說,會有兩種不同的情況,要看答案本身之間的關係.舉例,以貓狗照片辦識來說,輸入的數據是貓或狗或是其他動物的照片,模型的輸出是貓或狗或其他,答案本身是一種固定在三個值的變數,我們把這種答案稱為 “分類型” (Classification) .舉另外一個例子,某公司下個月的銷售量預測,輸入的數據是每個月的銷售量,季節因素,經濟好壞等數據,而模型的輸出是一個預測銷售量數字,這些答案並不是固定在幾個固定值的變數,而且會隨著時間和許多其他不同因素變動時而變動的數字,我們把這種答案稱為 “回歸型” (Regression).不同答案類型所需要的演算法或統計法也是不同的.同理也能用在非監督學習裡,答案也可分為 “群組型” (Cluster) 和 “資料探勘型” (Data mining).其實,不論是那一種方法,都是在從你給的輸入數據裡依照你要的答案找出一個數學公式。我們要把輸入資料能 “座標化”,然後數學公式就是在這座標系統裡一個 n 維度的線或面,透過把輸入數據傳給該數學公式後就能推導出答案.

我們來用另一個例子, 假設我們得到十個病人的身高體重資料,而我們要的答案是從這些病人的資料來學習 (預測) 某一個人會不會有高血壓.假設,我們知道每一個病人有沒有高血壓,也就是說我們有答案,我們將身高體重座標化,體重是 x 軸,身高是 y 軸,呈現如下,

因為我們知道那些病人有高血壓 (紅色圈標記) ,因此,我們很容易能找一個能區分有高血壓和沒高血壓的直線或曲線. (線條的選擇或建立就是機器學習課本裡的重點.)

以上是透過 SVM 演算法所製作出來的直線,它就是一個數學公式.因此,當你有新的病人數據進入到這個直線時,我們就能知道這新病人是否有高血壓,因為只要看新輸入數據的座標是在直線的左邊或右邊就能得到答案,左邊沒有高血壓,右邊則有.以上只是一個單純的例子,真實情況下,病人的輸入參數絕對不會只有身高和體重,有意義且足夠多的參數才能幫助產生更好的預測.現在你知道機器學習模型就是在座標系統裡的一條線或是一個面.問題越複雜時,我們需要提供的參數將越多,也代表座標系統的維度越高.這些高維度的座標系統運算在數學上用矩陣來表示,方便閱讀,也方便寫程式,因此在執行機器學習專案時才會需要擅長矩陣運算的 GPU 來執行座標系統裡相關的計算.

另一種情況是我們不知道有那些病人有高血壓,這表示我們要採用非監督學習的方式. 例如,採用 K-means 並將 cluster 數量設定為 2,會得到以下的圖型,

K-means 演算法把十個病人分成兩群組, 5,6,1,7,3是一組, 9,2,8,10,4 是一種. 可想而知,這是一個失敗的數學公式,因為和真實答案相比有很高的錯誤率.在這例子裡會有這種情況是很正常的,畢竟資料太少,只有十個人,資料維度也不夠,只有身高和體重,所以很難在這麼少的數據下得到些結論. 從這個簡單的例子也可以知道有正確答案的監督學習是處在多麼有利的位置.所以,在建立機器學習模型前的資料數據整理和答案標記是對模型的建立和準確率有很大的幫助.

在監督學習和非監督學習之間存在一個灰色區域,稱為半監督學習,也就是指有部份的輸入數據有了正確答案,其中模型在部分標籤化的數據上訓練。當獲取數據的標籤昂貴或耗時時,這種方法很有用。舉個例子,當你有一萬張的動物照片時,你要建立一個機器學習模型能辦識出照片裡是那一種動物,為了讓模型得到最好的辦識結果,你希望採用監督學習方式進行,也就是要將正確答案準備好.但你可以沒有足夠的時間金錢或是其他原因導致無法將一萬張照片標示好正確答案,可能只有三千張照片能完成正確答案標示,另外七千張照片沒有正確答案.此時,可以用一個簡單的方法,將三千張有正確答案標示的照片先進行模型訓練,訓練後得到的模型用於七千張沒正確答案照片的預測,然後再將七千張照片的預測視為正確答案和三千張已有正確答案的照片再重新訓練出一個模型,半監督學習的方法有好幾種,這只是其中一種簡單好懂的.如果這個程過是循序漸進的,則模型還可以適時地改變,這樣就能漸漸地得到更好的模型,這也是所謂的增強學習 (reinforcement learning)。從這個方法延伸下去還可以有許多的理論和應用產生.

機器學習是一個動態且快速發展的領域,具有廣泛的應用範圍。理解不同類型的機器學習、如何訓練模型以及最新進展對於任何希望利用這項強大技術的人來說都至關重要。隨著機器學習繼續融入各個行業,它對社會的影響勢必增長,使其成為一個令人興奮的研究和創新領域。


Share: