| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/translate/core/browser/translate_ranker_impl.h" | 5 #include "components/translate/core/browser/translate_ranker_impl.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
| 13 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
| 14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
| 15 #include "base/metrics/histogram_macros.h" | 15 #include "base/metrics/histogram_macros.h" |
| 16 #include "base/metrics/metrics_hashes.h" | 16 #include "base/metrics/metrics_hashes.h" |
| 17 #include "base/profiler/scoped_tracker.h" | 17 #include "base/profiler/scoped_tracker.h" |
| 18 #include "base/strings/string_number_conversions.h" | |
| 19 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 20 #include "base/task_runner.h" | 19 #include "base/task_runner.h" |
| 21 #include "base/threading/thread_task_runner_handle.h" | 20 #include "base/threading/thread_task_runner_handle.h" |
| 22 #include "components/metrics/proto/translate_event.pb.h" | 21 #include "components/metrics/proto/translate_event.pb.h" |
| 23 #include "components/translate/core/browser/proto/ranker_model.pb.h" | 22 #include "components/translate/core/browser/proto/ranker_model.pb.h" |
| 24 #include "components/translate/core/browser/proto/translate_ranker_model.pb.h" | 23 #include "components/translate/core/browser/proto/translate_ranker_model.pb.h" |
| 25 #include "components/translate/core/browser/ranker_model.h" | 24 #include "components/translate/core/browser/ranker_model.h" |
| 26 #include "components/translate/core/browser/translate_download_manager.h" | |
| 27 #include "components/translate/core/browser/translate_prefs.h" | |
| 28 #include "components/translate/core/browser/translate_url_fetcher.h" | |
| 29 #include "components/translate/core/common/translate_switches.h" | 25 #include "components/translate/core/common/translate_switches.h" |
| 30 #include "components/ukm/public/ukm_entry_builder.h" | 26 #include "components/ukm/public/ukm_entry_builder.h" |
| 31 #include "components/ukm/public/ukm_recorder.h" | 27 #include "components/ukm/public/ukm_recorder.h" |
| 32 #include "components/variations/variations_associated_data.h" | 28 #include "components/variations/variations_associated_data.h" |
| 33 #include "url/gurl.h" | 29 #include "url/gurl.h" |
| 34 | 30 |
| 35 namespace translate { | 31 namespace translate { |
| 36 | 32 |
| 37 namespace { | 33 namespace { |
| 38 | 34 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 ignored_count(ignored), | 95 ignored_count(ignored), |
| 100 total_count(accepted_count + denied_count + ignored_count), | 96 total_count(accepted_count + denied_count + ignored_count), |
| 101 src_lang(src), | 97 src_lang(src), |
| 102 dst_lang(dst), | 98 dst_lang(dst), |
| 103 country(cntry), | 99 country(cntry), |
| 104 app_locale(locale), | 100 app_locale(locale), |
| 105 accepted_ratio(SafeRatio(accepted_count, total_count)), | 101 accepted_ratio(SafeRatio(accepted_count, total_count)), |
| 106 denied_ratio(SafeRatio(denied_count, total_count)), | 102 denied_ratio(SafeRatio(denied_count, total_count)), |
| 107 ignored_ratio(SafeRatio(ignored_count, total_count)) {} | 103 ignored_ratio(SafeRatio(ignored_count, total_count)) {} |
| 108 | 104 |
| 109 TranslateRankerFeatures::TranslateRankerFeatures(const TranslatePrefs& prefs, | 105 // TODO(hamelphi): Log locale in TranslateEventProtos. |
| 110 const std::string& src, | 106 TranslateRankerFeatures::TranslateRankerFeatures( |
| 111 const std::string& dst, | 107 const metrics::TranslateEventProto& translate_event) |
| 112 const std::string& locale) | 108 : TranslateRankerFeatures(translate_event.accept_count(), |
| 113 : TranslateRankerFeatures(prefs.GetTranslationAcceptedCount(src), | 109 translate_event.decline_count(), |
| 114 prefs.GetTranslationDeniedCount(src), | 110 translate_event.ignore_count(), |
| 115 prefs.GetTranslationIgnoredCount(src), | 111 translate_event.source_language(), |
| 116 src, | 112 translate_event.target_language(), |
| 117 dst, | 113 translate_event.country(), |
| 118 prefs.GetCountry(), | 114 "" /*locale*/) {} |
| 119 locale) {} | |
| 120 | 115 |
| 121 TranslateRankerFeatures::~TranslateRankerFeatures() {} | 116 TranslateRankerFeatures::~TranslateRankerFeatures() {} |
| 122 | 117 |
| 123 void TranslateRankerFeatures::WriteTo(std::ostream& stream) const { | 118 void TranslateRankerFeatures::WriteTo(std::ostream& stream) const { |
| 124 stream << "src_lang='" << src_lang << "', " | 119 stream << "src_lang='" << src_lang << "', " |
| 125 << "dst_lang='" << dst_lang << "', " | 120 << "dst_lang='" << dst_lang << "', " |
| 126 << "country='" << country << "', " | 121 << "country='" << country << "', " |
| 127 << "app_locale='" << app_locale << "', " | 122 << "app_locale='" << app_locale << "', " |
| 128 << "accept_count=" << accepted_count << ", " | 123 << "accept_count=" << accepted_count << ", " |
| 129 << "denied_count=" << denied_count << ", " | 124 << "denied_count=" << denied_count << ", " |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 | 183 |
| 189 void TranslateRankerImpl::EnableLogging(bool value) { | 184 void TranslateRankerImpl::EnableLogging(bool value) { |
| 190 is_logging_enabled_ = value; | 185 is_logging_enabled_ = value; |
| 191 } | 186 } |
| 192 | 187 |
| 193 uint32_t TranslateRankerImpl::GetModelVersion() const { | 188 uint32_t TranslateRankerImpl::GetModelVersion() const { |
| 194 return model_ ? model_->proto().translate().version() : 0; | 189 return model_ ? model_->proto().translate().version() : 0; |
| 195 } | 190 } |
| 196 | 191 |
| 197 bool TranslateRankerImpl::ShouldOfferTranslation( | 192 bool TranslateRankerImpl::ShouldOfferTranslation( |
| 198 const TranslatePrefs& translate_prefs, | |
| 199 const std::string& src_lang, | |
| 200 const std::string& dst_lang, | |
| 201 metrics::TranslateEventProto* translate_event) { | 193 metrics::TranslateEventProto* translate_event) { |
| 202 DCHECK(sequence_checker_.CalledOnValidSequence()); | 194 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 203 // The ranker is a gate in the "show a translation prompt" flow. To retain | 195 // The ranker is a gate in the "show a translation prompt" flow. To retain |
| 204 // the pre-existing functionality, it defaults to returning true in the | 196 // the pre-existing functionality, it defaults to returning true in the |
| 205 // absence of a model or if enforcement is disabled. As this is ranker is | 197 // absence of a model or if enforcement is disabled. As this is ranker is |
| 206 // subsumed into a more general assist ranker, this default will go away | 198 // subsumed into a more general assist ranker, this default will go away |
| 207 // (or become False). | 199 // (or become False). |
| 208 const bool kDefaultResponse = true; | 200 const bool kDefaultResponse = true; |
| 209 | 201 |
| 210 translate_event->set_ranker_request_timestamp_sec( | 202 translate_event->set_ranker_request_timestamp_sec( |
| (...skipping 16 matching lines...) Expand all Loading... |
| 227 return kDefaultResponse; | 219 return kDefaultResponse; |
| 228 } | 220 } |
| 229 | 221 |
| 230 SCOPED_UMA_HISTOGRAM_TIMER("Translate.Ranker.Timer.ShouldOfferTranslation"); | 222 SCOPED_UMA_HISTOGRAM_TIMER("Translate.Ranker.Timer.ShouldOfferTranslation"); |
| 231 | 223 |
| 232 // TODO(rogerm): Remove ScopedTracker below once crbug.com/646711 is closed. | 224 // TODO(rogerm): Remove ScopedTracker below once crbug.com/646711 is closed. |
| 233 tracked_objects::ScopedTracker tracking_profile( | 225 tracked_objects::ScopedTracker tracking_profile( |
| 234 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 226 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 235 "646711 translate::TranslateRankerImpl::ShouldOfferTranslation")); | 227 "646711 translate::TranslateRankerImpl::ShouldOfferTranslation")); |
| 236 | 228 |
| 237 TranslateRankerFeatures features( | 229 bool result = GetModelDecision(*translate_event); |
| 238 translate_prefs, src_lang, dst_lang, | |
| 239 TranslateDownloadManager::GetInstance()->application_locale()); | |
| 240 | 230 |
| 241 bool result = GetModelDecision(features); | |
| 242 UMA_HISTOGRAM_BOOLEAN("Translate.Ranker.QueryResult", result); | 231 UMA_HISTOGRAM_BOOLEAN("Translate.Ranker.QueryResult", result); |
| 243 | 232 |
| 244 translate_event->set_ranker_response( | 233 translate_event->set_ranker_response( |
| 245 result ? metrics::TranslateEventProto::SHOW | 234 result ? metrics::TranslateEventProto::SHOW |
| 246 : metrics::TranslateEventProto::DONT_SHOW); | 235 : metrics::TranslateEventProto::DONT_SHOW); |
| 247 | 236 |
| 248 if (!is_enforcement_enabled_ && !is_decision_override_enabled_) { | 237 if (!is_enforcement_enabled_ && !is_decision_override_enabled_) { |
| 249 return kDefaultResponse; | 238 return kDefaultResponse; |
| 250 } | 239 } |
| 251 | 240 |
| 252 return result; | 241 return result; |
| 253 } | 242 } |
| 254 | 243 |
| 255 bool TranslateRankerImpl::GetModelDecision( | 244 bool TranslateRankerImpl::GetModelDecision( |
| 256 const TranslateRankerFeatures& features) { | 245 const metrics::TranslateEventProto& translate_event) { |
| 257 DCHECK(sequence_checker_.CalledOnValidSequence()); | 246 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 258 SCOPED_UMA_HISTOGRAM_TIMER("Translate.Ranker.Timer.CalculateScore"); | 247 SCOPED_UMA_HISTOGRAM_TIMER("Translate.Ranker.Timer.CalculateScore"); |
| 259 DCHECK(model_ != nullptr); | 248 DCHECK(model_ != nullptr); |
| 260 const TranslateRankerModel::LogisticRegressionModel& logit = | 249 |
| 250 // TODO(hamelphi): consider deprecating TranslateRankerFeatures and move the |
| 251 // logic here. |
| 252 const TranslateRankerFeatures features(translate_event); |
| 253 |
| 254 const TranslateRankerModel::LogisticRegressionModel& lr_model = |
| 261 model_->proto().translate().logistic_regression_model(); | 255 model_->proto().translate().logistic_regression_model(); |
| 262 | 256 |
| 263 double dot_product = | 257 double dot_product = |
| 264 (features.accepted_count * logit.accept_count_weight()) + | 258 (features.accepted_count * lr_model.accept_count_weight()) + |
| 265 (features.denied_count * logit.decline_count_weight()) + | 259 (features.denied_count * lr_model.decline_count_weight()) + |
| 266 (features.ignored_count * logit.ignore_count_weight()) + | 260 (features.ignored_count * lr_model.ignore_count_weight()) + |
| 267 (features.accepted_ratio * logit.accept_ratio_weight()) + | 261 (features.accepted_ratio * lr_model.accept_ratio_weight()) + |
| 268 (features.denied_ratio * logit.decline_ratio_weight()) + | 262 (features.denied_ratio * lr_model.decline_ratio_weight()) + |
| 269 (features.ignored_ratio * logit.ignore_ratio_weight()) + | 263 (features.ignored_ratio * lr_model.ignore_ratio_weight()) + |
| 270 ScoreComponent(logit.source_language_weight(), features.src_lang) + | 264 ScoreComponent(lr_model.source_language_weight(), features.src_lang) + |
| 271 ScoreComponent(logit.target_language_weight(), features.dst_lang) + | 265 ScoreComponent(lr_model.target_language_weight(), features.dst_lang) + |
| 272 ScoreComponent(logit.country_weight(), features.country) + | 266 ScoreComponent(lr_model.country_weight(), features.country) + |
| 273 ScoreComponent(logit.locale_weight(), features.app_locale); | 267 ScoreComponent(lr_model.locale_weight(), features.app_locale); |
| 274 | 268 |
| 275 double score = Sigmoid(dot_product + logit.bias()); | 269 double score = Sigmoid(dot_product + lr_model.bias()); |
| 276 | 270 |
| 277 DVLOG(2) << "TranslateRankerImpl::GetModelDecision: " | 271 DVLOG(2) << "TranslateRankerImpl::GetModelDecision: " |
| 278 << "Score = " << score << ", Features=[" << features << "]"; | 272 << "Score = " << score << ", Features=[" << features << "]"; |
| 279 | 273 |
| 280 float decision_threshold = kTranslationOfferDefaultThreshold; | 274 float decision_threshold = kTranslationOfferDefaultThreshold; |
| 281 if (logit.threshold() > 0) { | 275 if (lr_model.threshold() > 0) { |
| 282 decision_threshold = logit.threshold(); | 276 decision_threshold = lr_model.threshold(); |
| 283 } | 277 } |
| 284 | 278 |
| 285 return score >= decision_threshold; | 279 return score >= decision_threshold; |
| 286 } | 280 } |
| 287 | 281 |
| 288 void TranslateRankerImpl::FlushTranslateEvents( | 282 void TranslateRankerImpl::FlushTranslateEvents( |
| 289 std::vector<metrics::TranslateEventProto>* events) { | 283 std::vector<metrics::TranslateEventProto>* events) { |
| 290 DCHECK(sequence_checker_.CalledOnValidSequence()); | 284 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 291 DVLOG(3) << "Flushing translate ranker events."; | 285 DVLOG(3) << "Flushing translate ranker events."; |
| 292 events->swap(event_cache_); | 286 events->swap(event_cache_); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 } | 365 } |
| 372 } | 366 } |
| 373 | 367 |
| 374 } // namespace translate | 368 } // namespace translate |
| 375 | 369 |
| 376 std::ostream& operator<<(std::ostream& stream, | 370 std::ostream& operator<<(std::ostream& stream, |
| 377 const translate::TranslateRankerFeatures& features) { | 371 const translate::TranslateRankerFeatures& features) { |
| 378 features.WriteTo(stream); | 372 features.WriteTo(stream); |
| 379 return stream; | 373 return stream; |
| 380 } | 374 } |
| OLD | NEW |