Single threaded version of back propagation.
| 121 | |
| 122 | // Single threaded version of back propagation. |
| 123 | void Individual::BP_Single_Thread() { |
| 124 | this->fitness = 0; |
| 125 | float output[outputNum]; |
| 126 | std::map<uint32_t, float> gradient; // Store the gradient of all nodes. |
| 127 | for (uint32_t z = 0; z < args->batchSize; ++z) { |
| 128 | this->forward(args->inputArray[z], output); |
| 129 | |
| 130 | gradient.clear(); |
| 131 | if (args->mode == "predict") { // Predict. |
| 132 | for (uint32_t j = 0; j < nodeSlice->size(); ++j) { |
| 133 | auto index = (*nodeSlice)[nodeSlice->size() - 1 - j]; |
| 134 | auto n = (*nodeMap)[index]; |
| 135 | |
| 136 | // The output nodes. |
| 137 | if (index >= inputNum && index < (inputNum + outputNum)) { |
| 138 | gradient[index] = n->value - args->desireArray[z][index - inputNum]; |
| 139 | } |
| 140 | |
| 141 | auto grad = gradient[index] * (n->value > 0 ? 1.0f : 0.2f); |
| 142 | |
| 143 | for (auto iter = n->genomeMap->begin(); iter != n->genomeMap->end(); ++iter) { |
| 144 | auto p = gradient.find(iter->first.in); |
| 145 | if (p != gradient.end()) { |
| 146 | gradient[iter->first.in] += grad * iter->second.weight; |
| 147 | } else { |
| 148 | gradient[iter->first.in] = grad * iter->second.weight; |
| 149 | } |
| 150 | |
| 151 | (*(n->genomeMap))[iter->first].delta_backup = ((*(n->genomeMap))[iter->first].delta_backup * z - |
| 152 | args->lr * grad * |
| 153 | (*nodeMap)[iter->first.in]->value) / |
| 154 | float(z + 1); |
| 155 | |
| 156 | if (z == args->batchSize - 1) { |
| 157 | (*(n->genomeMap))[iter->first].delta = (*(n->genomeMap))[iter->first].delta * 0.9f + |
| 158 | (*(n->genomeMap))[iter->first].delta_backup * 0.1f; |
| 159 | (*(n->genomeMap))[iter->first].weight += (*(n->genomeMap))[iter->first].delta; |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | n->delta_backup = (n->delta_backup * z - args->lr * grad) / float(z + 1); |
| 164 | if (z == args->batchSize - 1) { |
| 165 | n->delta = n->delta * 0.9f + n->delta_backup * 0.1f; |
| 166 | n->bias += n->delta; |
| 167 | } |
| 168 | } |
| 169 | } else { // Classify. |
| 170 | LycorisUtils::softmax(output, outputNum); |
| 171 | |
| 172 | for (uint32_t j = 0; j < nodeSlice->size(); ++j) { |
| 173 | auto index = (*nodeSlice)[nodeSlice->size() - 1 - j]; |
| 174 | auto n = (*nodeMap)[index]; |
| 175 | |
| 176 | // The output nodes. |
| 177 | if (index >= inputNum && index < (inputNum + outputNum)) { |
| 178 | gradient[index] = output[index - inputNum] - args->desireArray[z][index - inputNum]; |
| 179 | } |
| 180 |
no test coverage detected