library(sigmoid)
getLabels <- function(lbldb, nget=0) {
magic <- readBin(lbldb, what="integer", n=1, endian="big", size=4)
if(magic != 2049)
return(NULL)
n.lbls <- readBin(lbldb, what="integer", n=1, endian="big", size=4)
if(nget==0)
nget=n.lbls
labels <- readBin(lbldb, what="integer", n=nget, endian="big", size=1)
close(lbldb)
return(labels)
}
getImages <- function(imgdb, nget=0, progress=FALSE) {
magic <- readBin(imgdb, what="integer", n=1, endian="big", size=4)
## if(magic != 2049)
## return(NULL)
n.imgs <- readBin(imgdb, what="integer", n=1, endian="big", size=4)
if(nget==0)
nget <- n.imgs # trunc(sqrt(n.imgs))
n.rows <- readBin(imgdb, what="integer", n=1, endian="big", size=4)
n.cols <- readBin(imgdb, what="integer", n=1, endian="big", size=4)
print(gettextf("Getting %d %dx%d Images", nget, n.rows, n.cols))
images <- c()
for(i in 1:nget) {
.img <- matrix(readBin(imgdb, what="integer", n=n.rows*n.cols, endian="big", size=1), nrow=n.rows, ncol=n.cols)
images <- c(images, list(.img))
if(progress && i %% trunc(sqrt(nget)) == 0)
print(gettextf("%2.2f%%", round((100*i)/nget, digits=2)))
}
close(imgdb)
return(images)
}
## Works
tr.labels <- as.vector(getLabels(gzfile("datasets/training/labels", "rb"), nget=256))
tr.images <- getImages(gzfile("datasets/training/images", # data's filename
"rb"), # read it as binary
## Get 256 of the entries
nget=256, progress=TRUE)
tr.im.matrix <- do.call("rbind", # create rows out of the input data
lapply(tr.images, as.vector)) # transform each image
# matrix into a vector
tr.df <- cbind(as.factor(tr.labels), tr.im.matrix) # now create a data frame
oldpar <- par(mar=rep(0,4))
image(tr.images[[8]], useRaster=TRUE, col=seq(2^8))
par(oldpar)
- Label Frequency
Labels | Freq |
---|---|
0 | 30 |
1 | 35 |
2 | 25 |
3 | 30 |
4 | 24 |
5 | 17 |
6 | 24 |
7 | 26 |
8 | 19 |
9 | 26 |
ID | size (b) | Link |
---|---|---|
training set images | 9912422 | http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz |
training set labels | 28881 | http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz |
test set images | 1648877 | http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz |
test set labels | 4542 | http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz |
- Features
-
- builds arbitrarily layered ANN model
- has weights (rnorm), biases(rnorm), and layer nodes
- has member function for layer extraction
- returns class “layer” with 3 member lists for the given layers data
- TODO
-
- predict function
- feedforward (recursive chain of feedforwardstep?)
- train function
- backprop (step then recursive chain?)
- summary functions
- layer and model
- print functions
- layer, model
- plot functions
- model, inputs, outputs (eg plot the input rows of tr.df, and output of predict
summary.model.ann.classifier <- function(model) {
print(paste("Number of Layers: ", model$nlayers))
print(paste("Respective Lengths: ", toString(model$lengths)))
}
summary.layers <- function(layers) {
lapply(lapply(X=layers, str),print)
}
model.gen.annc <- function(length.input,
length.hidden,
length.output,
out.classes=as.factor(1:length.output),
input=NULL,
debug=TRUE) {
model <- list()
class(model) <- "model.ann.classifier"
.lengths <- c(length.input,
length.hidden,
length.output)
## print(lengths)
n.layers <- length(.lengths)
## print(paste("Input Length:", length.input))
if(debug) print(paste("Number of Layers:", n.layers))
if(debug) print(paste("Layer Lengths:", toString(.lengths)))
## print(paste("Output Length:", length.output))
model$nlayers <- n.layers
model$lengths <- .lengths
.nodes <- mapply(matrix,
data=0,
ncol=1,
nrow=.lengths)
model$nodes <- .nodes
.biases <- numeric()
.biases <- lapply(.lengths, rnorm)
model$biases <- .biases
# .weights <-
## <- mapply(matrix,
## ncol=1,
## nrow=.lengths,
## data=lapply(.lengths,rnorm))
## TODO: this needs to be converted to mapply or the function needs to be
## fixed, rn it errors
.weights <- lapply(1:(length(model$nodes)-1),
function(k)
matrix(rnorm(lengths[k+1]*lengths[k])),
nrow=lengths[],
ncol=lengths[]
)
model$weights <- .weights
## model$biases <- lapply(1:(length(model$nodes)-1),
## function(k)
## matrix(rnorm(lengths[k+1]),
## nrow=lengths[k+1]))
model$input <- if(length(input))
as.matrix(input)
else
.nodes[[1]]
model$nodes[[1]] <- model$input
## model$get_layer <- function(k) { ## 1 -> k=nlayers->output=nodes[[n]]
## ret <- list()
## class(ret) <- "layer"
## ret$nodes <- model$nodes[k]
## ret$weights<- ifelse(k==1, 0, model$weights[k-1])
## ret$biases <- ifelse(k==1, 0, model$biases[k-1])
## return(ret)
## }
layers <- list()
update_layers <- function() {
layers <- list()
layers[[1]] <- list(Nodes=model$nodes[[1]],
Weights=model$weights[[1]],
Biases=model$biases[[1]])
for(i in 2:(model$nlayers-1)) {
layers[[i]] <- list(Weights=model$weights[[i]],
Biases=model$biases[[i]],
Nodes=model$nodes[[i+1]])
}
model$layers <- layers
return(layers)
}
## IMPORTANT: we need to profile this and the update function, think about
## how best to implement this/model$layers so that it stays updated,
model$get_layer <- function(k) {
update_layers()
if(k!=1)
return(layers[k-1])
else
return(list(Weights=0,
Biases=0,
Nodes=model$nodes[[k]]))
}
model$predict <- function(input) {
forwardstep <- function(k) {
if(k==model$nlayers)
return(model$weights[[k]])
return(model$weights[[k]]%*%model$nodes[[k]]+model$biases[[k]]) ## W1.N1+B1,
}
model$nodes[[2]] <- forwardstep(1)
model$nodes[[3]] <- forwardstep(2)
return(0)
}
model$train <- function(train.df, train.labels) {
}
##
feedforward <- function(input) {
output <- list()
return(output)
}
stopifnot(length(model$weights)==(model$nlayers-1))
return(model)
}
model.genstd <- function()
return(model.gen.annc(2,2,1, input=rbinom(n=2, size=1, prob=0.5)))
forwardstep <- function(model, k) {
if(k==1)
model$nodes[[k]] <- model$weights[[k-1]]%*%model$input
else
model$nodes[[k]] <- model$weights[[k-1]]%*%model$nodes[[k-1]]
return(model)
}
predict.model.ann.classifier <- function(model, input) {
}
## basic layout, 4 layers of 5x1
model <- model.gen.annc(2,2,1, input=rbinom(n=2, size=1, prob=0.5))
names(model)
print(model$get_layer(1))
[1] "Number of Layers: 3" [1] "Layer Lengths: 2, 2, 1" [1] "nlayers" "lengths" "nodes" "weights" "biases" "input" [7] "get_layer" [1] "Number of Layers: 3" [1] "Respective Lengths: 2, 2, 1"
TRUE
These I read in the process of completing this project. In places where specific citations could be made, I have places them and linked here.
- https://journal.r-project.org/archive/2010-1/RJournal_2010-1_Guenther+Fritsch.pdf
- https://en.wikipedia.org/wiki/Perceptron
- https://cran.r-project.org/web/packages/sigmoid/sigmoid.pdf
https://github.com/mnielsen/neural-networks-and-deep-learning/blob/master/src/network.py