@@ -3139,6 +3139,39 @@ namespace dlib
31393139
31403140 // ----------------------------------------------------------------------------------------
31413141
3142+ __global__ void _cuda_count_valid_tokens (
3143+ float * valid_count,
3144+ const unsigned long * truth,
3145+ const float * input_data,
3146+ size_t batch_size,
3147+ size_t seq_len,
3148+ long ignore_index
3149+ )
3150+ {
3151+ float count = 0 .0f ;
3152+
3153+ for (auto sample_idx : grid_stride_range (0 , batch_size))
3154+ {
3155+ for (size_t t = 0 ; t < seq_len; ++t)
3156+ {
3157+ unsigned long target_class;
3158+ if (t < seq_len - 1 ) {
3159+ const size_t input_idx = sample_idx * seq_len + (t + 1 );
3160+ target_class = static_cast <unsigned long >(input_data[input_idx]);
3161+ }
3162+ else {
3163+ target_class = truth[sample_idx];
3164+ }
3165+
3166+ if (ignore_index < 0 || static_cast <long >(target_class) != ignore_index) {
3167+ count += 1 .0f ;
3168+ }
3169+ }
3170+ }
3171+
3172+ warp_reduce_atomic_add (*valid_count, count);
3173+ }
3174+
31423175 __global__ void _cuda_compute_loss_cross_entropy_per_logit (
31433176 float * loss_out,
31443177 float * g,
@@ -3148,7 +3181,8 @@ namespace dlib
31483181 size_t batch_size,
31493182 size_t seq_len,
31503183 size_t vocab_size,
3151- const float scale
3184+ float scale,
3185+ long ignore_index
31523186 )
31533187 {
31543188 float total_loss = 0 ;
@@ -3158,7 +3192,6 @@ namespace dlib
31583192 for (size_t t = 0 ; t < seq_len; ++t)
31593193 {
31603194 unsigned long target_class;
3161-
31623195 if (t < seq_len - 1 ) {
31633196 const size_t input_idx = sample_idx * seq_len + (t + 1 );
31643197 target_class = static_cast <unsigned long >(input_data[input_idx]);
@@ -3168,7 +3201,15 @@ namespace dlib
31683201 }
31693202
31703203 const size_t base_idx = sample_idx * seq_len * vocab_size + t * vocab_size;
3171- float max_val = out_data[base_idx + 0 ];
3204+
3205+ if (ignore_index >= 0 && static_cast <long >(target_class) == ignore_index) {
3206+ for (size_t c = 0 ; c < vocab_size; ++c) {
3207+ g[base_idx + c] = 0 .0f ;
3208+ }
3209+ continue ;
3210+ }
3211+
3212+ float max_val = out_data[base_idx];
31723213 for (size_t c = 1 ; c < vocab_size; ++c)
31733214 {
31743215 max_val = ::max (max_val, out_data[base_idx + c]);
@@ -3210,7 +3251,8 @@ namespace dlib
32103251 const tensor& input_tensor,
32113252 const tensor& subnetwork_output,
32123253 tensor& gradient,
3213- double & loss
3254+ double & loss,
3255+ long ignore_index
32143256 )
32153257 {
32163258 CHECK_CUDA (cudaMemset (gradient.device (), 0 , gradient.size () * sizeof (float )));
@@ -3220,7 +3262,35 @@ namespace dlib
32203262 const long seq_len = subnetwork_output.nr ();
32213263 const long vocab_size = subnetwork_output.nc ();
32223264
3223- const double scale = 1.0 / (batch_size * seq_len);
3265+ double scale;
3266+ if (ignore_index < 0 )
3267+ {
3268+ scale = 1.0 / (batch_size * seq_len);
3269+ }
3270+ else {
3271+ cuda_data_void_ptr count_buf = device_global_buffer (sizeof (float ));
3272+ auto valid_count_ptr = static_pointer_cast<float >(count_buf, 1 );
3273+ CHECK_CUDA (cudaMemset (valid_count_ptr, 0 , sizeof (float )));
3274+
3275+ launch_kernel (_cuda_count_valid_tokens, max_jobs (batch_size),
3276+ valid_count_ptr.data (),
3277+ truth_buffer.data (),
3278+ input_tensor.device (),
3279+ batch_size,
3280+ seq_len,
3281+ ignore_index
3282+ );
3283+
3284+ float valid_count;
3285+ dlib::cuda::memcpy (&valid_count, valid_count_ptr);
3286+
3287+ if (valid_count == 0 ) {
3288+ loss = 0.0 ;
3289+ return ;
3290+ }
3291+
3292+ scale = 1.0 / valid_count;
3293+ }
32243294
32253295 launch_kernel (_cuda_compute_loss_cross_entropy_per_logit, max_jobs (batch_size),
32263296 loss_work_buffer.data (),
@@ -3231,7 +3301,8 @@ namespace dlib
32313301 batch_size,
32323302 seq_len,
32333303 vocab_size,
3234- scale
3304+ static_cast <float >(scale),
3305+ ignore_index
32353306 );
32363307
32373308 float floss;
0 commit comments