Você está na página 1de 87

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 Realiza
Experimentos Simulações

Resultados Resultados das


Experimentais 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 Realiza
Experimentos Simulações

Resultados Resultados das


Experimentais 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. QSAR
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.
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  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,
onde C é a concentração molar de um aumentando as chances de disponibilidade oral.
composto necessário para produzir uma Fonte da imagem:
http://www.sciencephoto.com/media/350656/enlarge
dada atividade biológica, por exemplo Acesso em: 25 de novembro de 2016.
IC50, log P é o coeficiente de partição Hansch, C., Ruth, A.S., Anderson, S.M., Bentley, D.L.
entre octanol e água,  é outro descritor Parabolic dependence of drug action upon lipophilic
molecular, como número de doadores de character as revealed by study of hypnotics. J. Med Chem 11
(1968) 1-11.
ligação de hidrogênio da molécula.
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, Reta (em vermelho) obtida por regressão linear para um
número de doadores de ligação de H etc. conjunto de pontos experimentais (pontos azuis).
O 1 é coeficiente angular da reta, ou do O gráfico foi gerado com o programa Mathematica
ponto de vista de otimização, o peso da (http://demonstrations.wolfram.com/VisualizingrsquareddInSt
variável x e 0 é a constante de atistics/)

regressão. 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
 ( x i  x )( y i  y )  0  y  1 x
i 1
1  N
 (xi  x )
2
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 1 N
x   xi y   yi
N i 1 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 1.25
0.2 1.5 problema, temos como primeiro passo o cálculo da
0.3 4 média, com as equações abaixo:
0.4 5.1 1 N
1 N y   yi
0.5
0.6
6.3
5
x   xi N i 1
0.7 8.7
N i 1
0.8 9 Em seguida calculamos 1, com a equação a seguir:
0.9 11
N
 ( x i  x )( y i  y )
1 14
1.1 13.75
i 1
1.2
1.3
15
18
1  N
 (xi  x )
2
1.4 17.5
1.5 19 i 1
1.6 17 Por último calculamos 0.
 0  y  1 x
1.7 21
1.8 22.5
1.9 26
2 25.1
Quantitative Structure Activity Relationship
www.python.org

Temos a seguinte sequencia de


x y x- <x> y-<y> (x-<x>)(y-<y>) (x-<x>)^2
cálculos: 0.1 1.25 -0.95 -11.785 11.19575 0.9025
1) Médias 0.2 1.5 -0.85 -11.535 9.80475 0.7225
0.3 4 -0.75 -9.035 6.77625 0.5625
1 N 0.4 5.1 -0.65 -7.935 5.15775 0.4225
x   x i  1,05 0.5 6.3 -0.55 -6.735 3.70425 0.3025
N i 1 0.6 5 -0.45 -8.035 3.61575 0.2025
0.7 8.7 -0.35 -4.335 1.51725 0.1225
1 N
y   y i  13,035 0.8
0.9
9
11
-0.25
-0.15
-4.035
-2.035
1.00875
0.30525
0.0625
0.0225
N i 1 1 14 -0.05 0.965 -0.04825 0.0025
1.1 13.75 0.05 0.715 0.03575 0.0025
2) Cálculo do 1 1.2 15 0.15 1.965 0.29475 0.0225
N 1.3 18 0.25 4.965 1.24125 0.0625
 ( x i  x )( y i  y ) 1.4 17.5 0.35 4.465 1.56275 0.1225
i 1 85,795
1 
1.5 19 0.45 5.965 2.68425 0.2025
N
 1.6 17 0.55 3.965 2.18075 0.3025
6,65
 (xi  x )
2 1.7 21 0.65 7.965 5.17725 0.4225
i 1 1.8 22.5 0.75 9.465 7.09875 0.5625
1.9 26 0.85 12.965 11.02025 0.7225
 12,902 2 25.1 0.95 12.065 11.46175 0.9025
1.05 13.035 85.795 6.65
3) Cálculo do 0
0  y  1 x 
 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:


X Y y = 1x + 0
y =12,902x – 0,512
0.1 1.25
0.2 1.5
30
0.3 4
0.4 5.1 25

Variável dependente
0.5 6.3 20
0.6 5 15
0.7 8.7
10
0.8 9
0.9 11 5
1 14 0
1.1 13.75 0 0,5 1 1,5 2 2,5
1.2 15 Variável independente

1.3 18 Na elaboração de modelos de QSAR, normalmente temos mais de uma


1.4 17.5 variável independente, o que leva ao uso de regressão linear múltipla.
1.5 19
Outro nível de abstração do modelo de QSAR, é o uso de variáveis
1.6 17
1.7 21
independentes não lineares. Tais métodos de aproximação estão
1.8 22.5 disponíveis em pacotes como o Mathematica (www.wolfram.com). Além
1.9 26 disso, podemos implementar os métodos de regressão linear, a partir
2 25.1 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  ESS   y calc ,i  y  RSS   y i  y calc ,i 


N 2 N 2 N 2

i 1 i 1 i 1

Que são usados para o cálculo de R2, como segue:

RSS
R  1
2
TSS
Quantitative Structure Activity Relationship
www.python.org
x y x-<x> y-<y> ycalc,i (y-ycalc,i)^2 (y-<y>)^2 (ycalc,i-<y))^2
0.1 1.25 -0.95 -11.785 0.7782 0.22259524 138.886225 150.2291462
0.2 1.5 -0.85 -11.535 2.0684 0.32307856 133.056225 120.2663156
0.3 4 -0.75 -9.035 3.3586 0.41139396 81.631225 93.63271696
0.4 5.1 -0.65 -7.935 4.6488 0.20358144 62.964225 70.32835044
0.5 6.3 -0.55 -6.735 5.939 0.130321 45.360225 50.353216
0.6 5 -0.45 -8.035 7.2292 4.96933264 64.561225 33.70731364
0.7 8.7 -0.35 -4.335 8.5194 0.03261636 18.792225 20.39064336
0.8 9 -0.25 -4.035 9.8096 0.65545216 16.281225 10.40320516
0.9 11 -0.15 -2.035 11.0998 0.00996004 4.141225 3.74499904
1 14 -0.05 0.965 12.39 2.5921 0.931225 0.416025
1.1 13.75 0.05 0.715 13.6802 0.00487204 0.511225 0.41628304
1.2 15 0.15 1.965 14.9704 0.00087616 3.861225 3.74577316
1.3 18 0.25 4.965 16.2606 3.02551236 24.651225 10.40449536
1.4 17.5 0.35 4.465 17.5508 0.00258064 19.936225 20.39244964
1.5 19 0.45 5.965 18.841 0.025281 35.581225 33.709636
1.6 17 0.55 3.965 20.1312 9.80441344 15.721225 50.35605444
1.7 21 0.65 7.965 21.4214 0.17757796 63.441225 70.33170496
1.8 22.5 0.75 9.465 22.7116 0.04477456 89.586225 93.63658756
1.9 26 0.85 12.965 24.0018 3.99280324 168.091225 120.2707022
2 25.1 0.95 12.065 25.292 0.036864 145.564225 150.234049
1.05 13.035 26.6659868 1133.5505 1106.969667

RSS   y i  y calc ,i   26,66599 TSS   y i  y 2  1133,551


N 2 N

i 1 i 1

RSS 26,66599
R2  1  1  0,9765
TSS 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

25
Variável dependente

20

y = 1x + 0
15

y =12,902x – 0,512 10

5
R2 = 0,9765
0
0 0,5 1 1,5 2 2,5
Variável independente
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 Polinômio de grau 2 (-0,634408x2 + 1,24534x + 0,0807008)
encontrarmos modelos matemáticos para usado para aproximar os cinco pontos experimentais
conjuntos de dados. Depois mostrados acima.

implementaremos em Python. 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

x y
A idéia básica atrás da aproximação de uma 73. 34.8105
função é usar uma lista de funções 74. 35.381
75. 35.8167
matemáticas especificadas antecipadamente, 76. 40.6048
e tentar encontrar uma combinação linear 77. 47.0132
dessas funções dadas, de forma que essa 78. 42.4577
79. 43.1319
combinação linear de funções fique o mais
80. 37.3182
próximo possível do conjunto de dados. 81. 33.6343
Vamos ilustrar as idéias principais com 82. 28.0988
exemplos. Vamos considerar um conjunto 83. 28.3107
84. 29.9822
formado pelos 19 pontos experimentais, 85. 27.2542
indicados na tabela ao lado. 86. 33.407
Para colocar essas informações no 87. 35.4875
88. 38.1126
Mathematica digitamos:
89. 41.57
90. 42.1533
91. 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: 26


12.9 x - 0.5116 , R^2 = 0.976475697411
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 scikit-
learn. 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 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

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]
31
return x,y
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 32


plt.savefig(output_file)
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 Diâmetro da Pizza (cm) Preço (R$)


Conjunto treino
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

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() A classe sklearn import linear_model é
model.fit(x_in, y_in) um “estimador”, que é usado para
# Get Linear Model
prever um valor, baseado em dados
alpha1 = float(model.coef_) observados.
const = float(model.intercept_)
z = np.array([alpha1,const])
p = np.poly1d(z)

print("\nBest fit linear regression model: ",p)


38
return p
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)


39
return p
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)


40
return p
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)


41
return p
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), '-') Gera o gráfico da reta
# Shows plot
plt.show()
# Saves plot on png file 42
plt.savefig(output_file)
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“
43
main()
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“
44
main()
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):
N
RSS   
i 1
y i  pi 2

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 Diâmetro da Pizza Preço (R$) Preço Previsto


Conjunto Test (cm) 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):
N

  yi     pi   y  pi 
N N
RSS 
2 2 2
TSS  p ESS  p i
i 1 i 1 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
2
TSS
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 Diâmetro da Pizza Preço (R$) Preço Previsto


Conjunto Test (cm) 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)
50
return p
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)
51
return p
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") 52
main()
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 Diâmetro da Pizza (cm) Número de Coberturas Preço (R$)


Conjunto Treino
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) Número de Preço (R$)


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

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) 57
main()
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) 58
main()
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) 59
main()
SciKit-Learn (Regressão Linear Simples) (pizza4.py)
www.python.org

Em seguida convertermos a variável resposta para que possa ser lida pelo scikit-
learn.

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) 60
main()
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) 61
main()
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) 62
main()
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) 63
main()
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: 2


1.415 x + 1.385 x + 4.156
R-squared: 0.7702

Predicted price for 40 cm pizza: 63.51

Índice
Veja do houve
que Dado do
umaDiâmetro
melhorada
noPizza R2 foi dede0,66 para 0,77.
(cm) o Número
modelo, Preço (R$)
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.

Método α1 α2
Linear Regression 0 0

 yi  ycalc,i 
N P P

 j 2 2 j
Ridge 0 1
RSS   11     
2 2 Ridge CV 0 1
Lasso 1 0
i 1 j 1 j 1 Lasso CV 1 0
Elastic Net 1 1
Elastic Net CV 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")
69
main()
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")
70
main()
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")
71
main()
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")
72
main()
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")
73
main()
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")
74
main()
CDKs com Ki (Regressão Linear)

O método “LinearRegression” determina os pesos de cada variável explanatória de

 y  x  
forma que a função RSS seja minimizada. N
2
RSS  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")
75
main()
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 : 30
Standard deviation : 1.209319
R : 0.524853
R-squared : 0.275470
p-value : 2.903439e-03
Adjusted R-square : 0.191871
Spearman correlation : 0.567138
p-value : 1.082796e-03
Quality factor (Q) : 0.434007
q-squared for LOO : 0.278364
F-stat : 3.295116
Chi-squared : 5.764193
RMSE : 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 Estrutura do taxol (CID 36314)

diferentes grupos químicos na posição Verma, R.P & Hansch, C. QSAR modeling of taxane
X, indicada na figura ao lado. 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 piX MRX ICYALK Observed log 1/IC50
CH3 0.7 0.46 0 8.62
C6H5 1.91 2.51 0 6.39
4-F-C6H4 2.05 2.53 0 6.1
CH2F 0.37 0.48 0 8.15
CCl3 2.58 1.94 0 8.4
C2H5 1.23 0.93 0 8.7
CH]CH2 0.85 0.98 0 8.22
(CH2)2CH3 1.76 1.39 0 8.96
CH(CH3)2 1.54 1.39 0 8.3
C(CH3) =CH2 1.16 1.44 0 8.35
trans-CH = CHCH3 1.38 1.44 0 8.64
Cy-C3H5 1.28 1.25 1 9
(CH2)3CH3 2.28 1.86 0 8.7
Cy-C4H7 1.61 1.68 1 8.82
(CH2)4CH3 2.81 2.32 0 8.22
Cy-C5H9 2.17 2.14 1 8.7
OCH3 0.68 0.62 0 8.7
OCH2CH3 1.21 1.08 0 9
O(CH2)2CH3 1.74 1.54 0 8.59
NH-Cy-C4H7 1.55 2.05 1 8.04
Imidazole 0.18 1.73 0 6.1
78
Aziridine 0.87 1.12 0 7.81
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 piX MRX ICYALK Observed log 1/IC50
CH3 0.7 0.46 0 8.62
C6H5 1.91 2.51 0 6.39
4-F-C6H4 2.05 2.53 0 6.1
CH2F 0.37 0.48 0 8.15
CCl3 2.58 1.94 0 8.4
C2H5 1.23 0.93 0 8.7
CH]CH2 0.85 0.98 0 8.22
(CH2)2CH3 1.76 1.39 0 8.96
CH(CH3)2 1.54 1.39 0 8.3
C(CH3) =CH2 1.16 1.44 0 8.35
trans-CH = CHCH3 1.38 1.44 0 8.64
Cy-C3H5 1.28 1.25 1 9
(CH2)3CH3 2.28 1.86 0 8.7
Cy-C4H7 1.61 1.68 1 8.82
(CH2)4CH3 2.81 2.32 0 8.22
Cy-C5H9 2.17 2.14 1 8.7
OCH3 0.68 0.62 0 8.7
OCH2CH3 1.21 1.08 0 9
O(CH2)2CH3 1.74 1.54 0 8.59
NH-Cy-C4H7 1.55 2.05 1 8.04
Imidazole 0.18 1.73 0 6.1
80
Aziridine 0.87 1.12 0 7.81
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     0   1 X   2MR X   3ICYALK
 IC 50 
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    9,04  1,34  X - 1,97 MR X  0,89 ICYALK
 IC 50 

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 <log 1/IC50(> 8.205

N 22 RSS 2.341235229
p 3
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

8,5
log (1/IC50)(teor)

7,5

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.

Método α1 α2
Linear Regression 0 0

 y  
N P P
  11   j   22   2j
2 Ridge 0 1
RSS  i xiT Ridge CV
Lasso
0
1
1
0
i 1 j 1 j 1 Lasso CV 1 0
Elastic Net 1 1
Elastic Net CV 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

Você também pode gostar