【💊 Python的解憂錦囊】亂數按比例分配資料集

更新於 2024/12/12閱讀時間約 0 分鐘

假設我們今天想要訓練一個AI模型, 那麼我們會有一批大型資料集, 通常會根據比例來切分三個模型訓練所需的訓練集(train)、驗證集(dev)、測試集(test), 而我們本次會示範一下Python如何對一個List清單進行切分, 基本上大同小異, 我們只要掌握作法即可概念相通。

任務提示

raw-image


我們有10個依序的號碼球, 每個桶子按照比例大小裝載這些球, 比例如下:

  • A桶 = 10 * 0.8 = 容納8個球
  • B桶 = 10 * 0.1 = 容納1個球
  • C桶 = 10 * 0.1 = 容納1個球

並且每個球會被分到哪邊是隨機亂數的, 請依照這些條件完成隨機分配的任務。

拆解問題並釐清作法

從任務的描述之中我們可以觀察到幾個重點, 「隨機」與「按照比例分類」。

首先我們來談談「隨機」, 這方式最直白的就像是我們在玩撲克牌的洗牌一樣, 將排組盡量模糊掉順序, 避免每次的結果都一樣。

raw-image

那「按照比例分類」呢? 其實就想像成蛋糕切成幾等份一樣, 一定有些人食量較大, 有些人食量較小, 那我們便按照大小的比例來切成幾等份。

raw-image


那上述的情境我們可能會有以下幾個思路:

  1. 分成三桶後, 依序拿球隨機丟桶。
  2. 分成三桶後, 隨機抽球依序丟桶。
  3. 對球洗牌, 依序分到小桶子。

首先我們來分析一下這三種作法吧!

思路1: 分成三桶後,依序拿球隨機丟桶

  • 優點:簡單且容易理解,程式碼簡潔。
  • 缺點:隨機性較差,可能會導致某些桶子球數量不均勻。
import random

# 初始號碼球列表
balls = list(range(1, 11))

# 各桶比例
props = [0.8, 0.1, 0.1]

buckets = {
'A': [],
'B': [],
'C': []
}

# 依序抽球
for ball in balls:
# 隨機抽桶
bucket = random.choices(list(buckets.keys()), weights=props)[0]
buckets[bucket].append(ball)

# 印出各桶子裝載的內容
for bucket, content in buckets.items():
print(f'桶子 {bucket}: {content}')

思路2: 分成三桶後,隨機抽球依序丟桶

  • 優點:使用隨機抽球的方式,可以確保較好的隨機性和分布。
  • 缺點:可能需要較多的迴圈運算,如果球數量很大,效率可能較低。
import random

# 10個號碼球
balls = list(range(1, 11))

# 按比例分配球到不同桶子
bucket_a = int(10 * 0.8)
bucket_b = int(10 * 0.1)
bucket_c = int(10 * 0.1)

buckets = {'A': [], 'B': [], 'C': []}

for _ in range(bucket_a):
ball = random.choice(balls)
buckets['A'].append(ball)
balls.remove(ball)

for _ in range(bucket_b):
ball = random.choice(balls)
buckets['B'].append(ball)
balls.remove(ball)

for _ in range(bucket_c):
ball = random.choice(balls)
buckets['C'].append(ball)
balls.remove(ball)

# 印出各桶子裝載的內容
print("A桶:", buckets['A'])
print("B桶:", buckets['B'])
print("C桶:", buckets['C'])

思路3: 對球洗牌,依序分到小桶子

import random

# 10個號碼球
total = 10
balls = list(range(0, total))

# 隨機洗牌
random.shuffle(balls)

# 分成三桶後依序放入桶子
# 0 ~ A的區段
a_size = int(total * 0.8)
start = 0
end = a_size
bucket_a = balls[start:end]

# A ~ B的區段
b_size = int(total * 0.1)
start = a_size
end = a_size + b_size
bucket_b = balls[start:end]

# B ~ C的區段
c_size = int(total * 0.1)
start = a_size + b_size
end = a_size + b_size + c_size
bucket_c = balls[start:end]

print("Bucket A:", bucket_a)
print("Bucket B:", bucket_b)
print("Bucket C:", bucket_c)

優缺點分析

  • 思路1(分成三桶後,依序拿球隨機丟桶): 這方式簡單實作, 但隨機性較差, 因為是以比例抽桶子為出發點下去進行的, 且未依照球的比例下去分配。
  • 思路2(分成三桶後,隨機抽球依序丟桶): 這種方式依照桶子可容納的大小來分別抽球, 可以達到一定的隨機性且能夠依照比例分配, 但缺點是
  • 思路3(對球洗牌,依序分到小桶子): 這種方式會預先對球池進行洗牌, 之後只要按照比例切分球桶並按照可容納的量丟入即可, 易讀、易理解, 運作上較有效率。

結語

原來一個需求可以不只有一種方式可以達到目的, 我們應該深入分析之後選擇一個適合我們的方式下去進行實作,而在這裡我們也提供了三種不同的思路下去解決問題,並分析優缺點,相信這樣的技能不只能夠用在軟體開發,生活上的大小事,也都可以進行深入的分析與決策。

當然過程中也不忘ChatGPT的幫忙,至於應該怎麼問對問題呢? 不妨參考以下的篇章學習提問的技巧:


學習軟體開發的路上常常苦於網路資訊爆炸嗎? 教學何其多,但卻遇到無法明確選擇的困境呢? 歡迎加入「🔒 阿Han的軟體心法實戰營」, 這裡不給您冗餘的雜訊, 單刀直入直接送您業界開發重點, 避開選擇障礙的困境, 讓您獲得業界標準的開發起手式, 成為Top 1的頂尖人才。

avatar-img
116會員
260內容數
哈囉,我是阿Han,是一位 👩‍💻 軟體研發工程師,喜歡閱讀、學習、撰寫文章及教學,擅長以圖代文,化繁為簡,除了幫助自己釐清思路之外,也希望藉由圖解的方式幫助大家共同學習,甚至手把手帶您設計出高品質的軟體產品。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
阿Han的沙龍 的其他內容
我們在使用Python語言進行軟體開發時, 常常會需要dict這個資料結構來儲存複雜結構的資料, 就如同JSON一般, 我們會具有這樣的Key/Value模式組成的資料結構, 如下圖: 而當我們在Python的世界裡, 除了嚴謹規範資料欄位的@dataclass之外, 更常使用的就是「di
我們在「【🔒 Python 先修班】👆 打造友善的使用者互動CLI介面」有介紹Python的Click命令列參數設計介面的方式, 那我們除了設計出介面提供使用者互動之外, 有時候也需要一點驗證機制, 畢竟我們心裡都清楚「garbage in, garbage out」的後果, 為了減少這種狀
Python雖然是直譯式的腳本語言, 用起來非常方便, 但當我們的工具越發成熟時, 就會需要將使用方式、介面給設計好, 那通常都會用來處理後端伺服器的作業, 也比較面向IT端, 因此我們通常會以Command Line的形式與使用工具的人進行互動, 而內建模組雖然有「argparse」可以讓我們
排序這個動作在軟體開發中常常會使用到, 從使用者期望所見的順序到資料處理的效能議題都與排序息息相關, 因此掌握程式語言的排序功能是非常重要的一個環節, 而我們在閱讀他人的Go專案程式碼時也會看到排序的方式有些許不同, 那究竟有何差異呢? 就讓我們繼續看下去吧… 其實在進入今天的主題之前, 我們
我們在「【🔒 Python 先修班】⬆️ 培養良好的Coding Style讓專業度 Up!Up!Up!」談到了Coding Style, 在文末也分享了pylint的程式碼檢查工具, 雖然內建、簡單快速上手, 但隨著技術的演進, 我們總需要又快、又好、又簡單的工具做為預設的工具庫, Ruff
撰寫Python的朋友都知道multithread/multiprocess能為我們帶來效能的改進,減少硬體資源的閒置,但在撰寫的過程中常常會發現到我們所設計的工作池模式會需要將「待辦清單」的工作項目當成參數傳遞進去執行, 除了「待辦清單」之外, 其餘的參數基本上都是固定的, 基於這樣的需求之下
我們在使用Python語言進行軟體開發時, 常常會需要dict這個資料結構來儲存複雜結構的資料, 就如同JSON一般, 我們會具有這樣的Key/Value模式組成的資料結構, 如下圖: 而當我們在Python的世界裡, 除了嚴謹規範資料欄位的@dataclass之外, 更常使用的就是「di
我們在「【🔒 Python 先修班】👆 打造友善的使用者互動CLI介面」有介紹Python的Click命令列參數設計介面的方式, 那我們除了設計出介面提供使用者互動之外, 有時候也需要一點驗證機制, 畢竟我們心裡都清楚「garbage in, garbage out」的後果, 為了減少這種狀
Python雖然是直譯式的腳本語言, 用起來非常方便, 但當我們的工具越發成熟時, 就會需要將使用方式、介面給設計好, 那通常都會用來處理後端伺服器的作業, 也比較面向IT端, 因此我們通常會以Command Line的形式與使用工具的人進行互動, 而內建模組雖然有「argparse」可以讓我們
排序這個動作在軟體開發中常常會使用到, 從使用者期望所見的順序到資料處理的效能議題都與排序息息相關, 因此掌握程式語言的排序功能是非常重要的一個環節, 而我們在閱讀他人的Go專案程式碼時也會看到排序的方式有些許不同, 那究竟有何差異呢? 就讓我們繼續看下去吧… 其實在進入今天的主題之前, 我們
我們在「【🔒 Python 先修班】⬆️ 培養良好的Coding Style讓專業度 Up!Up!Up!」談到了Coding Style, 在文末也分享了pylint的程式碼檢查工具, 雖然內建、簡單快速上手, 但隨著技術的演進, 我們總需要又快、又好、又簡單的工具做為預設的工具庫, Ruff
撰寫Python的朋友都知道multithread/multiprocess能為我們帶來效能的改進,減少硬體資源的閒置,但在撰寫的過程中常常會發現到我們所設計的工作池模式會需要將「待辦清單」的工作項目當成參數傳遞進去執行, 除了「待辦清單」之外, 其餘的參數基本上都是固定的, 基於這樣的需求之下
你可能也想看
Google News 追蹤
Thumbnail
本文探討了複利效應的重要性,並藉由巴菲特的投資理念,說明如何選擇穩定產生正報酬的資產及長期持有的核心理念。透過定期定額的投資方式,不僅能減少情緒影響,還能持續參與全球股市的發展。此外,文中介紹了使用國泰 Cube App 的便利性及低手續費,幫助投資者簡化投資流程,達成長期穩定增長的財務目標。
Thumbnail
MinIO 是一個高性能的物件存儲系統,設計用於大規模的數據存儲需求, 甚至是各種非結構化數據也都能往這邊儲存, 也支持群集擴展, 非常適合正在尋找儲存方案的朋友們。 我們在「【💎 Message Queue - Kafka 案例篇】如何將檔案流上傳到minio - 完整檔案 」介紹了如
Thumbnail
訊息的即時傳遞已然成為現代社會的趨勢了, 影音也是如此, 即時! 即時! 即時! 已經是目前使用者體驗的必要元素了, 在這邊我們要分享的主題是如何在python程式語言的情境下使用ffmpeg來將音檔串流的轉換格式, 為什麼會有這樣的需求呢? 因為我們處理音檔時可能會需要統一輸出的格式, 當然背後也
Thumbnail
我們在學習kafka的過程中最不習慣的就是不管什麼樣的資料, 在kafka的傳輸過程都會是binary的資料格式, 因此我們在撰寫程式的過程中並不是那麼的直觀, 必須將資料從float、int…資料型態轉型成binary才能順利傳送, 那麼基於這樣的前提之下, python這套程式語言可以怎麼做
Thumbnail
情境描述 我們在「🔒 阿Han的軟體心法實戰營 - kafka」有關於kafka的教學文章, 那麼在開發過程中我們遇到了 👻 詭異事件, 那就是我們嘗試在做一個檔案串流時, 發現Producer明明傳送了大約16MB檔案大小的封包到kafka, 每一包約(1024 * 1024 ) bytes
Thumbnail
更快、更短、更即時是串流傳輸必要的元素, 而我們常常在使用Python請求API時都是等待式回應, 也就是一個請求過去之後, 待對方處理完畢後再行回應, 但假設需要下載的檔案、內容非常大時, 是不是使用者只能傻傻的等待整個傳輸結束後才能顯示? 這樣的使用者體驗也實在太糟糕了, 對於使用者來說除了完全
Thumbnail
我們將探索函式的定義和調用,這是程式設計中非常重要且強大的概念,它可以將大型程式切割成小的、可重複使用的函式。讓我們一起來了解吧!函式的定義、呼叫和返回值是學習函式的核心。
Thumbnail
探索Python學習筆記中列表的建立、存取和常用方法。從使用中括號定義列表到了解索引、新增、刪除、修改等操作,並介紹append、remove、count等常用方法。
Thumbnail
在本篇Python學習筆記中,我們探討了字典的建立與存取,以及常用方法,字典是一種強大的資料型態,透過key和value的對應關係存儲和取得資料,我們學會了建立字典、存取資料、新增/修改/刪除項目,以及取得key和value的方法,字典是Python中不可或缺的工具!
Thumbnail
我們探討了while迴圈的使用,不同於for迴圈,while迴圈以條件式判斷為基礎,而非限定重複次數。我們介紹了使用break語句強制結束迴圈,以及使用continue語句跳過特定程式碼並返回迴圈開頭,同時,我們提及了無窮迴圈的概念,強調了在迴圈中必須更改迴圈變數的值,以避免無窮迴圈的發生。
Thumbnail
經濟是國家的命脈,社稷重點無可厚非,國際情勢不好、經濟危機出現時,國家資源救市,穩定法人、投資人信心,維持正常的金融機轉,讓國家度過危機,👍值得嘉許,只是這次國安基金護盤的故事,讓人百般尋味。 台股去年創下18650破紀錄新高,隨著國際局勢一起回檔,國安基金決定進場護盤: 第一:當時股市萬八,不是
Thumbnail
本文探討了複利效應的重要性,並藉由巴菲特的投資理念,說明如何選擇穩定產生正報酬的資產及長期持有的核心理念。透過定期定額的投資方式,不僅能減少情緒影響,還能持續參與全球股市的發展。此外,文中介紹了使用國泰 Cube App 的便利性及低手續費,幫助投資者簡化投資流程,達成長期穩定增長的財務目標。
Thumbnail
MinIO 是一個高性能的物件存儲系統,設計用於大規模的數據存儲需求, 甚至是各種非結構化數據也都能往這邊儲存, 也支持群集擴展, 非常適合正在尋找儲存方案的朋友們。 我們在「【💎 Message Queue - Kafka 案例篇】如何將檔案流上傳到minio - 完整檔案 」介紹了如
Thumbnail
訊息的即時傳遞已然成為現代社會的趨勢了, 影音也是如此, 即時! 即時! 即時! 已經是目前使用者體驗的必要元素了, 在這邊我們要分享的主題是如何在python程式語言的情境下使用ffmpeg來將音檔串流的轉換格式, 為什麼會有這樣的需求呢? 因為我們處理音檔時可能會需要統一輸出的格式, 當然背後也
Thumbnail
我們在學習kafka的過程中最不習慣的就是不管什麼樣的資料, 在kafka的傳輸過程都會是binary的資料格式, 因此我們在撰寫程式的過程中並不是那麼的直觀, 必須將資料從float、int…資料型態轉型成binary才能順利傳送, 那麼基於這樣的前提之下, python這套程式語言可以怎麼做
Thumbnail
情境描述 我們在「🔒 阿Han的軟體心法實戰營 - kafka」有關於kafka的教學文章, 那麼在開發過程中我們遇到了 👻 詭異事件, 那就是我們嘗試在做一個檔案串流時, 發現Producer明明傳送了大約16MB檔案大小的封包到kafka, 每一包約(1024 * 1024 ) bytes
Thumbnail
更快、更短、更即時是串流傳輸必要的元素, 而我們常常在使用Python請求API時都是等待式回應, 也就是一個請求過去之後, 待對方處理完畢後再行回應, 但假設需要下載的檔案、內容非常大時, 是不是使用者只能傻傻的等待整個傳輸結束後才能顯示? 這樣的使用者體驗也實在太糟糕了, 對於使用者來說除了完全
Thumbnail
我們將探索函式的定義和調用,這是程式設計中非常重要且強大的概念,它可以將大型程式切割成小的、可重複使用的函式。讓我們一起來了解吧!函式的定義、呼叫和返回值是學習函式的核心。
Thumbnail
探索Python學習筆記中列表的建立、存取和常用方法。從使用中括號定義列表到了解索引、新增、刪除、修改等操作,並介紹append、remove、count等常用方法。
Thumbnail
在本篇Python學習筆記中,我們探討了字典的建立與存取,以及常用方法,字典是一種強大的資料型態,透過key和value的對應關係存儲和取得資料,我們學會了建立字典、存取資料、新增/修改/刪除項目,以及取得key和value的方法,字典是Python中不可或缺的工具!
Thumbnail
我們探討了while迴圈的使用,不同於for迴圈,while迴圈以條件式判斷為基礎,而非限定重複次數。我們介紹了使用break語句強制結束迴圈,以及使用continue語句跳過特定程式碼並返回迴圈開頭,同時,我們提及了無窮迴圈的概念,強調了在迴圈中必須更改迴圈變數的值,以避免無窮迴圈的發生。
Thumbnail
經濟是國家的命脈,社稷重點無可厚非,國際情勢不好、經濟危機出現時,國家資源救市,穩定法人、投資人信心,維持正常的金融機轉,讓國家度過危機,👍值得嘉許,只是這次國安基金護盤的故事,讓人百般尋味。 台股去年創下18650破紀錄新高,隨著國際局勢一起回檔,國安基金決定進場護盤: 第一:當時股市萬八,不是