-
Agora que você já sabe o que é
um modelo de IA generativa,
-
nós vamos dar um mergulho
mais profundo e começar a ver
-
como podemos implementar
esses modelos na prática.
-
Para isso, precisamos conhecer
a base desses modelos.
-
A base para modelos
de IA generativas
-
são redes neurais artificiais,
-
e a base para redes neurais
artificiais é álgebra linear.
-
Então, nesse laboratório, veremos
uma revisão sobre a álgebra linear
-
utilizando a biblioteca
NumPy do Python.
-
Álgebra linear, basicamente, é
como podemos fazer operações
-
com vetores e matrizes.
-
Então, para começar
esse laboratório,
-
a gente vai começar a relembrar
um pouco sobre vetores
-
e ver como podemos representar
esses vetores no Python.
-
Para isso, vamos utilizar
a biblioteca NumPy do Python.
-
Essa biblioteca é especializada
em cálculo numérico e álgebra linear,
-
então é a principal biblioteca
do Python para esse fim.
-
Então, vamos começar o código
mportando essa biblioteca
-
para dentro do código.
-
Então "import numpy as np".
-
Bom, para definir
um vetor no NumPy,
-
eu posso utilizar o módulo
"array" do NumPy.
-
Então, se eu criar
um "vetor_a = np.array"
-
e passar uma lista
de valores para ele,
-
ele vai criar
um vetor para mim.
-
Se eu quiser criar
um segundo vetor, "b",
-
eu também posso
utilizar o mesmo código.
-
Então, "np.array", vou passar
uma lista de valores
-
e será criado um array, ou um vetor,
e associado à variável "vetor_b".
-
Nesse código aqui, vamos
criar dois vetores, "A" e "B",
-
e vamos printar
esses vetores.
-
Então, aqui nas respostas,
vetor A e vetor B,
-
da forma como a gente
criou anteriormente,
-
e as dimensões do vetor A,
-
por exemplo, o vetor B tem
a mesma dimensão do vetor A.
-
Então, o que é a dimensão
de um vetor?
-
São quantos elementos
tem nesse vetor.
-
Então, esse vetor tem
três elementos, perfeito?
-
Se eu quiser fazer a soma
desses dois vetores,
-
eu posso simplesmente vir aqui
e criar uma variável "soma_vetores",
-
que vai ser igual
a "vetor_a + vetor_b".
-
E, aqui, eu vou printar
a soma desses vetores.
-
Então, quando nós somamos dois
vetores, qual a operação é feita?
-
Basicamente, uma soma,
elemento a elemento,
-
então cada elemento
do vetor A
-
vai ser somado com o mesmo
elemento do vetor B,
-
e eu vou ter esse
resultado aqui na soma.
-
Se eu quiser fazer uma subtração,
da mesma forma, "vetor_a - vetor_b",
-
e o resultado é uma subtração
elemento a elemento.
-
Então, eu posso, por exemplo, criar
uma variável "vetor_multiplicado",
-
que vai ser igual ao vetor_a vezes
um valor escalar, por exemplo, "2".
-
Essa multiplicação também
será feita elemento a elemento,
-
então cada elemento do vetor A
será multiplicado por 2,
-
e aqui a gente tem,
no nosso código,
-
a resposta desse
vetor multiplicado.
-
Então, 1 vezes 2,
2 vezes 2, 3 vezes 2,
-
e a resposta aqui na variável
vetor_multiplicado.
-
Uma outra operação
muito importante
-
que eu posso fazer
com dois vetores,
-
se chama "produto escalar".
-
O produto escalar
entre dois vetores
-
é uma operação onde eu vou
multiplicar esses dois vetores
-
e o resultado será
um número escalar.
-
O que esse número representa?
-
Esse número representa
um certo grau de similaridade
-
entre esses dois
vetores, ou seja,
-
se esses vetores
estiverem apontando
-
para uma mesma direção,
esse produto será maior.
-
Se esses produtos estiverem
perpendiculares um com o outro,
-
ou seja, se tiver um ângulo
de 90 graus entre eles,
-
esse produto escalar vai
retornar algo próximo de 0.
-
E se eles estiverem apontando
para direções opostas,
-
isso significa que esse produto
escalar terá um valor negativo.
-
Então, basicamente,
o produto escalar
-
é uma forma de você
multiplicar dois vetores
-
e obter um escalar
como resposta,
-
e esse escalar tem
um certo significado,
-
indica, mais ou menos,
se esses dois vetores
-
estão apontando
para direções parecidas.
-
Como eu calculo isso?
-
Por trás dos panos,
eu estou fazendo
-
linhas de um vetor
versus colunas do outro.
-
Então, se for necessário,
por exemplo, nesse caso,
-
a gente tem vetores
de mesmas dimensões,
-
o segundo vetor vai ser
transposto, nesse caso.
-
Então, se eu fizer, aqui, o produto
escalar do vetor A com o vetor B,
-
eu vou ter um número, 32.
-
Esse número indica,
de certa forma,
-
se esses dois vetores
estão apontando
-
para direções similares
ou opostas.
-
Outro conceito
muito importante
-
quando a gente fala
de álgebra linear
-
é o conceito de matrizes.
-
Então, diferentemente dos vetores,
que têm apenas uma dimensão,
-
as matrizes podem ter
duas dimensões.
-
Então, as matrizes vão
ter linhas e colunas.
-
Então, serão parecidas
com uma tabelinha,
-
que teria linhas e colunas.
-
Então, eu posso criar, aqui
no Python, uma matriz X,
-
usando o np.array,
-
e, em vez de passar apenas
uma lista de valores,
-
eu vou passar uma lista
de listas de valores,
-
onde cada lista vai representar
uma linha dessa matriz.
-
Essa matriz tem duas linhas,
essa linha e essa linha,
-
e duas colunas, essa
coluna e essa coluna.
-
Então, é uma matriz que tem
dimensões 2 por 2.
-
A matriz Y também é
uma matriz 2 por 2,
-
porque ela tem duas
linhas e duas colunas.
-
Se a gente rodar esse código,
a gente vai ver essas duas matrizes
-
dispostas, aqui, da forma
que a gente criou elas, perfeito?
-
As operações que a gente
pode fazer com as matrizes
-
são muito similares às operações
que a gente pode fazer
-
com os vetores.
-
Então, eu posso olhar
para o shape dessa matriz,
-
vai me dar
as dimensões dela,
-
então quais são
as dimensões dessa matriz?
-
No vetor, a gente tinha
apenas uma dimensão,
-
então a gente criou
um vetor de três posições.
-
Aqui, eu tenho duas dimensões,
eu tenho linhas e colunas,
-
então cada uma das nossas matrizes
tem duas linhas e duas colunas.
-
Isso, a gente consegue saber usando
o atributo "shape" da nossa matriz.
-
Da mesma forma
como vetores,
-
como a gente fez
para os nossos vetores,
-
a gente pode somar matrizes.
-
Então, quando eu somo
a matriz X com a matriz Y,
-
eu estou fazendo a mesma operação
que a gente fez para os vetores,
-
então eu estou somando,
elemento a elemento,
-
os valores das duas matrizes.
-
Então, se a gente fizer
a soma e printar essa soma,
-
a gente vai ter o resultado,
que é a soma das duas matrizes,
-
elemento a elemento.
-
Da mesma forma,
se a gente fizer a subtração
-
entre essas duas matrizes,
eu também vou ter o resultado
-
como sendo uma matriz resultante
de mesma dimensão, 2 por 2,
-
onde cada valor é a subtração,
elemento a elemento,
-
dessas duas matrizes.
-
Por fim, eu posso multiplicar
essa matriz, ou alguma matriz,
-
por um valor escalar, e aí eu
também terei uma resposta
-
que vai ser a multiplicação desse
escalar, por exemplo, o valor "3",
-
por cada elemento
dessa matriz.
-
Então, o resultado também
é uma matriz 2 por 2,
-
e essa matriz 2 por 2,
cada elemento dela
-
é o resultado da multiplicação
desse escalar pelo valor da matriz.
-
Da mesma forma que fizemos
o produto escalar para vetores,
-
podemos, também,
aplicar para matrizes,
-
porém, com uma pequena
diferença.
-
Nos vetores, temos
apenas uma dimensão,
-
nas matrizes, a gente
tem duas dimensões.
-
Então, se eu criar
uma matriz, por exemplo,
-
chamada "matriz_a_mult",
-
como uma matriz que vai ter
duas linhas e três colunas,
-
eu utilizaria esse código
aqui para criá-la.
-
Poderia criar, também,
uma "matriz_b_mult",
-
essa matriz ao invés de ter
duas linhas por três colunas,
-
vai ter três linhas
por duas colunas.
-
Então, se a gente rodar
esse código aqui,
-
a gente pode ver, aqui,
as nossas duas matrizes.
-
Uma tem dimensões dois por três,
uma tem dimensões três por dois.
-
Para fazer o produto escalar
dessas duas matrizes,
-
eu posso utilizar o mesmo
código do NumPy,
-
a mesma função,
o mesmo método,
-
"np.dot", "matriz_a_mult"
e "matriz_b_mult",
-
e eu vou ter o resultado
dessa multiplicação.
-
Note que o resultado
dessa multiplicação
-
é uma matriz de 2 por 2.
-
Então, existe uma regrinha
-
para a gente fazer multiplicação
matricial através do produto escalar
-
e essa multiplicação
ser possível.
-
Qual seria essa regra?
-
As dimensões da minha matriz A,
a quantidade de colunas dela
-
tem que ser igual à quantidade
de linhas da matriz B.
-
Então, sempre que eu estiver
fazendo o produto escalar
-
entre duas matrizes, a quantidade
de colunas da primeira
-
tem que ser igual à quantidade
de linhas da segunda.
-
E o resultado sempre será
a quantidade de linhas da primeira
-
por a quantidade
de colunas da segunda.
-
Então, essas duas matrizes,
eu posso multiplicar, por quê?
-
Porque elas obedecem
o primeiro quesito,
-
a quantidade de colunas
da matriz A
-
é igual à quantidade
de linhas da matriz B.
-
E o resultado dessa conta
desse produto escalar
-
vai dar a quantidade
de linhas da matriz A
-
pela quantidade de colunas
da matriz B, que vai dar 2 por 2.
-
Então, se a gente pudesse
fixar um pouco essa regra,
-
você poderia pensar assim: quando
eu for multiplicar duas matrizes,
-
fazer o produto escalar delas,
os valores de dentro, ou seja,
-
a quantidade de colunas da primeira
e de linhas da segunda
-
tem que ser igual, e o resultado
vai dar os dois de fora, ou seja,
-
a quantidade de linhas
da primeira
-
e a quantidade
de colunas da segunda.
-
Então, seguindo aqui,
vamos passar, agora,
-
por outras operações relevantes
no nosso contexto de álgebra linear.
-
Um conceito mega importante,
uma operação mega importante
-
é inverter uma matriz.
-
Para inverter uma matriz, qualquer
matriz tem que ser quadrada,
-
como a que a gente
está criando aqui,
-
"matriz_quadrada = np.array",
uma matriz de 2 por 2.
-
Então, o que é
uma matriz quadrada?
-
Mesma quantidade de linhas é
a mesma quantidade de colunas.
-
E ela precisa ser não singular.
-
Ser não singular significa que
o determinante dela não pode ser 0.
-
Então, basicamente, inverter
uma matriz, no Python,
-
a gente pode fazer utilizando
o módulo do NumPy de linear algebra,
-
então "np.linalg",
-
e do linalg, eu vou usar
o método "inv", de inverter.
-
Então, vou criar uma variável
matriz inversa
-
e vou atribuir
para ela a inversa,
-
o cálculo da inversa dessa matriz
quadrada que a gente criou.
-
Quando a gente inverte
uma matriz, o que significa?
-
É como se eu estivesse
fazendo um cálculo análogo
-
a 1 sobre um determinado
número, esse é o inverso dela.
-
Então, 1 sobre
essa matriz
-
é a mesma coisa que a inversa
dessa matriz, perfeito?
-
Então, se a gente
rodar esse código,
-
a gente vai ver, aqui, a matriz
quadrada que a gente tinha criado
-
e, aqui, a inversa
dessa matriz quadrada.
-
Ela é uma matriz quadrada,
então ela pode ser invertível
-
e ela é não singular, então ela
pode ser invertível também,
-
tem que obedecer esses
dois critérios aí, perfeito?
-
E aí, a gente pode,
depois, no nosso código
-
verificar essa inversão
dessa matriz.
-
Como eu poderia
fazer isso?
-
Se eu fizer o produto escalar
da matriz original com a sua inversa,
-
eu tenho que ter como resultado
a matriz identidade, ou seja,
-
a matriz identidade
no contexto de álgebra
-
é como se fosse o valor 1.
-
Então, é como se eu multiplicasse
a matriz por 1 sobre a matriz,
-
eu vou ter 1 como resposta, é isso
que quer dizer esse código aqui.
-
Seguindo no nosso código,
-
como a gente falou
de determinante da matriz,
-
a gente pode verificar, aqui,
-
como calcular o determinante
de uma matriz.
-
Então, vou criar,
aqui, uma matriz
-
para a gente calcular
o determinante com base nela
-
e eu vou utilizar o mesmo módulo
de linear algebra do NumPy,
-
só que eu vou usar, agora,
o método "det", de determinante.
-
Então, qual é o determinante
dessa matriz?
-
Se a gente rodar
esse código,
-
a gente vai ver que o determinante
dessa matriz é 4.99.
-
Se eu tiver
uma matriz singular,
-
o que significa
uma matriz singular?
-
Significa que é uma matriz
cujo determinante é 0.
-
Se o determinante dela é 0, eu
não consigo inverter essa matriz.
-
Então, essa matriz
singular que a gente criou
-
mais embaixo do nosso código é
uma matriz que não teria inversa,
-
não seria possível calcular
a inversa dessa matriz, perfeito?
-
Outra operação extremamente
importante é a norma de um vetor.
-
Então, a norma de um vetor
é como a gente calcula,
-
de certa forma,
o tamanho desse vetor.
-
Então, a norma desse vetor...
-
Existem várias formas de se
calcular a norma de um vetor.
-
A mais conhecida e a mais
utilizada é a norma L2,
-
que é também conhecida
como a norma Euclidiana.
-
Então, ela é dada
por essa continha aqui,
-
então vai ser a raiz quadrada
da soma dos valores dessa matriz,
-
desse vetor, ao quadrado,
então a raiz quadrada da soma
-
dos quadrados dos valores
dessa matriz, perfeito?
-
Então, se a gente tiver
aqui uma matriz 3 e -4,
-
a norma Euclidiana
dessa matriz vai ser 5.
-
Como eu chego
nesse cálculo?
-
Fazendo a raiz quadrada
da soma dos quadrados
-
dos valores desse
vetor, perfeito?
-
Bom, então, para calcular
a norma Euclidiana,
-
eu posso usar o módulo
de álgebra linear do NumPy,
-
utilizando o método
"norm", certo?
-
E eu vou ter a norma
Euclidiana.
-
Existem, também, outras formas
de normas que a gente pode utilizar,
-
por exemplo, a norma
de Frobenius.
-
Não é uma norma
muito utilizada,
-
mas apenas para a gente conseguir
visualizar que existe um parâmetro,
-
eu posso parametrizar o tipo
de norma que eu quero
-
na função, no método
"norm" do NumPy.
-
Então, por padrão, essa biblioteca
já utiliza a norma Euclidiana,
-
mas eu poderia definir outra
dentre as normas possíveis,
-
e, para saber
as normas possíveis,
-
a gente pode olhar na documentação
dessa biblioteca, perfeito?
-
Outro cálculo muito interessante, muito importante para criar IAs e
-
para a álgebra linear como um todo, é você calcular distâncias entre
-
vetores.
-
Então eu posso ter dois vetores e eu quero calcular o quão distantes
-
esses vetores são.
-
Para fazer a distância entre vetores, eu posso simplesmente calcular
-
a diferença entre eles.
-
Então se eu calcular a diferença entre eles eu vou ter um menos o
-
outro.
-
Eu vou ter a distância de cada vetor em cada dimensão.
-
Quando eu quero criar, utilizar uma distância euclidiana, o que é a
-
distância euclidiana?
-
É uma distância baseada na norma euclidiana, então vai ser a norma
-
L2, a norma euclidiana da diferença entre os dois vetores.
-
Então eu vou fazer a raiz quadrada das diferenças elevado ao
-
quadrado, essa que é a conta.
-
No Python, eu poderia simplesmente fazer a norma das diferenças dos
-
vetores que a gente calculou aqui.
-
E aqui eu coloco a ordem 2, a ordem já é presumida que é
-
o 2, por default, e aí a gente tem aqui o que a gente
-
chama de distância euclidiana entre dois vetores, o quão distantes
-
esses dois vetores estão, certo?
-
Outra métrica bastante interessante para se calcular entre dois
-
vetores é a distância de Manhattan.
-
Então a única diferença entre a distância euclidiana e a distância de
-
Manhattan é a ordem dessa norma.
-
Então 1 a gente chama de norma L2, a distância euclidiana, a
-
distância de Manhattan a gente chama de L1, tudo por causa da norma,
-
da ordem da norma.
-
O que é que isso muda na prática?
-
Na norma euclidiana isso muda que a gente usa o quadrado das
-
diferenças.
-
Na norma de Manhattan, na distância de Manhattan, norma L1, a gente
-
usa o módulo, como se estivesse usando uma ordem 1, elevado a 1 aqui,
-
esse número, então a gente usa a norma dos valores.
-
Então se a gente verificar aqui a gente vai ter diferentes normas e
-
cada norma dessa vai ser mais útil ou menos útil dependendo do caso
-
de uso que a gente tiver.
-
Outras operações úteis aqui no contexto de álgebra linear, a gente
-
pode transpor uma matriz, então frequentemente a gente vai ter que
-
calcular a transposta de uma matriz.
-
O que é a transposta de uma matriz?
-
É simplesmente eu transformar o que era linha em coluna e o que era
-
coluna em linha.
-
Então se eu criar uma matriz 3 por 2 com esses valores, com esses
-
elementos, a transposta dessa matriz original vai ser simplesmente
-
essa matriz transposta, ou seja, linhas vão virar colunas e colunas
-
vão virar linhas.
-
Então no final a dimensão dessa matriz vai ir de 3 por 2 para
-
2 por 3.
-
Então vamos rodar esse código aqui para visualizar.
-
Eu tinha uma matriz original 3 por 2, a matriz transposta vai ser 2
-
por 3.
-
Outro conceito interessante é você criar uma matriz identidade.
-
Então a matriz identidade é uma matriz similar a um número 1, então
-
aquela matriz que se você multiplicar uma matriz por ela, é como se
-
você estivesse multiplicando um número por 1, então vai dar ela
-
mesma.
-
Então a matriz identidade no Python, utilizando numpy, a gente usa a
-
função i.
-
Se eu colocar aqui como entrada 2, eu vou ter uma matriz identidade 2
-
por 2.
-
Se eu colocar 3, eu vou ter uma matriz identidade 3 por 3.
-
Então matriz identidade sempre são matrizes quadradas, ou seja, mesmo
-
número de linhas e de colunas.
-
Então se a gente rodar aqui, a gente vai ter a matriz identidade 2
-
por 2, vou ter a matriz transposta, e se eu multiplicar uma matriz
-
por sua identidade, se eu fizer o produto escalar entre eles, eu vou
-
ter como resultado a mesma matriz original.
-
Certo?
-
1, 2, 3, 4, resposta 1, 2, 3, 4, perfeito?
-
Agora algumas funções auxiliares que o numpy oferece para a gente.
-
Então o numpy oferece, por exemplo, uma funçãozinha que é
-
interessante para o que a gente vai fazer durante as aulas, que se
-
chama linspace.
-
O que esse linspace faz?
-
Ele simplesmente cria pontos linearmente, igualmente espaçados, vamos
-
dizer assim.
-
Então o que essa funçãozinha aqui está fazendo?
-
Eu vou criar 5 pontos entre 0 e 10, e esses pontos vão ser
-
linearmente espaçados.
-
Então 0, 2.5, 5, 7.5, 10.
-
Tenho 5 pontos e a distância entre eles é igual.
-
Outras funções auxiliares.
-
Eu posso criar uma matriz só com 0s no Python, utilizando a função np
-
.0s, e aqui eu posso passar como entrada, como parâmetro para essa
-
função, a dimensão da matriz que eu quero criar.
-
Então eu vou criar uma matriz de 0s com dimensões 2 linhas e 3
-
colunas.
-
Da mesma forma eu posso criar uma matriz de números 1s, utilizando np
-
.ones. Vou passar aqui, eu quero criar uma matriz de 3 linhas e 2
-
colunas, só com números 1s.
-
Então está aqui a nossa matriz de 0s e a nossa matriz de 1s.
-
E a gente pode também concatenar esses vetores, ou seja, eu posso
-
juntar dois vetores ou juntar duas matrizes.
-
Então aqui, por exemplo, eu tenho uma matriz chamada array1 e essa
-
matriz é np.array, primeira linha, segunda linha, cada uma com duas
-
colunas.
-
E eu posso ter um vetor, uma matriz que na verdade aqui vai ter
-
uma linha só, uma linha e duas colunas.
-
Então se eu concatenar esses dois arrays aqui, esses dois vetores,
-
essas duas matrizes aqui no caso, eu vou ter, na verdade, no final
-
uma matriz, esse array concatenado vai adicionar essa linha nesse
-
vetor original que tinha só duas linhas.
-
Então vou ter um vetor de 3 linhas e 2 colunas, uma matriz, no
-
caso, de 3 linhas e 2 colunas.
-
Esse parâmetro aqui, axis, ele significa quando é 0 eu vou adicionar
-
nas linhas, quando é colunas eu vou adicionar nas colunas.
-
Então um eu vou adicionar embaixo, o outro eu vou adicionar ao lado,
-
é como se fosse isso.
-
Então aqui eu tenho um exemplo tanto adicionando linhas a uma matriz
-
original, quanto adicionando colunas a uma matriz original.
-
Então se a gente rodar esse exemplo, eu tenho a matriz 1, 2 por
-
2, e a matriz 2, que é uma linha por duas colunas.
-
Quando eu concateno elas utilizando o eixo 0, o axis 0, eu vou
-
adicionar uma linha a mais.
-
No outro exemplo, debaixo, eu tenho uma matriz aqui de duas linhas e
-
uma coluna, e eu vou concatenar um array nas colunas, então eu vou
-
adicionar duas colunas diferentes.
-
Então eu continuo com 7 e 8, vou adicionar o 1, 3, 2, 4
-
aqui, como colunas novas nessa matriz original.
-
E por último, para fechar o nosso lab, eu também posso utilizar uma
-
função de reshape nos meus dados, nos meus arrays, nos meus vetores e
-
matrizes.
-
O que o reshape vai fazer?
-
Eu consigo alterar o formato dessa matriz ou desse array.
-
Então imagina que eu tenho uma matriz aqui, um array na verdade, que
-
eu tenho 6 elementos nesse array.
-
Eu posso reshape, fazer um reshape nesse dado, nessa matriz, e
-
transformá-lo em uma matriz de duas linhas e três colunas.
-
O único ponto aqui importante para a gente pensar é, no final, essa
-
conta tem que fechar.
-
Então se eu tenho 6 colunas, 6 números, 6 elementos nesse vetor, e eu
-
quero transformá-lo em uma matriz, as dimensões aqui têm que
-
multiplicar e dar o mesmo resultado que a quantidade de elementos
-
desse vetor original.
-
Então se eu tenho 6 elementos, 2 vezes 3 tem que dar 6.
-
Eu poderia também fazer 3 por 2, ou 6 por 1, mas eu não
-
poderia fazer 2 por 4, porque daria erro.
-
Então se a gente rodar aqui, tem o array original, e esse array,
-
quando eu fizer o reshape de 2 por 3 dele, ele vai reajustar esses
-
elementos em uma matriz de duas linhas e três colunas.
-
Se eu colocasse 4 aqui, daria erro.
-
Por que daria erro?
-
Porque eu só tenho 6 elementos.
-
Para fazer um reshape de 2 e 4, eu teria que ter 8 elementos.
-
Então o único ponto de atenção seria esse.
-
Então agora você já sabe muito sobre a generativa e já deu seus
-
primeiros passos sobre álgebra linear para conseguir você mesmo
-
implementar os seus próprios modelos de a generativa.