Privacidade Diferencial no R usando o diffpriv
2021 Jan 04Aqui mesmo no Data Hackers eu postei a algum tempo sobre as consequências de confiar apenas na anomimização, e de como a Privacidade Diferencial (PD) pode ajudar a minimizar ataques adversariais, como o de Inferência de Associação [NA1] entre outros tipos de ataques/falhas.
Contudo, neste post vou tentar trazer alguns aspectos práticos, e claro um pouco de código para deixar alguns conceitos um pouco mais concretos.
Para quem está chegando agora neste post e não sabe o que é Privacidade Diferencial, eu recomendo a leitura do artigo “O que é a Privacidade Diferencial e como isso está relacionado com segurança em Machine Learning?” que tem uma explicação bem simples sobre o tema. O post de hoje vai ser sobre potenciais usos, implementação e *tradeoffs *entre rigor x incerteza quando usamos PD.
Usos de Privacidade Diferencial
A Privacidade Diferencial pode ser aplicada em alguns cenários como:
-
Situações em que é necessária a análise de dados sensíveis em que a privacidade não pode ser violada (ex: informações sobre a saúde de um grupo de pessoas, informações bancárias, etc.);
-
Para aumentar a robustez de algoritmos de Machine Learning em relação a dados não vistos (ex: aplicação de PD múltiplas vezes na base de treinamento realizando modificações do epsilon);
-
Na minimização do [Data Leakage](https://en.wikipedia.org/wiki/Leakage_(machine_learning) (vazamento de dados) através do reuso de bases holdout modificadas com mecanismo de PD; mecansimo este conhecido como Análise de Dados Adaptativa;
-
Em modelos de regressão do tipo Stepwise no momento de ajuste do modelo (fit) em que a base de treinamento é reutilizada utilizando Privacidade Diferencial para remoção de viés amostral;
-
Em disponibilização de dados sintéticos ou micro-dados (ex: informações censitárias); e
-
Geração de bases de dados com garantias mínimas de privacidade para modelos de Machine Learning (e até mesmo aumento de dados (Data Augmentation))
Estes são apenas alguns poucos cenários que ilustram o potencial de uso de Privacidade Diferencial no dia a dia.
Entretanto, vamos para a parte de código em um cenário de análise de dados sensíveis.
Usando o diffpriv para aplicação de Privacidade Diferencial
O diffpriv é uma biblioteca do R criada em 2017 por Benjamin Rubinstein e Francesco Ald apara analise de dados que demandem a aplicação de privacidade diferencial; como, por exemplo, a disponibilização de relatórios/bases de dados/análises para terceiros.
O diffpriv contém a implementação de mecanismos genéricos para transformar dados privados. O mecanismos presentes são: Laplace, Gaussiano, Exponencial e o Mecanismo de Bernstein. A documentação do pacote é bem completa e as explicações são bem didáticas.
Para o nosso caso, vamos realizar uma análise de dados relativos ao salário e a idade de pessoas em uma determinada empresa. A ideia é ver o mecanismo de privacidade diferencial na prática em relação ao resultado final.
Primeiramente, vamos instalar as bibliotecas gsl e diffpriv NA[2]:
Com as bibliotecas carregadas, vamos criar um conjunto de dados com os funcionários dessa empresa:
Agora que temos o nosso conjunto de dados no R, vamos criar uma função para calcular a média; função esta que usaremos para calcular a idade e salários médios desta empresa:
Podemos ver que a média de idade das pessoas do conjunto de dados é de 45 anos e a média de salários é de 9830 reais.
Porém, estas informações precisas não podem ser repassadas dado que queremos apenas representar a dinâmica dos dados ao invés de oferecer alguma anlálise/mecanismo que viole a privacidade destas pessoas.
Sendo assim, vamos partir para a criação de um mecanismo de privacidade diferencial usando o diffpriv.
A biblioteca diffpriv tem 4 mecanismos de adição de ruído para Privacidade Diferencial. Eles são:
-
Mecanismo de Laplace: O Mecanismo de Laplace vai simplesmente computar a função f() e perturbar cada registro com ruído e a escala do ruído vai ser calibrado de acordo com a sensibilidade preservando a privacidade (ε, 0); e
-
Mecanismo de Bernstein: É baseada no mecanismo desenvolvido no trabalho seminal de Alda e Rubinstein (2017). Este mecanismo faz o uso de polinômios de Bernstein para realizar a aproximação da função de privacidade trabalhando com perturbações aplicadas aos coeficientes ao invés dos perturbar os valores em si. Como os coeficientes são os únicos componentes da função que sofrerão perturbações, isso já e suficiente para preservação da privacidade.
Dito isso, vamos escolher o Mecanismo de Laplace que vai realizar a adição de ruído para manter as nossas respostas numéricas privativas.
Para isso vamos passar a nossa função retorna_media para esse mecanismo de Laplace (que vamos chamar de mecanismo_privacidade) da seguinte forma:
Dentro do mecanismo DPMechLaplace temos os seguintes atributos:
-
sensitivity: Essa variável vai determinar amplitude de pertubação inerente da função; perturbação esta que vamos passar para a nossa lista numérica. Em outras palavras, a sensibilidade é magnitude pela qual os dados de um único indivíduo podem alterar a função f no pior caso. Uma sensibilidade maior necessariamente aumenta a privacidade; mas também a incerteza/ruído nos dados;
-
target: É uma função não privada que terá o seu resultado (output) privatizado e espera uma lista de valores. O Mecanismo de Laplace espera funções que vão retornar como resultado vetores numéricos;
-
gammaSensitivity: Nível de confiança de privacidade. Significa que uma confiança alta vai demandar uma sensibilidade maior (e um espectro de ruído maior, ou seja mais incerteza nos dados e menos utilidade) enquanto um nível de confiança menor reduz o espectro de ruído, e com isso aumenta a a utilidade (pois tem menos incerteza/ruído) mas reduz o nível de privacidade.
Após a definição do nosso mecanismo de privacidade, vamos criar uma função escolhendo uma distribuição que iremos passar como ruído. Neste caso vamos escolher a distribuição normal ( rnorm) para gerar a quantidade de registros n (que no nosso caso vai ser o número de empregados) e faremos um teste de execução.
Eu multipliquei os resultados por 10.000 apenas para que o resultado desta lista ficasse na mesma escala que os salários. A distribuição deve sempre estar na mesma escala que a variável de resposta que será privatizada.
Uma peça importante que temos que criar é o mecanismo de geração amostral que vai levar em conta a sensibilidade que determinamos no mecanismo_privacidade além da função de distribuição que vai gerar as amostras randomizadas.
A intuição por trás do mecanismo de geração amostral baseado na sensibilidade (que no diffpriv é chamado de sensitivitySampler()) é que para cada registro na base de dados serão criados registros aleatórios independentes e identicamente distribuídas. usando o mecanismo de privacidade que escolhemos anteriormente. Tudo isso levando em consideração o fato de que o ruído será gerado de acordo com a sensibilidade escolhida (*i.e. *dentro de um determinado espectro de ruído).
Isso é implementado no diffpriv da seguinte forma:
A função sensitivitySampler() tem como parâmetros:
-
object: Um objeto da classe DPMech-class (isto é, um mecanismo de privacidade;
-
oracle: Um oráculo que será a fonte de registros aleatórios. Uma função que retorna uma lista, matriz ou data.frame;
-
n: Número de registros contido noconjunto de dados. Neste caso tem que ser exatamente consitente com o número de registros que passarão pelo processo de PD;
-
m: Valor inteiro que indica a sensibilidade em relação ao tamanho da amostra; e
-
gamma: Nível de confianca de privacidade de acordo com a função Rényi Differential Privacy (RDP) [NA3]
Com o nosso objeto mecanismo_resposta_privado criado, podemos verificar alguns dos seus valores executando o seguinte bloco de código:
Com o nosso mecanismo de resposta privativa criado, agora podemos partir para a parte em que geramos as nossas respostas privatizadas em relação à base de dados que criamos no começo deste post.
Para isso, vamos chamar a função releaseResponse como no snippet abaixo:
Os parâmetros do releaseResponse são:
-
mechanism: Um objeto do tipo DPMech-class, i.e., o sensitivitySample que instanciamos anteriormente que vai ser o responsável por gerar as nossas respostas randomizadas considerando o mecanismo que escolhemos (Laplace), a sensibilidade, a distribuição, e o grau de confiança;
-
privacyParams: Vai receber os parâmetros de privacidade como ε(épsilon). Quanto menor for o ε mais privacidade é mantida, mas a acurácia tem uma piora (por conta de mais ruído); se o valor do ε for muito grande significa que menos ruído é colocado; então haverá piora na privacidade; e
-
X: A base de dados que tem dados que precisam passar por PD.
Para obter as respostas privativas em relação à lista de salários que passamos (empregados$lista_salarios) precisamos executar o seguinte código:
Os resultados obtidos na minha execução foram:
# Lista Salarios
[1] "parametros_privacidade - gamma: 0.7"
[1] "parametros_privacidade - delta: 0"
[1] "parametros_privacidade - epsilon: 1"
[1] "resposta_sem_privacidade: 9830"
[1] "resposta_com_privacidade: 9213"
Neste caso, o salário médio que calculamos anteriormente da lista de funcionários era de 9830; e usando o mecanismo de privacidade diferencial o valor está em 9213. Lembrando que o objetivo aqui é ter a mesma dinâmica dos números mesmo com a adição de ruído em detrimento de obtermos a informação precisa (que pode revelar informações sensíveis dos funcionários).
A lista com a idade pode ser calculada usando os mesmos parâmetros através do script abaixo:
Neste caso eu tive o seguinte resultado:
# Lista Idade
[1] "parametros_privacidade - gamma: 0.5"
[1] "parametros_privacidade - delta: 0"
[1] "parametros_privacidade - epsilon: 1"
[1] "resposta_sem_privacidade: 45"
[1] "resposta_com_privacidade: 43"
Os valores na minha execução foram bem similares: 45 da média original, contra 43 com ruído de privacidade diferencial; mas dependendo da execução os dados podem ter outros valores devido ao fato de que não colocamos uma semente antes da execução.
Tradeoff: Utilidade x Privacidade
Dado que a utilização de mecanismos de Privacidade Diferencial sobre os dados implica necessariamente em alteração dos dados, é natural que o rigor seja reduzido, afinal de contas estamos colocando incerteza nos dados.
Sendo esse tradeoff utilidade (rigor/consistência) x privacidade (incerteza/ofuscação) algo certo quando utilizamos a Privacidade Diferencial, não exite regra definitiva que determine a utilização de um cenario ou outro, cabendo a utilização para as organizações e profissionais envolvidos.
Alguns modelos de arquitetura de sistemas de analise de dados considerando privacidde diferencial ja estão aparecendo e podem servir de inspiração, como o PriPeARL do Linkedin que garante privacidade *por design *na parte de relatorios e analytics.
Considerações Finais
A Privacidade Diferencial tem inúmeros casos de uso e dentro do contexto brasileiro em que um endurecimento regulatório aponta no horizonte com a Lei Geral de Proteção de Dados Pessoais (LGPD) é mais do que necessário que CTOs/CIOs/CDOs, analistas de dados, cientistas de dados, engenherios de machine learning e demais stakeholders estejam alinhados com esse tipo de mecanismo que protege os seus clientes e os seus proprios negócios.
A conformidade de um ambiente que lida com dados pessoas passa necessáriamente pela tríade {Privacidade Diferencial / Anonimização de Dados / Sistemas de Segurança Internos}; e é inocente pensar que apenas uma delas vai garantir o padrão mínimo de compliance entre todos os stakeholders.
Este post teve como objetivo apresentar a implementação de mecanismos de PD de forma descomplicada e prática. Existe uma infinidade de aspectos tecnicos a serem considerados como sensibilidade amostral, budget de privacidade, sensibilidade restrita e irrestrita, algorimos de domínio limitados, mecanismos de Pay-what-you-get, etc.
Comparado com o risco potencial de colocar pessoas em situação de fragilidade devido vazamento de dados pessoais não anomizados, e até mesmo o volume de passivo jurídico que isso pode causar; a Privacidade Diferencial se apresenta como uma ótima ferramenta para minimizar tais riscos.
Referências
-
Practical Differentially Private Top-k Selection with Pay-what-you-get Composition
-
The Bernstein Mechanism: Function Release under Differential Privacy
-
LinkedIn’s Audience Engagements API: A Privacy Preserving Data Analytics System at Scale
-
Pain-Free Random Differential Privacy with Sensitivity Sampling
-
The reusable holdout: Preserving validity in adaptive data analysis
-
The Bernstein Mechanism: Function Release under Differential Privacy
-
PriPeARL: A Framework for Privacy-Preserving Analytics and Reporting at LinkedIn
-
Practical Differentially Private Top-k Selection with Pay-what-you-get Composition
-
Difference between ε-differential privacy and (ε, δ)-differential privacy
Notas do Autor
[NA1] — Ataques adversariais do tipo “Inferência por Associação” são aqueles em que o atacante através de consulta ao modelo (pode ser um arquivo .R ou mesmo um binário) consegue inferir se um registro específico estava ou não no conjunto de treinamento através do uso de alguns atributos presentes no modelo. Na minha palestra de Segurança em Machine Learning eu mostro como as informações pessoais de uma senhora de 91 foi parar em um modelo de Machine Learning. O código está no Github.
[NA2] — Se você estiver usando o sistema operacional MacOS a instalação do gsl (Gnu Scientific Library) é obrigatória.
[NA3] — Nem a documentação ou paper são claros em relação à influência do nível de confiança no fator de relaxamento (ou não) da privacidade usando o RDP e a influência na sensibilidade.