Um mit den bisherigen Verfahren Lineare Regression und Logistische Regression nichtlineare Vorhersagen zu treffen, muss man die Zahl der Merkmale um polynomiale Merkmale erhöhen. Auf den Seiten NRW Wahl 2017 Gesamtergebnis und NRW Wahl 2017 Düsseldorf können Sie mit höhergradigen Merkmalen für das Problem den Wahlerfolg einer Partei aus den Ergebnissen zweier anderer vorherzusagen spielen. Hat man zwei Merkmale x1,x2 (also zum Beispiel zwei Parteiergebnisse) und wählt alle als Hypothesenfunktion die Funktion Σ6i=0Σij=0θi,jxi1xi−j2 sprich die Funktion mit allen polynomialen Merkmalen bis zum Grad 6, so erhält man 28 Merkmale.
mapFeature(c(2),c(3),6)
## x1^0*x2^0 x1^1*x2^0 x1^0*x2^1 x1^2*x2^0 x1^1*x2^1 x1^0*x2^2 x1^3*x2^0
## [1,] 1 2 3 4 6 9 8
## x1^2*x2^1 x1^1*x2^2 x1^0*x2^3 x1^4*x2^0 x1^3*x2^1 x1^2*x2^2 x1^1*x2^3
## [1,] 12 18 27 16 24 36 54
## x1^0*x2^4 x1^5*x2^0 x1^4*x2^1 x1^3*x2^2 x1^2*x2^3 x1^1*x2^4 x1^0*x2^5
## [1,] 81 32 48 72 108 162 243
## x1^6*x2^0 x1^5*x2^1 x1^4*x2^2 x1^3*x2^3 x1^2*x2^4 x1^1*x2^5 x1^0*x2^6
## [1,] 64 96 144 216 324 486 729
dim(mapFeature(c(2),c(3),6))
## [1] 1 28
Neuronale Netze ermöglichen es, nichtlineare Hypothesen zu formulieren, ohne die Zahl der Merkmale zu erhöhen.
Wichtige Notationen:
Anstatt die Strategie 1-versus-all anzuwenden, wenn wir in mehr als zwei Klassen klassifizieren wollen, wählen wir die Outputschicht so, dass sie genausoviele Zellen hat, wie unser Problem Klassen. Die n-te Klasse wird nun über einen Outputvektor repräsentiert, der überall 0-en und nur an der n-ten Position eine 1 hat.
Gegeben eine Menge von handgeschriebenen Ziffern klassifiziert nach den dargestellten Ziffern, gesucht ist ein Algorithmus, der zuverlässig neue Ziffern erkennen kann.
In der Variable X
haben wir jetzt eine Matrix der Dimension 5000, 400. Sprich 5000 Bilder jeweils kodiert in 20*20 Pixeln.
# Randomly select 100 data points to display
rand_indices <- sample(m)
sel <- X[rand_indices[1:100], ]
displayData(sel)
Hier die Durchschnitte der Input-Bilder:
average <- c()
for (i in 1:10){
down <- (i-1)*500+1
up <- i*500
numberi <- X[down:up,]
average <- rbind(average,apply(numberi,2,mean))
}
displayData(average)
Wir werden zunächst einen Klassifikator mit logistischer Regression trainieren.
lambda <- 1
classes <- 10
#XsubIndex <- sample(5000,5)
#X <- X[XsubIndex,]
#y <- y[XsubIndex,]
oneVersusAll_theta <- oneVersusAll(X, y, classes, lambda)
Diesen Klassifikator können wir jetzt für einzelne Vorhersagen nutzen:
for (i in 1:10){
ex <- sample(5000,1)
displayData(X[ex,])
Xex <- matrix(X[ex,],nrow=length(ex))
predict <- predictOneVersusAll(Xex,oneVersusAll_theta)
real <- y[ex]
real <- real %% 10 # modulo 10 in order to set class 10 back to 0.
predict <- predict %% 10 # modulo 10 in order to set class 10 back to 0.
print(paste("predict number:",predict,"real number:", real))
}
## [1] "predict number: 3 real number: 3"
## [1] "predict number: 9 real number: 9"
## [1] "predict number: 5 real number: 5"
## [1] "predict number: 6 real number: 6"
## [1] "predict number: 0 real number: 0"
## [1] "predict number: 0 real number: 0"
## [1] "predict number: 8 real number: 8"
## [1] "predict number: 2 real number: 2"
## [1] "predict number: 4 real number: 4"
## [1] "predict number: 4 real number: 4"
Wir können aber auch alle Ziffern vorhersagen lassen und die Accuracy berechnen:
predict_all <- predictOneVersusAll(X,oneVersusAll_theta)
acc <- mean(predict_all == y) *100
Die Accuracy ist 92.96.
Beachte, dass wir auf denselben Daten trainiert und getestet haben. Dies birgt immer das Risiko des Overfittings, wir werden daher nun noch einen Durchlauf machen, in dem wir auf 90% der Daten trainieren und auf den übrigen 10% testen.
# Choosing training and test data:
m <- dim(X)[1]
n <- dim(X)[1]
t <- round(m/10)
testIndex <- sample(m)[1:t]
Xtest <- X[testIndex, ]
Xtrain <- X[-testIndex,]
ytest <- y[testIndex]
ytrain <- y[-testIndex]
# training the one-versus-all classificator
lambda <- 1
classes <- 10
oneVersusAll_theta <- oneVersusAll(Xtrain, ytrain, classes, lambda)
# predicting the values for the test data and calculate accuracy
predict_all <- predictOneVersusAll(Xtest,oneVersusAll_theta)
acc <- mean(predict_all == ytest) *100
Die Testdaten werden mit einer Genauigkeit von 89.8% vorhergesagt.
Das Trainieren des one-versus-all Klassifikators benötigt relativ viel Zeit, da pro Klasse ein eigenes logistisches Regressionsmodell trainiert werden muss.
Zunächst legen wir die Architektur unseres neuronalen Netzes fest:
# Load data
load('ex3data1.rda')
list2env(data,.GlobalEnv)
## <environment: R_GlobalEnv>
rm(data)
## Setup the parameters you will use for this exercise
input_layer_size <- 400; # 20x20 Input Images of Digits
hidden_layer_size <- 25; # 25 hidden units
classes <- 10; # 10 labels, from 1 to 10
# (note that we have mapped "0" to label 10)
# Load the pretrained weights / parameters Theta1 and Theta2
load('ex3weights.Rda')
list2env(data,.GlobalEnv)
## <environment: R_GlobalEnv>
rm(data)
Wir haben jetzt ein neuronales Netz mit einem Input layer der Größe 400, einem Hidden Layer der Größe 25 und einem Output Layer der Größe 10 definiert. Die Dimension von θ(0) ist dementsprechend 25, 401 und die von θ(1) ist 10, 26.
Mit diesem neuronalen Netz können wir jetzt Vorhersagen mittels feedforward propagation machen:
pred <- predictNN(X,Theta1,Theta2)$prediction
acc <- mean(pred==y) * 100
Die Vorhersagen haben eine Genauigkeit von 97.52%.
Hier noch ein paar Beispielvorhersagen:
ex <- sample(5000,10)
for (i in ex){
displayData(X[i,])
Xex <- matrix(X[i,],nrow=length(i))
predict <- predictNN(Xex,Theta1,Theta2)$prediction
real <- y[i]
real <- real %% 10 # modulo 10 in order to set class 10 back to 0.
predict <- predict %% 10 # modulo 10 in order to set class 10 back to 0.
print(paste("predict number:",predict,"real number:", real))
}
## [1] "predict number: 8 real number: 8"
## [1] "predict number: 9 real number: 9"
## [1] "predict number: 2 real number: 2"
## [1] "predict number: 3 real number: 3"
## [1] "predict number: 4 real number: 4"
## [1] "predict number: 3 real number: 3"
## [1] "predict number: 0 real number: 0"
## [1] "predict number: 7 real number: 7"
## [1] "predict number: 8 real number: 8"
## [1] "predict number: 2 real number: 2"
Im obigen Beispiel haben wir mit einem bereits vortrainierten Netz gearbeitet. Nun werden wir die Parameter des neuronalen Netzes selbst trainieren. Hierzu nutzen wir den backpropagation Algorithmus.
Wir benutzen die Kostenfunktion für neuronale Netze:
# unroll parameters
nn_params <-c(c(Theta1),c(Theta2))
lambda <- 0
cost_noReg <- CostFunctionNN(input_layer_size, hidden_layer_size, classes,X, y, lambda)(nn_params)
lambda <- 1
cost_Reg <- CostFunctionNN(input_layer_size, hidden_layer_size, classes,X, y, lambda)(nn_params)
Die Kosten für die vortrainierten Parameter belaufen sich ohne Regularisierung auf 0.2876292 und mit Regularisierung ($=$1) auf 0.3837699.
Als nächstes rufen wir die Funktion zur Gradientenbestimmung auf. Hierzu müssen wir zunächst die Parameter initialisieren. Vorsicht: Die Parameter sollten zufällig initialisiert werden, denn werden alle Parameter eines Layers auf denselben Wert gesetzt, so erhalten alle Zellen des Nachfolgelayers dasselbe Aktivierungspotential.
hidden_layer_size <- 25; # 25 hidden units
# initialize parameters
initial_Theta1 <- randInitializeWeights(input_layer_size, hidden_layer_size)
initial_Theta2 <- randInitializeWeights(hidden_layer_size, classes)
# Unroll parameters
initial_nn_params <- c(initial_Theta1,initial_Theta2)
# Try different values of lambda
lambda <- 10 # try 1, 100, 1000, 10000
# Create "short hand" for the cost function to be minimized
costFunction <- CostFunctionNN(input_layer_size, hidden_layer_size,
classes, X, y, lambda) #over nn_params
gradFunction <- GradFunctionNN(input_layer_size, hidden_layer_size,
classes, X, y, lambda) #over nn_params
# Now, costFunction and gradFunction are functions that take in only one argument (the
# neural network parameters)
# maxit determines how many training is performed (play with the value)
opt <- lbfgsb3_(initial_nn_params, fn= costFunction, gr=gradFunction,
control = list(trace=1,maxit=50))
## This problem is unconstrained.
## At iteration 0 f = 6.918046
## At iteration 2 f = 4.382569
## At iteration 3 f = 3.304774
## At iteration 4 f = 3.300055
## At iteration 5 f = 3.283462
## At iteration 6 f = 3.168527
## At iteration 7 f = 3.019232
## At iteration 8 f = 2.802168
## At iteration 9 f = 2.514399
## At iteration 10 f = 2.282309
## At iteration 11 f = 2.038313
## At iteration 12 f = 1.866893
## At iteration 13 f = 1.764616
## At iteration 14 f = 1.667788
## At iteration 15 f = 1.553399
## At iteration 16 f = 1.494607
## At iteration 17 f = 1.451037
## At iteration 18 f = 1.399745
## At iteration 19 f = 1.365587
## At iteration 20 f = 1.336838
## At iteration 21 f = 1.303861
## At iteration 22 f = 1.261485
## At iteration 23 f = 1.231109
## At iteration 24 f = 1.211539
## At iteration 25 f = 1.194892
## At iteration 26 f = 1.182291
## At iteration 27 f = 1.167282
## At iteration 28 f = 1.149426
## At iteration 29 f = 1.131873
## At iteration 30 f = 1.122178
## At iteration 31 f = 1.111812
## At iteration 32 f = 1.10676
## At iteration 33 f = 1.097758
## At iteration 34 f = 1.093236
## At iteration 35 f = 1.088706
## At iteration 36 f = 1.082141
## At iteration 37 f = 1.079005
## At iteration 38 f = 1.074037
## At iteration 39 f = 1.071057
## At iteration 40 f = 1.067004
## At iteration 41 f = 1.061896
## At iteration 42 f = 1.058808
## At iteration 43 f = 1.055794
## At iteration 44 f = 1.053721
## At iteration 45 f = 1.051593
## At iteration 46 f = 1.050312
## At iteration 47 f = 1.047184
## At iteration 48 f = 1.045752
## At iteration 49 f = 1.044215
## At iteration 50 f = 1.041669
## At iteration 51 f = 1.041307
nn_params <- opt$prm
cost <- opt$f
# Obtain Theta1 and Theta2 back from nn_params
Theta1 <- matrix(nn_params[1:(hidden_layer_size * (input_layer_size + 1))],
nrow=hidden_layer_size, ncol=(input_layer_size + 1))
Theta2 <- matrix(nn_params[(1 + (hidden_layer_size * (input_layer_size + 1))):length(nn_params)],
nrow=classes, ncol=(hidden_layer_size + 1))
# Visualize Weights:
# displaying the hidden units
displayData(Theta1[, -1])
# displaying the output units
displayData(Theta2[, -1])
# displaying the product of both theta matrices
displayData(t(t(Theta1[, -1]) %*% t(Theta2[,-1])))
Als nächstes berechnen wir die Accuracy unseres trainierten Netzes:
pred <- predictNN(X,Theta1,Theta2)$prediction
acc <- mean(pred==y) * 100
Die Accuracy ist 93.58.