Aprendizado de Máquina. Uma Introdução com a Linguagem Python

Propaganda
azevedolab.net
1
Modelagem de Sistemas
O fluxograma abaixo destaca o uso de uma abordagem computacional para o estudo
de sistemas biológicos, destacado em vermelho. Em verde temos a abordagem
experimental. Ao final comparamos os resultados para validar a abordagem
computacional.
Sistema
Biológico
Modelagem
Realiza
Simulações
Realiza
Experimentos
Resultados
Experimentais
Resultados das
Simulações
Compara
Testes dos
Modelos
2
Modelagem de Sistemas
A comparação é necessária para a validação da abordagem computacional, sem tal
etapa a modelagem fica sem base experimental para o estudo do sistema biológico a
ser simulado.
Sistema
Biológico
Modelagem
Realiza
Simulações
Realiza
Experimentos
Resultados
Experimentais
Resultados das
Simulações
Compara
Testes dos
Modelos
3
Quantitative Structure Activity Relationship
www.python.org
A abordagem moderna do desenho e
desenvolvimento de fármacos é resultado
de um processo iterativo. Em cada
iteração (ciclo de desenvolvimento),
espera-se que a atividade farmacológica
da molécula seja aprimorada, de forma
que haja uma evolução no processo
(otimização da atividade farmacológica).
O diagrama ao lado ilustra o ciclo. No
processo iterativo, a molécula é
desenhada e passa para síntese. Neste
ponto pode ser necessário retorno à fase
de desenho, caso a síntese apresente
desafios, não previstos na fase de
desenho.
Quantitative Structure Activity Relationship
www.python.org
Chegando-se à fase de teste, a atividade
é averiguada e os resultados relacionados
à estrutura do fármaco em potencial.
Neste processo podemos inserir uma fase
de análise, onde elaboramos um modelo
computacional. O modelo permite que a
atividade da molécula seja relacionada
com sua estrutura, ou seja, um estudo da
Relação Quantitativa-Estrutura-Atividade
(Quantitative
Structure-Activity
Relationship, QSAR). Neste estudo,
descritores
moleculares
são
relacionados à atividade da molécula, e
uma análise estatística dos descritores
leva a um modelo, que pode ser usado
para prever atividade farmacológica.
QSAR
Quantitative Structure Activity Relationship
www.python.org
A abordagem de QSAR foi introduzida
pelo trabalho pioneiro de Corwin Hansch
na década de 1960, no seu estudo da
atividade biológica de uma série de
compostos relacionados estruturalmente.
A atividade biológica pode ser relacionada
com a estrutura molecular, a partir de
equações como a descrita abaixo:
 1
log    0   1 logP    2
C 
onde C é a concentração molar de um
composto necessário para produzir uma
dada atividade biológica, por exemplo
IC50, log P é o coeficiente de partição
entre octanol e água,  é outro descritor
molecular, como número de doadores de
ligação de hidrogênio da molécula.
Descritores moleculares descrevem propriedade gerais de
uma dada molécula, que podem estar relacionadas com a
atividade farmacológica. Por exemplo, um logP abaixo de 5,
indica que a molécula tem baixa hidrofobicidade,
aumentando as chances de disponibilidade oral.
Fonte
da
imagem:
http://www.sciencephoto.com/media/350656/enlarge
Acesso em: 25 de novembro de 2016.
Hansch, C., Ruth, A.S., Anderson, S.M., Bentley, D.L.
Parabolic dependence of drug action upon lipophilic
character as revealed by study of hypnotics. J. Med Chem 11
(1968) 1-11.
Quantitative Structure Activity Relationship
www.python.org
Várias metodologias têm sido usadas
para elaborar modelos de QSAR, sendo
regressão a mais aplicada, colocada na
sua forma linear, a equação de regressão
tem o seguinte aspecto: y = 0 + 1 x
onde y é a variável dependente (a
propriedade biológica a ser modelada),
um exemplo de variável dependente
usada em QSAR é log (1/IC50). IC50 é a
constante inibitória para que a
atividade biológica caia 50 %. O termo x
é a variável independente (descritor
molecular), como exemplos de variáveis
independentes, usadas em QSAR, temos
o log P, número de ligações rotáveis,
número de doadores de ligação de H etc.
O 1 é coeficiente angular da reta, ou do
ponto de vista de otimização, o peso da
variável x e 0 é a constante de
regressão.
Reta (em vermelho) obtida por regressão linear para um
conjunto de pontos experimentais (pontos azuis).
O gráfico foi gerado com o programa Mathematica
(http://demonstrations.wolfram.com/VisualizingrsquareddInSt
atistics/)
Acesso em: 25 de novembro de 2016.
Quantitative Structure Activity Relationship
www.python.org
Não é objetivo do presente curso ir a fundo em métodos numéricos, mas a matemática
necessária para entendermos a regressão linear é simples, por isso vamos ver as
equações usadas no método. Nas equações abaixo, os termos entre < > indicam
média aritmética. Na regressão linear, os coeficientes ’s são dados pelas seguintes
equações,
N
1 
 ( x i  x )( y i  y )
 0  y  1 x
i 1
N
2
 (xi  x )
i 1
As linhas descritas por regressão linear passam pelo ponto médio ( x , y ), onde <x>
e <y> são as médias das variáveis independente e dependente, respectivamente,
como mostrada nas equações abaixo, N é o número de dados disponíveis (pares x,y):
1 N
x   xi
N i 1
1 N
y   yi
N i 1
Quantitative Structure Activity Relationship
www.python.org
Vamos considerar um conjunto de 20 pontos, mostrados na tabela abaixo. Usaremos
estes dados para calcular a melhor reta, a partir das equações da regressão linear. O
Excel já tem uma função de regressão, usaremos o exemplo abaixo para explicitar os
termos.
X
Y
Numa abordagem algorítmica para resolução do
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
2
1.25
1.5
4
5.1
6.3
5
8.7
9
11
14
13.75
15
18
17.5
19
17
21
22.5
26
25.1
problema, temos como primeiro passo o cálculo da
média, com as equações abaixo:
x 
1 N
y   yi
N i 1
1
 xi
N i 1
N
Em seguida calculamos 1, com a equação a seguir:
N
1 
 ( x i  x )( y i  y )
i 1
Por último calculamos 0.
 0  y  1 x
N
2
 (xi  x )
i 1
Quantitative Structure Activity Relationship
www.python.org
Temos a seguinte sequencia de
cálculos:
1) Médias
1 N
x   x i  1,05
N i 1
1 N
y   y i  13,035
N i 1
2)
Cálculo do 1
N
1 
 ( x i  x )( y i  y )
i 1
N
2
 (xi  x )

85,795
6,65
i 1
 12,902
3)
Cálculo do 0
0 
y
x
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
2
1.05
y
1.25
1.5
4
5.1
6.3
5
8.7
9
11
14
13.75
15
18
17.5
19
17
21
22.5
26
25.1
13.035
 1 x
x- <x>
-0.95
-0.85
-0.75
-0.65
-0.55
-0.45
-0.35
-0.25
-0.15
-0.05
0.05
0.15
0.25
0.35
0.45
0.55
0.65
0.75
0.85
0.95
y-<y> (x-<x>)(y-<y>)
(x-<x>)^2
-11.785
11.19575
0.9025
-11.535
9.80475
0.7225
-9.035
6.77625
0.5625
-7.935
5.15775
0.4225
-6.735
3.70425
0.3025
-8.035
3.61575
0.2025
-4.335
1.51725
0.1225
-4.035
1.00875
0.0625
-2.035
0.30525
0.0225
0.965
-0.04825
0.0025
0.715
0.03575
0.0025
1.965
0.29475
0.0225
4.965
1.24125
0.0625
4.465
1.56275
0.1225
5.965
2.68425
0.2025
3.965
2.18075
0.3025
7.965
5.17725
0.4225
9.465
7.09875
0.5625
12.965
11.02025
0.7225
12.065
11.46175
0.9025
85.795
6.65

 13,035  12,902.1,05  0,512
Quantitative Structure Activity Relationship
www.python.org
No final temos a melhor reta (equação de regressão), indicada abaixo:
y = 1x + 0
y =12,902x – 0,512
Y
0.1 1.25
0.2
1.5
0.3
4
0.4
5.1
0.5
6.3
0.6
5
0.7
8.7
0.8
9
0.9
11
1
14
1.1 13.75
1.2
15
1.3
18
1.4 17.5
1.5
19
1.6
17
1.7
21
1.8 22.5
1.9
26
2 25.1
30
25
Variável dependente
X
20
15
10
5
0
0
0,5
1
1,5
2
2,5
Variável independente
Na elaboração de modelos de QSAR, normalmente temos mais de uma
variável independente, o que leva ao uso de regressão linear múltipla.
Outro nível de abstração do modelo de QSAR, é o uso de variáveis
independentes não lineares. Tais métodos de aproximação estão
disponíveis em pacotes como o Mathematica (www.wolfram.com). Além
disso, podemos implementar os métodos de regressão linear, a partir
da linguagem de programação Python.
Quantitative Structure Activity Relationship
www.python.org
Tanto nos modelos de QSAR, obtidos por regressão linear, como para aqueles obtidos
por regressão linear múltipla, ou mesmo não linear, temos que acessar a qualidade do
modelo de regressão, ou seja, a qualidade do ajuste da curva (ou reta) modelada,
contra os pontos experimentais (yi). Um dos parâmetros usados, é o coeficiente de
correlação quadrado (R2). Considere que ycalc,i são valores calculados a partir da
equação de regressão, usando observações experimentais xi. Assim temos os
seguintes termos: soma total dos quadrados (Total Sum of Squares, TSS), soma
dos quadrados “explicada” (Explained Sum of Squares, ESS) e soma residual dos
quadrados (Residual Sum of Squares):
TSS   y i  y
N
i 1

2
ESS   y calc ,i  y
N
i 1

2
Que são usados para o cálculo de R2, como segue:
RSS
R  1
TSS
2
RSS   y i  y calc ,i 
N
i 1
2
Quantitative Structure Activity Relationship
www.python.org
x
y
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
2
1.05
1.25
1.5
4
5.1
6.3
5
8.7
9
11
14
13.75
15
18
17.5
19
17
21
22.5
26
25.1
13.035
x-<x>
-0.95
-0.85
-0.75
-0.65
-0.55
-0.45
-0.35
-0.25
-0.15
-0.05
0.05
0.15
0.25
0.35
0.45
0.55
0.65
0.75
0.85
0.95
y-<y>
-11.785
-11.535
-9.035
-7.935
-6.735
-8.035
-4.335
-4.035
-2.035
0.965
0.715
1.965
4.965
4.465
5.965
3.965
7.965
9.465
12.965
12.065
ycalc,i
0.7782
2.0684
3.3586
4.6488
5.939
7.2292
8.5194
9.8096
11.0998
12.39
13.6802
14.9704
16.2606
17.5508
18.841
20.1312
21.4214
22.7116
24.0018
25.292
RSS   y i  y calc ,i   26,66599
N
i 1
R2  1
2
(y-ycalc,i)^2
0.22259524
0.32307856
0.41139396
0.20358144
0.130321
4.96933264
0.03261636
0.65545216
0.00996004
2.5921
0.00487204
0.00087616
3.02551236
0.00258064
0.025281
9.80441344
0.17757796
0.04477456
3.99280324
0.036864
26.6659868
(y-<y>)^2
(ycalc,i-<y))^2
138.886225 150.2291462
133.056225 120.2663156
81.631225 93.63271696
62.964225 70.32835044
45.360225
50.353216
64.561225 33.70731364
18.792225 20.39064336
16.281225 10.40320516
4.141225
3.74499904
0.931225
0.416025
0.511225
0.41628304
3.861225
3.74577316
24.651225 10.40449536
19.936225 20.39244964
35.581225
33.709636
15.721225 50.35605444
63.441225 70.33170496
89.586225 93.63658756
168.091225 120.2707022
145.564225
150.234049
1133.5505 1106.969667
TSS   y i  y
RSS
26,66599
 1
 0,9765
TSS
1133,551
N
i 1
2  1133,551
Quantitative Structure Activity Relationship
www.python.org
O coeficiente de correlação quadrado mede a qualidade do ajuste da função
teórica (equação de regressão) aos pontos experimentais. Esse índice varia de 0
a 1. O valor zero não indica correlação entre os dados. Para R2 igual a 1, ou próximo
desse, temos uma equação de regressão com boa correlação como os dados
experimentais. A equação de regressão obtida, no exemplo apresentado, tem
excelente correlação, R2 = 0,9765, tal concordância pode ser vista na análise do
gráfico, onde todos os pontos experimentais estão próximos à reta de regressão.
30
y = 1x + 0
y =12,902x – 0,512
R2 = 0,9765
Variável dependente
25
20
15
10
5
0
0
0,5
1
1,5
Variável independente
2
2,5
Quantitative Structure Activity Relationship
www.python.org
É óbvio que sistemas biológicos,
caracterizados por uma dada atividade,
raramente podem ser modelados com
funções lineares simples. A introdução de
variáveis independentes no modelo de
QSAR leva, muitas vezes, a um modelo
mais robusto, onde características
químicas relevantes (descritores) são
considerados. Contudo, o princípio da
parcimônia deve ser adotado, ou seja,
nem sempre um modelo com mais
variáveis independentes é o mais
adequado para modelar a atividade
biológica. Colocaremos como exemplo o
uso do programa Mathematica para
encontrarmos modelos matemáticos para
conjuntos
de
dados.
Depois
implementaremos em Python.
Polinômio de grau 2 (-0,634408x2 + 1,24534x + 0,0807008)
usado para aproximar os cinco pontos experimentais
mostrados acima.
O gráfico foi gerado com o programa Mathematica
(http://demonstrations.wolfram.com/CurveFitting/)
Acesso em: 25 de novembro de 2016.
Quantitative Structure Activity Relationship
www.python.org
A idéia básica atrás da aproximação de uma
função é usar uma lista de funções
matemáticas especificadas antecipadamente,
e tentar encontrar uma combinação linear
dessas funções dadas, de forma que essa
combinação linear de funções fique o mais
próximo possível do conjunto de dados.
Vamos ilustrar as idéias principais com
exemplos. Vamos considerar um conjunto
formado pelos 19 pontos experimentais,
indicados na tabela ao lado.
Para
colocar
essas
informações
no
Mathematica digitamos:
x
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
y
34.8105
35.381
35.8167
40.6048
47.0132
42.4577
43.1319
37.3182
33.6343
28.0988
28.3107
29.9822
27.2542
33.407
35.4875
38.1126
41.57
42.1533
39.5108
data={{73.,34.8105},{74.,35.381},{75.,35.8167},{76.,40.6048},{77., 47.0132},
{78., 42.4577},{79., 43.1319}, {80.,37.3182},{81.,33.6343},{82.,28.0988},
{83.,28.3107},{84.,29.9822},{85.,27.2542},{86.,33.407},{87.,35.4875},{88.,38.11
26},{89.,41.57},{90.,42.1533},{91.,39.5108}};
Quantitative Structure Activity Relationship
www.python.org
Vamos gerar o gráfico dos pontos experimentais e conectá-los. Para isto definimos lp1
e lp2 que no Mathematica fica da seguinte forma:
lp1=ListPlot[data,PlotStyle->PointSize[0.03],DisplayFunction->Identity];
lp2=ListPlot[data,PlotJoined->True, DisplayFunction->Identity];
Agora preparamos o gráfico, digitando:
Show[lp1,lp2, DisplayFunction->$DisplayFunction]
O resultado é mostrado ao lado.
Quantitative Structure Activity Relationship
www.python.org
Vamos gerar curvas que ajustem-se ao conjunto de dados experimentais. Podemos
testar vários cenários, esta é uma das vantagens de usarmos um pacote poderoso
como o Mathematica, ou ainda uma linguagem de programação como o Python, que
veremos adiante. Para gerarmos um ajuste por regressão linear e graficarmos os
resultados, usamos os seguintes comandos:
Clear[p]
p=Fit[data,{1,x},x]
plotp=Plot[p,{x,71,93},DisplayFunction->Identity];
Show[plotp,lp1,PlotRange->{0,50},DisplayFunction->$DisplayFunction]
Os resultados são mostrados no gráfico.
A equação de regressão é:
Y= 42.2346 -0.0695772 x
Vemos pelo gráfico que o ajuste é
insatisfatório.
Quantitative Structure Activity Relationship
www.python.org
Vamos tentar uma nova curva, com um polinômio com x e x2, para isto basta
mudarmos a linha de comando Fit (indicado em vermelho), o restante é mantido.
Clear[p]
p=Fit[data,{1,x,x^2},x]
plotp=Plot[p,{x,71,93},DisplayFunction->Identity];
Show[plotp,lp1,PlotRange->{0,50},DisplayFunction->$DisplayFunction]
Os resultados são mostrados no gráfico.
A equação de regressão é:
Y= 549.149 -12.4887 x+0.0757266 x2
Vemos pelo gráfico que o ajuste é
Insatisfatório. No próximo slide temos
aproximações para polinômios até o grau 5.
Quantitative Structure Activity Relationship
www.python.org
Nas figuras a seguir temos ajustes para diversas funções polinomiais.
Aproximação com polinômio de grau 3
Aproximação com polinômio de grau 4
y = -13615.6+508.522 x-6.29506 x2+0.0258975 x3
y = -198884.+9597.83 x-173.196 x2+1.38539 x3-0.00414481 x4
A última função (com termos até a quinta potência)
é a que melhor se ajusta aos pontos experimentais.
y = 2.82867×106-176099. x+4376. x2-54.2556 x3+0.335627 x4-0.000828711 x5
Programa: qsar1.py
www.python.org
Usaremos o programa qsar1.py, as linhas
de código estão no próximo slide. O gráfico
gerado está na figura ao lado. O arquivo de
entrada é o data2.csv. A equação
polinomial está mostrada abaixo. Veja que
o resultado está próximo ao obtido com o
Mathematica para o polinômio de grau 5.
Type CSV file name => data2.csv
Type polynomial equation degree => 5
Best fit polynomial equation:
5
4
3
2
-0.0008287 x + 0.3356 x - 54.26 x + 4376 x - 1.761e+05 x + 2.829e+0
21
Programa: qsar1.py
www.python.org
Abaixo temos a função main(). Inicialmente chamamos a função read_csv() que
retorna as colunas lidas como array e o grau do polinômio a ser aproximado aos
pontos experimentais. Em seguida é chamada a função lsq() que determina o
polinômio. Por último, é chamada a função gen_plot() que gera o gráfico.
def main():
# Call read_csv()
x,y,my_deg = read_csv()
# Call lsq()
p = lsq(x,y,my_deg)
# Call gen_plot()
gen_plot(x,y,p)
main()
22
Programa: qsar1.py
www.python.org
Abaixo temos a função read_csv(), que retorna as duas colunas lidas do arquivo csv
como arrays. Além do grau do polinômio.
def read_csv():
"""Function to read csv"""
import numpy as np
# Reads input file name and polynomial equation degree
my_input_file = input("Type CSV file name => ")
my_deg = int(input("Type polynomial equation degree => "))
# Reads CSV file
my_csv = np.genfromtxt (my_input_file, delimiter=",", skip_header = 1)
# Gets each column from CSV file
x = my_csv[:,0]
y = my_csv[:,1]
return x,y,my_deg
23
Programa: qsar1.py
www.python.org
Abaixo temos a função lsq() que determina os coeficientes do polinômio por meio do
método de regressão.
def lsq(x,y,my_deg):
"""Function to generate regression model"""
import numpy as np
# Least-squares polynomial fitting
z = np.polyfit(x,y, my_deg)
p = np.poly1d(z)
print("\nBest fit polynomial equation: ",p)
return p
24
Programa: qsar1.py
www.python.org
Por último a função gen_plot() gera o gráfico da função.
ddef gen_plot(x,y,p):
"""Function to generate plot"""
import matplotlib.pyplot as plt
# Generates plot
plt.scatter(x,y)
# Generates plot
plt.plot(x, p(x), '-')
# Shows plot
plt.show()
# Saves plot on png file
plt.savefig('qsar1.png')
25
Programa: qsar2.py
www.python.org
Vimos que o coeficiente de correlação ao
quadrado (R2) é usado para atestar a
qualidade de um modelo obtido por
regressão. A biblioteca NumPy tem a
função np.corrcoef(x,y)[0,1], para o cálculo
do coeficiente de correlação (R) entre os
arrays x e y. A partir deste valor, basta
elevarmos ao quadrado para obtermos R2.
O código qsar2.py traz esta função. Se
usarmos o programa qsar2.py, com o
arquivo data1.csv, podemos conferir com os
resultados anteriormente determinados. O
gráfico está ao lado. Os resultados estão
no quadro abaixo. O código está no
próximo slide, com as linhas em vermelho
indicando as modificações com relação ao
qsar1.py.
Type CSV file name => data1.csv
Type polynomial equation degree => 1
Best fit polynomial equation:
12.9 x - 0.5116 , R^2 = 0.976475697411
26
Programa: qsar2.py
www.python.org
A única modificação no programa qsar2.py é na função lsq() que agora calcula o R2,
como destacado abaixo.
def lsq(x,y,my_deg):
"""Function to generate regression model"""
import numpy as np
# Least-squares polynomial fitting
z = np.polyfit(x,y, my_deg)
p = np.poly1d(z)
rsquare = (np.corrcoef(y,p(x))[0,1] )**2
print("\nBest fit polynomial equation: ",p,", R^2 = ",rsquare)
return p
27
SciKit-Learn
www.python.org
Já vimos programas que faziam uso de funções pré-definidas das bibliotecas NumPy
e Matplotlib. Agora continuaremos a expandir nosso arsenal de bibliotecas, com
alguns programas que usam recursos da biblioteca scikit-learn. Esta biblioteca é
dedicada a disponibilizar para comunidade de programadores em Python
ferramentas de aprendizado de máquina. Usaremos scikit-learn para resolver um
problema simples e depois aplicaremos o que aprendemos para um problema para a
previsão de atividade de uma série de fármacos contra câncer.
“Machine Learning is the study
and design of programs that
improve the performance of a task
by learning from experience. It is
the study of programs that learn
from data.”
HACKELING G. Mastering
Machine Learning with scikitlearn. Birmingham: Packt
Publishing Ltd., 2014. 221 p.
Página de entrada do site scikit-learn.org.
Acesso em 25 de novembro de 2016.
28
SciKit-Learn
www.python.org
Vamos supor que você quer usar métodos de aprendizado de máquina para prever o
preço de uma pizza. Você foi recentemente 5 vezes ao Blondie’s Pizza e comprou
pizzas de diferentes diâmetros, como detalhado na tabela abaixo.
Índice do Dado do
Conjunto Treino
Diâmetro da Pizza (cm) Preço (R$)
1
15,0
24,50
2
20,0
31,50
3
25,0
45,50
4
35,0
61,25
5
45,0
63,00
29
SciKit-Learn (pizza1.py)
www.python.org
Abaixo temos a função main() que evoca as funções read_CSV() e
gen_scatter_plot1(). Veja que a primeira função a ser evocada é a read_CSV(), que
retorna os arrays x e y que são passados como argumentos da função
gen_scatter_plot1().
def main():
# Call read_CSV() function
x,y = read_CSV()
# Call gen_scatter_plot1()
gen_scatter_plot1(x,y,"Diameter (cm)","R$","Pizza Price vs
Diameter","pizza1.png")
main()
30
SciKit-Learn (pizza1.py)
www.python.org
Iremos gerar um gráfico de dispersão para os dados da tabela anterior (arquivo
pizza1.csv) com os recursos da biblioteca Matplotlib. O programa pizza1.py tem duas
funções, uma para leitura de um arquivo no formato CSV (read_CSV()) e outra para
o gráfico de dispersão dos pontos. Abaixo temos a função read_CSV(). Nesta função
importamos a biblioteca NumPy, em seguida lemos o nome do arquivo de entrada.
Depois usamos o genfromtxt() para realizarmos a leitura de um arquivo no formato
CSV. As colunas são atribuídas como arrays às variáveis x e y. Estes arrays retornam
ao trecho onde a função foi evocada.
def read_CSV():
"""Function to read a CSV file and return two columns"""
import numpy as np
# Reads input file name
my_input_file = input("Type CSV file name => ")
# Reads CSV file
my_csv = np.genfromtxt (my_input_file, delimiter=",", skip_header = 1)
# Gets each column from CSV file
x = my_csv[:,0]
y = my_csv[:,1]
return x,y
31
SciKit-Learn (pizza1.py)
www.python.org
Abaixo temos a função gen_scatter_plot1(), que gera o gráfico de dispersão. Nesta
função temos os recursos do Matplotlib vistos anteriormente.
def gen_scatter_plot1(x,y,x_label,y_label,title,output_file):
"""Function to generate scatter plot"""
import matplotlib.pyplot as plt
# Generates plot
plt.scatter(x,y)
# Title
plt.title(title)
# X-axis label
plt.xlabel(x_label)
# Y-axis label
plt.ylabel(y_label)
# Grid
plt.grid(True)
# Shows plot
plt.show()
# Saves plot on png file
plt.savefig(output_file)
32
SciKit-Learn (pizza1.py)
www.python.org
Abaixo temos a execução do código pizza1.py, onde usamos o arquivo pizza1.csv
como entrada. O programa gera o gráfico pizza1.png, também mostrado abaixo.
Type CSV file name => pizza1.csv
33
SciKit-Learn (Regressão Linear Simples)
www.python.org
Retornamos à tabela do arquivo pizza1.csv. Vamos supor que você queira saber,
baseado nas informações da tabela abaixo, o preço de uma pizza com diâmetro de
30 cm.
Índice do Dado do Diâmetro da Pizza (cm) Preço (R$)
Conjunto Treino
1
15,0
24,50
2
20,0
31,50
3
25,0
45,50
4
35,0
61,25
5
45,0
63,00
Veja, não temos na tabela o diâmetro de 30 cm, mas podemos usar a informação
conhecida, chamada de observações passadas, no jargão de aprendizado da
máquina, para prever o preço de uma pizza com 30 cm de diâmetro. Para esta
previsão, usaremos o método de regressão linear simples, onde as observações
passadas serão usadas para elaborarmos um modelo (equação) para a previsão do
preço.
34
SciKit-Learn (Regressão Linear Simples)
www.python.org
Para nos familiarizarmos com a notação dos métodos de aprendizado de máquina,
vamos definir os termos necessários para a elaboração do modelo de regressão
linear.
Variável explanatória
Variável resposta
Índice do Dado do
Conjunto Treino
Diâmetro da Pizza (cm) Preço (R$)
1
15,0
24,50
2
20,0
31,50
3
25,0
45,50
4
35,0
61,25
5
45,0
63,00
Conjunto treino
A variável diâmetro é chamada variável explanatória e o preço correspondente é a
variável resposta, os valores conhecidos destas variáveis compõem o conjunto
treino (training data). O método de regressão é chamado de método de
aprendizado supervisionado, visto que usamos as observações passadas, para
obter um modelo contínuo entre variável resposta e a variável explanatória.
35
SciKit-Learn (Regressão Linear Simples)
www.python.org
Vimos a função polyfit() da biblioteca NumPy para realizar a regressão linear. Na
biblioteca SciKit-learn temos o método linear_model.LinearRegression(). Vamos
ilustrar seu uso no programa pizza2.py. Mas antes de iniciarmos o código, devemos
fazer algumas considerações sobre o uso de métodos das bibliotecas do Python.
Essas bibliotecas facilitam a vida do programador, pois disponibilizam métodos
sofisticados, prontos para uso. Por outro lado, temos que estar atentos à estrutura
dos dados que são inseridos nos métodos. No nosso exemplo do preço da pizza, se
colocarmos um print() para os arrays x e y, que retornam da função read_CSV(),
teremos o seguinte resultado.
[ 15. 20. 25. 35. 45.]
[ 24.5 31.5 45.5 61.25 63. ]
O que funcionou bem quando foram passados para a função gen_scatter_plot1(). Por
outro lado, para usarmos o método linear_model.LinearRegression(), temos que ter
os arrays na seguinte estrutura.
[[15.0], [20.0], [25.0], [35.0], [45.0]]
[[24.5], [31.5], [45.5], [61.25], [63.0]]
Assim, temos que converter os arrays para a estrutura acima, caso contrário teremos
uma mensagem de erro ao executar o código.
36
SciKit-Learn (Regressão Linear Simples) (pizza2.py)
www.python.org
O programa pizza2.py tem uma função para converter os arrays, chamada
convert2scikit(). O código está mostrado abaixo. O que a função faz é basicamente
receber um array x e convertê-lo num array de arrays. Para isto a função varre o
array de entrada e atribui o elemento do array a uma lista (list0) que então é passada
para o array de arrays (X). A função retorna o array modificado.
def convert2scikit(x):
"""Function to convert array to scikit-learn format"""
# Set up empty lists
X = []
list0 = []
# Looping through x
for line in x:
# Converts element to list
list0.append(line)
# Append list to list
X.append(list0)
list0 = []
# Return new array
return X
37
SciKit-Learn (Regressão Linear Simples) (pizza2.py)
www.python.org
Para geramos o modelo, usamos a função simple_linear_regression1(). Os arrays
x_in e y_in são os parâmetros da função. Explicaremos cada linha. Inicialmente
importamos o método linear_model da biblioteca simple_linear_regression1. Também
importamos a biblioteca NumPy, ambas indicadas em vermelho abaixo.
def simple_linear_regression1(x_in,y_in):
"""Function to generate a linear regression model for one explanatory variable
and their response variable. This function uses
sklearn.linear_model.LinearRegression method."""
# Import library
from sklearn import linear_model
import numpy as np
# Create and fit the model
model = linear_model.LinearRegression()
model.fit(x_in, y_in)
# Get Linear Model
alpha1 = float(model.coef_)
const = float(model.intercept_)
z = np.array([alpha1,const])
p = np.poly1d(z)
A classe sklearn import linear_model é
um “estimador”, que é usado para
prever um valor, baseado em dados
observados.
print("\nBest fit linear regression model: ",p)
return p
38
SciKit-Learn (Regressão Linear Simples) (pizza2.py)
www.python.org
Para criarmos o modelo de regressão linear (model), usamos o comando model =
linear_model.LinearRegression(), que permite que usemos o método para regressão
linear, chamado .fit(), como indicado abaixo. O método .fit() ajusta uma reta com
equação y = const + alpha1.x aos pontos do conjunto treino.
def simple_linear_regression1(x_in,y_in):
"""Function to generate a linear regression model for one explanatory variable
and their response variable. This function uses
sklearn.linear_model.LinearRegression method."""
# Import library
from sklearn import linear_model
import numpy as np
# Create and fit the model
model = linear_model.LinearRegression()
model.fit(x_in, y_in)
# Get Linear Model
alpha1 = float(model.coef_)
const = float(model.intercept_)
z = np.array([alpha1,const])
p = np.poly1d(z)
print("\nBest fit linear regression model: ",p)
return p
39
SciKit-Learn (Regressão Linear Simples) (pizza2.py)
www.python.org
A constante da reta pode ser obtida a partir do comando const =
float(model.intercept_) e o coeficiente angular pode ser determinado a partir do
comando, alpha1 = float(model.coef_), como indicado abaixo.
def simple_linear_regression1(x_in,y_in):
"""Function to generate a linear regression model for one explanatory variable
and their response variable. This function uses
sklearn.linear_model.LinearRegression method."""
# Import library
from sklearn import linear_model
import numpy as np
# Create and fit the model
model = linear_model.LinearRegression()
model.fit(x_in, y_in)
# Get Linear Model
alpha1 = float(model.coef_)
const = float(model.intercept_)
z = np.array([alpha1,const])
p = np.poly1d(z)
print("\nBest fit linear regression model: ",p)
return p
40
SciKit-Learn (Regressão Linear Simples) (pizza2.py)
www.python.org
A seguir montamos um array com a constante e coeficiente angular, com o comando,
z = np.array([alpha1,const]). O array z é usado para gerar a equação da reta, com o
comando p = np.poly1d(z). Por último, a equação da reta de regressão linear é
mostrada na tela e retornamos o p para o programa principal.
def simple_linear_regression1(x_in,y_in):
"""Function to generate a linear regression model for one explanatory variable
and their response variable. This function uses
sklearn.linear_model.LinearRegression method."""
# Import library
from sklearn import linear_model
import numpy as np
# Create and fit the model
model = linear_model.LinearRegression()
model.fit(x_in, y_in)
# Get Linear Model
alpha1 = float(model.coef_)
const = float(model.intercept_)
z = np.array([alpha1,const])
p = np.poly1d(z)
print("\nBest fit linear regression model: ",p)
return p
41
SciKit-Learn (Regressão Linear Simples) (pizza2.py)
www.python.org
A função gen_scatter_plot2() traz como novidade a inclusão da equação da reta p
como parâmetro e uma linha de código para incluir a reta no gráfico, destacada em
vermelho no código abaixo. O restante do código é o mesmo da função
gen_scatter_plot1(), vista no programa pizza1.py.
def gen_scatter_plot2(x,y,p,x_label,y_label,title,output_file):
"""Function to generate scatter plot"""
import matplotlib.pyplot as plt
# Generates plot
plt.scatter(x,y)
# Title
plt.title(title)
# X-axis label
plt.xlabel(x_label)
# Y-axis label
plt.ylabel(y_label)
# Grid
plt.grid(True)
# Generates plot
plt.plot(x, p(x), '-')
# Shows plot
plt.show()
# Saves plot on png file
plt.savefig(output_file)
Gera o gráfico da reta
42
SciKit-Learn (Regressão Linear Simples) (pizza2.py)
www.python.org
A função main() evoca duas vezes a função convert2scikit(), em seguida evocamos a
função simple_linear_regression1(). Depois mostramos o valor previsto para preço
da pizza de 30 cm e, por ultimo, chamamos a função gen_scatter_plot2() para
gerarmos o gráfico.
def main():
# Call read_CSV() function
x,y = read_CSV()
# Call convert2scikit(x)
xs = convert2scikit(x)
ys = convert2scikit(y)
# Call simple_linear_regression1()
p = simple_linear_regression1(xs,ys)
# Predict the price for 30 cm pizza
pred = p(30)
print("Predicted price for 30 cm pizza (R$): %.2f"%pred)
# Call gen_scatter_plot2()
gen_scatter_plot2(x,y,p,"Diameter (cm)","R$","Pizza Price vs
Diameter","pizza2.png“
main()
43
SciKit-Learn (Regressão Linear Simples) (pizza2.py)
www.python.org
Vejam que ao usarmos a linha de comando pred = p(30) colocamos como argumento
da equação p o valor 30. A equação p é a equação obtida por regressão linear,
quando evocamos a função simple_linear_regression1().
def main():
# Call read_CSV() function
x,y = read_CSV()
# Call convert2scikit(x)
xs = convert2scikit(x)
ys = convert2scikit(y)
# Call simple_linear_regression1()
p = simple_linear_regression1(xs,ys)
# Predict the price for 30 cm pizza
pred = p(30)
print("Predicted price for 30 cm pizza (R$): %.2f"%pred)
# Call gen_scatter_plot2()
gen_scatter_plot2(x,y,p,"Diameter (cm)","R$","Pizza Price vs
Diameter","pizza2.png“
main()
44
SciKit-Learn (pizza2.py)
www.python.org
Abaixo temos a execução do código pizza2.py, onde usamos o arquivo pizza1.csv
como entrada. O programa gera o gráfico pizza2.png, também mostrado abaixo. A
linha azul do gráfico é a equação obtida por regressão linear.
Type CSV file name => pizza1.csv
Best fit linear regression model:
1.367 x + 6.879
Predicted price for 30 cm pizza (R$): 47.88
45
SciKit-Learn (pizza2.py)
www.python.org
De forma resumida, podemos dizer que a melhor reta é aquela que minimiza a
distância dos pontos experimentais (dados do conjunto treino) para a reta.
Matematicamente, a equação da reta (p) tem a seguinte forma:
p  0  1 x1
Onde p tem o valor estimado (teórico) para o preço da pizza e x1 recebe o valor do
diâmetro da pizza( variável explanatória). Os coeficientes (0 e 1) são determinados
de forma minimizar a diferença entre p e os valores experimentais do preço da pizza
(yi), ou seja, minimizam a soma do quadrado dos resíduos (Residual Sum of
Squares):
RSS 
N
2


y

p
i
i

i 1
A somatória é feita para todos os pontos do conjunto treino.
46
SciKit-Learn (Regressão Linear Simples) (pizza3.py)
www.python.org
Muito bem, temos um modelo para previsão do preço da pizza, mas o quão confiável
é nosso modelo? Vamos supor que vimos um anuncio da Blondie’s pizza com a
seguinte tabela de preços (pizza2.csv). Esta informação não foi usada para obtermos
o modelo de regressão, tal conjunto de dados é chamado de conjunto teste (test
set). Adicionamos uma coluna com os valores previstos pelo nosso modelo. O
conjunto teste pode ser usado para avaliar o poder de previsão do nosso modelo.
Índice do Dado do
Conjunto Test
Diâmetro da Pizza
(cm)
Preço (R$)
Preço Previsto
pelo Modelo
(R$)
1
20,0
38,50
34,22
2
22,5
29,75
37,63
3
27,5
52,50
44,47
4
40,0
63,00
61,55
5
30,0
38,50
47,88
47
Quantitative Structure Activity Relationship
www.python.org
Para acessar a qualidade do modelo de regressão, ou seja, a qualidade do ajuste da
curva (ou reta) modelada, contra os pontos experimentais (yi), podemos calcular o
coeficiente r2. Considere que pi são valores calculados a partir da equação de
regressão, usando observações experimentais xi. Assim temos os seguintes termos:
soma total dos quadrados (Total Sum of Squares, TSS), soma dos quadrados
“explicada” (Explained Sum of Squares, ESS) e soma residual dos quadrados
(Residual Sum of Squares):
TSS 
  yi 
N
i 1
p

2
ESS 
  pi 
N
p

2
i 1
RSS 
N
y
 pi 
2
i
i 1
O termo <p> representa o valor médio do preço da pizza estimado pela equação de
regressão linear (p). O termo yi representa o valor do preço (experimental) da pizza
para os diferentes diâmetros.
Os termos acima são usados para o cálculo de R2, como segue:
RSS
R  1
TSS
2
SciKit-Learn (Regressão Linear Simples) (pizza3.py)
www.python.org
Modificaremos a função simple_linear_regression1() para que esta calcule o R2 no
programa pizza3.py. O programa pizza3.py lerá os dados dos conjuntos treino
(pizza1.csv) e teste (pizza2.csv).
Índice do Dado do
Conjunto Test
Diâmetro da Pizza
(cm)
Preço (R$)
Preço Previsto
pelo Modelo
(R$)
1
20,0
38,50
34,22
2
22,5
29,75
37,63
3
27,5
52,50
44,47
4
40,0
63,00
61,55
5
30,0
38,50
47,88
49
SciKit-Learn (Regressão Linear Simples) (pizza3.py)
www.python.org
A função simple_linear_regression2() tem quatro parâmetros, além dos dois
anteriores (x_in,y_in), com os dados do conjunto treino, temos dois novos arrays
para os dados do conjunto teste (parâmetros x_test e y_test).
def simple_linear_regression2(x_in,y_in,x_test,y_test):
"""Function to generate a linear regression model for one explanatory variable
and their response variable. This function uses
sklearn.linear_model.LinearRegression method."""
# Import library
from sklearn import linear_model
import numpy as np
# Create and fit the model
model = linear_model.LinearRegression()
model.fit(x_in, y_in)
# Get Linear Model
alpha1 = float(model.coef_)
const = float(model.intercept_)
z = np.array([alpha1,const])
p = np.poly1d(z)
r_square = model.score(x_test, y_test)
print("\nBest fit linear regression model: ",p)
print('R-squared: %.4f' % r_square)
return p
50
SciKit-Learn (Regressão Linear Simples) (pizza3.py)
www.python.org
A outra novidade é o método .score(), que é usado para calcular o R2 que é atribuído
à variável r_square. O resultado é mostrado na tela.
def simple_linear_regression2(x_in,y_in,x_test,y_test):
"""Function to generate a linear regression model for one explanatory variable
and their response variable. This function uses
sklearn.linear_model.LinearRegression method."""
# Import library
from sklearn import linear_model
import numpy as np
# Create and fit the model
model = linear_model.LinearRegression()
model.fit(x_in, y_in)
# Get Linear Model
alpha1 = float(model.coef_)
const = float(model.intercept_)
z = np.array([alpha1,const])
p = np.poly1d(z)
r_square = model.score(x_test, y_test)
print("\nBest fit linear regression model: ",p)
print('R-squared: %.4f' % r_square)
return p
51
SciKit-Learn (Regressão Linear Simples) (pizza3.py)
www.python.org
No programa principal (função main()) temos que evocar duas vezes a leitura dos
arquivos CSV (função read_CSV()) além das respectivas conversões, como
destacado em vermelho abaixo.
def main():
# Call read_CSV() function
x1,y1 = read_CSV()
# Call convert2scikit()
xs1 = convert2scikit(x1)
ys1 = convert2scikit(y1)
# Call read_CSV() function again
x2,y2 = read_CSV()
# Call convert2scikit(x) again
xs2 = convert2scikit(x2)
ys2 = convert2scikit(y2)
# Call simple_linear_regression2()
p = simple_linear_regression2(xs1,ys1,xs2,ys2)
# Call gen_scatter_plot2()
gen_scatter_plot2(xs1,ys1,p,"Diameter (cm)","R$","Pizza Price vs
Diameter","pizza3.png")
main()
52
SciKit-Learn (Regressão Linear Simples) (pizza3.py)
www.python.org
Abaixo temos o resultado de rodar o programa pizza3.py, veja que temos dois
arquivos de entrada.
Type CSV file name => pizza1.csv
Type CSV file name => pizza2.csv
Best fit linear regression model:
1.367 x + 6.879
R-squared: 0.6620
53
SciKit-Learn (Regressão Linear Múltipla)
www.python.org
Muito bem, evoluímos com nosso modelo para previsão do preço das pizzas. Mas se
refletimos sobre a qualidade do nosso modelo, podemos imaginar que temos como
melhoras. Qualquer apreciador de pizza sabe que um dos determinantes do preço da
pizza é o número de coberturas. Assim podemos adicionar esta nova variável
explanatória ao nosso modelo. Assim, a equação de regressão passa a ter múltiplas
varáveis, um caso geral a equação tem a seguinte forma,
p  0  1 x1  2 x2  3 x3  ...   M xM
Onde M é o número de variáveis explanatórias. Quando usamos a equação acima
para obtermos um modelo estamos usando o método de regressão linear múltipla.
No nosso novo modelo para previsão do preço das pizzas adicionamos uma variável
explanatória, assim a equação tem a seguinte forma,
p  0  1 x1  2 x2
54
SciKit-Learn (Regressão Linear Múltipla)
www.python.org
Retornamos às tabelas de preço, só que agora temos uma informação adicional, com
o número de coberturas para o conjunto treino.
Índice do Dado do
Conjunto Treino
Diâmetro da Pizza (cm)
Número de Coberturas
Preço (R$)
1
15,0
2
24,50
2
20,0
1
31,50
3
25,0
0
45,50
4
35,0
2
61,25
5
45,0
0
63,00
A nova coluna é a variável explanatória x2.
55
SciKit-Learn (Regressão Linear Múltipla)
www.python.org
Abaixo temos a tabela para o conjunto teste
Índice do Dado do Diâmetro da Pizza (cm)
Conjunto Teste
Número de
Coberturas
Preço (R$)
1
20,0
2
38,50
2
22,5
0
29,75
3
27,5
2
52,50
4
40,0
2
63,00
5
30,0
0
38,50
A nova coluna é a variável explanatória x2.
56
SciKit-Learn (Regressão Linear Simples) (pizza4.py)
www.python.org
Para simplificar a apresentação vamos elaborar um código para gerar o modelo de
regressão múltipla e prever o preço da pizza de 40 cm. O código da função main()
segue abaixo.
def main():
# Call read_CSV_3cols() function
x1,x2,y1 = read_CSV_3cols()
# Call convert2scikit()
ytr = convert2scikit(y1)
# Call make_2d_array()
Xtr = make_2d_array(x1,x2)
# Call read_CSV_3cols() function again
x1,x2,y2 = read_CSV_3cols()
# Call convert2scikit(x) again
yte = convert2scikit(y2)
# Call make_2d_array()
Xte = make_2d_array(x1,x2)
# Call multiple_linear_regression()
p = multiple_linear_regression(Xtr,ytr,Xte,yte)
# Prediction of the price for 40 cm pizza
y = p[0] + p[1]*2.0 + p[2]*40.0
print("\nPredicted price for 40 cm pizza: %6.2f"%y)
main()
57
SciKit-Learn (Regressão Linear Simples) (pizza4.py)
www.python.org
A principal novidade é que temos que converter as duas colunas com as variáveis
explanatórias (diâmetro e número de coberturas) num array bidimensional, ou seja,
uma matriz. Usaremos a função make_2d_array().
def main():
# Call read_CSV_3cols() function
x1,x2,y1 = read_CSV_3cols()
# Call convert2scikit()
ytr = convert2scikit(y1)
# Call make_2d_array()
Xtr = make_2d_array(x1,x2)
# Call read_CSV_3cols() function again
x1,x2,y2 = read_CSV_3cols()
# Call convert2scikit(x) again
yte = convert2scikit(y2)
# Call make_2d_array()
Xte = make_2d_array(x1,x2)
# Call multiple_linear_regression()
p = multiple_linear_regression(Xtr,ytr,Xte,yte)
# Prediction of the price for 40 cm pizza
y = p[0] + p[1]*2.0 + p[2]*40.0
print("\nPredicted price for 40 cm pizza: %6.2f"%y)
main()
58
SciKit-Learn (Regressão Linear Simples) (pizza4.py)
www.python.org
Inicialmente é evocada a função read_CSV_3cols() que é similar à read_CSV() só
que agora retornamos três arrays, que são atribuídos às variáveis x1,x2, y1.
def main():
# Call read_CSV_3cols() function
x1,x2,y1 = read_CSV_3cols()
# Call convert2scikit()
ytr = convert2scikit(y1)
# Call make_2d_array()
Xtr = make_2d_array(x1,x2)
# Call read_CSV_3cols() function again
x1,x2,y2 = read_CSV_3cols()
# Call convert2scikit(x) again
yte = convert2scikit(y2)
# Call make_2d_array()
Xte = make_2d_array(x1,x2)
# Call multiple_linear_regression()
p = multiple_linear_regression(Xtr,ytr,Xte,yte)
# Prediction of the price for 40 cm pizza
y = p[0] + p[1]*2.0 + p[2]*40.0
print("\nPredicted price for 40 cm pizza: %6.2f"%y)
main()
59
SciKit-Learn (Regressão Linear Simples) (pizza4.py)
www.python.org
Em seguida convertermos a variável resposta para que possa ser lida pelo scikitlearn.
def main():
# Call read_CSV_3cols() function
x1,x2,y1 = read_CSV_3cols()
# Call convert2scikit()
ytr = convert2scikit(y1)
# Call make_2d_array()
Xtr = make_2d_array(x1,x2)
# Call read_CSV_3cols() function again
x1,x2,y2 = read_CSV_3cols()
# Call convert2scikit(x) again
yte = convert2scikit(y2)
# Call make_2d_array()
Xte = make_2d_array(x1,x2)
# Call multiple_linear_regression()
p = multiple_linear_regression(Xtr,ytr,Xte,yte)
# Prediction of the price for 40 cm pizza
y = p[0] + p[1]*2.0 + p[2]*40.0
print("\nPredicted price for 40 cm pizza: %6.2f"%y)
main()
60
SciKit-Learn (Regressão Linear Simples) (pizza4.py)
www.python.org
A função make_2d_array() tem como argumentos os array lidos e converte estes
numa matriz, que é atribuída à variável Xtr. Até então só lemos os dados do conjunto
treino (ytr e Xtr).
def main():
# Call read_CSV_3cols() function
x1,x2,y1 = read_CSV_3cols()
# Call convert2scikit()
ytr = convert2scikit(y1)
# Call make_2d_array()
Xtr = make_2d_array(x1,x2)
# Call read_CSV_3cols() function again
x1,x2,y2 = read_CSV_3cols()
# Call convert2scikit(x) again
yte = convert2scikit(y2)
# Call make_2d_array()
Xte = make_2d_array(x1,x2)
# Call multiple_linear_regression()
p = multiple_linear_regression(Xtr,ytr,Xte,yte)
# Prediction of the price for 40 cm pizza
y = p[0] + p[1]*2.0 + p[2]*40.0
print("\nPredicted price for 40 cm pizza: %6.2f"%y)
main()
61
SciKit-Learn (Regressão Linear Simples) (pizza4.py)
www.python.org
As linhas seguintes fazem a leitura e conversão dos dados do conjunto treino. Em
seguida é chamada a função multiple_linear_regression() que recebe as matrizes Xtr
e Xte.
def main():
# Call read_CSV_3cols() function
x1,x2,y1 = read_CSV_3cols()
# Call convert2scikit()
ytr = convert2scikit(y1)
# Call make_2d_array()
Xtr = make_2d_array(x1,x2)
# Call read_CSV_3cols() function again
x1,x2,y2 = read_CSV_3cols()
# Call convert2scikit(x) again
yte = convert2scikit(y2)
# Call make_2d_array()
Xte = make_2d_array(x1,x2)
# Call multiple_linear_regression()
p = multiple_linear_regression(Xtr,ytr,Xte,yte)
# Prediction of the price for 40 cm pizza
y = p[0] + p[1]*2.0 + p[2]*40.0
print("\nPredicted price for 40 cm pizza: %6.2f"%y)
main()
62
SciKit-Learn (Regressão Linear Simples) (pizza4.py)
www.python.org
Por último usamos o polinômio determinado, para obtermos uma estimativa do preço
da pizza de 40 cm com duas coberturas.
def main():
# Call read_CSV_3cols() function
x1,x2,y1 = read_CSV_3cols()
# Call convert2scikit()
ytr = convert2scikit(y1)
# Call make_2d_array()
Xtr = make_2d_array(x1,x2)
# Call read_CSV_3cols() function again
x1,x2,y2 = read_CSV_3cols()
# Call convert2scikit(x) again
yte = convert2scikit(y2)
# Call make_2d_array()
Xte = make_2d_array(x1,x2)
# Call multiple_linear_regression()
p = multiple_linear_regression(Xtr,ytr,Xte,yte)
# Prediction of the price for 40 cm pizza
y = p[0] + p[1]*2.0 + p[2]*40.0
print("\nPredicted price for 40 cm pizza: %6.2f"%y)
main()
63
SciKit-Learn (Regressão Linear Simples) (pizza4.py)
www.python.org
A única função nova é a make_2d_array(), mostrada abaixo. A novidade aqui é que
geramos uma matriz de zeros. Em seguida temos um loop for que atribui os
elementos dos vetores aos elementos da matrix.
def make_2d_array(x1,x2):
"""Function to make 2-d array"""
import numpy as np
# Set up number of columns and rows
number_columns = 2
number_rows = len(x1)
# Set up zero matrix
X= [[0]*number_columns for i in range(number_rows)]
# Get matrix
for i in range(number_rows):
X[i][0] = x1[i]
X[i][1] = x2[i]
return X
64
SciKit-Learn (Regressão Linear Simples) (pizza3.py)
www.python.org
Abaixo temos o resultado de rodar o programa pizza4.py, veja que temos dois
arquivos de entrada.
Type CSV file name => pizza3.csv
Type CSV file name => pizza4.csv
Best fit linear regression model:
1.415 x + 1.385 x + 4.156
R-squared: 0.7702
Predicted price for 40 cm pizza:
2
63.51
Índice
do houve
Dado do
(cm) o Número
Preço (R$)
Veja
que
umaDiâmetro
melhorada
noPizza
modelo,
R2 foi dede0,66 para 0,77.
Conjunto Teste
Coberturas
1
20,0
2
38,50
2
22,5
0
29,75
3
27,5
2
52,50
4
40,0
2
63,00
5
30,0
0
38,50
65
Métodos de Aprendizado de Máquina Supervisionado
www.python.org
Vimos a aplicação do método de regressão linear para a elaboração de um modelo,
a partir dos dados do conjunto treino. A biblioteca scikit-learn tem um arsenal de
métodos de aprendizado de máquina supervisionado, além da regressão linear.
Abaixo temos seis métodos disponíveis no scikit-learn. Esses métodos adicionais
visam reduzir o número de variáveis explanatórias no modelo de regressão. A tabela
verdade abaixo traz a identificação de cada termo com o respectivo peso do termo
adicional somado ao RSS.
RSS 
 yi  ycalc,i 
N
2
i 1
 11
P
P
j 1
j 1
2





 j 2 2 j
Método
Linear Regression
Ridge
Ridge CV
Lasso
Lasso CV
Elastic Net
Elastic Net CV
α1
0
0
0
1
1
1
1
α2
0
1
1
0
0
1
1
66
Modelagem de Sistemas (CDKs com Ki)
Para discutirmos os principais métodos para melhora de funções escores com
métodos de aprendizado de máquina supervisionado, iremos considerar como sistema
biológico uma proteína chamada quinase dependente de ciclina (CDKs) com
informação de Ki (constante de inibição). Moléculas que se ligam à CDK tem o
potencial de serem usadas como drogas contra o câncer.
67
Modelagem de Sistemas (CDKs com Ki)
Abaixo temos uma tabela com informações para 30 estruturas de CDKs para as quais
há informação de Ki. Iremos considerar somente três variáveis explanatórias, Protein
Score, Water Score e Electro Long Score. A variável log(Ki) é a variável resposta.
68
CDKs com Ki (Regressão Linear)
Usaremos um programa que é parte integrante do SAnDReS (Xavier et al., 2016). O
programa
chamado
sml15.py
chama
um
módulo
(scikit_regression_methods_v001z_works.py). Nos concentraremos no seu uso.
Abaixo temos o trecho do programa principal que faz a leitura do arquivo CSV e indica
o método de regressão linear.
def main():
#
#
#
#
#
#
Get the CSV file name, we the following file to be used as imput:
Verma_Hansch_EJMC_2010_Table1.csv
Verma_Hansch_EJMC_2010_Table2.csv
Verma_Hansch_EJMC_2010_Table3.csv
cdk_ki.csv
data01_19col.csv
csv_file = "cdk_ki.csv"
# Call get_number_of_cols()
n_columns = get_number_of_cols(csv_file)
# Call generate_LOO_files()
generate_LOO_files(csv_file,n_columns)
# Call SF()
SF(csv_file,n_columns-1,"ElasticNetCV")
main()
69
CDKs com Ki (Regressão Linear)
Na função main() inicialmente definimos o nome do arquivo CSV que tem as variáveis
explanatórias e a variável resposta (log(Ki)), indicada em vermelho.
def main():
#
#
#
#
#
#
Get the CSV file name, we the following file to be used as imput:
Verma_Hansch_EJMC_2010_Table1.csv
Verma_Hansch_EJMC_2010_Table2.csv
Verma_Hansch_EJMC_2010_Table3.csv
cdk_ki.csv
data01_19col.csv
csv_file = "cdk_ki.csv"
# Call get_number_of_cols()
n_columns = get_number_of_cols(csv_file)
# Call generate_LOO_files()
generate_LOO_files(csv_file,n_columns)
# Call SF()
SF(csv_file,n_columns-1,"ElasticNetCV")
main()
70
CDKs com Ki (Regressão Linear)
Em seguida é chamada a função get_number_of_cols() que determina o número de
colunas do arquivo CSV.
def main():
#
#
#
#
#
#
Get the CSV file name, we the following file to be used as imput:
Verma_Hansch_EJMC_2010_Table1.csv
Verma_Hansch_EJMC_2010_Table2.csv
Verma_Hansch_EJMC_2010_Table3.csv
cdk_ki.csv
data01_19col.csv
csv_file = "cdk_ki.csv"
# Call get_number_of_cols()
n_columns = get_number_of_cols(csv_file)
# Call generate_LOO_files()
generate_LOO_files(csv_file,n_columns)
# Call SF()
SF(csv_file,n_columns-1,"ElasticNetCV")
main()
71
CDKs com Ki (Regressão Linear)
Depois é chamada a função generate_LOO_files(), que gera arquivos CSV auxiliares
com uma estrutura deixada fora (leave one out)(loo). Tal abordagem visa verificar a
consistência interna do modelo de regressão linear gerado, onde uma linha de dado é
deixada de fora para cada iteração da determinação dos pesos das variáveis
explanatórias.
def main():
#
#
#
#
#
#
Get the CSV file name, we the following file to be used as imput:
Verma_Hansch_EJMC_2010_Table1.csv
Verma_Hansch_EJMC_2010_Table2.csv
Verma_Hansch_EJMC_2010_Table3.csv
cdk_ki.csv
data01_19col.csv
csv_file = "cdk_ki.csv"
# Call get_number_of_cols()
n_columns = get_number_of_cols(csv_file)
# Call generate_LOO_files()
generate_LOO_files(csv_file,n_columns)
# Call SF()
SF(csv_file,n_columns-1,"ElasticNetCV")
main()
72
CDKs com Ki (Regressão Linear)
A última função chamada é a SF() que determina o modelo de regressão linear. Um
dos argumentos passado é o método de regressão a ser usado, no caso abaixo
“LinearRegression”. Além deste, o programa pode testar: Lasso, LassoCV, Ridge,
RidgeCV, ElasticNet e ElasticNetCV
def main():
#
#
#
#
#
#
Get the CSV file name, we the following file to be used as imput:
Verma_Hansch_EJMC_2010_Table1.csv
Verma_Hansch_EJMC_2010_Table2.csv
Verma_Hansch_EJMC_2010_Table3.csv
cdk_ki.csv
data01_19col.csv
csv_file = "cdk_ki.csv"
# Call get_number_of_cols()
n_columns = get_number_of_cols(csv_file)
# Call generate_LOO_files()
generate_LOO_files(csv_file,n_columns)
# Call SF()
SF(csv_file,n_columns-1,“LinearRegression")
main()
73
CDKs com Ki (Regressão Linear)
Como já vimos, o método “LinearRegression” determina os pesos de cada variável
explanatória onde x1 é o Protein Score, x2 o Water Score e x3 o Electro Long Score.
log( Ki )  0  1.x1  2 .x2  3 .x3
def main():
#
#
#
#
#
#
Get the CSV file name, we the following file to be used as imput:
Verma_Hansch_EJMC_2010_Table1.csv
Verma_Hansch_EJMC_2010_Table2.csv
Verma_Hansch_EJMC_2010_Table3.csv
cdk_ki.csv
data01_19col.csv
csv_file = "cdk_ki.csv"
# Call get_number_of_cols()
n_columns = get_number_of_cols(csv_file)
# Call generate_LOO_files()
generate_LOO_files(csv_file,n_columns)
# Call SF()
SF(csv_file,n_columns-1,“LinearRegression")
main()
74
CDKs com Ki (Regressão Linear)
O método “LinearRegression” determina os pesos de cada variável explanatória de
N
forma que a função RSS seja minimizada.
2
RSS 
 y  x  
i
T
i
i 1
RSS representa o resíduo, yi o valor experimental de log(Ki) para cada
estrutura do conjunto treino. Os termos xi são as variáveis explanatórias e ω um vetor
com o peso de cada variável explanatória.
def main():
#
#
#
#
#
#
Get the CSV file name, we the following file to be used as imput:
Verma_Hansch_EJMC_2010_Table1.csv
Verma_Hansch_EJMC_2010_Table2.csv
Verma_Hansch_EJMC_2010_Table3.csv
cdk_ki.csv
data01_19col.csv
csv_file = "cdk_ki.csv"
# Call get_number_of_cols()
n_columns = get_number_of_cols(csv_file)
# Call generate_LOO_files()
generate_LOO_files(csv_file,n_columns)
# Call SF()
SF(csv_file,n_columns-1,“LinearRegression")
main()
75
CDKs com Ki (Regressão Linear)
Ao rodarmos o programa obtemos os seguintes resultados (arquivo SF.log).
######################################### MODEL GENERATOR ###############################################
File: cdk_ki.csv
Regression equation :
Pred. Log(Ki) = - 4.571716 + 0.017517*(Protein) - 0.141223*(Water) - 0.511956*(ElectroLong)
Error for c(0) :
2.166260
Error for Protein
:
0.015999
Error for Water
:
0.142385
Error for ElectroLong
:
0.536931
Best fit equation between observed and predicted information:
0.2755 x - 4.834
N
:
Standard deviation :
R
:
R-squared
:
p-value
:
Adjusted R-square :
Spearman correlation :
p-value
:
Quality factor (Q) :
q-squared for LOO :
F-stat
:
Chi-squared
:
RMSE
:
30
1.209319
0.524853
0.275470
2.903439e-03
0.191871
0.567138
1.082796e-03
0.434007
0.278364
3.295116
5.764193
0.125592
76
Modelos de QSAR (Taxol)
www.python.org
Vamos analisar um modelo de QSAR
publicado para fixarmos os conceitos de
regressão. Selecionei um artigo do
criador do método, Dr. C. Hansch
(Verma & Hansch. QSAR modeling of
taxane analogues against colon cancer.
European
Journal
of
Medicinal
Chemistry 45 (2010) 1470–1477). Nesse
artigo são elaborados modelos de
QSAR para uma série de compostos
anti-cancerígenos, análogos do taxol
(CID 36314), mostrado na figura ao
lado. O taxol apresenta atividade
anticancerígena e é extraído da casca
da árvore Taxus brevefolia. Os
substituintes para gerar os análogos
foram montados pela adição de
diferentes grupos químicos na posição
X, indicada na figura ao lado.
Estrutura do taxol (CID 36314)
Verma, R.P & Hansch, C. QSAR modeling of taxane
analogues against colon cancer. European Journal of
Medicinal Chemistry 45 (2010) 1470–1477.
77
Modelos de QSAR (Taxol)
www.python.org
A tabela usada para obter um dos modelos de QSAR está mostrada abaixo. Nela
temos os seguintes descritores moleculares: X, MRX e ICYALK. A atividade é a inibição
de células cancerosas de HCT-116 (câncer de cólon). Descreveremos brevemente os
descritores moleculares.
Molecule
CH3
C6H5
4-F-C6H4
CH2F
CCl3
C2H5
CH]CH2
(CH2)2CH3
CH(CH3)2
C(CH3) =CH2
trans-CH = CHCH3
Cy-C3H5
(CH2)3CH3
Cy-C4H7
(CH2)4CH3
Cy-C5H9
OCH3
OCH2CH3
O(CH2)2CH3
NH-Cy-C4H7
Imidazole
Aziridine
piX
0.7
1.91
2.05
0.37
2.58
1.23
0.85
1.76
1.54
1.16
1.38
1.28
2.28
1.61
2.81
2.17
0.68
1.21
1.74
1.55
0.18
0.87
MRX
0.46
2.51
2.53
0.48
1.94
0.93
0.98
1.39
1.39
1.44
1.44
1.25
1.86
1.68
2.32
2.14
0.62
1.08
1.54
2.05
1.73
1.12
ICYALK
0
0
0
0
0
0
0
0
0
0
0
1
0
1
0
1
0
0
0
1
0
0
Observed log 1/IC50
8.62
6.39
6.1
8.15
8.4
8.7
8.22
8.96
8.3
8.35
8.64
9
8.7
8.82
8.22
8.7
8.7
9
8.59
8.04
6.1
7.81
78
Modelos de QSAR (Taxol)
www.python.org
O descritor X, é a diferença entre o log P para o composto (no caso taxol) e os
análogos deste (log PX ), como definido pela equação abaixo:
 X  log PX - log P
Este descritor é uma medida da hidrofobicidade.
O descritor MRX é a refractividade molar, dada pela equação a seguir:
 n 2 - 1   MW 
.
MR X   2


n  2 d 
onde n é o índice de refração, d a densidade e MW a massa molecular. Normalmente
esse descritor é usado para descrever o volume da molécula.
79
Modelos de QSAR (Taxol)
www.python.org
O termo e ICYALK é um indicador da atividade incomum dos substituintes que
apresentam cicloaquila (cycloalkyl). O termo assume o valor “1” se apresenta o grupo
cicloaquila, caso contrário o valor é “0”. É o que podemos chamar de um descritor
binário, que assume somente valores “0” e “1”.
Molecule
CH3
C6H5
4-F-C6H4
CH2F
CCl3
C2H5
CH]CH2
(CH2)2CH3
CH(CH3)2
C(CH3) =CH2
trans-CH = CHCH3
Cy-C3H5
(CH2)3CH3
Cy-C4H7
(CH2)4CH3
Cy-C5H9
OCH3
OCH2CH3
O(CH2)2CH3
NH-Cy-C4H7
Imidazole
Aziridine
piX
0.7
1.91
2.05
0.37
2.58
1.23
0.85
1.76
1.54
1.16
1.38
1.28
2.28
1.61
2.81
2.17
0.68
1.21
1.74
1.55
0.18
0.87
MRX
0.46
2.51
2.53
0.48
1.94
0.93
0.98
1.39
1.39
1.44
1.44
1.25
1.86
1.68
2.32
2.14
0.62
1.08
1.54
2.05
1.73
1.12
ICYALK
0
0
0
0
0
0
0
0
0
0
0
1
0
1
0
1
0
0
0
1
0
0
Observed log 1/IC50
8.62
6.39
6.1
8.15
8.4
8.7
8.22
8.96
8.3
8.35
8.64
9
8.7
8.82
8.22
8.7
8.7
9
8.59
8.04
6.1
7.81
80
Modelos de QSAR (Taxol)
www.python.org
A abordagem clássica da modelagem de QSAR parte da tabela de atividades e
descritores, para alimentarmos o programa de regressão. A atividade biológica a ser
relacionada com a estrutura molecular é o IC50, assim nossa equação de regressão
terá a seguinte forma geral (sem a determinação dos coeficientes ),
 1
log 
 IC 50

   0   1 X   2MR X   3ICYALK

A equação acima tem 3 variáveis explanatórias (X, MRX e ICYALK ) e a variável
resposta é log (1/IC50).
81
Modelos de QSAR (Taxol)
www.python.org
A equação de regressão obtida é a seguinte:
log (1/IC50) = 9.04307 +0.887579 icy-1.96693 mrx+1.33766 pix
Onde:
0 = 9,04307
1 = 1,33766
2 = -1,96693
3 = 0,887579
Assim temos a seguinte equação de regressão:
 1
log 
 IC 50

  9,04  1,34  X - 1,97 MR X  0,89 ICYALK

A presença de um  positivo para o termo ICYALK sugere que a presença do grupo é
favorável à atividade dos análogos de taxol.
Veja que seguimos a ordem: X, MRX, ICYALK e log (1/IC50).
82
Modelos de QSAR (Taxol)
www.python.org
Vamos realizar uma análise estatística dos resultados. Para isto precisamos calcular o
Predicted log (1/IC50) (ycalc) para todos os pontos experimentais. A coluna indicada em
vermelho foi obtida a partir da inserção da equação de regressão, obtida com o
Mathematica, na planilha do Excel.
Molecule
piX
MRX
ICYALK Observed log 1/IC50 Predicted log 1/IC50 delta^2 (log 1/IC50(Exp)-<log 1/IC50(Exp)>)^2 (log 1/IC50(Teor)-<log 1/IC50(Exp)>)^2
CH3
0.7
0.46
0
8.62
9.0746442 0.206701
0.172225
0.756281035
C6H5
1.91
2.51
0
6.39
6.6610063 0.073444
3.294225
2.383916546
4-F-C6H4
2.05
2.53
0
6.1
6.8089401 0.502596
4.431025
1.948983244
CH2F
0.37
0.48
0
8.15
8.5938778 0.197028
0.003025
0.151225943
CCl3
2.58
1.94
0
8.4
8.6783886
0.0775
0.038025
0.224096767
C2H5
1.23
0.93
0
8.7
8.8591469 0.025328
0.245025
0.427908167
CH]CH2
0.85
0.98
0
8.22
8.2524896 0.001056
0.000225
0.002255262
(CH2)2CH3
1.76
1.39
0
8.96
8.6633189 0.08802
0.570025
0.210056214
CH(CH3)2
1.54
1.39
0
8.3
8.3690337 0.004766
0.009025
0.026907055
C(CH3) =CH2
1.16
1.44
0
8.35
7.7623764 0.345301
0.021025
0.195915651
trans-CH = CHCH3
1.38
1.44
0
8.64
8.0566616 0.340284
0.189225
0.022004281
Cy-C3H5
1.28
1.25
1
9
9.1841913 0.033926
0.632025
0.958815602
(CH2)3CH3
2.28
1.86
0
8.7
8.434445 0.070519
0.245025
0.052645008
Cy-C4H7
1.61
1.68
1
8.82
8.7798392 0.001613
0.378225
0.330440106
(CH2)4CH3
2.81
2.32
0
8.22
8.238617 0.000347
0.000225
0.001130103
Cy-C5H9
2.17
2.14
1
8.7
8.624141 0.005755
0.245025
0.175679178
OCH3
0.68
0.62
0
8.7
8.7331822 0.001101
0.245025
0.278976436
OCH2CH3
1.21
1.08
0
9
8.5373542 0.214041
0.632025
0.110459314
O(CH2)2CH3
1.74
1.54
0
8.59
8.3415262 0.061739
0.148225
0.018639403
NH-Cy-C4H7
1.55
2.05
1
8.04
7.9718155 0.004649
0.027225
0.054375011
Imidazole
0.18
1.73
0
6.1
5.8810599 0.047935
4.431025
5.400697588
Aziridine
0.87
1.12
0
7.81
8.0038726 0.037587
0.156025
0.040452231
83
Modelos de QSAR (Taxol)
www.python.org
Os valores para r2, sd e F são mostrados abaixo.
Entradas
N
p
<log 1/IC50(>
22
3
8.205
RSS
2.341235229
TSS
16.11315
ESS
13.77186015
R^2
0.854700339
sd
0.360650279
F
35.29383115
84
Modelos de QSAR (Taxol)
www.python.org
A partir do gráfico de dispersão entre os valores calculados (log (1/IC50)(teor) e os
valores experimentais Observed (log (1/IC50), podemos verificar a boa concordância
do modelo de QSAR com os dados experimentais.
9,5
9
log (1/IC50)(teor)
8,5
8
7,5
7
6,5
6
6
6,5
7
7,5
8
8,5
9
9,5
Observed log (1/IC50)
85
Trabalho 1
Considere os resultados da atividade anticâncer de uma família de moléculas
disponíveis nas tabela:
Verma_Hansch_EJMC_2010_Table1.csv
Aplique os métodos de aprendizado de máquina supervisionado indicados na tabela
abaixo e identifique o melhor modelo considerando como critério o valor de R2.
RSS 
 y 
N
i
i 1
xiT

P
P
j 1
j 1
  11   j   22   2j
2
Método
Linear Regression
Ridge
Ridge CV
Lasso
Lasso CV
Elastic Net
Elastic Net CV
α1
0
0
0
1
1
1
1
α2
0
1
1
0
0
1
1
Entrega: 29 de novembro de 2016.
86
Referências
www.python.org
-BRESSERT, Eli. SciPy and NumPy. Sebastopol: O’Reilly Media, Inc., 2013. 56 p.
-DAWSON, Michael. Python Programming, for the absolute beginner. 3ed. Boston: Course Technology, 2010. 455 p.
-HACKELING G. Mastering Machine Learning with scikit-learn. Birmingham: Packt Publishing Ltd., 2014. 221 p.
-HETLAND, Magnus Lie. Python Algorithms. Mastering Basic Algorithms in the Python Language. Nova York: Springer
Science+Business Media LLC, 2010. 316 p.
-IDRIS, Ivan. NumPy 1.5. An action-packed guide dor the easy-to-use, high performance, Python based free open source
NumPy mathematical library using real-world examples. Beginner’s Guide. Birmingham: Packt Publishing Ltd., 2011. 212 p.
-LUTZ, Mark. Programming Python. 4ed. Sebastopol: O’Reilly Media, Inc., 2010. 1584 p.
-MODEL, Mitchell L. Bioinformatics Programming Using Python. Sebastopol: O’Reilly Media, Inc., 2011. 1584 p.
-TOSI, Sandro. Matplotlib for Python Developers. Birmingham: Packt Publishing Ltd., 2009. 293 p.
Última atualização: 25 de novembro de 2016.
87
Download