Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Side by Side Diff: components/translate/core/browser/translate_ranker_impl.cc

Issue 2565873002: [translate] Add translate ranker model loader. (Closed)
Patch Set: comments from hamelphi Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/translate/core/browser/translate_ranker_impl.h"
6
7 #include <cmath>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/command_line.h"
12 #include "base/files/file_path.h"
13 #include "base/files/file_util.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/metrics/histogram_macros.h"
16 #include "base/profiler/scoped_tracker.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h"
19 #include "base/task_runner.h"
20 #include "base/threading/thread_task_runner_handle.h"
21 #include "components/metrics/proto/translate_event.pb.h"
22 #include "components/translate/core/browser/proto/ranker_model.pb.h"
23 #include "components/translate/core/browser/proto/translate_ranker_model.pb.h"
24 #include "components/translate/core/browser/translate_download_manager.h"
25 #include "components/translate/core/browser/translate_prefs.h"
26 #include "components/translate/core/browser/translate_url_fetcher.h"
27 #include "components/translate/core/common/translate_switches.h"
28 #include "components/variations/variations_associated_data.h"
29 #include "url/gurl.h"
30
31 namespace translate {
groby-ooo-7-16 2017/01/23 21:41:57 It's kind of hard to figure out what's new in here
Roger McFarlane (Chromium) 2017/02/08 23:08:12 Almost nothing changed from the old translate_rank
32
33 namespace {
34
35 const double kTranslationOfferThreshold = 0.5;
36
37 const char kTranslateRankerModelFileName[] = "Translate Ranker Model";
38 const char kUmaPrefix[] = "Translate.Ranker";
39 const char kUnknown[] = "UNKNOWN";
40
41 double Sigmoid(double x) {
42 return 1.0 / (1.0 + exp(-x));
43 }
44
45 double ScoreComponent(const google::protobuf::Map<std::string, float>& weights,
46 const std::string& key) {
47 auto i = weights.find(base::ToLowerASCII(key));
48 if (i == weights.end())
49 i = weights.find(kUnknown);
50 return i == weights.end() ? 0.0 : i->second;
51 }
52
53 } // namespace
54
55 const base::Feature kTranslateRankerQuery{"TranslateRankerQuery",
56 base::FEATURE_DISABLED_BY_DEFAULT};
57
58 const base::Feature kTranslateRankerEnforcement{
59 "TranslateRankerEnforcement", base::FEATURE_DISABLED_BY_DEFAULT};
60
61 const base::Feature kTranslateRankerLogging{"TranslateRankerLogging",
62 base::FEATURE_DISABLED_BY_DEFAULT};
63
64 TranslateRankerFeatures::TranslateRankerFeatures() {}
65
66 TranslateRankerFeatures::TranslateRankerFeatures(const TranslatePrefs& prefs,
67 const std::string& src,
68 const std::string& dst,
69 const std::string& locale)
70 : accepted_count(prefs.GetTranslationAcceptedCount(src)),
71 denied_count(prefs.GetTranslationDeniedCount(src)),
72 ignored_count(prefs.GetTranslationIgnoredCount(src)),
73 total_count(accepted_count + denied_count + ignored_count),
74 src_lang(src),
75 dst_lang(dst),
76 country(prefs.GetCountry()),
77 app_locale(locale),
78 accepted_ratio(total_count ? (accepted_count / total_count) : 0.0),
79 denied_ratio(total_count ? (denied_count / total_count) : 0.0),
80 ignored_ratio(total_count ? (ignored_count / total_count) : 0.0) {}
81
82 TranslateRankerFeatures::~TranslateRankerFeatures() {}
83
84 void TranslateRankerFeatures::WriteTo(std::ostream& stream) const {
85 stream << "src_lang='" << src_lang << "', "
86 << "dst_lang='" << dst_lang << "', "
87 << "country='" << country << "', "
88 << "app_locale='" << app_locale << "', "
89 << "accept_count=" << accepted_count << ", "
90 << "denied_count=" << denied_count << ", "
91 << "ignored_count=" << ignored_count << ", "
92 << "total_count=" << total_count << ", "
93 << "accept_ratio=" << accepted_ratio << ", "
94 << "decline_ratio=" << denied_ratio << ", "
95 << "ignore_ratio=" << ignored_ratio;
96 }
97
98 TranslateRankerImpl::TranslateRankerImpl(const base::FilePath& model_path,
99 const GURL& model_url)
100 : task_runner_(base::ThreadTaskRunnerHandle::Get()),
101 model_loader_(this, model_path, model_url, kUmaPrefix) {
102 model_loader_.Start();
103 }
104
105 TranslateRankerImpl::~TranslateRankerImpl() {}
106
107 // static
108 base::FilePath TranslateRankerImpl::GetModelPath(
109 const base::FilePath& data_dir) {
110 // Allow override of the ranker model path from the command line.
111 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
112 if (command_line->HasSwitch(switches::kTranslateRankerModelPath)) {
113 return base::FilePath(command_line->GetSwitchValueNative(
114 switches::kTranslateRankerModelPath));
115 }
116
117 if (data_dir.empty())
118 return base::FilePath();
119
120 // Otherwise, look for the file in data dir.
121 return data_dir.AppendASCII(kTranslateRankerModelFileName);
122 }
123
124 // static
125 GURL TranslateRankerImpl::GetModelURL() {
126 // Allow override of the ranker model URL from the command line.
127 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
128 if (command_line->HasSwitch(switches::kTranslateRankerModelURL)) {
129 return GURL(
130 command_line->GetSwitchValueASCII(switches::kTranslateRankerModelURL));
131 }
132
133 // Otherwise take the ranker model URL from the ranker query variation.
134 const std::string raw_url = variations::GetVariationParamValueByFeature(
135 kTranslateRankerQuery, switches::kTranslateRankerModelURL);
136
137 DVLOG(3) << switches::kTranslateRankerModelURL << " = " << raw_url;
138
139 return GURL(raw_url);
140 }
141
142 bool TranslateRankerImpl::IsEnabled() {
143 return IsQueryEnabled() || IsEnforcementEnabled();
144 }
145
146 bool TranslateRankerImpl::IsLoggingEnabled() {
147 return base::FeatureList::IsEnabled(kTranslateRankerLogging);
148 }
149
150 bool TranslateRankerImpl::IsQueryEnabled() {
151 return base::FeatureList::IsEnabled(kTranslateRankerQuery);
152 }
153
154 bool TranslateRankerImpl::IsEnforcementEnabled() {
155 return base::FeatureList::IsEnabled(kTranslateRankerEnforcement);
156 }
157
158 int TranslateRankerImpl::GetModelVersion() const {
159 return model_ ? model_->translate().version() : 0;
160 }
161
162 bool TranslateRankerImpl::ShouldOfferTranslation(
163 const TranslatePrefs& translate_prefs,
164 const std::string& src_lang,
165 const std::string& dst_lang) {
166 DCHECK(sequence_checker_.CalledOnValidSequence());
167 // The ranker is a gate in the "show a translation prompt" flow. To retain
168 // the pre-existing functionality, it defaults to returning true in the
169 // absence of a model or if enforcement is disabled. As this is ranker is
170 // subsumed into a more general assist ranker, this default will go away
171 // (or become False).
172 const bool kDefaultResponse = true;
173
174 // If we don't have a model, request one and return the default.
175 if (model_ == nullptr) {
176 return kDefaultResponse;
177 }
178
179 SCOPED_UMA_HISTOGRAM_TIMER("Translate.Ranker.Timer.ShouldOfferTranslation");
180
181 // TODO(rogerm): Remove ScopedTracker below once crbug.com/646711 is closed.
182 tracked_objects::ScopedTracker tracking_profile(
183 FROM_HERE_WITH_EXPLICIT_FUNCTION(
184 "646711 translate::TranslateRankerImpl::ShouldOfferTranslation"));
185
186 TranslateRankerFeatures features(
187 translate_prefs, src_lang, dst_lang,
188 TranslateDownloadManager::GetInstance()->application_locale());
189
190 double score = CalculateScore(features);
191
192 DVLOG(2) << "TranslateRankerImpl::ShouldOfferTranslation: "
193 << "Score = " << score << ", Features=[" << features << "]";
194
195 bool result = (score >= kTranslationOfferThreshold);
196
197 UMA_HISTOGRAM_BOOLEAN("Translate.Ranker.QueryResult", result);
198
199 return result;
200 }
201
202 double TranslateRankerImpl::CalculateScore(
203 const TranslateRankerFeatures& features) {
204 DCHECK(sequence_checker_.CalledOnValidSequence());
205 SCOPED_UMA_HISTOGRAM_TIMER("Translate.Ranker.Timer.CalculateScore");
206 DCHECK(model_ != nullptr);
207 const chrome_intelligence::TranslateRankerModel::LogisticRegressionModel&
208 logit = model_->translate().logistic_regression_model();
209
210 double dot_product =
211 (features.accepted_ratio * logit.accept_ratio_weight()) +
212 (features.denied_ratio * logit.decline_ratio_weight()) +
213 (features.ignored_ratio * logit.ignore_ratio_weight()) +
214 ScoreComponent(logit.source_language_weight(), features.src_lang) +
215 ScoreComponent(logit.dest_language_weight(), features.dst_lang) +
216 ScoreComponent(logit.country_weight(), features.country) +
217 ScoreComponent(logit.locale_weight(), features.app_locale);
218
219 return Sigmoid(dot_product + logit.bias());
220 }
221
222 void TranslateRankerImpl::FlushTranslateEvents(
223 std::vector<std::unique_ptr<metrics::TranslateEventProto>>* events) {
224 DCHECK(sequence_checker_.CalledOnValidSequence());
225 DVLOG(3) << "Flushing translate ranker events.";
226 events->swap(event_cache_);
227 event_cache_.clear();
228 }
229
230 void TranslateRankerImpl::AddTranslateEvent(
231 std::unique_ptr<metrics::TranslateEventProto> event) {
232 DCHECK(sequence_checker_.CalledOnValidSequence());
233 DVLOG(3) << "Adding translate ranker event.";
234 if (IsLoggingEnabled())
235 event_cache_.push_back(std::move(event));
236 }
237
238 RankerModelStatus TranslateRankerImpl::Validate(
239 const chrome_intelligence::RankerModel& model) const {
240 if (model.model_case() != chrome_intelligence::RankerModel::kTranslate)
241 return RankerModelStatus::VALIDATION_FAILED;
242
243 if (model.translate().model_revision_case() !=
244 chrome_intelligence::TranslateRankerModel::kLogisticRegressionModel) {
245 return RankerModelStatus::INCOMPATIBLE;
246 }
247
248 return RankerModelStatus::OK;
249 }
250
251 void TranslateRankerImpl::OnModelAvailable(
252 std::unique_ptr<chrome_intelligence::RankerModel> model) {
253 // Move ownership of |model| to this translate ranker, but be sure to do so
254 // on using this ranker's task runner to avoid threading issues.
255 task_runner_->PostTask(
256 FROM_HERE,
257 base::Bind(&TranslateRankerImpl::OnModelAvailableImpl,
258 base::Unretained(this), base::Passed(std::move(model))));
259 }
260
261 void TranslateRankerImpl::OnModelAvailableImpl(
262 std::unique_ptr<chrome_intelligence::RankerModel> model) {
263 DCHECK(sequence_checker_.CalledOnValidSequence());
264 model_ = std::move(model);
265 }
266
267 } // namespace translate
268
269 std::ostream& operator<<(std::ostream& stream,
270 const translate::TranslateRankerFeatures& features) {
271 features.WriteTo(stream);
272 return stream;
273 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698