Tính toán số liệu thống kê riêng tư bằng PipelineDP

1. Trước khi bắt đầu

Bạn có thể nghĩ rằng số liệu thống kê tổng hợp không làm rò rỉ bất kỳ thông tin nào về những cá nhân mà số liệu đó liên quan. Tuy nhiên, có nhiều cách để kẻ tấn công có thể tìm hiểu thông tin nhạy cảm về các cá nhân từ số liệu thống kê tổng hợp.

Trong lớp học lập trình này, bạn sẽ tìm hiểu cách tạo số liệu thống kê riêng tư bằng các phép tổng hợp riêng tư vi phân từ PipelineDP để bảo vệ quyền riêng tư của cá nhân. PipelineDP là một khung Python cho phép bạn áp dụng sự riêng tư biệt lập cho các tập dữ liệu lớn bằng hệ thống xử lý hàng loạt, chẳng hạn như Apache SparkApache Beam. Để biết thêm thông tin về cách tính toán số liệu thống kê có quyền riêng tư vi phân trong Go, hãy xem codelab Quyền riêng tư trên Beam.

Riêng tư có nghĩa là đầu ra được tạo ra theo cách không làm rò rỉ bất kỳ thông tin riêng tư nào về các cá nhân trong dữ liệu. Bạn có thể đạt được kết quả này thông qua sự riêng tư biệt lập, một khái niệm mạnh mẽ về quyền riêng tư của việc ẩn danh, là quy trình tổng hợp dữ liệu của nhiều người dùng để bảo vệ quyền riêng tư của người dùng. Tất cả các phương pháp ẩn danh đều sử dụng tính năng tổng hợp, nhưng không phải phương pháp tổng hợp nào cũng đạt được mục tiêu ẩn danh. Mặt khác, sự riêng tư biệt lập cung cấp các đảm bảo có thể đo lường được về việc rò rỉ thông tin và quyền riêng tư.

Điều kiện tiên quyết

  • Làm quen với Python
  • Làm quen với tính năng tổng hợp dữ liệu cơ bản
  • Có kinh nghiệm sử dụng pandas, Spark và Beam

Kiến thức bạn sẽ học được

  • Thông tin cơ bản về sự riêng tư biệt lập
  • Cách tính số liệu thống kê tóm tắt riêng tư vi phân bằng PipelineDP
  • Cách điều chỉnh kết quả bằng các thông số bổ sung về quyền riêng tư và tiện ích

Bạn cần có

  • Nếu muốn chạy lớp học lập trình trong môi trường của riêng mình, bạn cần cài đặt Python 3.7 trở lên trên máy tính.
  • Nếu muốn làm theo hướng dẫn trong lớp học lập trình mà không cần môi trường riêng, bạn cần có quyền truy cập vào Colaboratory.

2. Tìm hiểu về sự riêng tư biệt lập

Để hiểu rõ hơn về sự riêng tư biệt lập, hãy xem ví dụ đơn giản này.

Hãy tưởng tượng rằng bạn làm việc trong bộ phận tiếp thị của một nhà bán lẻ thời trang trực tuyến và bạn muốn biết sản phẩm nào có khả năng bán được nhiều nhất.

Biểu đồ này cho biết khách hàng xem sản phẩm nào đầu tiên khi họ truy cập vào trang web của cửa hàng: áo thun, áo len, tất hoặc quần jean. Áo thun là mặt hàng phổ biến nhất, trong khi tất là mặt hàng ít phổ biến nhất.

ea813c698889a4c6.png

Có vẻ như tính năng này hữu ích, nhưng có một điểm hạn chế. Khi muốn xem xét thêm thông tin, chẳng hạn như việc khách hàng đã mua hàng hay sản phẩm nào họ đã xem thứ hai, bạn có nguy cơ tiết lộ thông tin về các cá nhân trong dữ liệu của mình.

Biểu đồ này cho thấy chỉ có một khách hàng xem áo len trước rồi mới thực sự mua hàng:

b7c6f7f891778366.png

Điều này không tốt về quyền riêng tư. Số liệu thống kê ẩn danh không được tiết lộ đóng góp của từng cá nhân, vậy bạn phải làm gì? Bạn thêm nhiễu ngẫu nhiên vào biểu đồ thanh để biểu đồ đó ít chính xác hơn một chút!

Biểu đồ thanh này không hoàn toàn chính xác, nhưng vẫn hữu ích và không tiết lộ đóng góp của từng cá nhân:

b55e8d7f99f6d574.gif

Sự riêng tư biệt lập là việc thêm một lượng nhiễu ngẫu nhiên phù hợp để che giấu các thông tin đóng góp của từng cá nhân.

Ví dụ này quá đơn giản. Việc triển khai đúng cách sự riêng tư biệt lập sẽ phức tạp hơn và có một số điểm tinh tế ngoài dự kiến khi triển khai. Tương tự như mật mã học, bạn không nên tự triển khai sự riêng tư biệt lập. Thay vào đó, bạn có thể sử dụng PipelineDP.

3. Tải xuống và cài đặt PipelineDP

Bạn không cần cài đặt PipelineDP để làm theo lớp học lập trình này vì bạn có thể tìm thấy tất cả mã và biểu đồ có liên quan trong tài liệu này.

Để chơi bằng PipelineDP, hãy tự chạy hoặc sử dụng sau:

  • Tải xuống và cài đặt PipelineDP:
pip install pipeline-dp

Nếu bạn muốn chạy ví dụ bằng Apache Beam:

  • Tải xuống và cài đặt Apache Beam:
pip install apache_beam

Bạn có thể tìm thấy mã cho lớp học lập trình này và tập dữ liệu trong thư mục PipelineDP/examples/codelab/.

4. Tính toán các chỉ số về lượt chuyển đổi cho mỗi sản phẩm đầu tiên được xem

Giả sử bạn làm việc tại một nhà bán lẻ thời trang trực tuyến và bạn muốn biết danh mục sản phẩm nào tạo ra số lượt chuyển đổi và giá trị lượt chuyển đổi cao nhất khi được xem lần đầu. Bạn muốn chia sẻ thông tin này với công ty quảng cáo cũng như các nhóm nội bộ khác, nhưng bạn muốn ngăn chặn việc rò rỉ thông tin về bất kỳ khách hàng cá nhân nào.

Cách tính toán các chỉ số về lượt chuyển đổi cho mỗi sản phẩm đầu tiên được xem trên trang web:

  1. Xem lại tập dữ liệu mô phỏng về lượt truy cập vào trang web của bạn trong thư mục PipelineDP/examples/codelab/.

Ảnh chụp màn hình này là một ví dụ về tập dữ liệu. Nội dung này chứa mã nhận dạng của người dùng, các sản phẩm mà người dùng đã xem, liệu khách truy cập có chuyển đổi hay không và nếu có thì giá trị của lượt chuyển đổi đó.

user_id

product_view_0

product_view_1

product_view_2

product_view_3

product_view_4

has_conversion

conversion_value

0

quần jean

t_shirt

t_shirt

không có

không có

false

0.0

1

quần jean

t_shirt

quần jean

jumper

không có

false

0.0

2

t_shirt

jumper

t_shirt

t_shirt

không có

true

105,19

3

t_shirt

t_shirt

quần jean

không có

không có

false

0.0

4

t_shirt

bít tất

quần jean

quần jean

không có

false

0.0

Bạn quan tâm đến những chỉ số sau:

  • view_counts: Số lần khách truy cập trang web của bạn nhìn thấy từng sản phẩm lần đầu tiên.
  • total_conversion_value: Tổng số tiền mà khách truy cập chi tiêu khi họ chuyển đổi.
  • conversion_rate: Tỷ lệ chuyển đổi của khách truy cập.
  1. Tạo các chỉ số theo cách không riêng tư:
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)

Như bạn đã tìm hiểu trước đó, những số liệu thống kê này có thể tiết lộ thông tin về các cá nhân trong tập dữ liệu của bạn. Ví dụ: chỉ có một người chuyển đổi sau khi người đó nhìn thấy một người nhảy dù trước. Đối với 22 lượt xem, tỷ lệ chuyển đổi của bạn là khoảng 0,05. Giờ đây, bạn cần chuyển đổi từng biểu đồ dạng thanh thành biểu đồ riêng tư.

  1. Xác định các thông số về quyền riêng tư bằng lớp pipeline_dp.NaiveBudgetAccountant, sau đó chỉ định các đối số epsilondelta mà bạn muốn dùng cho hoạt động phân tích.

Cách bạn đặt các đối số này sẽ phụ thuộc vào vấn đề cụ thể của bạn. Để tìm hiểu thêm về các tham số này, hãy xem phần Không bắt buộc: Điều chỉnh các tham số quyền riêng tư vi phân.

Đoạn mã này sử dụng các giá trị ví dụ:

budget_accountant = pipeline_dp.NaiveBudgetAccountant(
     total_epsilon=1, total_delta=1e-5)
  1. Khởi động phiên bản LocalBackend:
ops = pipeline_dp.LocalBackend()

Bạn có thể sử dụng phiên bản LocalBackend vì bạn chạy chương trình này cục bộ mà không cần các khung bổ sung, chẳng hạn như Beam hoặc Spark.

  1. Khởi động phiên bản DPEngine:
dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)

PipelineDP cho phép bạn chỉ định các tham số khác thông qua lớp pipeline_dp.AggregateParams, ảnh hưởng đến việc tạo số liệu thống kê riêng tư.

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. Chỉ định rằng bạn muốn tính toán chỉ số count và sử dụng phân phối nhiễu LAPLACE.
  2. Đặt đối số max_partitions_contributed thành giá trị 1.

Đối số này giới hạn số lượt truy cập khác nhau mà người dùng có thể đóng góp. Bạn muốn người dùng truy cập vào trang web một lần mỗi ngày và bạn không quan tâm đến việc họ truy cập nhiều lần trong ngày.

  1. Đặt đối số max_contributions_per_partitions thành giá trị 1.

Đối số này chỉ định số lượng đóng góp mà một khách truy cập duy nhất có thể thực hiện cho một phân vùng riêng lẻ hoặc một danh mục sản phẩm trong trường hợp này.

  1. Tạo một thực thể data_extractor chỉ định vị trí tìm các trường privacy_id, partitionvalue.

Mã của bạn sẽ có dạng như đoạn mã sau:

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. Thêm mã này để chuyển đổi Pandas DataFrame thành một danh sách các hàng mà bạn có thể trực tiếp tính toán số liệu thống kê riêng tư vi phân:
rows = [index_row[1] for index_row in df.iterrows()]
dp_result_local = run_pipeline(rows, ops) # Returns generator
list(dp_result_local)

Xin chúc mừng! Bạn đã tính toán số liệu thống kê riêng tư vi phân đầu tiên!

Biểu đồ này cho thấy kết quả của số lượt truy cập riêng tư vi phân bên cạnh số lượt truy cập không riêng tư mà bạn đã tính toán trước đó:

a5a25a00858219ab.png

Biểu đồ thanh mà bạn nhận được khi chạy mã có thể khác với biểu đồ này, điều này không sao cả. Do nhiễu trong sự riêng tư biệt lập, bạn sẽ nhận được một biểu đồ thanh khác mỗi khi chạy mã, nhưng bạn có thể thấy rằng các biểu đồ này tương tự như biểu đồ thanh ban đầu không riêng tư.

Xin lưu ý rằng để đảm bảo quyền riêng tư, bạn không được chạy quy trình nhiều lần. Để biết thêm thông tin, hãy xem phần Tính toán nhiều số liệu thống kê.

5. Sử dụng phân vùng công khai

Ở phần trước, có thể bạn đã nhận thấy rằng bạn đã loại bỏ tất cả dữ liệu lượt truy cập cho một phân vùng, cụ thể là những khách truy cập lần đầu tiên nhìn thấy tất trên trang web của bạn.

Điều này là do việc chọn phân vùng hoặc ngưỡng, một bước quan trọng để đảm bảo quyền riêng tư khác biệt khi sự tồn tại của các phân vùng đầu ra phụ thuộc vào chính dữ liệu người dùng. Trong trường hợp này, chỉ cần có một phân vùng trong đầu ra là có thể làm lộ sự tồn tại của một người dùng riêng lẻ trong dữ liệu. Để tìm hiểu thêm về lý do dẫn đến hành vi vi phạm quyền riêng tư, hãy xem bài đăng này trên blog. Để ngăn chặn hành vi xâm phạm quyền riêng tư này, PipelineDP chỉ giữ lại những phân vùng có đủ số lượng người dùng.

Khi danh sách các phân vùng đầu ra không phụ thuộc vào dữ liệu người dùng riêng tư, bạn không cần bước chọn phân vùng này. Đây thực sự là trường hợp cho ví dụ của bạn vì bạn biết tất cả danh mục sản phẩm có thể mà khách hàng có thể thấy trước tiên.

Cách sử dụng phân vùng:

  1. Tạo danh sách các phân vùng có thể có:
public_partitions_products = ['jeans', 'jumper', 'socks', 't-shirt']
  1. Truyền danh sách đến hàm run_pipeline(). Hàm này sẽ đặt danh sách làm một dữ liệu đầu vào bổ sung cho lớp 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)

Nếu bạn sử dụng các phân vùng công khai và có LAPLACE nhiễu, bạn có thể đặt đối số total_delta thành giá trị 0.

Giờ đây, bạn sẽ thấy trong kết quả rằng dữ liệu cho tất cả các phân vùng hoặc sản phẩm đều được báo cáo.

a4f6302c8efcd5da.png

Phân vùng công khai không chỉ giúp bạn giữ lại nhiều phân vùng hơn mà còn giảm khoảng một nửa lượng nhiễu vì bạn không tốn Hạn mức quyền riêng tư cho việc chọn phân vùng. Do đó, sự khác biệt giữa số lượng thô và số lượng riêng tư sẽ ít hơn một chút so với lần chạy trước.

Bạn cần lưu ý 2 điều quan trọng khi sử dụng phân vùng công khai:

  • Hãy thận trọng khi bạn lấy danh sách phân vùng từ dữ liệu thô. Nếu bạn không thực hiện việc này theo cách đảm bảo sự riêng tư biệt lập, thì quy trình của bạn sẽ không còn đảm bảo sự riêng tư biệt lập nữa. Để biết thêm thông tin, hãy xem bài viết Nâng cao: Lấy phân vùng từ dữ liệu.
  • Nếu không có dữ liệu cho một số phân vùng công khai, bạn cần áp dụng nhiễu cho những phân vùng đó để duy trì sự riêng tư biệt lập. Ví dụ: nếu bạn sử dụng một sản phẩm bổ sung như quần dài, không xuất hiện trong tập dữ liệu hoặc trên trang web của bạn, thì đó vẫn là dữ liệu nhiễu và kết quả có thể cho thấy một số lượt truy cập vào sản phẩm khi không có lượt truy cập nào.

Nâng cao: Tạo phân vùng từ dữ liệu

Nếu chạy nhiều hoạt động tổng hợp với cùng một danh sách các phân vùng đầu ra không công khai trong cùng một quy trình, bạn có thể lấy danh sách phân vùng một lần bằng phương thức dp_engine.select_private_partitions() và cung cấp các phân vùng cho từng hoạt động tổng hợp dưới dạng đầu vào public_partitions. Điều này không chỉ an toàn về quyền riêng tư mà còn giúp bạn giảm bớt nhiễu vì bạn chỉ sử dụng ngân sách quyền riêng tư cho việc chọn phân vùng một lần cho toàn bộ quy trình.

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. Tính nhiều số liệu thống kê

Giờ đây, bạn đã biết cách hoạt động của PipelineDP, bạn có thể xem cách sử dụng công cụ này cho một số trường hợp sử dụng nâng cao hơn. Như đã đề cập ở phần đầu, bạn quan tâm đến 3 số liệu thống kê. PipelineDP cho phép bạn tính toán nhiều số liệu thống kê cùng một lúc miễn là các số liệu đó dùng chung các tham số trong phiên bản AggregateParams mà bạn sẽ thấy sau. Không chỉ gọn gàng và dễ dàng tính toán nhiều chỉ số cùng một lúc, mà giải pháp này còn đảm bảo quyền riêng tư tốt hơn.

Nếu bạn nhớ các tham số epsilondelta mà bạn cung cấp cho lớp NaiveBudgetAccountant, thì các tham số này đại diện cho một thứ gọi là Hạn mức quyền riêng tư, đây là thước đo mức độ quyền riêng tư của người dùng mà bạn tiết lộ từ dữ liệu.

Một điều quan trọng cần lưu ý về ngân sách quyền riêng tư là ngân sách này có tính cộng dồn. Nếu chạy một quy trình với epsilon ε và delta δ cụ thể một lần, bạn sẽ chi tiêu ngân sách (ε,δ). Nếu chạy lần thứ hai, bạn sẽ chi tiêu tổng ngân sách là (2ε, 2δ). Tương tự, nếu tính nhiều số liệu thống kê bằng phương thức NaiveBudgetAccountant và liên tiếp là ngân sách quyền riêng tư ε,δ, bạn sẽ chi tiêu tổng ngân sách là (2ε, 2δ). Điều này có nghĩa là bạn làm giảm các cam kết về quyền riêng tư.

Để khắc phục vấn đề này, bạn cần sử dụng một phiên bản NaiveBudgetAccountant duy nhất với tổng ngân sách mà bạn muốn sử dụng khi cần tính toán nhiều số liệu thống kê trên cùng một dữ liệu. Sau đó, bạn cần chỉ định các giá trị epsilondelta mà bạn muốn sử dụng cho mỗi lượt tổng hợp. Cuối cùng, bạn sẽ nhận được sự đảm bảo về quyền riêng tư tổng thể như nhau, nhưng giá trị epsilondelta càng cao mà một hoạt động tổng hợp cụ thể có, thì độ chính xác càng cao.

Để xem điều này trong thực tế, bạn có thể tính toán số liệu thống kê count, meansum.

Bạn tính toán số liệu thống kê dựa trên 2 chỉ số khác nhau: chỉ số conversion_value mà bạn dùng để suy ra số tiền doanh thu được tạo ra dựa trên sản phẩm được xem đầu tiên và chỉ số has_conversion mà bạn dùng để tính số lượng khách truy cập vào trang web của mình và tỷ lệ chuyển đổi trung bình.

Đối với mỗi chỉ số, bạn cần chỉ định riêng các thông số hướng dẫn việc tính toán số liệu thống kê riêng tư. Bạn chia ngân sách quyền riêng tư cho 2 chỉ số. Bạn tính toán 2 số liệu thống kê từ chỉ số has_conversion, vì vậy, bạn muốn chỉ định 2/3 ngân sách ban đầu cho chỉ số này và chỉ định 1/3 còn lại cho chỉ số conversion_value.

Cách tính nhiều số liệu thống kê:

  1. Thiết lập kế toán ngân sách về quyền riêng tư bằng tổng giá trị epsilondelta mà bạn muốn sử dụng trên 3 số liệu thống kê:
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
     total_epsilon=1, total_delta=0)
  1. Khởi động DPEngine để tính toán các chỉ số của bạn:
 dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)
  1. Chỉ định các thông số cho chỉ số này.
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)

Đối số cuối cùng (không bắt buộc) chỉ định trọng số của ngân sách quyền riêng tư. Bạn có thể đặt trọng số bằng nhau cho tất cả, nhưng bạn muốn đặt đối số này thành 1/3 như đã giải thích trước đó.

Bạn cũng đặt đối số min_valuemax_value để chỉ định giới hạn dưới và giới hạn trên được áp dụng cho một giá trị do một đơn vị quyền riêng tư đóng góp trong một phân vùng. Bạn cần có các thông số này khi muốn tính tổng hoặc giá trị trung bình riêng tư. Bạn không mong đợi các giá trị âm, vì vậy, bạn có thể giả định 0100 là các giới hạn hợp lý.

  1. Trích xuất dữ liệu có liên quan rồi truyền dữ liệu đó vào hàm tổng hợp:
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. Làm theo các bước tương tự để tính toán hai chỉ số dựa trên biến 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))

Thay đổi duy nhất là trong phiên bản pipeline_dp.AggregateParams, trong đó giờ đây bạn xác định meancount là các phép tổng hợp, đồng thời chỉ định 2/3 ngân sách bảo mật cho phép tính này. Vì bạn muốn có cùng giới hạn đóng góp cho cả hai số liệu thống kê và tính toán chúng dựa trên cùng một biến has_conversion, nên bạn có thể kết hợp chúng trong cùng một phiên bản pipeline_dp.AggregateParams và tính toán chúng cùng một lúc.

  1. Gọi phương thức budget_accountant.compute_budgets():
budget_accountant.compute_budgets()

Bạn có thể vẽ biểu đồ cho cả 3 số liệu thống kê riêng tư này để so sánh với số liệu thống kê ban đầu. Tuỳ thuộc vào lượng dữ liệu nhiễu được thêm vào, bạn sẽ thấy rằng kết quả thực tế có thể nằm ngoài phạm vi hợp lý. Trong trường hợp này, bạn sẽ thấy tỷ lệ chuyển đổi và tổng giá trị lượt chuyển đổi âm cho những người nhảy vì nhiễu được thêm vào là đối xứng xung quanh số 0. Để phân tích và xử lý thêm, tốt nhất là bạn không nên xử lý hậu kỳ số liệu thống kê riêng tư theo cách thủ công. Tuy nhiên, nếu muốn thêm những biểu đồ đó vào báo cáo, bạn chỉ cần đặt giá trị tối thiểu thành 0 mà không vi phạm các đảm bảo về quyền riêng tư.

cb1fc563f817eaf.png

7. Chạy quy trình bằng Beam

Ngày nay, việc xử lý dữ liệu đòi hỏi bạn phải xử lý một lượng lớn dữ liệu, đến mức bạn không thể xử lý dữ liệu đó trên thiết bị. Thay vào đó, nhiều người sử dụng các khung để xử lý dữ liệu quy mô lớn, chẳng hạn như Beam hoặc Spark, và chạy các quy trình của họ trên đám mây.

PipelineDP hỗ trợ Beam và Spark mà bạn chỉ cần thay đổi một chút đối với mã của mình.

Cách chạy quy trình bằng Beam với API private_beam:

  1. Khởi chạy một biến runner rồi tạo một quy trình mà trong đó bạn áp dụng các thao tác về quyền riêng tư cho một biểu thị Beam của rows:
runner = fn_api_runner.FnApiRunner()  # local runner

with beam.Pipeline(runner=runner) as pipeline:
   beam_data = pipeline | beam.Create(rows)
  1. Tạo một biến budget_accountant bằng các tham số bắt buộc về quyền riêng tư:
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
               total_epsilon=1, total_delta=0)
  1. Tạo một biến pcol hoặc biến bộ sưu tập riêng tư để đảm bảo mọi hoạt động tổng hợp đều tuân thủ các yêu cầu về quyền riêng tư của bạn:
pcol = beam_data | pbeam.MakePrivate(
                                 budget_accountant=budget_accountant,
                                 privacy_id_extractor=lambda 
                                                    row: row.user_id)
  1. Chỉ định các thông số của quy trình tổng hợp riêng tư trong lớp thích hợp.

Ở đây, bạn sử dụng lớp pipeline_dp.aggregate_params.SumParams() vì bạn tính tổng số lượt xem sản phẩm.

  1. Truyền các tham số tổng hợp vào phương thức pbeam.Sum để tính toán số liệu thống kê:
dp_result = pcol | pbeam.Sum(params)
  1. Cuối cùng, mã của bạn sẽ có dạng như đoạn mã sau:
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. Không bắt buộc: Điều chỉnh các thông số về quyền riêng tư và sự tiện ích

Bạn đã thấy khá nhiều tham số được đề cập trong lớp học lập trình này, chẳng hạn như tham số epsilon, deltamax_partitions_contributed. Bạn có thể chia các tham số này thành 2 danh mục: tham số về quyền riêng tưtham số về tiện ích.

Tham số về quyền riêng tư

Các tham số epsilondelta định lượng quyền riêng tư mà bạn cung cấp bằng sự riêng tư biệt lập. Chính xác hơn, chúng là thước đo lượng thông tin mà kẻ tấn công tiềm ẩn có thể thu thập được về dữ liệu từ đầu ra ẩn danh. Giá trị của các thông số càng cao thì kẻ tấn công càng thu thập được nhiều thông tin về dữ liệu, đây là một rủi ro về quyền riêng tư. Mặt khác, giá trị của các tham số epsilondelta càng thấp thì bạn càng cần thêm nhiều nhiễu vào đầu ra để ẩn danh và số lượng người dùng riêng biệt mà bạn cần trong mỗi phân vùng càng cao để giữ họ trong đầu ra ẩn danh. Trong trường hợp này, có sự đánh đổi giữa tính hữu ích và quyền riêng tư.

Trong PipelineDP, bạn cần chỉ định các đảm bảo về quyền riêng tư mong muốn của đầu ra ẩn danh khi đặt tổng ngân sách quyền riêng tư trong phiên bản NaiveBudgetAccountant. Lưu ý là nếu muốn đảm bảo quyền riêng tư, bạn cần thận trọng khi sử dụng một phiên bản NaiveBudgetAccountant riêng cho mỗi hoạt động tổng hợp hoặc chạy quy trình nhiều lần để tránh sử dụng quá mức ngân sách của mình.

Để biết thêm thông tin về sự riêng tư biệt lập và ý nghĩa của các tham số quyền riêng tư, hãy xem Danh sách tài liệu đọc về sự riêng tư biệt lập.

Tham số tiện ích

Các thông số tiện ích không ảnh hưởng đến các đảm bảo về quyền riêng tư, nhưng ảnh hưởng đến độ chính xác và do đó, ảnh hưởng đến tính hữu ích của đầu ra. Chúng được cung cấp trong phiên bản AggregateParams và dùng để điều chỉnh quy mô của nhiễu được thêm.

Một tham số tiện ích được cung cấp trong thực thể AggregateParams và áp dụng cho tất cả các hoạt động tổng hợp là tham số max_partitions_contributed. Phân vùng tương ứng với một khoá của dữ liệu do thao tác tổng hợp PipelineDP trả về, vì vậy, tham số max_partitions_contributed giới hạn số lượng giá trị khoá riêng biệt mà người dùng có thể đóng góp vào đầu ra. Nếu một người dùng đóng góp cho số lượng khoá vượt quá giá trị của tham số max_partitions_contributed, thì một số nội dung đóng góp sẽ bị loại bỏ để chúng đóng góp cho chính xác giá trị của tham số max_partitions_contributed.

Tương tự, hầu hết các hàm tổng hợp đều có tham số max_contributions_per_partition. Chúng cũng được cung cấp trong phiên bản AggregateParams và mỗi lượt tổng hợp có thể có các giá trị riêng biệt cho chúng. Chúng ràng buộc mức đóng góp của người dùng cho từng khoá.

Độ nhiễu được thêm vào đầu ra sẽ được điều chỉnh theo các tham số max_partitions_contributedmax_contributions_per_partition, vì vậy, bạn cần cân nhắc ở đây: Giá trị càng lớn được chỉ định cho mỗi tham số thì bạn càng giữ được nhiều dữ liệu, nhưng kết quả sẽ có nhiều nhiễu hơn.

Một số hoạt động tổng hợp yêu cầu tham số min_valuemax_value. Các tham số này chỉ định giới hạn cho mức đóng góp của mỗi người dùng. Nếu người dùng đóng góp một giá trị thấp hơn giá trị được chỉ định cho tham số min_value, thì giá trị đó sẽ tăng lên thành giá trị của tham số. Tương tự, nếu người dùng đóng góp một giá trị lớn hơn giá trị của tham số max_value, thì giá trị đó sẽ giảm xuống giá trị của tham số. Để giữ lại nhiều giá trị ban đầu hơn, bạn phải chỉ định các ranh giới lớn hơn. Nhiễu được điều chỉnh theo kích thước của ranh giới, vì vậy, ranh giới càng lớn thì bạn càng giữ được nhiều dữ liệu hơn, nhưng kết quả cuối cùng sẽ có nhiều nhiễu hơn.

Cuối cùng, tham số noise_kind hỗ trợ 2 cơ chế nhiễu khác nhau trong PipelineDP: nhiễu GAUSSIAN và nhiễu LAPLACE. Phân phối LAPLACE mang lại tiện ích tốt hơn với các giới hạn đóng góp thấp, đó là lý do PipelineDP sử dụng phân phối này theo mặc định. Tuy nhiên, nếu muốn sử dụng nhiễu phân phối GAUSSIAN, bạn có thể chỉ định nhiễu đó trong phiên bản AggregateParams.

9. Xin chúc mừng

Tuyệt vời! Bạn đã hoàn thành lớp học lập trình PipelineDP và tìm hiểu được nhiều điều về sự riêng tư biệt lập và PipelineDP.

Tìm hiểu thêm