Нейронная сеть с выводом softmax не может сходиться

Я работал над Учебником по глубокому обучению Стэмфорда, и у меня возникла проблема с одним из упражнений, нейронной сетью с выходным слоем softmax. Вот моя реализация на R:

train <- function(training.set, labels, costFunc, activationFunc, outputActivationFunc, activationDerivative, hidden.unit.count = 7, learningRate = 0.3, decayRate=0.02, momentumRate=0.02, samples.count, batch.size, verbose=F, debug=F){

  #initialize weights and biases
  w1 <- matrix( rnorm(hidden.unit.count * input.unit.count, sd=0.5), nrow=hidden.unit.count, ncol=input.unit.count)
  b1 <- matrix(-1, nrow=hidden.unit.count, ncol=1)
  w2 <- matrix(rnorm(output.unit.count * hidden.unit.count, sd=0.5), nrow=output.unit.count, ncol=hidden.unit.count)
  b2 <- matrix(-1, nrow=output.unit.count, ncol=1)

  cost.list<- matrix(rep(seq(1:floor(samples.count / batch.size)), each=2), byrow=T, ncol=2)
  cost.list[, 2] <- 0

  i <- 1
  while(i < samples.count){
    z2 <- w1 %*% training.set[, i: (i + batch.size - 1)] + matrix(rep(b1, each=batch.size), ncol=batch.size,byrow=T)
    a2 <- activationFunc(z2)

    z3 <- w2 %*% a2 + matrix(rep(b2, each=batch.size), ncol=batch.size,byrow=T)
    h  <- outputActivationFunc(z3)

    #calculate error
    output.error <- (h - labels[, i: (i + batch.size - 1)]) 
    hidden.error <- (t(w2) %*% output.error) * sigmoidPrime(z2)

    # calculate gradients for both layers
    gradW2 <- hidden.error %*% t(training.set[ ,i: (i + batch.size - 1)]) - momentumRate * gradW2.prev - decayRate * w1
    gradw2 <- output.error %*% t(a2) - momentumRate * gradw2.prev - decayRate * w2

    gradW2.prev <- gradW2
    gradw2.prev <- gradw2

    #update weights and biases
    w1 <- w1 - learningRate * gradW2 / batch.size
    w2 <- w2 - learningRate * gradW3 / batch.size

    b1 <- b1 - learningRate * rowSums(gradW2) / batch.size
    b2 <- b2 - learningRate * rowSums(gradW3) / batch.size

    i <- i + batch.size
  }

  return (list(w1, w2, b1, b2, cost.list))
}

Вот функция softmax, которую я использую на выходном слое, а также функция стоимости, которую я использую с softmax:

softmax <- function(a){
  a <- a - apply(a, 1, function(row){ 
      return (max(row))
  })

  a <- exp(a)

  return (sweep(a, 2, colSums(a), FUN='/'))
}

softmaxCost <- function(w, b, x, y, decayRate, batch.size){
  a <- w %*% x + matrix(rep(b, each=dim(x)[2]), byrow = T, ncol=dim(x)[2])

  h <- softmax(a)

  cost <- -1/batch.size * (sum(y * log(h))) + decayRate/2 * sum((w * w))

  return (cost)
}

Я проверил градиенты, вычисленные моей программой, по числовым градиентам, и они разные. Однако я не могу найти источник неправильного расчета градиента.

Кроме того, я успешно использовал эту сеть, используя сигмовидную активацию на выходном уровне в MNIST, тогда как использование слоя softmax просто не работает (точность 11%). Это заставляет меня думать, что проблема заключается в моей реализации softmax.


person Devjeet Roy    schedule 04.01.2016    source источник


Ответы (1)


Если я правильно понял, я думаю, проблема в max части вашего кода (ReLu). В DNN softmax выбираем max(0, value). В частности, в этом случае мы делаем это для каждого элемента матрицы a.

Итак, код будет выглядеть так:

# XW + b
hidden.layer <- sweep(X %*% W ,1, b, '+', check.margin = F)
# max for each element in maxtir
hidden.layer <- pmax(hidden.layer, 0)

Кстати, вы можете использовать sweep для добавления b в матрицу вместо дублирования T строк, что будет тратить много памяти. Три подхода показаны здесь.

Будьте осторожны с приведенным ниже кодом, y должно быть 0/1, правильная метка w / 1 и другие 0, чтобы вы могли получить правильную потерю к sum(y * log(h)).

cost <- -1/batch.size * (sum(y * log(h))) + decayRate/2 * sum((w * w))

Изменить: я написал блог о том, как создать DNN с помощью R в здесь.

person Patric    schedule 05.01.2016