• Nenhum resultado encontrado

Dual scaling: uma implementação em GPU com o TensorFlow

N/A
N/A
Protected

Academic year: 2021

Share "Dual scaling: uma implementação em GPU com o TensorFlow"

Copied!
46
0
0

Texto

(1)

UNIVERSIDADE FEDERAL FLUMINENSE

MARCELO SOUZA DE MELO

DUAL SCALING: UMA IMPLEMENTAÇÃO EM GPU COM O

TENSORFLOW

Niterói

2018

(2)

MARCELO SOUZA DE MELO

DUAL SCALING: UMA IMPLEMENTAÇÃO EM GPU COM O

TENSORFLOW

Trabalho de Conclusão de Curso submetido ao Curso de Tecnologia em Sistemas de Computação da Universidade Federal Fluminense como requisito parcial para obtenção do título de Tecnólogo em Sistemas de Computação.

Orientador(a):

ALTOBELLI DE BRITO MANTUAN

NITERÓI

2018

(3)
(4)

MARCELO SOUZA DE MELO

DUAL SCALING: UMA IMPLEMENTAÇÃO EM GPU COM O

TENSORFLOW

Trabalho de Conclusão de Curso submetido ao Curso de Tecnologia em Sistemas de Computação da Universidade Federal Fluminense como requisito parcial para obtenção do título de Tecnólogo em Sistemas de Computação.

Niterói, 12 de junho de 2018. Banca Examinadora:

_________________________________________ Prof. Altobelli de Brito Mantuan, Msc. – Orientador

UFF – Universidade Federal Fluminense

_________________________________________ Prof. José Angel Riveaux Merino, Msc. – Avaliador

(5)

Dedico este trabalho a minha mãe e aos meus estimados filhos.

(6)

AGRADECIMENTOS

A Deus, que sempre me abençoou para alcançar mais uma conquista.

A meu Orientador Altobelli de Brito Mantuan pela atenção e dedicação durante o trabalho de conclusão do curso.

Aos Colegas de curso pelo incentivo e troca de experiências.

A todos os meus familiares e amigos pelo apoio e colaboração.

(7)

RESUMO

Neste trabalho propomos uma abordagem ao leitor explicando como as técnicas de

Dual Scaling simplificam a análise de dados, definem um maior relacionamento entre

as variáveis e fornecem uma maior quantidade de dados que estão interligados em uma mesma categoria. No desenvolvimento do texto essas técnicas são representadas através de equações na implementação de algoritmos de complexidade O(m3) e são utilizadas funções da biblioteca TensorFlow, que trabalha

com computação numérica de alto desempenho, para tratar os dados de entrada que são matrizes. As GPUs com sua arquitetura dedicada e paralelizada junto às técnicas de Dual Scaling têm o propósito de mostrar como é significativo o ganho de tempo no processamento, principalmente quando se trabalha com grande volume de dados. Testes de comparação feitos em placa gráfica em relação à CPU, usando os mesmos algoritmos, revelam a eficiência das placas mostrando a diferença percentual de tempo no resultado final.

(8)

LISTA DE ILUSTRAÇÕES

Figura 1: Dados de Múltipla Escolha - Parte 1 ... 31

Figura 2: Dados de Múltipla Escolha - Parte 2 ... 33

Figura 3: Tabela de Contingência - Parte 1 ... 35

Figura 4: Tabela de Contingência - Parte 2 ... 36

Figura 5: Tabela de Contingência - Parte 3 ... 38

Figura 6: Comparação do tempo de processamento para bases de incidência. ... 41

(9)

LISTA DE TABELAS

Tabela 1: Tabela de Resposta Padrão ... 13 Tabela 2: Matriz de Padrão de Resposta ... 13 Tabela 3: Tabela de Contingência ... 16

(10)

LISTA DE ABREVIATURAS E SIGLAS

TF -TensorFlow.

CPU - Central Processing Unit (Unidade de Processamento Central). GPU - Graphics Processing Unit (Unidade de Processamento Gráfico).

API - Application Programming Interface (Interface de Programação de Aplicativo). CUDA - Compute Unified Device Architecture (Computação de Arquitetura Unificada de Dispositivo).

(11)

SUMÁRIO

RESUMO... 6

LISTA DE ILUSTRAÇÕES ... 7

LISTA DE TABELAS ... 8

LISTA DE ABREVIATURAS E SIGLAS ... 9

1 INTRODUÇÃO ... 11

2 DUAL SCALING ... 12

2.1 DADOS CATEGÓRICO ... 12

2.1.1 DADOS DE INCIDÊNCIA ... 13

2.1.2 DADOS DE DOMINÂNCIA ... 16

3 ALGORITMO DUAL SCALING EM GPU ... 20

3.1 COMPLEXIDADE DE UM ALGORITMO ... 20

3.2 TENSORFLOW ... 21

3.3 FUNCÕES TENSORFLOW ... 22

3.4 DADOS DE INCIDÊNCIA ... 31

3.5 DADOS DE DOMINÂNCIA ... 35

4 TESTE DE TEMPO DE PROCESSAMENTO ... 40

5 CONCLUSÃO ... 43

5.1 TRABALHOS FUTUROS ... 43

(12)

1

INTRODUÇÃO

Com a grande quantidade de informações e a velocidade que elas chegam atualmente, conseguir a separação e correlacionar todo esse conteúdo de forma que tenhamos mais eficiência, não é uma tarefa simples. O aumento das informações traz uma maior dificuldade e, nesse contexto, uma análise de dados se faz necessária. Diante de todo esse cenário de crescimento, criam-se novas técnicas, funções, algoritmos, hardware para melhorar o tempo de processamento dos dados sem, no entanto, comprometer o resultado final.

Na proposta deste trabalho, podemos ver como foram desenvolvidos os modelos matemáticos, Dual Scaling [1], utilizados para o mapeamento de indivíduos e suas preferências a estímulos. Ressaltamos à importância do uso das GPUs junto à implementação dessa técnica.

Além disso, é mostrada a biblioteca TensorFlow com suas funções para resolver problemas que envolvem matrizes. E por fim, fazemos uma comparação dos tempos dos algoritmos sequenciais confrontando com a implementação em GPU.

Este trabalho tem o intuito de mostrar o desenvolvimento do algoritmo Dual

Scaling em GPU usando a biblioteca TensorFlow [2]. Esse importante framework tem

se tornado uma das bibliotecas de Machine Learning disponíveis, com diversas melhorias, otimizações, novos recursos e uma crescente comunidade. Dentre as contribuições, usando este framework (TensorFlow), deste trabalho temos:

• Implementação do Dual Scaling para dados de incidência em GPU; • Implementação do Dual Scaling para dados de Dominância em GPU;

• Comparação de desempenho de um programa sequencial com um programa em paralelo (GPU).

2

DUAL SCALING

O Dual Scaling [1] é método versátil para análise de dados, reuni um conjunto de técnicas relacionadas para a análise de uma ampla variedade de tipos de dados categóricos, incluindo tabelas de contingência, dados de múltipla escolha, dados ordenados, ordem de classificação e comparação pareada.

(13)

12 A análise de dados possui diferentes facetas e abordagens, incorporando diversas técnicas. Tem grande importância em áreas como: ciências, estudos sociais e negócios, por conta da diversidade de modelos possíveis. Tem como objetivo descobrir relacionamentos entre as variáveis e obter delas a maior quantidade possível dos dados categóricos multivariados. O Dual Scaling, proposto por Shizuhiko Nishisato [1], é um método adequado para realizar tais funcionalidades.

2.1 DADOS CATEGÓRICO

Dados categóricos são aqueles que identificam para cada caso uma categoria. As categorias podem ser derivadas de variáveis qualitativas (nominais ou ordinais) ou quantitativas.

Existem duas categorias definidas por Shizuhiko Nishisato, são elas: dados de incidência e dados de dominância. A primeira engloba os dados de múltipla escolha, as tabelas de contingências e os dados ordenados; a segunda, os dados por ordem de classificação e os dados de comparação pareada. Usando as técnicas do método

Dual Scaling, faremos um estudo mais detalhado dos dados de incidência e dos dados

de dominância. Aquele inclui os dados de múltipla escolha e este, tabela de contingência.

2.1.1 DADOS DE INCIDÊNCIA

O cálculo do Dual Scaling para dados de incidência [18] proposto por Shizuhiko Nishisato, são perguntas de múltipla escolha. Elas são versáteis, intuitivas e geram dados limpos e fáceis de serem analisados. Como elas fornecem uma lista fixa de opções de resposta, proporcionam respostas estruturadas e facilitam para seu entrevistado concluir o questionário.

(14)

Baseado nas preferências para estímulos dos indivíduos, é feito um questionário de opinião de múltipla escolha e logo após respondidas todas as perguntas, transfere-se os resultados para uma tabela chamada de Tabela de Resposta Padrão da seguinte forma: para cada pergunta feita no questionário, a alternativa escolhida recebe o valor 1 e para as demais o valor 0. Concluída essa etapa, com a base de dados D pronta, cria-se uma Matriz de Padrão de Resposta Fn,m,

onde n (linhas da matriz) representa os indivíduos e m (colunas da matriz) os possíveis estímulos ou respostas de múltipla escolha.

Na apresentação dessa subseção, temos duas tabelas como exemplo de transformação dos estímulos dos indivíduos (respostas) em uma matriz.

Tabela 1: Tabela de Resposta Padrão

Perguntas com três alternativas

Indivíduo P1 P2 P3 P4 1 100 001 001 001 2 100 001 100 001 3 001 100 010 001 4 100 100 001 001 5 001 100 001 010

Tabela 2: Matriz de Padrão de Resposta

Colunas (m) Linhas (n) 1 2 3 4 5 6 7 8 9 10 11 12 1 1 0 0 0 0 1 0 0 1 0 0 1 2 1 0 0 0 0 1 1 0 0 0 0 1 3 0 0 1 1 0 0 0 1 0 0 0 1 4 1 0 0 1 0 0 0 0 1 0 0 1 5 0 0 1 1 0 0 0 0 1 0 1 0

O próximo passo é encontrar os vetores de frequência de linhas e colunas de F, onde fr e fc são, respectivamente, somatório das linhas e somatório das colunas.

(15)

14 𝑓𝑟𝑖 = ∑ 𝑚 𝑘 𝐹𝑖,𝑘 (1) 𝑓𝑐𝑗 = ∑ 𝑛 𝑘 𝐹𝑘,𝑗 (2)

Diagonalizando fr e fc, encontra-se a matriz diagonal de linhas Dr e a matriz diagonal de colunas Dc, ambas são quadradas e formadas em sua diagonal principal pelos valores dos seus respectivos vetores.

𝐷𝑟𝑖,𝑞 = {

𝑓𝑟𝑖𝑖 = 𝑞

0𝑖 ≠ 𝑞 (3)

𝐷𝑐𝑟,𝑗 = {𝑓𝑐𝑟𝑟 = 𝑗

0𝑟 ≠ 𝑗 (4)

Busca-se agora, uma matriz que defina as relações das variáveis entre as colunas da matriz F. Indicaremos por Mm,m, a matriz procurada e cuja equação é:

𝑀 = 𝐹𝑇𝐷𝑟−1𝐹𝐷𝑐−1, (5)

onde F t é a transposta de F, Dr-1 inversa de Dr e Dc-1 inversa deDc.

Sendo λ = { λ1, λ2, …, λm }, o vetor de autovalores e Vm,m, a matriz de

autovetores da matriz M, ordena-se os autovalores de forma decrescente e por conseguinte as colunas de Vm,m devem acompanhar seus respectivos autovalores.

Após essa etapa, remove-se o primeiro valor de λ bem como a primeira coluna de Vm,m. Observa-se também que o número máximo de elementos de λ e de colunas de

Vm,m deve ser iguais ao número de dimensões do espaço-solução ns, dado pela

equação

𝑛𝑠 = 𝑚 − 𝑞 − 1, (6)

onde m é o número de colunas (itens) de nossa matriz de padrão de respostas F, e q é o número de categorias dos itens de resposta (questões).

(16)

Assim obtém-se λf ={ λ2, λ3, λ4, …, λn-1 }, como o vetor final de autovalores,

e Vfm,n como a matriz final de autovetores.

Dando sequência, deve-se calcular as matrizes T, o vetor tc (somatório de todos os valores das colunas da matriz T), ft (somatório de todos os valores da matriz de padrão de respostas F) e o vetor Cc.

𝑇 = 𝐷𝑐(𝑉𝑓 ∘ 𝑉𝑓) (7)

O símbolo ᵒ não representa o produto de matrizes e sim o produto de

Hadamard [3]. Neste caso, o resultado é o quadrado de cada valor da matriz Vf.

𝑡𝑐𝑝 = ∑ 𝑚 𝑘 𝑇𝑘,𝑝 (8) 𝑓𝑡𝑛,𝑚 = ∑𝐹𝑛,𝑚 (9) 𝐶𝑐𝑝 = √𝑓𝑡 𝑡𝑐𝑝 (10)

Calculemos agora, o vetor ρ (raiz quadrada dos autovalores finais), a matriz N (peso padrão) e P (peso projetado).

𝜌𝑖 = √𝜆𝑓𝑖 (11)

Obtemos a matriz N, dado pelo produto de cada valor do vetor Cc para cada valor das respectivas coluna de Vf, ou seja, o primeiro elemento do vetor multiplica cada elemento da primeira coluna da matriz; o segundo elemento do vetor multiplica cada elemento da segunda coluna da matriz e assim por diante.

𝑁𝑖,𝑝= 𝑉𝑓𝑖,𝑝𝐶𝑐𝑝 (12)

Finalizando obtemos a matriz P, dado pelo produto de cada valor do vetor ρ para cada valor das respectivas coluna de N, ou seja, o primeiro elemento do vetor

(17)

16 multiplica cada elemento da primeira coluna da matriz; o segundo elemento do vetor multiplica cada elemento da segunda coluna da matriz e assim por diante.

Matriz de pesos projetados representa os valores do mapeamento dos itens em cada uma das dimensões do espaço-solução. Neste espaço n dimensional pode ser aplicadas técnicas de clusterização para agrupar itens semelhantes.

𝑃𝑖,𝑝= 𝑁𝑖,𝑝𝜌𝑝 (13)

2.1.2 DADOS DE DOMINÂNCIA

O cálculo do Dual Scaling para dados de dominância [17] proposto por Shizuhiko Nishisato é distinto daqueles para dados de incidência que são representados por 0 e 1. O objetivo é quantificar os elementos dos dados que são mensurações ordinais.

Na apresentação dessa subseção, temos uma tabela contingência como exemplo de dados de dominância. A tabela de contingência é a tabela que calcula observações por múltiplas variáveis categóricas. As linhas e colunas das tabelas correspondem a essas variáveis categóricas.

Tabela 3: Tabela de Contingência

Colunas (m)

Linhas (n) 1 2 3 4 5 6 7 8 9

1 10 09 05 06 03 12 44 16 78

2 01 00 86 07 64 55 75 83 12

3 48 73 02 06 07 04 98 32 41

Em nossa implementação criamos a matriz de entrada Eoriginal, de

dimensões n (linhas) e m (colunas). Os cálculos são iniciados multiplicando a matriz Eoriginal por um escalar -2, obtendo uma matriz E1.

(18)

Em seguida, somamos a E1, uma matriz Emais, de mesma dimensão, onde

seus valores são determinados por m (número de colunas de E1) + 1, obtendo Eadd.

(𝐸𝑎𝑑𝑑)𝑛,𝑚 = 𝐸1 + 𝐸𝑚𝑎𝑖𝑠 (15)

O próximo passo é encontrar a matriz C, obtida através do produto da matriz transposta (Eadd)t e Eadd, representado por C

1 e dividido por um escalar Q.

(𝐶1)𝑚,𝑚 = (𝐸𝑎𝑑𝑑)𝑡𝐸𝑎𝑑𝑑 (16)

𝑄 = (𝑛) ⋅ (𝑁) ⋅ (𝑛 − 1)2 (17)

(𝐶)𝑚,𝑚= 𝐶1⁄ 𝑄 (18)

Devemos agora encontrar os autovalores e os autovetores de C. Sendo D, o vetor de autovalores e V, a matriz de autovetores, ordena-se os autovalores de forma decrescente e por conseguinte as colunas de V devem acompanhar seus respectivos autovalores.

Dando sequência, devemos encontrar a raiz quadrada dos autovalores de D, representada ρ; a matriz x, através do produto de um escalar -1 e a matriz de autovetores V; e uma matriz Xsqr, que é obtida com o quadrado de cada valor da matriz

x.

𝜌𝑖 = √𝜆𝑓𝑖. (19)

(𝑥)𝑛,𝑚 = −1 ⋅ 𝑉 (20)

(19)

18 O próximo passo é encontrar Dc, uma matriz diagonal, onde sua diagonal principal é formada pelo vetor fc.

𝑓𝑐𝑚 = 𝑛 ⋅ (𝑚 − 1) (22)

𝐷𝑐𝑟,𝑗 = {𝑓𝑐𝑟𝑟 = 𝑗

0𝑟 ≠ 𝑗 (23)

Agora devemos obter uma matriz T com produto de Dc e Xsqr.

𝑇𝑛,𝑚 = 𝐷𝑐(𝑋𝑠𝑞𝑟) (24)

Encontramos também o vetor Cc, para isso achamos a raiz quadrada da divisão de ft e tc (somatório de todos os valores das colunas da matriz T).

𝑓𝑡 = 𝑛 ⋅ 𝑚 ⋅ (𝑚 − 1) (25) 𝑡𝑐𝑜= ∑ 𝑚 𝑘 𝑇𝑘,𝑜 (26) 𝐶𝑐𝑝 = √ 𝑓𝑡 𝑡𝑐𝑝 (27)

Dando continuidade, obtemos a matriz Xnormed, dado pelo produto de cada

valor do vetor Cc para cada valor das respectivas coluna de x, ou seja, o primeiro elemento do vetor multiplica cada elemento da primeira coluna da matriz; o segundo elemento do vetor multiplica cada elemento da segunda coluna da matriz e assim por diante.

(𝑋𝑛𝑜𝑟𝑚𝑒𝑑)𝑛,𝑚= 𝐶𝑐(𝑥) (28)

Em seguida, devemos achar a matriz Ynormed da mesma forma que obtemos

Xnormed. Porém temos que obter primeiro o vetor t, inverso do vetor L, que por sua vez,

(20)

produto de Eoriginal e Xnormed. Encontrado t e Ynorm, achamos a matriz Ynormed

multiplicando cada valor de t para cada valor das respectivas colunas da matriz Ynorm.

𝑓𝑟 = 𝑚 ⋅ (𝑚 − 1) (29)

𝐿𝑚 = 𝑓𝑟 ⋅ 𝜌 (30)

𝑡𝑚 = 1 𝐿⁄ (31)

(𝑌𝑛𝑜𝑟𝑚)𝑛,𝑚 = 𝐸𝑜𝑟𝑖𝑔𝑖𝑛𝑎𝑙(𝑋𝑛𝑜𝑟𝑚𝑒𝑑) (32)

(𝑌𝑛𝑜𝑟𝑚𝑒𝑑)𝑛,𝑚 = 𝑡𝑚(𝑌𝑛𝑜𝑟𝑚) (33)

Finalizando os cálculos, encontramos as matrizes Xprojected e Yprojected. Elas

são obtidas através do produto vetor ρ com as respectivas matrizes, da seguinte forma: o primeiro elemento do vetor, multiplica cada elemento da primeira coluna da matriz; o segundo elemento do vetor, multiplica cada elemento da segunda coluna da matriz e assim por diante.

(𝑌𝑝𝑟𝑜𝑗𝑒𝑐𝑡𝑒𝑑)𝑛,𝑚 = 𝜌(𝑌𝑛𝑜𝑟𝑚𝑒𝑑) (34)

(𝑋𝑝𝑟𝑜𝑗𝑒𝑐𝑡𝑒𝑑)𝑛,𝑚 = 𝜌(𝑋𝑛𝑜𝑟𝑚𝑒𝑑) (35)

Essas matrizes têm a mesma finalidade que é a representação do mapeamento dos itens da base para o espaço de n dimensões onde os itens são projetados. Neste espaço n dimensional pode ser aplicadas técnicas de clusterização para agrupar itens semelhantes.

3

ALGORITMO DUAL SCALING EM GPU

A cada dia fica evidente a importância de placas gráficas no auxílio ao processamento de grande quantidade de informações[4]. Muitas inovações surgiram para resolver problemas complexos. Com a linguagem CUDA [5] podemos explorar a capacidade de processamento das placas, não só na computação gráfica, mas também na científica.

(21)

20 As unidades de processamento gráfico (GPUs) que foram originalmente projetadas para renderização de gráficos surgiram como coprocessadores massivamente paralelos para a unidades de processamento central (CPUs). Estações de trabalho multi-GPU de tamanho pequeno com centenas de elementos de processamento podem acelerar substancialmente as aplicações científicas de simulação com uso intensivo de computação. Por apresentarem arquitetura dedicada e altamente paralelizada, as GPUs trazem muito mais ganhos do que as CPUs [6] .

O intuito de utilizar as GPUs em cálculos mais complexos é buscar minimizar o tempo gasto no processamento sem alterar os resultados. É mostrar que a exploração de paralelismo utilizando essa tecnologia pode fornecer um desempenho computacional significativo e que os resultados dessa implementação proposta é mais eficiente e pode ser indispensável para que simulações sejam realizadas com qualidade e que tenham um menor custo.

3.1 COMPLEXIDADE DE UM ALGORITMO

A complexidade de um algoritmo é um mecanismo para entender e avaliar um algoritmo em relação aos critérios como robustez, compatibilidade, desempenho (rapidez), consumo de recursos (memória), portabilidade e outros, bem como saber aplicá-los em problemas práticos.

No estudo da complexidade de algoritmo, é feito o uso de uma notação chamada Notação (O) ou Big-O, usada para análise de pior caso de um algoritmo, também chamado limite superior. A ideia da notação é descrever o comportamento geral, também chamado de assintótico, do algoritmo em termos do crescimento do número de operações conforme cresce o número de elementos processados.

Em nossos algoritmos de estudo, cuja complexidade é dada por O(m3) [7],

onde m representa o número de colunas da matriz, o uso das GPUs junto à escolha de um melhor algoritmo para o processamento dos dados traz um ganho muito significativo, abrindo um caminho de alta velocidade para o aprendizado de máquina, possibilitando processar imensos conjuntos de dados, em tempo cada vez menor, gerando modelos cada vez mais eficientes.

(22)

3.2 TENSORFLOW

É uma biblioteca de software de código aberto para computação numérica de alto desempenho. Sua arquitetura flexível permite a fácil implementação em várias plataformas como CPUs, GPUs, e de desktops a cluters de servidores para dispositivos móveis e periféricos. Outras vantagens do TF [2] é principalmente a disponibilização de APIs para linguagens de programação como Java [8], C++[9],

Python [10].

O TF foi lançado sob a licença de código aberto Apache 2.0 [11] em novembro de 2015. Originalmente desenvolvido por pesquisadores e engenheiros que trabalhavam na equipe do Google Brain [12] e na organização de Pesquisa de Inteligência de Artificial do Google para a realização de pesquisas em máquinas e em redes neurais profundas.

O nome TensorFlow é derivado das operações que as redes neurais realizam em arrays ou tensores de dados multidimensionais, é literalmente um fluxo de tensores. Essa arquitetura flexível permite que você implante computação para uma ou mais CPUs ou GPUs em uma área de trabalho, servidor ou dispositivo móvel sem reescrever o código. Embora contenha uma ampla gama de funcionalidades, o TF é projetado principalmente para modelos de redes neurais profundas. O aprendizado profundo é um subcampo de aprendizado de máquina que é um conjunto de algoritmos inspirados pela estrutura e função do cérebro.

Devemos notar que o TF não tem como objetivo principal fornecer soluções prontas de aprendizagem de máquina. Além disso, embora tenha suporte extensivo para a funcionalidade específica de Machine Learning, é igualmente adequado para executar cálculos matemáticos complexos. Existem dois fatores que levaram ao surgimento e expansão do TF, Big Data [14] e Deep Learning [15].

As aplicações do TF são inúmeras. Podem ser usadas em pesquisa, desenvolvimento, iteração através de novas arquiteturas de aprendizagem de máquina, implementação dos modelos diretamente em produção a partir da conclusão do treinamento, implementação em arquiteturas complexas existentes, criação e treinamento de modelos para sistemas móveis e embarcados.

(23)

22

3.3 FUNCÕES TENSORFLOW

O TensorFlow [2], como o nome indica, é uma estrutura para definir e executar cálculos envolvendo tensores. Um tensor é uma generalização de vetores e matrizes para dimensões potencialmente mais altas. Internamente, o TF representa os tensores como matrizes n-dimensionais de tipos de dados de base.

Na apresentação desse capítulo, vamos nos limitar a mostrar as funções do TF com apenas os argumentos utilizados na implementação dos programas

multiple_choice_data e contingency_table.

tf.convert_to_tensor

tf.convert_to_tensor(value,dtype=None)

Argumentos:

• value: Um objeto cujo tipo tem uma função de conversão.

• dtype: Tipo de elemento opcional para o tensor retornado.

Retorna: Uma saída com base no valor.

Observações: Converte o valor fornecido em um tensor. Essa função converte objetos

Python de vários tipos em objetos tensor. Ele aceita objetos tensor, matrizes numpy,

listas e escalares Python.

tf.matrix_transpose

matrix_transpose(a,name='matrix_transpose')

Argumentos:

• a: Um tensor com rank >= 2.

(24)

Retorna: Um tensor onde o número de linhas e o de colunas são invertidos.

Observações: Determinar a transposta de uma matriz é reescrevê-la de forma que suas linhas e colunas troquem de posições ordenadamente, isto é, a primeira linha é reescrita como a primeira coluna, a segunda linha é reescrita como a segunda coluna e assim por diante, até que se termine de reescrever todas as linhas na forma de coluna.

A classificação de um objeto tf.Tensor é seu número de dimensões. Sinônimos para

rank incluem ordem ou grau ou n-dimensão.

tf.reduce_sum

tf.reduce_sum(input_tensor,axis=None)

Argumentos:

• input_tensor: O tensor para ser reduzido. Deve ter tipo numérico.

• axis: As dimensões para reduzir. Se Nenhum (o padrão), reduz todas as dimensões. Deve estar no intervalo [-rank (input_tensor), rank (input_tensor)]. Retorna: Um tensor reduzido do mesmo tipo numérico que o input_tensor.

Observações: Em nossa implementação de dados de múltipla escolha, temos três variáveis fc, fr e ft que representam, respectivamente, a soma das colunas, das linhas e de todos os valores da matriz F.

fc = tf.reduce_sum(F,0) fr = tf.reduce_sum(F,1) ft = tf.reduce_sum(F) tf.diag tf.diag(x,name=None) Argumentos:

(25)

24 • x: Um tensor. Deve ser um dos seguintes tipos: bfloat16, half, float32, float64,

int32, int64, complex64, complex128. Rank k tensor onde k é no máximo 1. • name: Nome opcional para o tensor.

Retorna: Um tensor com os valores de x em sua diagonal principal.

Observações: Uma matriz diagonal é uma matriz quadrada onde os elementos que não pertencem à diagonal principal são obrigatoriamente iguais a zero.

tf.matrix_inverse

tf.matrix_inverse(input)

Argumentos:

• input: Um tensor. Deve ser um dos seguintes tipos: float64, float32, complex64,

complex128. A forma é [..., M, M].

Retorna: Um tensor com mesmo tipo numérico e forma do tensor de entrada.

Observações: Se uma matriz não é invertível, não há garantia do retorno da operação. Pode-se detectar a condição e gerar uma exceção ou simplesmente retornar um resultado não válido.

tf.matmul

tf.matmul(a,b,name=None)

Argumentos:

• a: Tensor do tipo float16, float32, float64, int32, complex64, complex128 e rank> 1.

• b: Tensor com o mesmo tipo e classificação de a. • name: Nome opcional para o tensor.

Retorna: Um tensor, onde o número de linhas é igual ao da matriz a, e o número de colunas, igual ao a da matriz b.

(26)

Observações: Deve-se observar que a propriedade comutativa de um produto elementar não é válida para um produto matricial, exceto quando as duas matrizes são iguais.

tf.self_adjoint_eig

tf.self_adjoint_eig(tensor,name=None)

Argumentos:

• tensor: Tensor de forma [..., N, N].

• name: Nome opcional da operação. Retorna:

• D: Autovalores. A forma é [..., N]. Ordenado em ordem não decrescente. • X: Autovetores. A forma é [..., N, N].

Observações: Para que autovalores e autovetores retornem separados, devemos usar a função da seguinte forma:

D,X = tf.self_adjoint_eig(M)

tf.multiply

tf.multiply(x,y,name=None)

Argumentos:

• x: Um tensor. Deve ser um dos seguintes tipos: bfloat16, half, float32, float64, uint8, int8, uint16, int16, int32, int64, complex64, complex128.

• y: Um tensor. Deve ter o mesmo tipo de x. • name: Um nome para a operação (opcional).

(27)

26

Observações: Como exemplo, a mesma função foi usada em nossa implementação tanto para encontrar o produto de Hadamard quanto para encontrar N, matriz de peso padrão.

H = tf.multiply(V,V) N = multiply(V,Cc)

O retorno dessa função não é um produto matricial. Em H, temos o produto de duas matrizes iguais, nesse caso particular a mesma matriz, onde cada elemento da primeira multiplica o elemento que se encontra na mesma posição da segunda matriz. Em N, temos um produto de uma matriz V e um vetor Cc, com o mesmo número de coluna, onde primeiro elemento do vetor multiplica cada elemento da primeira coluna da matriz; o segundo elemento do vetor, multiplica cada elemento da segunda coluna da matriz e assim por diante. Nessa função, a propriedade comutativa não altera o resultado final do produto.

tf.div

tf.div(x,y,name=None)

Argumentos:

• x: Numerador do tipo numérico real. • y: Denominador do tipo numérico real.

• name: Um nome para a operação (opcional).

Retorna: x / y retorna o quociente de x e y.

Observações: Se um dos números, x ou y é um float, então o resultado será um float. Caso contrário, a saída será um tipo inteiro.

tf.sqrt

tf.sqrt(x,name=None)

(28)

• x: Um tensor. Deve ser um dos seguintes tipos: half, float32, float64, complex64, complex128.

• name: Um nome para a operação (opcional).

Retorna: Um tensor com a raiz quadrada dos elementos de x.

Observações: Se o elemento for um número negativo, o retorno é dado por NAN. Observe o retorno da matriz Raiz no exemplo:

X = tf.constant([[25.0, -25.0],[-16.0, 16.0]]) Raiz = tf.sqrt(X)

Matriz Raiz = [[5. nan] [nan 4.]] tf.divide

tf.divide(x,y,name=None)

Argumentos:

• x: Um tensor para ser dimensionado. • y: Um tensor escalar 0-D.

• name: Um nome para a operação (opcional).

Retorna: Um tensor do mesmo tipo de x.

Observações: Nesta função, temos um escalar y dividindo todos os valores x.

tf.scalar_mul

tf.scalar_mul(scalar,x)

Argumentos:

• scalar: Um tensor escalar 0-D. Deve ter uma forma conhecida.

• x: Um tensor para ser dimensionado.

(29)

28 Observações: Nesta função, temos um escalar multiplicando todos os valores x. Se o escalar não é um escalar 0-D, teremos um erro no retorno da função.

tf.add

tf.add(x,y,name=None)

Argumentos:

• x: Um tensor. Deve ser um dos seguintes tipos: bfloat16, half, float32, float64, uint8, int8, int16, int32, int64, complex64, complex128, string.

• y: Um tensor. Deve ter o mesmo tipo de x. • name: Um nome para a operação (opcional).

Retorna: Um tensor com o mesmo tipo de x.

Observações: O número de linhas e colunas de x e y deve ser igual.

tf.reverse

tf.reverse(x,axis,name=None)

Argumentos:

• x: Um tensor. Deve ser um dos seguintes tipos: uint8, int8, uint16, int16, int32, int64, bool, half, bfloat16, float32, float64, complex64, complex128, string. Até 8-d.

• axis: Deve ser um dos seguintes tipos: int32, int64. 1-D. Os índices das dimensões para reverter deve estar no intervalo [-rank (tensor), rank (tensor)]. • name: Um nome para a operação (opcional).

Retorna: Um tensor com o mesmo tipo de x.

Observações: Em nossa implementação, usamos a função reverse para colocar os autovalores em ordem decrescente, já que a função self_adjoint_eig retorna em ordem crescente. Usamos também a mesma função para inversão da matriz de autovetores para acompanhar os respectivos valores do vetor de autovalores. Como exemplo temos:

(30)

tf.slice

tf.slice(input_,begin,size,name=None)

Argumentos:

• input_: Um tensor.

• begin: Deve ser do tipo: int32 ou int64.

• size: Deve ser do tipo: int32 ou int64.

• name: Um nome para a operação (opcional).

Retorna: Um subtensor (fatia) do tensor de entrada.

Observações: Essa operação extrai uma fatia de uma entrada do tensor, começando no local especificado por begin e o tamanho da fatia, por size. Devemos observar que a contagem do número de linhas e colunas em Python inicia-se por 0. Observe:

V = tf.slice(Vr,[0,1],[m,q])

No exemplo acima, o retorno é uma matriz onde o início (begin) será a partir da linha 0 e da coluna 1 e o tamanho (size) terá m linhas e q colunas.

tf.fill

tf.fill(dims,value,name=None)

Argumentos:

• dims : Um tensor. Deve ser um dos seguintes tipos: int32, int64. 1-D, representa

forma do tensor de saída.

• value: Um tensor 0-D (escalar). Valor para preencher o tensor a ser retornado.

• name: Um nome para a operação (opcional).

Retorna: Um tensor. com o mesmo tipo de value.

(31)

30 tf.shape

tf.shape(input,name=None)

Argumentos:

• input: Um tensor.

• name: Um nome para a operação (opcional).

Retorna: A forma do tensor.

Observações: Essa operação retorna um tensor inteiro 1-D representando a forma da entrada.

3.4 DADOS DE INCIDÊNCIA

Dividiremos o código multiple_choice_data em duas partes. Mostraremos, através das linhas de código em Python, o mapeamento das funções do TensorFlow com a importação de sua biblioteca como tf e onde foram aplicadas as equações usando as técnicas do Dual Scaling.

(32)

De acordo com a figura 1, temos:

• Na linha 68 do código, através da função convert_to_tensor, obtemos a matriz de entrada F;

• Na linha 71 do código, através da função transpose, obtemos a transposta de F, matriz ft;

• Na linha 74 do código, através da função reduce_sum, obtemos fr (vetor de frequência de linha, somatório de todas as linhas de F), representado pela equação (1);

• Na linha 78 do código, através da função diag, obtemos Dr (matriz diagonal formada em sua diagonal principal por fr), representada pela equação (3); • Na linha 81 do código, através da função matrix_inverse, obtemos Dr_inverse,

matriz inversa de Dr;

(33)

32 • Na linha 84 do código, através da função matmul, obtemos a matriz A,

resultante do produto das matrizes ft e Dr_inverse;

• Na linha 87 do código, através da função matmul, obtemos a matriz B, resultante do produto das matrizes A e F;

• Na linha 90 do código, através da função reduce_sum, obtemos fc (o vetor de frequência de coluna, somatório de todas as colunas F), representado pela equação (2);

• Na linha 94 do código, através da função diag, obtemos Dc (matriz diagonal formada em sua diagonal principal por fc), representada pela equação (4); • Na linha 97 do código, através da função matrix_inverse, obtemos Dc_inverse,

matriz inversa de Dc;

• Na linha 100 do código, através da função matmul, para obter M (matriz resultante do produto das matrizes B e Dc_inverse), representada pela equação (5);

(34)

De acordo com a figura 2, temos:

• Na linha 103 do código, através da função self_adjoint_eig, obtemos o vetor D, de autovalores, e a matriz X, de autovetores, ambos da matriz M;

• Na linha 106 do código, através da função reverse, obtemos er, vetor de autovalores de D em ordem decrescente;

• Na linha 107 do código, através da função reverse, obtemos Vr, matriz de autovetores de X ordenado com os autovalores;

• Na linha 110 do código, através da função slice, obtemos e, vetor de autovalores de er com o número de dimensões do espaço solução reduzido;

(35)

34 • Na linha 111 do código, através da função slice, obtemos V, matriz de

autovetores de Vr com o número de dimensões do espaço solução reduzido; • Na linha 114 do código, através da função multiply, obtemos H, matriz com

todos elementos de V elevados ao quadrado;

• Na linha 117 do código, através da função matmul, obtemos T (matriz resultante do produto das matrizes Dc e H), representada pela equação (7);

• Na linha 120 do código, através da função reduce_sum, obtemos o vetor de frequência de coluna tc (somatório de todas colunas de T), representado pela equação (8);

• Na linha 123 do código, através da função reduce_sum, obtemos ft (soma de todos os valores de F), representado pela equação (9);

• Na linha 126 do código, através da função div, obtemos G, obtemos um vetor resultante da divisão de ft por tc;

• Na linha 129 do código, através da função sqrt, obtemos Cc (vetor resultante da raiz quadrada da divisão de ft por tc), representado pela equação (10); • Na linha 132 do código, através da função sqrt, obtemos Rho (vetor resultante

da raiz quadrada do vetor de autovalores e), representado pela equação (11); • Na linha 134 do código, através da função multiply, obtemos N (matriz de peso

padrão resultante do produto de cada valor do vetor de Cc para cada valor da respectiva coluna de V), representada pela equação (12);

• Na linha 137 do código, através da função multiply, obtemos P (matriz de peso projetado resultante do produto de cada valor do vetor Cc para cada valor da respectiva coluna de N), representada pela equação (13).

(36)

Na apresentação dessa subseção, dividiremos o código contingency_table em três partes. Mostraremos, através das linhas de código em Python, o mapeamento das funções do TensorFlow com a importação de sua biblioteca como tf e onde foram aplicadas as equações usando as técnicas do Dual Scaling.

Primeira parte do código

De acordo com a figura 3, temos:

• Na linha 69 do código, através da função convert_to_tensor, obtemos a matriz de entrada Eoriiginal,;

• Na linha 72 do código, através da função scalar_mul, obtemos E1 (matriz

resultante do produto de um escalar -2 e a matriz Eoriiginal), sendo representada

pela equação (14);

• Na linha 75 do código, através da função fill, obtemos a matriz Emais (matriz

onde seus valores são formados por m + 1);

• Na linha 78 do código, através da função add, obtemos Eadd (matriz resultante

do somatório das matrizes E1 e Emais ), sendo representada pela equação (15);

• Na linha 81 do código, através da função matmul e da função transpose, obtemos C1 (matriz resultante do produto da transposta de Eadd ea Eadd), sendo

representada pela equação (16);

(37)

36 • Na linha 84 do código, Q, número determinado por uma expressão que envolve

n e m, representado pela equação (17);

• Na linha 87 do código, através da função divide, obtemos C (matriz resultante da divisão da matriz C1 e o escalar Q), sendo representada pela equação (18);

Segunda parte do código

De acordo com a figura 4, temos:

• Na linha 89 do código, através da função self_adjoint_eig, obtemos o vetor D, de autovalores, a matriz V, de autovetores, ambos da matriz C;

• Na linha 92 do código, através da função reverse, obtemos Drev, vetor de autovalores de D em ordem decrescente;

• Na linha 95 do código, através da função slice, obtemos D, vetor de autovalores de Drev com o último valor removido;

(38)

• Na linha 98 do código, através da função reverse, obtemos Vrev, matriz de autovetores de V ordenado com os autovalores;

• Na linha 101 do código, através da função slice, obtemos V, matriz de autovetores de Vr com o número de dimensões do espaço solução reduzido; • Na linha 104 do código, através da função sqrt, obtemos Rho (vetor resultante

da raiz quadrada do vetor de autovalores D), sendo representado pela equação (19);

• Na linha 107 do código, através da função scalar_mul, obtemos x (matriz resultante do produto de um escalar -1 e a matriz V), sendo representada pela equação (20);

• Na linha 110 do código, através da função multiply, obtemos Xsqr (matriz com

todos elementos de x elevados ao quadrado), sendo representada pela equação (21);

• Na linha 113 do código, através da função fill, obtemos a vetor fc, (matriz formada por uma exprssão que envolve n e m), sendo representado pela equação (22);

• Na linha 116 do código, através da função diag, obtemos a matriz diagonal Dc (formada em sua diagonal principal por fc), sendo representada pela equação (23);

• Na linha 119 do código, através da função matmul, obtemos T (matriz resultante do produto das matrizes Dc e Xsqr), sendo representada pela equação (24);

• Na linha 122 do código, ft, número determinado por uma expressão que envolve n e m, representado pela equação (25);

(39)

38

De acordo com a figura 5, temos:

• Na linha 125 do código, através da função reduce_sum, obtemos o vetor de frequência de coluna tc (somatório de todas colunas de T), sendo representado pela equação (26);

• Na linha 128 do código, através da função div, obtemos G ( vetor resultante da divisão ft por tc);

• Na linha 131 do código, através da função sqrt, obter Cc (vetor resultante da raiz quadrada da divisão de ft por tc ) sendo representado pela equação (27); • Na linha 134 do código, através da função multiply, obtemos Xnormed (matriz

resultante do produto de cada valor do vetor Cc para cada valor da respectiva coluna da matriz x), sendo representada pela equação (28);

(40)

• Na linha 137 do código, fr, número determinado por uma expressão que envolve m, representado pela equação (29);

• Na linha 140 do código, através da função scalar_mul, obtemos L (vetor resultante do produto de um escalar fr e vetor Rho), sendo representado pela equação (30);

• Na linha 143 do código, através da função div, obtemos t (vetor resultante do inverso dos valores de L), sendo representado pela equação (31);

• Na linha 146 do códiigo, através da função matmul, obtemos Ynorm (matriz

resultante do produto das matrizes Eoriginal e Xnormed), sendo representada pela

equação (32);

• Na linha 149 do código, através da função multiply, obtemos Ynormed (matriz

resultante do produto de cada valor do vetor t para cada valor da respectiva coluna de Ynorm), sendo representada pela equação (33)

• Na linha 152 do código, através da função multiply, obtemos Xprojected (matriz

resultante do produto de cada valor do vetor Rho para cada valor da respectiva coluna de Xnormed), sendo representada pela equação (34);

• Na linha 155 do código, através da função multiply, obtemos Yprojected (matriz

resultante do produto de cada valor do vetor Rho para cada valor da respectiva coluna de Ynormed), sendo representada pela equação (35);

• Na linha 157 do código, obtemos a através da função shape (retorna as dimensões da matriz Xprojected);

• Na linha 158 do código, obtemos b através da função shape (retorna as dimensões da matriz Yprojected);

4

TESTE DE TEMPO DE PROCESSAMENTO

O objetivo deste trabalho foi desenvolver os algoritmos de Dual Scaling de forma paralela rodando em GPU. Para validar os nossos algoritmos, desenvolvido em

(41)

40 Python usando TensorFlow, vamos comparar com a implementação sequencial em C++ sem uso de TensorFlow. Embora sejam linguagem diferentes, uma compilada (C++) e a outra interpretada (Python), a diferença de tempo de execução dos dois cenários é disprezível, pois o algoritmo C++ é sequencial enquanto o Python é paralelo. Os experimentos foram realizados em um PC, com sistema operacional Windows 8 64 bits, com CPU Intel I7 4.0GHz, placa de vídeo NVIDIA Geforce GTX 760 com 2GB de memória e 16GB de memória RAM.

Nossos testes foram realizados em bases reais fornecidas por LUCS-KDD ARM e CARM biblioteca [15]. Infelizmente, são foram selecionadas 5 bases porque as outras não couberam na memória de vídeo, impossibilitando assim a comparação do algoritmo sequencial e paralelo. Para bases de incidência foi selecionado duas bases: mFeat com 2000 transações e 1648 iten; e WaveForm com 5000 transações e 98 itens. Para bases de Dominância foi selecionado três bases: Chess com 3196 transações e 75 itens; BMS com 59602 transações e 497 itens; e connect-4 com 67557 transações e 129 itens.

O primeiro experimento foi realizado em base de incidência, veja Figura 6. Nesse teste podemos perceber que o algoritmo em GPU teve um desempenho muito superior para base mFeat, cujo o tempo em GPU foi 7,30 segundos contra 136.4 segundos em CPU. O mesmo comportamento não foi observado para a segunda base Waveform, onde o tempo em CPU foi 3,30 segundos contra 9,45 segundos da GPU.

(42)

Esse comportamento acontece por dois motivos, o primeiro é o TensorFlow não implementa matriz esparsa, consequentemente, as matrizes diagonais Dc e Dr são altamente esparsas. A implementação em C++ utiliza essa propriedade para evitar contas desnecessárias. Outro problema, que foi observado, foi o tempo de comunicação para copiar a matriz da memória principal para GPU e vice-versa. Logo, para matrizes com poucos itens (m), o tempo de comunicação com GPU gera um

overheard no tempo final de processamento.

O segundo experimento foi realizado com bases de dominância, veja Figura 7. A base Chess, teve um desempenho na GPU 1,60 segundos, contra 2,90 segundos da CPU. A base BMS, o tempo de processamento foi 18,20 segundos em GPU, contra

Figura 6: Comparação do tempo de processamento para bases de incidência.

(43)

42 21,90 segundos em CPU. A última base Connec4, teve o tempo de processamento em 2,75 segundos em GPU, contra 5,71 segundos em CPU. Neste teste percebemos que a base connect teve maior diferença de tempo de processamento. Os mesmos problemas que ocorreram nas bases de incidência, aconteceu nas bases de dominância.

Durante os experimentos percebemos que uma das desvantagens do TensorFlow é que a biblioteca não implementa matrizes esparsas. Isso limitou o uso do algoritmo, uma vez que, para determinadas bases a matriz diagonal Dr tinha um tamanho muito superior comportado pela placa de vídeo. Desta forma a implementação ficou muito limitada ao tamanho de transações, para o caso de base de incidência.

5

CONCLUSÃO

Em nosso trabalho buscamos apresentar um estudo que fornecesse uma melhora no tratamento das informações, como obter resultados mais simplificados, mais rápidos e que mantivesse confiabilidade na solução final. Para que esses objetivos fossem alcançados, utilizamos método Dual Scaling, que reuni várias

Figura 7: Comparação do tempo de processamento para bases de dominância.

(44)

técnicas para trabalhar com bases de dados complexas, para analisar e gerar informações mais simplificadas, devido ao seu método multidimensional e não linear de quantificação; utilizamos GPUs, com suas arquiteturas paralelizadas, para aumentar o desempenho no processamento dos dados e com isso diminuir o tempo de resposta; fizemos uso da biblioteca TensorFlow para fornecer um conjunto extenso de funções que permitem aos usuários definir modelos personalizados e flexíveis de forma rápida e intuitiva. Porém, ao longo do projeto, embora tenha cumprida alguns pontos, foram observadas limitações no que se refere a algumas bases de dados por não trabalhar com matrizes esparsas em GPUs. Uma alternativa para esse problema é utilização do Cupy , framework genérico para qualquer tipo de base.

5.1 TRABALHOS FUTUROS

Um possível trabalho futuro é explorar a matriz de pesos projetados para calcular a matriz de distância quadrada entre eles, pois quanto menor a distância ente os itens, maior o relacionamento entre eles. Obter um valor delta, percentual que representa um todo no espaço-solução, para calcular cada uma das dimensões do espaço-solução.

(45)

44

REFERÊNCIA BIBLIOGRÁFICA

1. NISHISATO, S. Elements of Dual Scaling: An Introduction To Practical Data Analysis. [S.l.]: Psychology Press.,1993.

2. ABADI, Martín; AGARWAL, Ashish.TensorFlow: Large-scale Machine Learning on Heterogeneous Systems. <htttp://www.tensorflow.org>Acesso em 20 mar. 2018.

3. NISHISATO, Shizuhiko. On quantifying different types of categorical data. Psychometrika .,1993.

4. Hadamard product (matrices). In: Wikipédia: a enciclopédia livre.

<https://en.wikipedia.org/wiki/Hadamard_product_(matrices) > Acesso em 01 jun. 2018.

5. RIOS, E. Exploração de Estratégias de Busca Local em Ambientes CPU/GPU,2016. Tese de Doutorado, Programa de Pós-graduação em Computação, Instituto de Computação, Universidade Federal Fluminense.

6. CUDA. <https://developer.nvidia.com/cuda-zone>Acesso em 03 mar. 2018.

7. DETOMINI, Renan Correa . Using GPU to exploit parallelism on cryptography. In: Information Systems and Technologies., 2011.

8. COUTINHO, Demétrios. Complexidade Algoritmo. <https://docente.ifrn.edu.br/> Acesso em 15 de mai. 2018.

9. DEITEL, Paul; DEITEL, Harvey. Java How to Program, 2014. Curso de Graduação em Sistema de Informação, MIT Sloan School of Management.

10. JAMSA, Kris; KLANDER, Lars. Jamsa's C/C++ Programmer's Bible: The Ultimate Guide to C/C++ Programming, 1997. Doutorado em ciência da computação com ênfase em sistemas operacionais , Arizona State University, Arizona.

11. VAN ROSSUM, Guido; DRAKE, Fred L. The Python Language Reference Manual. Network Theory Ltd, 2011. Mestrado na Universidade de Amsterdã, Holanda.

12. McCOOL, Robert. Apache Software Foundation. <http://www.apache.org> Acesso em 25 abr. 2018.

(46)

14. TAURION, Cezar. Big data, 2013. Mestrado em Ciência da Computação. 15. GOODFELLOW, Ian. Deep learning, 2016. MIT, Cambridge.

16. Coenen. The LUCS-KDD discretised/normalised ARM and CARM data library.

<http://www.csc.liv.ac.uk/∼frans/KDD/Software/LUCS-KDD-DN/DataSets/dataSets.html> Acessado em 30 mai. 2018.

17. Nishisato, Shizuhiko. Optimal scaling of paired comparison and rank order

data: An alternative to guttman's formulation. 1978. Psychometrika.

18. Nishisato, Shizuhiko and Sheu, Wen-Jenn. A note on dual scaling of successive

Referências

Documentos relacionados

Vale ressaltar que, para direcionar os trabalhos da Coordenação Estadual do Projeto, é imprescindível que a mesma elabore seu Planejamento Estratégico, pois para Mintzberg (2006,

O fortalecimento da escola pública requer a criação de uma cultura de participação para todos os seus segmentos, e a melhoria das condições efetivas para

De fato, na escola estudada, o projeto foi desenvolvido nos moldes da presença policial na escola quando necessária e palestras para os alunos durante o bimestre,

Bento Pereira apresenta uma lista de autores e obras em língua portuguesa, de vários pendores: religioso, enciclopédico, dicionarístico, e literário.A escolha destas obras

O 6º ano do Mestrado Integrado em Medicina (MIM) é um estágio profissionalizante (EP) que inclui os estágios parcelares de Medicina Interna, Cirurgia Geral,

Todas as outras estações registaram valores muito abaixo dos registados no Instituto Geofísico de Coimbra e de Paços de Ferreira e a totalidade dos registos

Realizar a manipulação, o armazenamento e o processamento dessa massa enorme de dados utilizando os bancos de dados relacionais se mostrou ineficiente, pois o

Por fim, na terceira parte, o artigo se propõe a apresentar uma perspectiva para o ensino de agroecologia, com aporte no marco teórico e epistemológico da abordagem