คำนวณสถิติส่วนตัวด้วย PipelineDP

คำนวณสถิติส่วนตัวด้วย PipelineDP

เกี่ยวกับ Codelab นี้

subjectอัปเดตล่าสุดเมื่อ เม.ย. 4, 2022
account_circleเขียนโดย Christiane Ahlheim, Mirac Vuslat Basaran, Vadym Doroshenko, Miguel Guevera, Yurii Sushko

1 ก่อนเริ่มต้น

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

ใน Codelab นี้ คุณจะได้เรียนรู้วิธีสร้างสถิติส่วนตัวด้วยการรวมข้อมูลส่วนตัวจาก PipelineDP เพื่อปกป้องตัวบุคคล ความเป็นส่วนตัว PipelineDP เป็นเฟรมเวิร์ก Python ที่ช่วยให้คุณใช้ Differential Privacy กับชุดข้อมูลขนาดใหญ่ด้วยระบบการประมวลผลแบบกลุ่ม เช่น Apache Spark และ Apache Beam ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีคํานวณสถิติ Differentially Private ใน Go ได้ที่ Codelab เกี่ยวกับความเป็นส่วนตัวบนบีม

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

ข้อกำหนดเบื้องต้น

  • คุ้นเคยกับ Python
  • ความคุ้นเคยกับการรวมข้อมูลพื้นฐาน
  • ใกล้ชิดกับแพนด้า สปาร์ค และบีม

สิ่งที่คุณจะได้เรียนรู้

  • ข้อมูลเบื้องต้นเกี่ยวกับ Differential Privacy
  • วิธีคำนวณสถิติสรุปแบบ Differentially Private ด้วย PipelineDP
  • วิธีปรับแต่งผลลัพธ์ด้วยพารามิเตอร์ด้านความเป็นส่วนตัวและยูทิลิตีเพิ่มเติม

สิ่งที่ต้องมี

  • หากต้องการเรียกใช้ Codelab ในสภาพแวดล้อมของคุณเอง คุณต้องติดตั้ง Python 3.7 ขึ้นไปในคอมพิวเตอร์
  • หากต้องการใช้งาน Codelab โดยไม่มีสภาพแวดล้อมของคุณเอง คุณจะต้องมีสิทธิ์เข้าถึง Colaboratory

2 ทำความเข้าใจ Differential Privacy

ดูตัวอย่างง่ายๆ นี้เพื่อให้เข้าใจ Differential Privacy ได้ดียิ่งขึ้น

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

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

ea813c698889a4c6.png

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

แผนภูมินี้แสดงให้เห็นว่าลูกค้าเพียงคนเดียวที่มองจั๊มพลางก่อนแล้วทำการซื้อจริง

b7c6f7f891778366.png

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

แผนภูมิแท่งนี้อาจจะไม่ได้แม่นยำทั้งหมด แต่ก็ยังคงมีประโยชน์และจะไม่แสดงการมีส่วนร่วมแต่ละรายการ

b55e8d7f99f6d574.gif

Differential Privacy คือการเพิ่มขึ้นของสัญญาณรบกวนแบบสุ่มในจำนวนที่เหมาะสมเพื่อปกปิดการมีส่วนร่วมแต่ละรายการ

ตัวอย่างนี้อธิบายยากเกินไป การนำ Differential Privacy ที่เหมาะสมมาใช้นั้นมีความเกี่ยวข้องมากกว่า และมาพร้อมกับรายละเอียดเล็กๆ น้อยๆ ในการใช้งานที่ไม่คาดคิด เช่นเดียวกับวิทยาการเข้ารหัส แต่ก็อาจไม่ใช่ความคิดที่ดีที่จะสร้างการใช้งาน Differential Privacy ในตัวเอง แต่คุณจะใช้ PipelineDP แทนได้

3 ดาวน์โหลดและติดตั้ง PipelineDP

คุณไม่จำเป็นต้องติดตั้ง PipelineDP โดยทำตาม Codelab นี้ เนื่องจากคุณจะค้นหาโค้ดและกราฟที่เกี่ยวข้องทั้งหมดในเอกสารนี้ได้

หากต้องการเล่นกับ PipelineDP ให้เรียกใช้เองหรือใช้ภายหลัง:

  • ดาวน์โหลดและติดตั้ง PipelineDP:
pip install pipeline-dp

หากต้องการเรียกใช้ตัวอย่างโดยใช้ Apache Beam ให้ทำดังนี้

  • ดาวน์โหลดและติดตั้ง Apacheบีม
pip install apache_beam

คุณจะหาโค้ดสำหรับ Codelab นี้และชุดข้อมูลได้ในไดเรกทอรี PipelineDP/examples/codelab/

4 คํานวณเมตริก Conversion ต่อผลิตภัณฑ์แรกที่ดู

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

วิธีคํานวณเมตริก Conversion ต่อผลิตภัณฑ์แรกที่ดูสําหรับเว็บไซต์

  1. ตรวจสอบชุดข้อมูลจำลองการเข้าชมเว็บไซต์ในไดเรกทอรี PipelineDP/examples/codelab/

ภาพหน้าจอนี้เป็นตัวอย่างของชุดข้อมูล ซึ่งประกอบด้วยรหัสผู้ใช้ ผลิตภัณฑ์ที่ผู้ใช้ดู ผู้เข้าชมทํา 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: จำนวนเงินทั้งหมดที่ผู้เข้าชมจ่ายเมื่อเกิด Conversion
  • conversion_rate: อัตราที่ผู้เข้าชมทำ Conversion
  1. สร้างเมตริกแบบไม่เป็นส่วนตัว
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 หลังจากบุคคลนั้นเห็นนักกระโดดก่อน สำหรับการดู 22 ครั้ง อัตรา Conversion จะอยู่ที่ประมาณ 0.05 ตอนนี้คุณจะต้องเปลี่ยนแผนภูมิแท่งแต่ละรายการให้เป็นแบบส่วนตัว

  1. กำหนดพารามิเตอร์ความเป็นส่วนตัวด้วยคลาส pipeline_dp.NaiveBudgetAccountant แล้วระบุอาร์กิวเมนต์ epsilon และ delta ที่ต้องการใช้สำหรับการวิเคราะห์

วิธีกำหนดอาร์กิวเมนต์เหล่านี้ขึ้นอยู่กับปัญหาเฉพาะของคุณ ดูข้อมูลเพิ่มเติมเกี่ยวกับพารามิเตอร์เหล่านี้ได้ในส่วนไม่บังคับ: ปรับแต่งพารามิเตอร์ Differential Privacy

ข้อมูลโค้ดนี้ใช้ค่าตัวอย่างดังนี้

budget_accountant = pipeline_dp.NaiveBudgetAccountant(
     total_epsilon
=1, total_delta=1e-5)
  1. เริ่มต้นอินสแตนซ์ LocalBackend:
ops = pipeline_dp.LocalBackend()

คุณใช้อินสแตนซ์ LocalBackend ได้เนื่องจากเรียกใช้โปรแกรมนี้ในเครื่องโดยไม่ต้องใช้เฟรมเวิร์กเพิ่มเติม เช่นบีมหรือ Spark

  1. เริ่มต้นอินสแตนซ์ 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)
  1. ระบุว่าคุณต้องการคำนวณเมตริก count และใช้การกระจายสัญญาณรบกวน LAPLACE
  2. ตั้งค่าอาร์กิวเมนต์ max_partitions_contributed เป็นค่า 1

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

  1. ตั้งค่าอาร์กิวเมนต์ max_contributions_per_partitions เป็นค่า 1

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

  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
  1. เพิ่มโค้ดนี้เพื่อเปลี่ยน Pandas DataFrame เป็นรายการแถวที่คุณสามารถคำนวณสถิติ Differentiated Private ได้โดยตรง
rows = [index_row[1] for index_row in df.iterrows()]
dp_result_local
= run_pipeline(rows, ops) # Returns generator
list
(dp_result_local)

ยินดีด้วย คุณได้คำนวณสถิติส่วนตัวที่แตกต่างกันเป็นครั้งแรก

แผนภูมินี้แสดงผลลัพธ์ของจำนวนส่วนตัวที่แตกต่าง ข้างจำนวนที่ไม่ใช่แบบส่วนบุคคลซึ่งคุณคำนวณไว้ก่อนหน้านี้

a5a25a00858219ab.png

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

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

5 ใช้พาร์ติชันสาธารณะ

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

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

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

วิธีใช้พาร์ติชัน

  1. สร้างรายการพาร์ติชันที่เป็นไปได้ดังนี้
public_partitions_products = ['jeans', 'jumper', 'socks', 't-shirt']
  1. ส่งรายชื่อไปยังฟังก์ชัน 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 ได้

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

a4f6302c8efcd5da.png

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

มีสิ่งสำคัญ 2 สิ่งที่ควรคำนึงถึงเมื่อใช้พาร์ติชันสาธารณะ ดังนี้

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

ขั้นสูง: ได้รับพาร์ติชันจากข้อมูล

หากเรียกใช้การรวมหลายรายการด้วยรายการพาร์ติชันเอาต์พุตที่ไม่เป็นสาธารณะเดียวกันในไปป์ไลน์เดียวกัน คุณจะดึงข้อมูลรายการพาร์ติชันได้เพียงครั้งเดียวด้วยเมธอด 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 แล้ว ต่อไปก็ดูวิธีใช้งาน PipelineDP สำหรับ Use Case ขั้นสูงขึ้นอีกบางส่วนได้ ตามที่ได้กล่าวไปแล้วในตอนต้น คุณสนใจสถิติ 3 อย่างนี้ PipelineDP ช่วยให้คุณคำนวณสถิติหลายรายการพร้อมกันได้ตราบใดที่สถิติเหล่านั้นใช้พารามิเตอร์เดียวกันในอินสแตนซ์ AggregateParams ซึ่งคุณจะเห็นในภายหลัง นอกจากจะดูสะอาดตาและง่ายขึ้นในการคํานวณเมตริกหลายรายการในครั้งเดียวแล้ว แต่ยังดีกว่าในแง่ของความเป็นส่วนตัวด้วย

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

สิ่งสำคัญที่ควรคำนึงถึงเกี่ยวกับงบประมาณความเป็นส่วนตัวคืองบประมาณที่เพิ่มขึ้น หากคุณเรียกใช้ไปป์ไลน์ที่มี epsilon ÷ และ delta markup ที่เฉพาะเจาะจง 1 ครั้ง คุณจะใช้จ่ายงบประมาณ (File, ÷) หากคุณเรียกใช้เป็นครั้งที่ 2 คุณจะใช้จ่ายงบประมาณทั้งหมด (2สแปม, 2÷) ในทำนองเดียวกัน หากคุณคำนวณสถิติหลายรายการด้วยเมธอด NaiveBudgetAccountant และรวมงบประมาณด้านความเป็นส่วนตัวเท่ากับ ÷ กำไร ต่อกัน คุณจะต้องใช้งบประมาณรวม (2FE, 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

วิธีคำนวณสถิติหลายรายการ

  1. สร้างบัญชีงบประมาณความเป็นส่วนตัวด้วยค่า epsilon และ delta รวมที่คุณต้องการใช้ในสถิติ 3 รายการ ได้แก่
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
     total_epsilon
=1, total_delta=0)
  1. เริ่มต้น DPEngine เพื่อคํานวณเมตริก ดังนี้
 dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)
  1. ระบุพารามิเตอร์สำหรับเมตริกนี้
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 เป็นขอบเขตที่สมเหตุสมผล

  1. แยกข้อมูลที่เกี่ยวข้องแล้วส่งไปยังฟังก์ชันการรวมข้อมูล โดยทำดังนี้
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))
  1. ทำตามขั้นตอนเดียวกันเพื่อคำนวณเมตริก 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 เดียวกันและคำนวณทั้งสองพร้อมๆ กัน

  1. เรียกเมธอด budget_accountant.compute_budgets():
budget_accountant.compute_budgets()

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

cb1fc563f817eaf.png

7 เรียกใช้ไปป์ไลน์ด้วยบีม

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

PipelineDP รองรับบีมและ Spark ที่มีการเปลี่ยนแปลงโค้ดเพียงเล็กน้อย

วิธีเรียกใช้ไปป์ไลน์ด้วยบีมด้วย private_beam API

  1. เริ่มต้นตัวแปร runner แล้วสร้างไปป์ไลน์ที่คุณใช้การดำเนินการด้านความเป็นส่วนตัวกับการแสดงบีมของ rows ดังนี้
runner = fn_api_runner.FnApiRunner()  # local runner

with beam.Pipeline(runner=runner) as pipeline:
   beam_data
= pipeline | beam.Create(rows)
  1. สร้างตัวแปร budget_accountant ที่มีพารามิเตอร์ความเป็นส่วนตัวที่จำเป็น
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
               total_epsilon
=1, total_delta=0)
  1. สร้างตัวแปร pcol หรือคอลเล็กชันส่วนตัว ซึ่งรับประกันว่าการรวมใดๆ จะเป็นไปตามข้อกำหนดด้านความเป็นส่วนตัวต่อไปนี้
pcol = beam_data | pbeam.MakePrivate(
                                 budget_accountant
=budget_accountant,
                                 privacy_id_extractor
=lambda
                                                    row
: row.user_id)
  1. ระบุพารามิเตอร์ของการรวมข้อมูลส่วนตัวในคลาสที่เหมาะสม

ในที่นี้ คุณใช้คลาส pipeline_dp.aggregate_params.SumParams() เพราะคำนวณผลรวมของการดูผลิตภัณฑ์

  1. ส่งพารามิเตอร์การรวมของคุณไปยังเมธอด pbeam.Sum เพื่อคำนวณสถิติ:
dp_result = pcol | pbeam.Sum(params)
  1. ซึ่งในท้ายที่สุด โค้ดของคุณควรมีลักษณะเช่นนี้
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 ไม่บังคับ: ปรับแต่งพารามิเตอร์ความเป็นส่วนตัวและยูทิลิตี

คุณเห็นพารามิเตอร์บางส่วนที่กล่าวถึงใน Codelab นี้ เช่น พารามิเตอร์ epsilon, delta และ max_partitions_contributed คุณจะแบ่งออกเป็น 2 หมวดหมู่คร่าวๆ ได้ ได้แก่ พารามิเตอร์ความเป็นส่วนตัวและพารามิเตอร์ยูทิลิตี

พารามิเตอร์ความเป็นส่วนตัว

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

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

ดูข้อมูลเพิ่มเติมเกี่ยวกับ Differential Privacy และความหมายของพารามิเตอร์ความเป็นส่วนตัวได้ที่เรื่องรออ่านเกี่ยวกับ Differential Privacy

พารามิเตอร์ยูทิลิตี

พารามิเตอร์ยูทิลิตีจะไม่ส่งผลกระทบต่อการรับประกันความเป็นส่วนตัว แต่จะส่งผลต่อความแม่นยำและประโยชน์ของเอาต์พุตด้วย ซึ่งระบุไว้ในอินสแตนซ์ 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 Noise การกระจาย LAPLACE ให้ประโยชน์ที่ดีกว่าโดยมีขอบเขตการมีส่วนร่วมต่ำ ซึ่งเป็นเหตุผลที่ PipelineDP ใช้ค่าเริ่มต้น แต่หากต้องการใช้เสียงรบกวนการกระจาย GAUSSIAN คุณสามารถระบุได้ในอินสแตนซ์ AggregateParams

9 ขอแสดงความยินดี

เก่งมาก คุณศึกษา Codelab ของ PipelineDP เสร็จแล้ว และได้เรียนรู้มากมายเกี่ยวกับ Differential Privacy และ PipelineDP

ดูข้อมูลเพิ่มเติม