2015-11-17 18 views
5

Tôi đã đọc khá nhiều trên Mạng nơron và đào tạo chúng với backprogpagation, chủ yếu là this Coursera course, với việc đọc bổ sung từ herehere. Tôi nghĩ rằng tôi đã có một nắm bắt khá soild của thuật toán cốt lõi, nhưng nỗ lực của tôi để xây dựng một mạng lưới thần kinh được đào tạo backpropagation đã không khá làm việc ra và tôi không chắc chắn lý do tại sao.Các vấn đề về triển khai truyền dẫn mạng thần kinh

Mã này có trong C++ mà không có vectơ nào.

Tôi muốn xây dựng 2 nơron đầu vào đơn giản, 1 nơron ẩn, 1 nơron đầu ra, mạng để mô hình hóa hàm AND. Chỉ cần hiểu cách các khái niệm hoạt động trước khi chuyển sang một ví dụ phức tạp hơn. Mã truyền bá tiếp của tôi làm việc khi tôi mã hóa bằng tay các giá trị cho trọng số và độ lệch.

float NeuralNetwork::ForwardPropagte(const float *dataInput) 
{ 
     int number = 0; // Write the input data into the input layer 
     for (auto & node : m_Network[0]) 
     { 
      node->input = dataInput[number++]; 
     } 

     // For each layer in the network 
     for (auto & layer : m_Network) 
     { 
      // For each neuron in the layer 
      for (auto & neuron : layer) 
      { 
       float activation; 
       if (layerIndex != 0) 
       { 
        neuron->input += neuron->bias; 
        activation = Sigmoid(neuron->input); 
       } else { 
        activation = neuron->input; 
       } 

       for (auto & pair : neuron->outputNeuron) 
       { 
        pair.first->input += static_cast<float>(pair.second)*activation; 
       } 
      } 
     } 

     return Sigmoid(m_Network[m_Network.size()-1][0]->input); 
} 

Một số biến này có tên khá kém nhưng về cơ bản, nơron-> đầu raNeuron là một vectơ các cặp. Đầu tiên là con trỏ tới nơron tiếp theo và thứ hai là giá trị trọng số. neuron-> input là giá trị "z" trong phương trình mạng thần kinh, tổng của tất cả các wieghts * activation + bais. Sigmoid được cho bởi:

float NeuralNetwork::Sigmoid(float value) const 
{ 
    return 1.0f/(1.0f + exp(-value)); 
} 

Hai thứ này có vẻ như hoạt động như dự định. Sau khi vượt qua tất cả các giá trị 'z' hoặc 'nơron-> đầu vào' được đặt lại về 0 (hoặc sau khi truyền ngược).

Sau đó tôi đào tạo mạng theo mã psudo bên dưới. Mã đào tạo được chạy nhiều lần.

for trainingExample=0 to m // m = number of training examples 
    perform forward propagation to calculate hyp(x) 
    calculate cost delta of last layer 
     delta = y - hyp(x) 
    use the delta of the output to calculate delta for all layers 
    move over the network adjusting the weights based on this value 
    reset network 

Mã thực tế là ở đây:

void NeuralNetwork::TrainNetwork(const std::vector<std::pair<std::pair<float,float>,float>> & trainingData) 
{ 
    for (int i = 0; i < 100; ++i) 
    { 
     for (auto & trainingSet : trainingData) 
     { 
      float x[2] = {trainingSet.first.first,trainingSet.first.second}; 
      float y  = trainingSet.second; 
      float estimatedY = ForwardPropagte(x); 

      m_Network[m_Network.size()-1][0]->error = estimatedY - y; 
      CalculateError(); 
      RunBackpropagation(); 
      ResetActivations(); 
     } 
    } 
} 

Với chức năng lan truyền ngược được cho bởi:

void NeuralNetwork::RunBackpropagation() 
{ 
    for (int index = m_Network.size()-1; index >= 0; --index) 
    { 
     for(auto &node : m_Network[index]) 
     { 
      // Again where the "outputNeuron" is a list of the next layer of neurons and associated weights 
      for (auto &weight : node->outputNeuron) 
      { 
       weight.second += weight.first->error*Sigmoid(node->input); 
      } 
      node->bias = node->error; // I'm not sure how to adjust the bias, some of the formulas seemed to point to this. Is it correct? 
     } 
    } 
} 

và chi phí tính theo:

void NeuralNetwork::CalculateError() 
{ 
    for (int index = m_Network.size()-2; index > 0; --index) 
    { 
     for(auto &node : m_Network[index]) 
     { 
      node->error = 0.0f; 

      float sigmoidPrime = Sigmoid(node->input)*(1 - Sigmoid(node->input)); 

      for (auto &weight : node->outputNeuron) 
      { 
       node->error += (weight.first->error*weight.second)*sigmoidPrime; 
      } 
     } 
    } 
} 

tôi ngẫu nhiên trọng lượng và chạy nó trên dữ liệu et:

x = {0.0f,0.0f} y =0.0f 
    x = {1.0f,0.0f} y =0.0f 
    x = {0.0f,1.0f} y =0.0f 
    x = {1.0f,1.0f} y =1.0f 

Tất nhiên là tôi không nên đào tạo và thử nghiệm với cùng một dữ liệu thiết nhưng tôi chỉ muốn để có được những algortithm lan truyền ngược cơ bản và chạy. Khi tôi chạy mã này tôi thấy trọng lượng/thành kiến ​​như sau:

Layer 0 
    Bias 0.111129 
    NeuronWeight 0.058659 
    Bias -0.037814 
    NeuronWeight -0.018420 
Layer 1 
    Bias 0.016230 
    NeuronWeight -0.104935 
Layer 2 
    Bias 0.080982 

Việc đào tạo bộ chạy và giá trị trung bình bình phương sai số của đồng bằng [outputLayer] trông somthing như:

Error: 0.156954 
Error: 0.152529 
Error: 0.213887 
Error: 0.305257 
Error: 0.359612 
Error: 0.373494 
Error: 0.374910 
Error: 0.374995 
Error: 0.375000 

... remains at this value for ever... 

Và trận chung kết trọng lượng như sau: (họ luôn kết thúc tại roughtly giá trị này)

Layer 0 
    Bias 0.000000 
    NeuronWeight 15.385233 
    Bias 0.000000 
    NeuronWeight 16.492933 
Layer 1 
    Bias 0.000000 
    NeuronWeight 293.518585 
Layer 2 
    Bias 0.000000 

tôi chấp nhận rằng điều này có vẻ giống như một cách khá vòng xoay của học mạng nơ-ron và thực hiện là (tại m oment) rất không tối ưu. Nhưng bất cứ ai có thể phát hiện bất kỳ điểm nào mà tôi đưa ra một giả định không hợp lệ, hoặc là việc thực hiện hoặc công thức là sai?

EDIT

Cảm ơn thông tin phản hồi cho các giá trị thiên vị, tôi dừng lại chúng được áp dụng cho các lớp đầu vào và dừng lại đi qua các lớp đầu vào thông qua các hàm sigmoid. Hàm bổ sung Sigmoid của tôi không hợp lệ. Nhưng mạng vẫn không hoạt động. Tôi đã cập nhật lỗi và đầu ra ở trên với những gì xảy ra ngay bây giờ.

+2

tại sao bạn có quá nhiều thành kiến? 2-1-1 mạng nên có 5 thông số trong tổng số: 2 trọng số giữa các tế bào thần kinh đầu vào và một ẩn; 1 trọng số giữa độ lệch trong lớp đầu vào và nơron ẩn; 1 trọng lượng giữa lớp ẩn và nơron đầu ra; 1 trọng số giữa độ lệch trong lớp ẩn và nơron đầu ra. Tổng cộng 5 trọng số. Ngay cả mã của bạn cũng cho bạn thấy - bạn và lên mà không có 2 thành kiến ​​dư thừa – lejlot

+0

Cảm ơn sự giúp đỡ của bạn với những thành kiến, hãy xem trả lời của tôi cho galloguille để giải thích thêm. Tôi đã sửa lỗi này nhưng tôi vẫn gặp sự cố với mạng thần kinh luôn luôn huấn luyện trọng số cho các giá trị w11 (15.385233), w12 (16.492933), w21 (293.518585). Tất cả các thành kiến ​​đều trở thành 0. Vì vậy, rõ ràng vẫn còn một vấn đề khác với mã. – Davors72

Trả lời

1

Tôi đã giải quyết được vấn đề của mình (ngoài các thành kiến ​​ban đầu/vấn đề chính đã ký ở trên). Tôi bắt đầu trừ đi, thay vì thêm vào, trọng số. Trong các nguồn tôi nhìn vào họ có một dấu trừ bên trong tính toán giá trị delta mà tôi không có nhưng tôi giữ định dạng của họ thêm giá trị phủ định vào trọng số. Ngoài ra, tôi đã bối rối về việc phải làm gì với trọng lượng và đọc sai một nguồn mà đã nói để gán cho lỗi đó. Bây giờ tôi thấy trực giác đang xử lý nó như là một trọng số bình thường nhưng nhân với hằng số thiên vị của 1 thay vì z. Sau khi tôi thêm vào trong những thay đổi này lặp đi lặp lại trên tập huấn luyện ~ 1000 lần có thể mô hình các biểu thức bitwise đơn giản như OR và AND.

4

Như lejilot đã nói, bạn có rất nhiều thành kiến ​​ở đó. Bạn không cần một sự thiên vị trong lớp cuối cùng, đó là một lớp đầu ra và một thiên vị phải được kết nối với đầu vào của nó, nhưng không được kết nối với đầu ra của nó. Hãy xem hình ảnh sau:

Trong hình ảnh này, bạn có thể thấy chỉ có một thiên vị mỗi lớp, ngoại trừ hình ảnh cuối cùng, nơi không cần thiên vị.

Here you can read một cách tiếp cận rất trực quan với mạng thần kinh. Nó là bằng Python, nhưng nó có thể giúp bạn hiểu một số khái niệm về mạng thần kinh tốt hơn.

+0

Cảm ơn bạn, và Lejlot's, giúp đỡ với những thành kiến, tôi quên loại trừ chúng khỏi các tính toán của lớp đầu vào. Trong ví dụ của tôi, các thành kiến ​​'gắn liền' với mỗi nút là giá trị độ lệch thiên vị * được áp dụng cho hàm từ lớp trước đó. Như tôi đã hiểu giá trị thiên vị được áp dụng cho hàm để "dịch chuyển" đường cong [http://stackoverflow.com/questions/2480650/role-of-bias-in-neural-networks] và tôi đã áp dụng sai chức năng sigmoid ngay cả các nơron đầu vào. Do đó những thành kiến ​​phụ. – Davors72

Các vấn đề liên quan