1. ก่อนเริ่มต้น
คุณอาจคิดว่าสถิติรวมไม่ได้รั่วไหลข้อมูลใดๆ เกี่ยวกับบุคคลที่เกี่ยวข้อง อย่างไรก็ตาม ผู้โจมตีสามารถเรียนรู้ข้อมูลที่ละเอียดอ่อนเกี่ยวกับบุคคลจากสถิติรวมได้หลายวิธี
ในโค้ดแล็บนี้ คุณจะได้เรียนรู้วิธีสร้างสถิติส่วนตัวด้วยการรวบรวมข้อมูลแบบ Differential Privacy จาก PipelineDP เพื่อปกป้องความเป็นส่วนตัวของบุคคล PipelineDP เป็นเฟรมเวิร์ก Python ที่ช่วยให้คุณใช้ความเป็นส่วนตัวเชิงอนุพันธ์กับชุดข้อมูลขนาดใหญ่ด้วยระบบการประมวลผลแบบกลุ่ม เช่น Apache Spark และ Apache Beam ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีคำนวณสถิติแบบส่วนตัวเชิงอนุพันธ์ใน Go ได้ที่ Codelab Privacy on Beam
ส่วนตัวหมายความว่าเอาต์พุตจะสร้างขึ้นในลักษณะที่ไม่รั่วไหลข้อมูลส่วนตัวเกี่ยวกับบุคคลในข้อมูล คุณสามารถบรรลุผลลัพธ์นี้ได้ผ่าน Differential Privacy ซึ่งเป็นแนวคิดด้านความเป็นส่วนตัวที่เข้มงวดของการลบข้อมูลระบุตัวบุคคล ซึ่งเป็นกระบวนการรวบรวมข้อมูลของผู้ใช้หลายรายเพื่อปกป้องความเป็นส่วนตัวของผู้ใช้ วิธีการลบข้อมูลระบุตัวบุคคลทั้งหมดใช้การรวบรวม แต่ไม่ใช่ทุกวิธีการรวบรวมที่จะลบข้อมูลระบุตัวบุคคลได้ ในทางกลับกัน ความเป็นส่วนตัวเชิงแตกต่างจะให้การรับประกันที่วัดผลได้เกี่ยวกับการรั่วไหลของข้อมูลและความเป็นส่วนตัว
ข้อกำหนดเบื้องต้น
- คุ้นเคยกับ Python
- มีความคุ้นเคยกับการรวมข้อมูลพื้นฐาน
- มีประสบการณ์ในการใช้ pandas, Spark และ Beam
สิ่งที่คุณจะได้เรียนรู้
- ข้อมูลพื้นฐานเกี่ยวกับ Differential Privacy
- วิธีคำนวณสถิติสรุปแบบส่วนตัวเชิงอนุพันธ์ด้วย PipelineDP
- วิธีปรับแต่งผลการค้นหาด้วยพารามิเตอร์ความเป็นส่วนตัวและยูทิลิตีเพิ่มเติม
สิ่งที่คุณต้องมี
- หากต้องการเรียกใช้โค้ดแล็บในสภาพแวดล้อมของคุณเอง คุณต้องติดตั้ง Python 3.7 ขึ้นไปในคอมพิวเตอร์
- หากต้องการทำตาม Codelab โดยไม่มีสภาพแวดล้อมของคุณเอง คุณต้องมีสิทธิ์เข้าถึง Colaboratory
2. ทำความเข้าใจ Differential Privacy
หากต้องการทำความเข้าใจความเป็นส่วนตัวเชิงแตกต่างให้ดียิ่งขึ้น ให้ดูตัวอย่างง่ายๆ นี้
ลองนึกภาพว่าคุณทำงานในแผนกการตลาดของผู้ค้าปลีกแฟชั่นออนไลน์ และต้องการทราบว่าผลิตภัณฑ์ใดมีแนวโน้มที่จะขายได้มากที่สุด
แผนภูมินี้แสดงผลิตภัณฑ์ที่ลูกค้าดูเป็นอันดับแรกเมื่อเข้าชมเว็บไซต์ของร้านค้า ได้แก่ เสื้อยืด เสื้อจัมเปอร์ ถุงเท้า หรือกางเกงยีนส์ เสื้อยืดเป็นสินค้ายอดนิยมมากที่สุด ในขณะที่ถุงเท้าเป็นสินค้ายอดนิยมน้อยที่สุด

ดูเหมือนว่าจะมีประโยชน์ แต่ก็มีข้อควรระวัง เมื่อต้องการพิจารณาข้อมูลเพิ่มเติม เช่น ลูกค้าทำการซื้อหรือไม่ หรือผลิตภัณฑ์ใดที่ลูกค้าดูเป็นอันดับที่ 2 คุณก็เสี่ยงที่จะเปิดเผยข้อมูลส่วนบุคคลในข้อมูล
แผนภูมินี้แสดงให้เห็นว่ามีลูกค้าเพียงรายเดียวเท่านั้นที่ดูจัมเปอร์ก่อน แล้วจึงทำการซื้อจริง

ซึ่งไม่ดีนักในมุมมองด้านความเป็นส่วนตัว สถิติที่ลบข้อมูลระบุตัวบุคคลออกไม่ควรเปิดเผยการมีส่วนร่วมของแต่ละบุคคล คุณจึงควรทำดังนี้ คุณเพิ่มสัญญาณรบกวนแบบสุ่มลงในแผนภูมิแท่งเพื่อให้มีความแม่นยำน้อยลงเล็กน้อย
แผนภูมิแท่งนี้อาจไม่แม่นยำนัก แต่ก็ยังมีประโยชน์และไม่ได้แสดงผลงานของแต่ละบุคคล

Differential Privacy คือการเพิ่มสัญญาณรบกวนแบบสุ่มในปริมาณที่เหมาะสมเพื่อปกปิดข้อมูลที่แต่ละคนมีส่วนร่วม
ตัวอย่างนี้เป็นเพียงการอธิบายแบบง่ายๆ การติดตั้งใช้งานความเป็นส่วนตัวเชิงอนุพันธ์อย่างเหมาะสมนั้นมีความซับซ้อนมากขึ้นและมาพร้อมกับความละเอียดในการติดตั้งใช้งานที่ไม่คาดคิดหลายประการ เช่นเดียวกับการเข้ารหัส การสร้างการใช้งานความเป็นส่วนตัวเชิงแตกต่างของคุณเองอาจไม่ใช่ความคิดที่ดี แต่คุณสามารถใช้ PipelineDP แทนได้
3. ดาวน์โหลดและติดตั้ง PipelineDP
คุณไม่จำเป็นต้องติดตั้ง PipelineDP เพื่อทำตาม Codelab นี้ เนื่องจากคุณจะเห็นโค้ดและกราฟที่เกี่ยวข้องทั้งหมดในเอกสารนี้
หากต้องการเล่นด้วย PipelineDP, เรียกใช้ด้วยตนเอง หรือใช้ในภายหลัง ให้ทำดังนี้
- ดาวน์โหลดและติดตั้ง PipelineDP โดยทำดังนี้
pip install pipeline-dp
หากต้องการเรียกใช้ตัวอย่างโดยใช้ Apache Beam ให้ทำดังนี้
- ดาวน์โหลดและติดตั้ง Apache Beam โดยทำดังนี้
pip install apache_beam
คุณดูโค้ดสำหรับ Codelab นี้และชุดข้อมูลได้ในPipelineDP/examples/codelab/ไดเรกทอรี
4. คำนวณเมตริก Conversion ต่อผลิตภัณฑ์แรกที่ดู
สมมติว่าคุณทำงานที่ร้านค้าปลีกแฟชั่นออนไลน์ และต้องการทราบว่าหมวดหมู่ผลิตภัณฑ์ใดที่สร้างจำนวนและมูลค่า Conversion สูงสุดเมื่อดูเป็นครั้งแรก คุณต้องการแชร์ข้อมูลนี้กับเอเจนซีการตลาดและทีมภายในอื่นๆ แต่ต้องการป้องกันการรั่วไหลของข้อมูลเกี่ยวกับลูกค้าแต่ละราย
วิธีคํานวณเมตริก Conversion ต่อผลิตภัณฑ์แรกที่ดูสําหรับเว็บไซต์
- ตรวจสอบชุดข้อมูลจำลองของการเข้าชมเว็บไซต์ในไดเรกทอรี
PipelineDP/examples/codelab/
ภาพหน้าจอนี้เป็นตัวอย่างของชุดข้อมูล ซึ่งประกอบด้วยรหัสของผู้ใช้ ผลิตภัณฑ์ที่ผู้ใช้ดู ผู้เข้าชมทํา Conversion หรือไม่ และหากทํา Conversion มูลค่าของ Conversion นั้นคือเท่าใด
user_id | product_view_0 | product_view_1 | product_view_2 | product_view_3 | product_view_4 | has_conversion | conversion_value |
0 | กางเกงยีนส์ | t_shirt | t_shirt | ไม่มี | ไม่มี | เท็จ | 0.0 |
1 | กางเกงยีนส์ | t_shirt | กางเกงยีนส์ | จัมเปอร์ | ไม่มี | เท็จ | 0.0 |
2 | t_shirt | จัมเปอร์ | t_shirt | t_shirt | ไม่มี | จริง | 105.19 |
3 | t_shirt | t_shirt | กางเกงยีนส์ | ไม่มี | ไม่มี | เท็จ | 0.0 |
4 | t_shirt | ถุงเท้า | กางเกงยีนส์ | กางเกงยีนส์ | ไม่มี | เท็จ | 0.0 |
คุณสนใจเมตริกต่อไปนี้
view_counts: จำนวนครั้งที่ผู้เข้าชมเว็บไซต์เห็นผลิตภัณฑ์แต่ละรายการเป็นครั้งแรกtotal_conversion_value: จำนวนเงินทั้งหมดที่ผู้เข้าชมใช้จ่ายเมื่อทำ Conversionconversion_rate: อัตราที่ผู้เข้าชมทำ Conversion
- สร้างเมตริกในลักษณะที่ไม่ใช่แบบส่วนตัว
conversion_metrics = df.groupby(['product_view_0'
])[['conversion_value', 'has_conversion']].agg({
'conversion_value': [len, np.sum],
'has_conversion': np.mean
})
conversion_metrics = conversion_metrics.rename(
columns={
'len': 'view_counts',
'sum': 'total_conversion_value',
'mean': 'conversion_rate'
}).droplevel(
0, axis=1)
ดังที่ได้ทราบไปก่อนหน้านี้ สถิติเหล่านี้อาจเปิดเผยข้อมูลเกี่ยวกับบุคคลในชุดข้อมูลของคุณ เช่น มีผู้ทำ Conversion เพียง 1 รายหลังจากที่เห็นจัมเปอร์ก่อน สำหรับการดู 22 ครั้ง อัตรา Conversion จะอยู่ที่ประมาณ 0.05 ตอนนี้คุณต้องเปลี่ยนแผนภูมิแท่งแต่ละรายการให้เป็นแบบส่วนตัว
- กำหนดพารามิเตอร์ความเป็นส่วนตัวด้วยคลาส
pipeline_dp.NaiveBudgetAccountantจากนั้นระบุอาร์กิวเมนต์epsilonและdeltaที่ต้องการใช้ในการวิเคราะห์
วิธีตั้งค่าอาร์กิวเมนต์เหล่านี้ขึ้นอยู่กับปัญหาเฉพาะของคุณ ดูข้อมูลเพิ่มเติมได้ที่ ไม่บังคับ: ปรับแต่งพารามิเตอร์ความเป็นส่วนตัวเชิงอนุพันธ์
ข้อมูลโค้ดนี้ใช้ค่าตัวอย่าง
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
total_epsilon=1, total_delta=1e-5)
- เริ่มต้นอินสแตนซ์
LocalBackend
ops = pipeline_dp.LocalBackend()
คุณใช้อินสแตนซ์ LocalBackend ได้เนื่องจากคุณเรียกใช้โปรแกรมนี้ในเครื่องโดยไม่ต้องใช้เฟรมเวิร์กเพิ่มเติม เช่น Beam หรือ Spark
- เริ่มต้นอินสแตนซ์
DPEngine
dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)
PipelineDP ช่วยให้คุณระบุพารามิเตอร์เพิ่มเติมผ่านคลาส pipeline_dp.AggregateParams ซึ่งส่งผลต่อการสร้างสถิติส่วนตัว
params = pipeline_dp.AggregateParams(
noise_kind=pipeline_dp.NoiseKind.LAPLACE,
metrics=[pipeline_dp.Metrics.COUNT],
max_partitions_contributed=1,
max_contributions_per_partition=1)
- ระบุว่าคุณต้องการคำนวณเมตริก
countและใช้การกระจายสัญญาณรบกวนLAPLACE - ตั้งค่าอาร์กิวเมนต์
max_partitions_contributedเป็นค่า1
อาร์กิวเมนต์นี้จะจำกัดจำนวนการเข้าชมที่แตกต่างกันซึ่งผู้ใช้สามารถมีส่วนร่วมได้ คุณคาดหวังให้ผู้ใช้เข้าชมเว็บไซต์วันละครั้ง และไม่สนใจว่าผู้ใช้จะเข้าชมหลายครั้งตลอดทั้งวันหรือไม่
- ตั้งค่าอาร์กิวเมนต์
max_contributions_per_partitionsเป็นค่า1
อาร์กิวเมนต์นี้ระบุจำนวนการมีส่วนร่วมที่ผู้เข้าชมรายเดียวสามารถทำได้ในพาร์ติชันแต่ละรายการหรือหมวดหมู่ผลิตภัณฑ์ในกรณีนี้
- สร้างอินสแตนซ์
data_extractorที่ระบุตำแหน่งของช่องprivacy_id,partitionและvalue
โค้ดควรมีลักษณะเหมือนข้อมูลโค้ดต่อไปนี้
def run_pipeline(data, ops):
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
total_epsilon=1, total_delta=1e-5)
dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)
params = pipeline_dp.AggregateParams(
noise_kind=pipeline_dp.NoiseKind.LAPLACE,
metrics=[pipeline_dp.Metrics.COUNT],
max_partitions_contributed=1, # A single user can only contribute to one partition.
max_contributions_per_partition=1, # For a single partition, only one contribution per user is used.
)
data_extractors = pipeline_dp.DataExtractors(
privacy_id_extractor=lambda row: row.user_id,
partition_extractor=lambda row: row.product_view_0
value_extractor=lambda row: row.has_conversion)
dp_result = dp_engine.aggregate(data, params, data_extractors)
budget_accountant.compute_budgets()
return dp_result
- เพิ่มโค้ดนี้เพื่อเปลี่ยน Pandas DataFrame เป็นรายการแถวที่คุณสามารถคำนวณสถิติแบบส่วนตัวเชิงแตกต่างได้โดยตรง
rows = [index_row[1] for index_row in df.iterrows()]
dp_result_local = run_pipeline(rows, ops) # Returns generator
list(dp_result_local)
ยินดีด้วย คุณได้คำนวณสถิติแรกที่ใช้ความเป็นส่วนตัวเชิงอนุพันธ์แล้ว
แผนภูมินี้แสดงผลลัพธ์ของจำนวนแบบส่วนตัวเชิงอนุพันธ์ข้างจำนวนที่ไม่ใช่แบบส่วนตัวที่คุณคำนวณไว้ก่อนหน้านี้

แผนภูมิแท่งที่คุณได้รับเมื่อเรียกใช้โค้ดอาจแตกต่างจากแผนภูมินี้ ซึ่งถือเป็นเรื่องปกติ เนื่องจากความผันผวนในความเป็นส่วนตัวเชิงอนุพันธ์ คุณจะได้รับแผนภูมิแท่งที่แตกต่างกันทุกครั้งที่เรียกใช้โค้ด แต่จะเห็นว่าแผนภูมิแท่งเหล่านั้นคล้ายกับแผนภูมิแท่งเดิมที่ไม่มีการใช้ความเป็นส่วนตัว
โปรดทราบว่าการไม่เรียกใช้ไปป์ไลน์หลายครั้งเพื่อรับประกันความเป็นส่วนตัวเป็นสิ่งสำคัญอย่างยิ่ง ดูข้อมูลเพิ่มเติมได้ที่คำนวณสถิติหลายรายการ
5. ใช้พาร์ติชันสาธารณะ
ในส่วนก่อนหน้า คุณอาจสังเกตเห็นว่าคุณทิ้งข้อมูลการเข้าชมทั้งหมดสำหรับพาร์ติชัน ซึ่งก็คือผู้เข้าชมที่เห็นถุงเท้าในเว็บไซต์เป็นครั้งแรก
ซึ่งเป็นผลมาจากการเลือกพาร์ติชันหรือการกำหนดเกณฑ์ ซึ่งเป็นขั้นตอนสำคัญในการรับประกันความเป็นส่วนตัวเชิงแตกต่างเมื่อการมีอยู่ของพาร์ติชันเอาต์พุตขึ้นอยู่กับข้อมูลผู้ใช้เอง ในกรณีนี้ การมีพาร์ติชันในเอาต์พุตอาจทำให้ข้อมูลของผู้ใช้แต่ละรายรั่วไหลได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับสาเหตุที่การกระทำนี้ละเมิดความเป็นส่วนตัวได้ที่บล็อกโพสต์นี้ PipelineDP จะเก็บเฉพาะพาร์ติชันที่มีผู้ใช้จำนวนเพียงพอไว้เพื่อป้องกันการละเมิดความเป็นส่วนตัวนี้
เมื่อรายการพาร์ติชันเอาต์พุตไม่ได้ขึ้นอยู่กับข้อมูลส่วนตัวของผู้ใช้ คุณก็ไม่จำเป็นต้องทำขั้นตอนการเลือกพาร์ติชันนี้ ซึ่งเป็นกรณีตัวอย่างของคุณเนื่องจากคุณทราบหมวดหมู่ผลิตภัณฑ์ที่เป็นไปได้ทั้งหมดที่ลูกค้าอาจเห็นเป็นอันดับแรก
วิธีใช้พาร์ติชัน
- สร้างรายการพาร์ติชันที่เป็นไปได้
public_partitions_products = ['jeans', 'jumper', 'socks', 't-shirt']
- ส่งรายการไปยังฟังก์ชัน
run_pipeline()ซึ่งจะตั้งค่าเป็นอินพุตเพิ่มเติมให้กับคลาสpipeline_dp.AggregateParamsดังนี้
run_pipeline(
rows, ops, total_delta=0, public_partitions=public_partitions_products)
# Returns generator
params = pipeline_dp.AggregateParams(
noise_kind=pipeline_dp.NoiseKind.LAPLACE,
metrics=[pipeline_dp.Metrics.COUNT],
max_partitions_contributed=1,
max_contributions_per_partition=1,
public_partitions=public_partitions_products)
หากคุณใช้พาร์ติชันสาธารณะและเสียงรบกวน LAPLACE คุณจะตั้งค่าอาร์กิวเมนต์ total_delta เป็นค่า 0 ได้
ตอนนี้คุณจะเห็นในผลลัพธ์ว่าระบบรายงานข้อมูลสำหรับพาร์ติชันหรือผลิตภัณฑ์ทั้งหมด

พาร์ติชันสาธารณะไม่เพียงช่วยให้คุณเก็บพาร์ติชันได้มากขึ้น แต่ยังเพิ่มสัญญาณรบกวนประมาณครึ่งหนึ่งด้วย เนื่องจากคุณไม่ต้องใช้งบประมาณด้านความเป็นส่วนตัวในการเลือกพาร์ติชัน ความแตกต่างระหว่างจำนวนดิบกับจำนวนส่วนตัวจึงน้อยกว่าการเรียกใช้ครั้งก่อนเล็กน้อย
เมื่อใช้พาร์ติชันสาธารณะ คุณควรคำนึงถึงสิ่งสำคัญ 2 ประการต่อไปนี้
- โปรดระมัดระวังเมื่อได้รายการพาร์ติชันจากข้อมูลดิบ หากไม่ดำเนินการในลักษณะที่รักษาความเป็นส่วนตัวแบบ Differential Privacy ไปป์ไลน์จะไม่รับประกัน Differential Privacy อีกต่อไป ดูข้อมูลเพิ่มเติมได้ที่ขั้นสูง: สร้างพาร์ติชันจากข้อมูล
- หากไม่มีข้อมูลสำหรับพาร์ติชันสาธารณะบางส่วน คุณต้องใช้ Noise กับพาร์ติชันเหล่านั้นเพื่อรักษาความเป็นส่วนตัวเชิงแตกต่าง เช่น หากคุณใช้ผลิตภัณฑ์เพิ่มเติมอย่างกางเกง ซึ่งไม่ได้อยู่ในชุดข้อมูลหรือบนเว็บไซต์ ก็ยังถือเป็นสัญญาณรบกวน และผลลัพธ์อาจแสดงการเข้าชมผลิตภัณฑ์บางอย่างเมื่อไม่มีการเข้าชม
ขั้นสูง: สร้างพาร์ติชันจากข้อมูล
หากเรียกใช้การรวมหลายรายการที่มีรายการพาร์ติชันเอาต์พุตที่ไม่ใช่แบบสาธารณะเดียวกันในไปป์ไลน์เดียวกัน คุณสามารถรับรายการพาร์ติชันได้ครั้งเดียวด้วยวิธี dp_engine.select_private_partitions() และระบุพาร์ติชันให้กับการรวมแต่ละรายการเป็นอินพุต public_partitions วิธีนี้ไม่เพียงปลอดภัยในมุมมองด้านความเป็นส่วนตัว แต่ยังช่วยให้คุณลดสัญญาณรบกวนได้ด้วย เนื่องจากคุณจะใช้งบประมาณด้านความเป็นส่วนตัวในการเลือกพาร์ติชันเพียงครั้งเดียวสำหรับทั้งไปป์ไลน์
def get_private_product_views(data, ops):
"""Obtains the list of product_views in a private manner.
This does not calculate any private metrics; it merely obtains the list of
product_views but does so while making sure the result is differentially private.
"""
# Set the total privacy budget.
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
total_epsilon=1, total_delta=1e-5)
# Create a DPEngine instance.
dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)
# Specify how to extract privacy_id, partition_key, and value from a
# single element.
data_extractors = pipeline_dp.DataExtractors(
partition_extractor=lambda row: row.product_view_0,
privacy_id_extractor=lambda row: row.user_id)
# Run aggregation.
dp_result = dp_engine.select_partitions(
data, pipeline_dp.SelectPrivatePartitionsParams(
max_partitions_contributed=1),
data_extractors=data_extractors)
budget_accountant.compute_budgets()
return dp_result
6. คำนวณสถิติหลายรายการ
เมื่อทราบวิธีการทำงานของ PipelineDP แล้ว คุณจะเห็นวิธีใช้สำหรับกรณีการใช้งานขั้นสูงขึ้น ดังที่กล่าวไว้ตอนต้น คุณสนใจสถิติ 3 รายการ PipelineDP ช่วยให้คุณคำนวณสถิติหลายรายการได้พร้อมกันตราบใดที่สถิติดังกล่าวใช้พารามิเตอร์เดียวกันในAggregateParamsอินสแตนซ์ ซึ่งคุณจะเห็นในภายหลัง ไม่เพียงแต่จะสะอาดตาและคำนวณเมตริกหลายรายการได้ง่ายขึ้นในคราวเดียว แต่ยังดีกว่าในแง่ของความเป็นส่วนตัวด้วย
หากคุณจำพารามิเตอร์ epsilon และ delta ที่คุณระบุให้กับคลาส NaiveBudgetAccountant ได้ พารามิเตอร์ดังกล่าวจะแสดงถึงสิ่งที่เรียกว่างบประมาณความเป็นส่วนตัว ซึ่งเป็นตัววัดปริมาณความเป็นส่วนตัวของผู้ใช้ที่คุณรั่วไหลจากข้อมูล
สิ่งสำคัญที่ควรทราบเกี่ยวกับงบประมาณความเป็นส่วนตัวคือเป็นงบประมาณที่เพิ่มขึ้น หากเรียกใช้ไปป์ไลน์ที่มีค่า epsilon ε และ delta δ ที่เฉพาะเจาะจงเพียงครั้งเดียว คุณจะใช้งบประมาณ (ε,δ) หากเรียกใช้เป็นครั้งที่ 2 คุณจะใช้งบประมาณทั้งหมด (2ε, 2δ) ในทำนองเดียวกัน หากคุณคำนวณสถิติหลายรายการด้วยNaiveBudgetAccountantวิธีและมีงบประมาณความเป็นส่วนตัว ε,δ ติดต่อกัน คุณจะใช้งบประมาณทั้งหมด (2ε, 2δ) ซึ่งหมายความว่าคุณจะลดระดับการรับประกันความเป็นส่วนตัว
หากต้องการหลีกเลี่ยงปัญหานี้ คุณต้องใช้NaiveBudgetAccountantอินสแตนซ์เดียวที่มีงบประมาณรวมที่คุณต้องการใช้เมื่อต้องคำนวณสถิติหลายรายการในข้อมูลเดียวกัน จากนั้นคุณต้องระบุค่า epsilon และ delta ที่ต้องการใช้สำหรับการรวบรวมแต่ละรายการ ท้ายที่สุดแล้ว คุณจะได้รับการรับประกันความเป็นส่วนตัวโดยรวมเหมือนเดิม แต่ยิ่งการรวบรวมข้อมูลหนึ่งๆ มีค่า epsilon และ delta สูงเท่าใด ความแม่นยำก็จะยิ่งสูงขึ้นเท่านั้น
หากต้องการดูการทำงานจริง คุณสามารถคำนวณสถิติ count, mean และ sum ได้
คุณคํานวณสถิติโดยอิงตามเมตริก 2 รายการที่แตกต่างกัน ได้แก่ เมตริก conversion_value ซึ่งคุณใช้เพื่ออนุมานจํานวนรายได้ที่สร้างขึ้นโดยอิงตามผลิตภัณฑ์ที่ดูเป็นอันดับแรก และเมตริก has_conversion ซึ่งคุณใช้เพื่อคํานวณจํานวนผู้เข้าชมเว็บไซต์และอัตรา Conversion เฉลี่ย
สําหรับเมตริกแต่ละรายการ คุณต้องระบุพารามิเตอร์ที่แนะนําการคํานวณสถิติส่วนตัวแยกกัน คุณแบ่งงบประมาณความเป็นส่วนตัวระหว่างเมตริกทั้ง 2 รายการ คุณคำนวณสถิติ 2 รายการจากเมตริก has_conversion จึงต้องการจัดสรรงบประมาณเริ่มต้น 2 ใน 3 ให้กับเมตริกนี้ และจัดสรรอีก 1 ใน 3 ให้กับเมตริก conversion_value
วิธีคำนวณสถิติหลายรายการ
- ตั้งค่าผู้ดูแลบัญชีงบประมาณความเป็นส่วนตัวด้วยค่า
epsilonและdeltaทั้งหมดที่คุณต้องการใช้ในสถิติทั้ง 3 รายการ
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
total_epsilon=1, total_delta=0)
- เริ่มต้น
DPEngineเพื่อคำนวณเมตริก
dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)
- ระบุพารามิเตอร์สําหรับเมตริกนี้
params_conversion_value_metrics = pipeline_dp.AggregateParams(
noise_kind=pipeline_dp.NoiseKind.LAPLACE,
metrics=[pipeline_dp.Metrics.SUM],
max_partitions_contributed=1,
max_contributions_per_partition=1,
min_value=0,
max_value=100,
public_partitions=public_partitions,
budget_weight=1/3)
อาร์กิวเมนต์สุดท้ายจะระบุน้ำหนักของงบประมาณความเป็นส่วนตัวโดยไม่บังคับ คุณอาจกำหนดน้ำหนักเท่ากันให้กับทุกรายการ แต่คุณต้องการตั้งค่าอาร์กิวเมนต์นี้เป็น 1 ใน 3 ตามที่อธิบายไว้ก่อนหน้านี้
นอกจากนี้ คุณยังตั้งค่าอาร์กิวเมนต์ min_value และ max_value เพื่อระบุขอบเขตล่างและขอบเขตบนที่ใช้กับค่าที่หน่วยความเป็นส่วนตัวในพาร์ติชันมีส่วนร่วมได้ด้วย พารามิเตอร์เหล่านี้จำเป็นเมื่อคุณต้องการคำนวณผลรวมหรือค่าเฉลี่ยแบบส่วนตัว คุณไม่คาดหวังค่าลบ ดังนั้นจึงถือว่า 0 และ 100 เป็นขอบเขตที่สมเหตุสมผล
- ดึงข้อมูลที่เกี่ยวข้อง แล้วส่งไปยังฟังก์ชันการรวม
data_extractors_conversion_value_metrics = pipeline_dp.DataExtractors(
privacy_id_extractor=lambda row: row.user_id,
partition_extractor=lambda row: row.product_view_0,
value_extractor=lambda row: row.conversion_value)
dp_result_conversion_value_metrics = (
dp_engine.aggregate(data, params_conversion_value_metrics,
data_extractors_conversion_value_metrics))
- ทำตามขั้นตอนเดียวกันเพื่อคำนวณเมตริกทั้ง 2 รายการโดยอิงตามตัวแปร
has_conversion
params_conversion_rate_metrics = pipeline_dp.AggregateParams(
noise_kind=pipeline_dp.NoiseKind.LAPLACE,
metrics=[pipeline_dp.Metrics.COUNT, pipeline_dp.Metrics.MEAN],
max_partitions_contributed=1,
max_contributions_per_partition=1,
min_value=0,
max_value=1,
public_partitions=public_partitions,
budget_weight=2/3)
data_extractors_conversion_rate_metrics = pipeline_dp.DataExtractors(
privacy_id_extractor=lambda row: row.user_id,
partition_extractor=lambda row: row.product_view_0,
value_extractor=lambda row: row.has_conversion)
dp_result_conversion_rate_metrics = (
dp_engine.aggregate(data, params_conversion_rate_metrics,
data_extractors_conversion_rate_metrics))
การเปลี่ยนแปลงเพียงอย่างเดียวคือในอินสแตนซ์ pipeline_dp.AggregateParams ซึ่งตอนนี้คุณกำหนด mean และ count เป็นการรวบรวม และกำหนดงบประมาณส่วนตัว 2 ใน 3 ให้กับการคำนวณนี้ เนื่องจากคุณต้องการให้ขอบเขตการมีส่วนร่วมเหมือนกันทั้งสถิติและคำนวณสถิติเหล่านั้นบนตัวแปร has_conversion เดียวกัน คุณจึงรวมสถิติเหล่านั้นไว้ในอินสแตนซ์ pipeline_dp.AggregateParams เดียวกันและคำนวณพร้อมกันได้
- เรียกใช้เมธอด
budget_accountant.compute_budgets()ดังนี้
budget_accountant.compute_budgets()
คุณสามารถพล็อตสถิติส่วนตัวทั้ง 3 รายการเพื่อเปรียบเทียบกับสถิติเดิมได้ คุณจะเห็นว่าผลลัพธ์อาจอยู่นอกเหนือช่วงที่สมเหตุสมผลได้จริง ทั้งนี้ขึ้นอยู่กับสัญญาณรบกวนที่เพิ่มเข้ามา ในกรณีนี้ คุณจะเห็นอัตรา Conversion และมูลค่า Conversion รวมที่เป็นลบสำหรับผู้ที่เปลี่ยนเส้นทาง เนื่องจากสัญญาณรบกวนที่เพิ่มเข้ามานั้นสมมาตรกันรอบๆ ศูนย์ สำหรับการวิเคราะห์และการประมวลผลเพิ่มเติม ทางที่ดีไม่ควรประมวลผลสถิติส่วนตัวด้วยตนเอง แต่หากต้องการเพิ่มพล็อตเหล่านั้นลงในรายงาน คุณก็สามารถตั้งค่าขั้นต่ำเป็น 0 ได้ในภายหลังโดยไม่ละเมิดการรับประกันความเป็นส่วนตัว

7. เรียกใช้ไปป์ไลน์ด้วย Beam
การประมวลผลข้อมูลในปัจจุบันกำหนดให้คุณต้องจัดการกับข้อมูลจำนวนมหาศาลจนไม่สามารถประมวลผลในเครื่องได้ แต่ผู้คนจำนวนมากใช้เฟรมเวิร์กสำหรับการประมวลผลข้อมูลขนาดใหญ่ เช่น Beam หรือ Spark และเรียกใช้ไปป์ไลน์ในระบบคลาวด์
PipelineDP รองรับ Beam และ Spark โดยคุณจะต้องเปลี่ยนแปลงโค้ดเพียงเล็กน้อยเท่านั้น
หากต้องการเรียกใช้ไปป์ไลน์ด้วย Beam โดยใช้ private_beam API ให้ทำดังนี้
- เริ่มต้นตัวแปร
runnerแล้วสร้างไปป์ไลน์ที่คุณใช้การดำเนินการด้านความเป็นส่วนตัวกับตัวแทน Beam ของrows
runner = fn_api_runner.FnApiRunner() # local runner
with beam.Pipeline(runner=runner) as pipeline:
beam_data = pipeline | beam.Create(rows)
- สร้าง
budget_accountantตัวแปรที่มีพารามิเตอร์ความเป็นส่วนตัวที่จำเป็น
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
total_epsilon=1, total_delta=0)
- สร้างตัวแปร
pcolหรือคอลเล็กชันส่วนตัว ซึ่งรับประกันว่าการรวบรวมข้อมูลใดๆ จะเป็นไปตามข้อกำหนดด้านความเป็นส่วนตัวของคุณ
pcol = beam_data | pbeam.MakePrivate(
budget_accountant=budget_accountant,
privacy_id_extractor=lambda
row: row.user_id)
- ระบุพารามิเตอร์ของการรวบรวมข้อมูลแบบส่วนตัวในคลาสที่เหมาะสม
ในที่นี้ คุณใช้คลาส pipeline_dp.aggregate_params.SumParams() เนื่องจากคุณคำนวณผลรวมของการดูผลิตภัณฑ์
- ส่งพารามิเตอร์การรวมไปยังเมธอด
pbeam.Sumเพื่อคำนวณสถิติ
dp_result = pcol | pbeam.Sum(params)
- สุดท้ายแล้ว โค้ดของคุณควรมีลักษณะเหมือนข้อมูลโค้ดนี้
import pipeline_dp.private_beam as pbeam
runner = fn_api_runner.FnApiRunner() # local runner
with beam.Pipeline(runner=runner) as pipeline:
beam_data = pipeline | beam.Create(rows)
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
total_epsilon=1, total_delta=0)
# Create private collection.
pcol = beam_data | pbeam.MakePrivate(
budget_accountant=budget_accountant,
privacy_id_extractor=lambda row:
row.user_id)
# Specify parameters.
params = pipeline_dp.aggregate_params.SumParams(
noise_kind=pipeline_dp.NoiseKind.LAPLACE,
max_partitions_contributed=1,
max_contributions_per_partition=1,
min_value=0,
max_value=100,
public_partitions=public_partitions_product_views,
partition_extractor=lambda row: row.product_view_0,
value_extractor=lambda row:row.conversion_value)
dp_result = pcol | pbeam.Sum(params)
budget_accountant.compute_budgets()
dp_result | beam.Map(print)
8. ไม่บังคับ: ปรับแต่งพารามิเตอร์ความเป็นส่วนตัวและยูทิลิตี
คุณได้เห็นพารามิเตอร์หลายรายการที่กล่าวถึงในโค้ดแล็บนี้ เช่น พารามิเตอร์ epsilon, delta และ max_partitions_contributed คุณแบ่งพารามิเตอร์ออกเป็น 2 หมวดหมู่ได้คร่าวๆ ได้แก่ พารามิเตอร์ความเป็นส่วนตัวและพารามิเตอร์ยูทิลิตี
พารามิเตอร์ความเป็นส่วนตัว
พารามิเตอร์ epsilon และ delta จะวัดความเป็นส่วนตัวที่คุณให้ด้วยความเป็นส่วนตัวแบบแตกต่าง กล่าวอย่างเจาะจงคือ ค่าเหล่านี้เป็นตัววัดปริมาณข้อมูลที่ผู้โจมตีที่อาจเกิดขึ้นสามารถได้รับเกี่ยวกับข้อมูลจากเอาต์พุตที่ไม่ระบุตัวบุคคล ยิ่งค่าของพารามิเตอร์สูงเท่าใด ผู้โจมตีก็จะได้รับข้อมูลเกี่ยวกับข้อมูลมากขึ้นเท่านั้น ซึ่งเป็นความเสี่ยงด้านความเป็นส่วนตัว ในทางกลับกัน ยิ่งค่าพารามิเตอร์ epsilon และ delta ต่ำเท่าใด คุณก็ยิ่งต้องเพิ่มสัญญาณรบกวนลงในเอาต์พุตเพื่อให้เป็นแบบไม่ระบุตัวตน และยิ่งต้องมีจำนวนผู้ใช้ที่ไม่ซ้ำกันมากขึ้นในแต่ละพาร์ติชันเพื่อให้ผู้ใช้เหล่านั้นอยู่ในเอาต์พุตที่ผ่านการปกปิดข้อมูล ในกรณีนี้ จะต้องเลือกระหว่างยูทิลิตีและความเป็นส่วนตัว
ใน PipelineDP คุณต้องระบุการรับประกันความเป็นส่วนตัวที่ต้องการของเอาต์พุตที่ลบข้อมูลระบุตัวบุคคลออกเมื่อตั้งค่า Privacy Budget ทั้งหมดในอินสแตนซ์ NaiveBudgetAccountant ข้อควรระวังคือหากต้องการให้การรับประกันความเป็นส่วนตัวมีผล คุณต้องใช้NaiveBudgetAccountantอินสแตนซ์แยกต่างหากอย่างระมัดระวังสำหรับการรวมแต่ละครั้ง หรือเรียกใช้ไปป์ไลน์หลายครั้งเพื่อหลีกเลี่ยงการใช้งบประมาณมากเกินไป
ดูข้อมูลเพิ่มเติมเกี่ยวกับความเป็นส่วนตัวเชิงอนุพันธ์และความหมายของพารามิเตอร์ความเป็นส่วนตัวได้ที่รายการอ่านเกี่ยวกับความเป็นส่วนตัวเชิงอนุพันธ์
พารามิเตอร์ยูทิลิตี
พารามิเตอร์ยูทิลิตีจะไม่ส่งผลต่อการรับประกันความเป็นส่วนตัว แต่จะส่งผลต่อความแม่นยำและยูทิลิตีของเอาต์พุต โดยจะระบุไว้ในอินสแตนซ์ AggregateParams และใช้เพื่อปรับขนาดสัญญาณรบกวนที่เพิ่ม
พารามิเตอร์ยูทิลิตีที่ระบุในอินสแตนซ์ AggregateParams และใช้ได้กับการรวมทั้งหมดคือพารามิเตอร์ max_partitions_contributed พาร์ติชันสอดคล้องกับคีย์ของข้อมูลที่การดำเนินการรวบรวม PipelineDP ส่งคืน ดังนั้นพารามิเตอร์ max_partitions_contributed จะจำกัดจำนวนค่าคีย์ที่ไม่ซ้ำกันที่ผู้ใช้สามารถมีส่วนร่วมในเอาต์พุตได้ หากผู้ใช้มีส่วนร่วมในคีย์จํานวนมากเกินค่าของพารามิเตอร์ max_partitions_contributed ระบบจะทิ้งการมีส่วนร่วมบางอย่างเพื่อให้ผู้ใช้มีส่วนร่วมในค่าที่แน่นอนของพารามิเตอร์ max_partitions_contributed
ในทำนองเดียวกัน การรวมส่วนใหญ่จะมีพารามิเตอร์ max_contributions_per_partition นอกจากนี้ ยังมีให้ใช้งานในอินสแตนซ์ AggregateParams และการรวบรวมแต่ละรายการอาจมีค่าแยกต่างหากสำหรับแอตทริบิวต์เหล่านี้ โดยจะจำกัดการมีส่วนร่วมของผู้ใช้สำหรับแต่ละคีย์
ระบบจะปรับขนาดสัญญาณรบกวนที่เพิ่มลงในเอาต์พุตตามพารามิเตอร์ max_partitions_contributed และ max_contributions_per_partition ดังนั้นจึงต้องมีการแลกเปลี่ยนกันในที่นี้ กล่าวคือ ค่าที่ใหญ่ขึ้นซึ่งกำหนดให้กับพารามิเตอร์แต่ละรายการหมายความว่าคุณจะเก็บข้อมูลได้มากขึ้น แต่ผลลัพธ์จะมีสัญญาณรบกวนมากขึ้น
การรวมบางอย่างต้องมีพารามิเตอร์ min_value และ max_value ซึ่งระบุขอบเขตสำหรับการมีส่วนร่วมของผู้ใช้แต่ละราย หากผู้ใช้มีส่วนร่วมด้วยมูลค่าที่ต่ำกว่ามูลค่าที่กำหนดให้กับพารามิเตอร์ min_value ระบบจะเพิ่มมูลค่าเป็นมูลค่าของพารามิเตอร์ ในทํานองเดียวกัน หากผู้ใช้มีส่วนร่วมด้วยค่าที่มากกว่าค่าของพารามิเตอร์ max_value ระบบจะลดค่าดังกล่าวให้เท่ากับค่าของพารามิเตอร์ หากต้องการเก็บค่าเดิมไว้มากขึ้น คุณต้องระบุขอบเขตที่ใหญ่ขึ้น ระบบจะปรับขนาดสัญญาณรบกวนตามขนาดขอบเขต ดังนั้นขอบเขตที่ใหญ่ขึ้นจะช่วยให้คุณเก็บข้อมูลได้มากขึ้น แต่ผลลัพธ์ที่ได้จะมีสัญญาณรบกวนมากขึ้น
สุดท้าย พารามิเตอร์ noise_kind รองรับกลไกการเพิ่มสัญญาณรบกวน 2 แบบใน PipelineDP ได้แก่ สัญญาณรบกวน GAUSSIAN และ LAPLACE LAPLACE การกระจายจะให้ยูทิลิตีที่ดีกว่าโดยมีขอบเขตการมีส่วนร่วมต่ำ ซึ่งเป็นเหตุผลที่ PipelineDP ใช้การกระจายนี้โดยค่าเริ่มต้น อย่างไรก็ตาม หากต้องการใช้GAUSSIANสัญญาณรบกวนการกระจาย คุณสามารถระบุได้ในอินสแตนซ์ AggregateParams
9. ขอแสดงความยินดี
เก่งมาก คุณทำ Codelab ของ PipelineDP เสร็จแล้วและได้เรียนรู้มากมายเกี่ยวกับ Differential Privacy และ PipelineDP