Audyt: CATS => R, R=> syntetyczne sieci neuronowe
REF/: https://rpubs.com/staszkiewicz/AI_EX_1_Back_Prop
Demonstracja działania prostej sieci neuronowej z propagacją wsteczną.
Ten dokument przedstawia prosty przykład sieci neuronowej, który demonstruje działanie propagacji wstecznej. Sieć neuronowa to model obliczeniowy inspirowany budową ludzkiego mózgu, zdolny do uczenia się wzorców z danych. Propagacja wsteczna to algorytm uczenia, który dostosowuje wagi sieci w celu minimalizacji błędu między przewidywaniami a rzeczywistymi wartościami.
W tej sekcji generujemy dane treningowe. Składają się one z dwóch cech (x1 i x2) oraz zmiennej docelowej (y), która przyjmuje wartość 1, jeśli punkt (x1, x2) znajduje się wewnątrz okręgu o promieniu 0.5, a 0 w przeciwnym razie. Jest to nieliniowy problem, który sieć neuronowa ma rozwiązać.
set.seed(123)
n <- 1000
x <- matrix(runif(n*2, -1, 1), ncol=2)
y <- ifelse(x[,1]^2 + x[,2]^2 < 0.5, 1, 0) # Okrąg decyzyjny
y_matrix <- matrix(y, ncol = 1)
W tej części definiujemy funkcje niezbędne do działania sieci neuronowej:
Funkcja sigmoidalna: Jest to funkcja aktywacji, która mapuje wartości do zakresu (0,1). Jej pochodna jest używana w propagacji wstecznej.
Inicjalizacja sieci: Tworzymy początkowe wagi sieci (W1, b1, W2, b2) jako małe liczby losowe.
Trenowanie sieci: Algorytm propagacji wstecznej, który składa się z propagacji wprzód (obliczenie wyjścia) i propagacji wstecznej (obliczenie gradientów i aktualizacja wag).
# Funkcje aktywacji
sigmoid <- function(x) {
1 / (1 + exp(-x))
}
sigmoid_deriv <- function(x) {
x * (1 - x)
}
# Inicjalizacja sieci
init_network <- function() {
list(
W1 = matrix(rnorm(2*4, 0, 0.1), 2, 4), # Warstwa ukryta: 2 wejścia -> 4 neurony
b1 = matrix(rep(0, 4), nrow = 1),
W2 = matrix(rnorm(4*1, 0, 0.1), 4, 1), # Warstwa wyjściowa: 4 neurony -> 1 wyjście
b2 = matrix(rep(0, 1), nrow = 1)
)
}
# Propagacja wsteczna
train_nn <- function(network, X, y, epochs = 1000, lr = 0.1) {
loss_history <- numeric(epochs)
for(epoch in 1:epochs) {
# Propagacja wprzód
hidden_input <- X %*% network$W1 + matrix(rep(network$b1, nrow(X)), ncol = ncol(network$b1), byrow = TRUE)
hidden_layer <- sigmoid(hidden_input)
output_input <- hidden_layer %*% network$W2 + matrix(rep(network$b2, nrow(hidden_layer)), ncol = ncol(network$b2), byrow = TRUE)
output_layer <- sigmoid(output_input)
# Obliczenie straty (MSE)
loss <- mean((output_layer - y)^2)
loss_history[epoch] <- loss
# Propagacja wsteczna
d_output <- (output_layer - y) * sigmoid_deriv(output_layer)
d_hidden <- (d_output %*% t(network$W2)) * sigmoid_deriv(hidden_layer)
# Aktualizacja wag
network$W2 <- network$W2 - lr * t(hidden_layer) %*% d_output
network$b2 <- network$b2 - lr * colSums(d_output)
network$W1 <- network$W1 - lr * t(X) %*% d_hidden
network$b1 <- network$b1 - lr * colSums(d_hidden)
if(epoch %% 200 == 0) {
cat("Epoka:", epoch, " Strata:", loss, "\n")
}
}
return(list(network = network, loss = loss_history))
}
Teraz inicjujemy sieć i trenujemy ją na wygenerowanych danych. Proces treningowy trwa przez zadaną liczbę epok (2000) i aktualizuje wagi sieci w celu minimalizacji straty.
nn <- init_network()
result <- train_nn(nn, x, y, epochs=2000, lr=0.1)
## Epoka: 200 Strata: 0.3951945
## Epoka: 400 Strata: 0.08709829
## Epoka: 600 Strata: 0.07555704
## Epoka: 800 Strata: 0.05678827
## Epoka: 1000 Strata: 0.04943748
## Epoka: 1200 Strata: 0.04149414
## Epoka: 1400 Strata: 0.03368687
## Epoka: 1600 Strata: 0.03210593
## Epoka: 1800 Strata: 0.03115282
## Epoka: 2000 Strata: 0.03033942
trained_nn <- result$network
Po treningu wizualizujemy wyniki:
Krzywa uczenia: Pokazuje, jak strata maleje z każdą epoką, co świadczy o postępie uczenia.
Granica decyzyjna: Wykres pokazuje, jak sieć neuronowa podzieliła przestrzeń na dwie klasy. Czerwona linia to granica decyzyjna (wartość 0.5). Punkty są kolorowane zgodnie z ich prawdziwą klasą.
# Krzywa uczenia
plot(result$loss, type = 'l', main = 'Krzywa uczenia',
xlab = 'Epoka', ylab = 'Strata', col = 'blue')
# Granica decyzyjna
library(ggplot2)
# Tworzenie siatki punktów
grid_size <- 100
x1_seq <- seq(-1, 1, length.out = grid_size)
x2_seq <- seq(-1, 1, length.out = grid_size)
grid <- expand.grid(x1 = x1_seq, x2 = x2_seq)
# Predykcja dla siatki
grid_matrix <- as.matrix(grid)
hidden_input_grid <- grid_matrix %*% trained_nn$W1 + matrix(rep(trained_nn$b1, nrow(grid_matrix)), ncol = ncol(trained_nn$b1), byrow = TRUE)
hidden_layer_grid <- sigmoid(hidden_input_grid)
output_input_grid <- hidden_layer_grid %*% trained_nn$W2 + matrix(rep(trained_nn$b2, nrow(hidden_layer_grid)), ncol = ncol(trained_nn$b2), byrow = TRUE)
grid$pred <- sigmoid(output_input_grid)
# Wykres
ggplot(grid) +
geom_raster(aes(x = x1, y = x2, fill = pred)) +
geom_contour(aes(x = x1, y = x2, z = pred), breaks = 0.5, color = 'red', linewidth = 1) +
geom_point(data = data.frame(x = x[,1], y = x[,2], class = as.factor(y)),
aes(x = x, y = y, color = class), alpha = 0.5) +
scale_fill_viridis_c(name = "Predykcja") +
scale_color_manual(values = c("0" = "blue", "1" = "yellow")) +
labs(title = 'Granica decyzyjna sieci neuronowej',
subtitle = 'Czerwona linia pokazuje granicę decyzyjną (0.5)') +
theme_minimal() +
coord_fixed()
Oceniamy dokładność modelu na danych treningowych. Obliczamy, jaki procent przykładów został poprawnie sklasyfikowany, oraz przedstawiamy macierz pomyłek, która pokazuje, ile przykładów każdej klasy zostało poprawnie i błędnie sklasyfikowanych.
# Przewidywania na danych treningowych
hidden_layer_test <- sigmoid(x %*% trained_nn$W1 + matrix(rep(trained_nn$b1, nrow(x)), ncol = ncol(trained_nn$b1), byrow = TRUE))
predictions <- sigmoid(hidden_layer_test %*% trained_nn$W2 + matrix(rep(trained_nn$b2, nrow(hidden_layer_test)), ncol = ncol(trained_nn$b2), byrow = TRUE))
predicted_classes <- ifelse(predictions > 0.5, 1, 0)
# Dokładność
accuracy <- mean(predicted_classes == y)
cat("Dokładność klasyfikacji:", round(accuracy * 100, 2), "%\n")
## Dokładność klasyfikacji: 94.9 %
# Macierz pomyłek
confusion_matrix <- table(Prawdziwe = y, Przewidziane = predicted_classes)
print("Macierz pomyłek:")
## [1] "Macierz pomyłek:"
print(confusion_matrix)
## Przewidziane
## Prawdziwe 0 1
## 0 599 0
## 1 51 350
Podsumowujemy działanie sieci neuronowej. Podajemy ostateczną wartość straty, architekturę sieci oraz użyte algorytmy.
cat("Ostateczna strata:", round(result$loss[length(result$loss)], 4), "\n")
## Ostateczna strata: 0.0303
cat("Architektura sieci: 2 -> 4 -> 1\n")
## Architektura sieci: 2 -> 4 -> 1
cat("Funkcja aktywacji: Sigmoid\n")
## Funkcja aktywacji: Sigmoid
cat("Algorytm uczenia: Propagacja wsteczna\n")
## Algorytm uczenia: Propagacja wsteczna
Wnioski Sieć neuronowa nauczyła się nieliniowego wzorca (okręgu) za pomocą propagacji wstecznej. Krzywa uczenia pokazuje, że strata systematycznie maleje, a granica decyzyjna jest zbliżona do prawdziwego okręgu. Dokładność klasyfikacji jest wysoka, co potwierdza skuteczność modelu.
Sieć poprawnie nauczyła się nieliniowego wzorca (okręgu) korzystając z: - Funkcji sigmoidalnej jako aktywacji - Algorytmu propagacji wstecznej - Gradient descent do aktualizacji wag
Tech. op.:
Ten kod: 1. Tworzy sieć neuronową z jedną warstwą ukrytą 2. Używa sigmoid jako funkcji aktywacji 3. Implementuje pełną propagację wsteczną 4. Wizualizuje wyniki za pomocą ggplot2 5. Jest napisany czysto w R bez zewnętrznych bibliotek 6. Działa efektywnie w RStudio 7. Może być bezpośrednio uruchomiony w R Markdown