CoolFace
Modelpublic

cwenzi/neuroflow-cpp

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
1likes
test_nan.cpp244 linesDownload Raw Back to scripts
1/**2 * 最小 NaN 诊断测试 — 绕过 DataLoader,直接测试 forward + CE loss3 */4#include <cmath>5#include <cstdio>6#include <cstdlib>7#include <random>8#include <vector>9 10#include "neuroflow/backprop.hpp"11#include "neuroflow/generative.hpp"12#include "neuroflow/model.hpp"13 14using namespace neuroflow;15 16int main() {17    // Load model config18    NeuroFlowModel::Config cfg;19    // Use defaults: d_model=512, hidden_dim=2048, output_dim=2048, vocab_size=12800020 21    NeuroFlowModel model(cfg);22    FullBackpropEngine backprop(model);23 24    // Load tokenizer25    BPETokenizer tok("configs/tokenizer_128k.json");26    printf("Tokenizer loaded: vocab=%zu\n", tok.vocab_size());27 28    // Create CausalLMHead29    CausalLMConfig lm_cfg;30    lm_cfg.vocab_size = cfg.vocab_size;31    lm_cfg.d_model = cfg.hidden_dim;  // 204832    lm_cfg.max_seq_len = cfg.max_seq_len;33    lm_cfg.causal_window_size = cfg.causal_window_size;34    lm_cfg.sae_k = cfg.sae_k;35    lm_cfg.ntm_memory_slots = cfg.ntm_memory_slots;36    lm_cfg.weight_tying = true;37    lm_cfg.num_attn_layers = cfg.lm_num_attn_layers;38    lm_cfg.pooling = cfg.lm_pooling;39    CausalLMHead lm_head(lm_cfg);40    lm_head.tie_weights();41 42    printf("CausalLMHead: d_model=%zu vocab=%zu\n", lm_cfg.d_model, lm_cfg.vocab_size);43 44    // Create bridge projection (matching train_v2.cpp)45    size_t d_model = lm_cfg.d_model;46    size_t hidden_dim = cfg.hidden_dim;47    Tensor lm_bridge_weight({d_model, hidden_dim}, QuantType::FP32);48    Tensor lm_bridge_bias({d_model}, QuantType::FP32);49    {50        float* bw = lm_bridge_weight.as_fp32();51        float scale = std::sqrt(2.0f / (hidden_dim + d_model));52        std::mt19937 br_rng(hidden_dim * 31 + d_model);53        std::uniform_real_distribution<float> br_dist(-scale, scale);54        for (size_t i = 0; i < lm_bridge_weight.numel(); ++i) bw[i] = br_dist(br_rng);55        memset(lm_bridge_bias.as_fp32(), 0, lm_bridge_bias.data_size_);56    }57 58    // Create random test data59    size_t batch_sz = 4;60    size_t seq_len = 16;61    std::mt19937 rng(42);62    std::uniform_int_distribution<size_t> id_dist(4, tok.vocab_size() - 1);63 64    printf("\n=== Testing %zu batches ===\n", batch_sz);65 66    for (int step = 0; step < 200; ++step) {67        // Create random token sequence68        std::vector<size_t> all_ids;69        for (size_t b = 0; b < batch_sz; ++b) {70            for (size_t s = 0; s < seq_len; ++s) {71                all_ids.push_back(id_dist(rng));72            }73        }74 75        // Create input tensor [batch_sz, input_dim=512]76        Tensor input({batch_sz, cfg.input_dim}, QuantType::FP32);77        float* inp = input.as_fp32();78        for (size_t b = 0; b < batch_sz; ++b) {79            for (size_t j = 0; j < cfg.input_dim; ++j) {80                inp[b * cfg.input_dim + j] = static_cast<float>(all_ids[b * seq_len + (j % seq_len)]) / 128000.0f;81            }82        }83 84        // Create target tensor [batch_sz, vocab_size]85        size_t vocab_sz = lm_cfg.vocab_size;86        Tensor target({batch_sz, vocab_sz}, QuantType::FP32);87        float* tgt = target.as_fp32();88        memset(tgt, 0, target.data_size_);89        for (size_t b = 0; b < batch_sz; ++b) {90            size_t next_id = all_ids[b * seq_len + 1]; // next token as target91            if (next_id < vocab_sz) tgt[b * vocab_sz + next_id] = 1.0f;92        }93 94        // Forward pass95        auto nf_output = backprop.forward_with_cache(input);96        const Tensor& nf_hidden = nf_output.output;97 98        // Bridge projection99        Tensor hidden_proj({batch_sz, d_model}, QuantType::FP32);100#ifdef USE_CBLAS101        cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasTrans,102                    batch_sz, d_model, hidden_dim,103                    1.0f, nf_hidden.as_fp32(), hidden_dim,104                    lm_bridge_weight.as_fp32(), hidden_dim,105                    0.0f, hidden_proj.as_fp32(), d_model);106#else107        {108            float* hp = hidden_proj.as_fp32();109            const float* nh = nf_hidden.as_fp32();110            const float* bw = lm_bridge_weight.as_fp32();111            for (size_t b = 0; b < batch_sz; ++b) {112                for (size_t j = 0; j < d_model; ++j) {113                    float sum = 0.0f;114                    for (size_t k = 0; k < hidden_dim; ++k) {115                        sum += nh[b * hidden_dim + k] * bw[j * hidden_dim + k];116                    }117                    hp[b * d_model + j] = sum;118                }119            }120        }121#endif122        // Add bias123        {124            float* hp = hidden_proj.as_fp32();125            const float* bb = lm_bridge_bias.as_fp32();126            for (size_t b = 0; b < batch_sz; ++b)127                for (size_t j = 0; j < d_model; ++j)128                    hp[b * d_model + j] += bb[j];129        }130 131        Tensor projected = lm_head.w_proj_->forward(hidden_proj);132        Tensor logits = lm_head.w_out_->forward(projected);133 134        // Check logits for NaN135        const float* pred = logits.as_fp32();136        size_t n = logits.numel();137        bool pred_nan = false;138        for (size_t i = 0; i < n; ++i) {139            if (!std::isfinite(pred[i])) { pred_nan = true; break; }140        }141        if (pred_nan) {142            printf("Step %d: logits NaN BEFORE loss!\n", step);143            return 1;144        }145 146        // Compute CE loss147        size_t dim = vocab_sz;148        float loss = 0.0f;149        for (size_t b = 0; b < batch_sz; ++b) {150            float max_val = -1e30f;151            for (size_t j = 0; j < dim; ++j) {152                if (pred[b * dim + j] > max_val) max_val = pred[b * dim + j];153            }154            float sum_exp = 0.0f;155            for (size_t j = 0; j < dim; ++j) {156                sum_exp += std::exp(pred[b * dim + j] - max_val);157            }158            if (!std::isfinite(sum_exp) || sum_exp <= 0) {159                printf("Step %d batch %zu: sum_exp=%f max_val=%f\n", step, b, sum_exp, max_val);160                return 1;161            }162            float log_sum_exp = max_val + std::log(sum_exp);163            if (!std::isfinite(log_sum_exp)) {164                printf("Step %d batch %zu: log_sum_exp=%f\n", step, b, log_sum_exp);165                return 1;166            }167 168            for (size_t j = 0; j < dim; ++j) {169                float softmax_val = std::exp(pred[b * dim + j] - max_val) / sum_exp;170                float t = tgt[b * dim + j];171                if (t > 0.5f) {172                    float contrib = pred[b * dim + j] - log_sum_exp;173                    loss -= contrib;174                    if (!std::isfinite(loss)) {175                        printf("Step %d batch %zu j=%zu: LOSS NaN! pred=%f log_sum_exp=%f contrib=%f\n",176                               step, b, j, pred[b*dim+j], log_sum_exp, contrib);177                        return 1;178                    }179                }180            }181        }182        loss /= batch_sz;183 184        // Backward185        Tensor output_grad({batch_sz, dim}, QuantType::FP32);186        float* og = output_grad.as_fp32();187        for (size_t b = 0; b < batch_sz; ++b) {188            float max_val = -1e30f;189            for (size_t j = 0; j < dim; ++j)190                if (pred[b*dim+j] > max_val) max_val = pred[b*dim+j];191            float sum_exp = 0.0f;192            for (size_t j = 0; j < dim; ++j)193                sum_exp += std::exp(pred[b*dim+j] - max_val);194            for (size_t j = 0; j < dim; ++j) {195                float softmax_val = std::exp(pred[b*dim+j] - max_val) / sum_exp;196                float t = tgt[b*dim+j];197                og[b*dim+j] = (softmax_val - t) / batch_sz;198            }199        }200 201        // Check output_grad202        for (size_t i = 0; i < output_grad.numel(); ++i) {203            if (!std::isfinite(og[i])) {204                printf("Step %d: output_grad NaN at i=%zu\n", step, i);205                return 1;206            }207        }208 209        // Backward through LM head210        // (simplified for test — just check that backward doesn't crash)211        auto nf_grads = backprop.backward(output_grad);212 213        // Check nf_grads for NaN214        auto check_nan = [](const Tensor& t, const char* name) {215            if (t.numel() == 0) return;216            const float* d = t.as_fp32();217            for (size_t i = 0; i < t.numel(); ++i) {218                if (!std::isfinite(d[i])) {219                    printf("  GRAD NaN in %s at i=%zu\n", name, i);220                    return;221                }222            }223        };224        check_nan(nf_grads.input_proj_weight_grad, "input_proj_weight");225        check_nan(nf_grads.output_fusion_up_weight_grad, "output_fusion_up_weight");226        check_nan(nf_grads.ecn_vmpfc2_weight_grad, "ecn_vmpfc2_weight");227        check_nan(nf_grads.sn_gate1_weight_grad, "sn_gate1_weight");228        check_nan(nf_grads.dmn_mem_encoder1_weight_grad, "dmn_mem_encoder1_weight");229        check_nan(nf_grads.mem_encode_proj_weight_grad, "mem_encode_proj_weight");230 231        if (step % 50 == 0) {232            float lmin = 1e30f, lmax = -1e30f;233            for (size_t i = 0; i < std::min(n, size_t(1000)); ++i) {234                if (pred[i] < lmin) lmin = pred[i];235                if (pred[i] > lmax) lmax = pred[i];236            }237            printf("Step %d: loss=%.4f logits=[%.4f, %.4f] OK\n", step, loss, lmin, lmax);238        }239    }240 241    printf("\nAll %d steps passed! No NaN detected.\n", 200);242    return 0;243}244