void NeuralNetwork::updateBeforeEdges(vector<double> &delta) { // 各中間ノード for(int m = 0; m < middle_nodes.size(); ++m) { // 修正量を計算 Node middle = getMiddleNode(m); double deriv = middle.value * (1.0 - middle.value); // 現在の中間ノードへ伝搬する誤差 double error = 0.0; for(int o = 0; o < output_nodes.size(); ++o) { Edge after_edge = after_edges.at(output_nodes.size() * middle.id + o); error += after_edge.weight * delta.at(o); } // 現在の中間ノードへ伸びてくるエッジ集合 vector<Edge> edges = getBeforeEdges(m); for(int i = 0; i < edges.size(); ++i) { Edge e = edges.at(i); // あるエッジ Node input = getInputNode(i); // 根元のノード // 修正量の計算 double update = learn_coeff * input.value * error * deriv; // 重みを修正して更新 e.weight += update; setBeforeEdge(e); } } }
void NeuralNetwork::updateAfterEdges(vector<double> &delta, double &total_error) { // 各出力ノード for(int o = 0; o < output_nodes.size(); ++o) { // 誤差を計算 Node output = getOutputNode(o); Node answer = getAnswerNode(o); double error = answer.value - output.value; total_error += error * error; // 微分値 double deriv = output.value * (1.0 - output.value); // 誤差伝搬に使う delta.push_back(error * deriv); // 現在の出力ノードへ伸びてくるエッジ集合 vector<Edge> edges = getAfterEdges(o); for(int i = 0; i < edges.size(); ++i) { Edge e = edges.at(i); // あるエッジ Node m = getMiddleNode(i); // 根元の中間ノード // 修正量の計算 double update = learn_coeff * m.value * error * deriv; // 重みを修正して更新 e.weight += update; setAfterEdge(e); } } }
int checkPalindrome(NODE *start){ NODE *p=start, *q=NULL, *temp; temp=getMiddleNode(start); while( temp!=NULL ){ insert(&q, temp->data); temp=temp->next; } while((p!=NULL) && (q!=NULL)){ if(p->data != q->data) return 0; p=p->next; q=q->next; } return 1; }