TODO(shengx): The helper classes/methods are changed to support multiclass SDCA, which lead to changes within this function. Need to revisit the convergence once the multiclass SDCA is in.
| 128 | // SDCA, which lead to changes within this function. Need to revisit the |
| 129 | // convergence once the multiclass SDCA is in. |
| 130 | void DoCompute(const ComputeOptions& options, OpKernelContext* const context) { |
| 131 | ModelWeights model_weights; |
| 132 | OP_REQUIRES_OK(context, model_weights.Initialize(context)); |
| 133 | |
| 134 | Examples examples; |
| 135 | OP_REQUIRES_OK( |
| 136 | context, |
| 137 | examples.Initialize(context, model_weights, options.num_sparse_features, |
| 138 | options.num_sparse_features_with_values, |
| 139 | options.num_dense_features)); |
| 140 | |
| 141 | const Tensor* example_state_data_t; |
| 142 | OP_REQUIRES_OK(context, |
| 143 | context->input("example_state_data", &example_state_data_t)); |
| 144 | TensorShape expected_example_state_shape({examples.num_examples(), 4}); |
| 145 | OP_REQUIRES(context, |
| 146 | example_state_data_t->shape() == expected_example_state_shape, |
| 147 | errors::InvalidArgument( |
| 148 | "Expected shape ", expected_example_state_shape.DebugString(), |
| 149 | " for example_state_data, got ", |
| 150 | example_state_data_t->shape().DebugString())); |
| 151 | |
| 152 | Tensor mutable_example_state_data_t(*example_state_data_t); |
| 153 | auto example_state_data = mutable_example_state_data_t.matrix<float>(); |
| 154 | OP_REQUIRES_OK(context, context->set_output("out_example_state_data", |
| 155 | mutable_example_state_data_t)); |
| 156 | |
| 157 | if (options.adaptive) { |
| 158 | OP_REQUIRES_OK(context, |
| 159 | examples.SampleAdaptiveProbabilities( |
| 160 | options.num_loss_partitions, options.regularizations, |
| 161 | model_weights, example_state_data, options.loss_updater, |
| 162 | /*num_weight_vectors =*/1)); |
| 163 | } else { |
| 164 | examples.RandomShuffle(); |
| 165 | } |
| 166 | struct { |
| 167 | mutex mu; |
| 168 | Status value GUARDED_BY(mu); |
| 169 | } train_step_status; |
| 170 | std::atomic<std::int64_t> atomic_index(-1); |
| 171 | auto train_step = [&](const int64 begin, const int64 end) { |
| 172 | // The static_cast here is safe since begin and end can be at most |
| 173 | // num_examples which is an int. |
| 174 | for (int id = static_cast<int>(begin); id < end; ++id) { |
| 175 | const int64 example_index = examples.sampled_index(++atomic_index); |
| 176 | const Example& example = examples.example(example_index); |
| 177 | const float dual = example_state_data(example_index, 0); |
| 178 | const float example_weight = example.example_weight(); |
| 179 | float example_label = example.example_label(); |
| 180 | const Status conversion_status = |
| 181 | options.loss_updater->ConvertLabel(&example_label); |
| 182 | if (!conversion_status.ok()) { |
| 183 | mutex_lock l(train_step_status.mu); |
| 184 | train_step_status.value = conversion_status; |
| 185 | // Return from this worker thread - the calling thread is |
| 186 | // responsible for checking context status and returning on error. |
| 187 | return; |
no test coverage detected