-
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 multi,
-
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 multi, 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 e matriz B, e eu vou ter o resultado dessa multiplicação.
-
Note que o resultado dessa multiplicação é uma matriz de dois por
-
dois.
-
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 multiplicá-las, por quê?
-
Porque ela obedece 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 dois por dois.
-
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 iguais.
-
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 igual NP-array, uma
-
matriz de dois por dois.
-
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 zero.
-
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 que significa?
-
É como se eu estivesse fazendo um cálculo análogo a um sobre um
-
determinado número.
-
Esse é o inverso dela.
-
Então um 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 que 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 nesse 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 álgebra 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, logo 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.
-
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.
-
Então se a gente tiver aqui uma matriz 3 e menos 4, a norma
-
euclidiana dessa matriz vai ser 5.
-
Como que eu chego nesse cálculo?
-
Fazendo a raiz quadrada da soma dos quadrados dos valores desse
-
vetor.
-
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?
-
Eu vou ter a norma euclidiana.
-
Existem também outras formas de norma, 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 a gente utiliza, 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.