Deixe-me saber se você acha isso valioso e continuarei!
Um dos conceitos mais simples, porém poderosos, é o modelo linear.
No ML, um dos nossos principais objetivos é fazer previsões com base em dados. O modelo linear é como o "Hello World" do aprendizado de máquina - é simples, mas constitui a base para a compreensão de modelos mais complexos.
Vamos construir um modelo para prever os preços das casas. Neste exemplo, a saída é o "preço da casa" esperado e suas entradas serão coisas como "pés quadrados", "num_quartos", etc...
def prediction(sqft, num_bedrooms, num_baths): weight_1, weight_2, weight_3 = .0, .0, .0 home_price = weight_1*sqft, weight_2*num_bedrooms, weight_3*num_baths return home_price
Você notará um "peso" para cada entrada. Esses pesos são o que criam a magia por trás da previsão. Este exemplo é enfadonho porque sempre produzirá zero, pois os pesos são zero.
Então vamos descobrir como podemos encontrar esses pesos.
O processo para encontrar os pesos é chamado de "treinamento" do modelo.
data = [ {"sqft": 1000, "bedrooms": 2, "baths": 1, "price": 200000}, {"sqft": 1500, "bedrooms": 3, "baths": 2, "price": 300000}, # ... more data points ... ]
home_price = prediction(1000, 2, 1) # our weights are currently zero, so this is zero actual_value = 200000 error = home_price - actual_value # 0 - 200000 we are way off. # let's square this value so we aren't dealing with negatives error = home_price**2
Agora que temos uma maneira de saber o quanto estamos errados (erro) para um ponto de dados, podemos calcular o erro médio em todos os pontos de dados. Isso é comumente referido como erro quadrático médio.
Poderíamos, é claro, escolher números aleatórios e continuar salvando o melhor valor à medida que avançamos - mas isso é ineficiente. Então, vamos explorar um método diferente: descida gradiente.
Gradiente descendente é um algoritmo de otimização usado para encontrar os melhores pesos para nosso modelo.
O gradiente é um vetor que nos diz como o erro muda à medida que fazemos pequenas alterações em cada peso.
Intuição da barra lateral
Imagine estar em uma paisagem montanhosa e seu objetivo é chegar ao ponto mais baixo (o erro mínimo). O gradiente é como uma bússola que sempre aponta para a subida mais íngreme. Ao ir contra a direção do gradiente, estamos dando passos em direção ao ponto mais baixo.
Funciona assim:
Como calculamos o gradiente para cada erro?
Uma maneira de calcular o gradiente é fazer pequenas mudanças no peso, ver como isso impactou nosso erro e ver para onde devemos nos mover a partir daí.
def calculate_gradient(weight, data, feature_index, step_size=1e-5): original_error = calculate_mean_squared_error(weight, data) # Slightly increase the weight weight[feature_index] = step_size new_error = calculate_mean_squared_error(weight, data) # Calculate the slope gradient = (new_error - original_error) / step_size # Reset the weight weight[feature_index] -= step_size return gradient
Detalhamento passo a passo
Parâmetros de entrada:
Calcular erro original:
original_error = calculate_mean_squared_error(weight, data)
Primeiro calculamos o erro quadrático médio com nossos pesos atuais. Isso nos dá nosso ponto de partida.
weight[feature_index] = step_size
Aumentamos o peso em uma pequena quantidade (step_size). Isso nos permite ver como uma pequena mudança no peso afeta nosso erro.
new_error = calculate_mean_squared_error(weight, data)
Calculamos o erro quadrático médio novamente com o peso ligeiramente aumentado.
gradient = (new_error - original_error) / step_size
Este é o passo principal. Estamos perguntando: "Quanto mudou o erro quando aumentamos ligeiramente o peso?"
A magnitude nos diz quão sensível é o erro às mudanças neste peso.
weight[feature_index] -= step_size
Colocamos o peso de volta ao valor original, pois estávamos testando o que aconteceria se o alterássemos.
return gradient
Retornamos o gradiente calculado para esse peso.
Isso é chamado de "cálculo de gradiente numérico" ou "método de diferença finita". Estamos aproximando o gradiente em vez de calculá-lo analiticamente.
Agora que temos nossos gradientes, podemos empurrar nossos pesos na direção oposta do gradiente subtraindo o gradiente.
weights[i] -= gradients[i]
Se nosso gradiente for muito grande, poderíamos facilmente ultrapassar nosso mínimo atualizando demais nosso peso. Para corrigir isso, podemos multiplicar o gradiente por algum número pequeno:
learning_rate = 0.00001 weights[i] -= learning_rate*gradients[i]
E aqui está como fazemos isso para todos os pesos:
def gradient_descent(data, learning_rate=0.00001, num_iterations=1000): weights = [0, 0, 0] # Start with zero weights for _ in range(num_iterations): gradients = [ calculate_gradient(weights, data, 0), # sqft calculate_gradient(weights, data, 1), # bedrooms calculate_gradient(weights, data, 2) # bathrooms ] # Update each weight for i in range(3): weights[i] -= learning_rate * gradients[i] if _ % 100 == 0: error = calculate_mean_squared_error(weights, data) print(f"Iteration {_}, Error: {error}, Weights: {weights}") return weights
Finalmente, temos nossos pesos!
Depois de termos nossos pesos treinados, podemos usá-los para interpretar nosso modelo:
Por exemplo, se nossos pesos treinados forem [100, 10000, 15000], significa:
Modelos lineares, apesar de sua simplicidade, são ferramentas poderosas em aprendizado de máquina. Eles fornecem uma base para a compreensão de algoritmos mais complexos e oferecem insights interpretáveis sobre problemas do mundo real.
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3