Commit b3f0a775 authored by Jia's avatar Jia Committed by Commit Bot

[Power ML] Change smart dim model interface to return ModelPrediction.

Model could error out so we need to record this response in the log.
Also, the logged inactivity_score and decision_threshold are quantized
version of the actual values used in the inference. Hence the
model now returns it decision as part of the prediction.

Bug: 862461
Change-Id: I14c889d97bebd93b88a86027ff94b2ce7fad5bfb
Reviewed-on: https://chromium-review.googlesource.com/1154243
Commit-Queue: Jia Meng <jiameng@chromium.org>
Reviewed-by: default avatarSteven Holte <holte@chromium.org>
Reviewed-by: default avatarAndrew Moylan <amoylan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#580740}
parent 804e7c9b
...@@ -17,16 +17,10 @@ class SmartDimModel { ...@@ -17,16 +17,10 @@ class SmartDimModel {
public: public:
virtual ~SmartDimModel() = default; virtual ~SmartDimModel() = default;
// Returns whether an upcoming dim should go ahead based on input |features|. // Returns a prediction whether an upcoming dim should go ahead based on input
// If |inactive_probability_out| and |threshold_out| are non-null, also // |features|.
// returns model confidence (probability that user will remain inactive if virtual UserActivityEvent::ModelPrediction ShouldDim(
// screen is dimmed now) and threshold: if probability >= threshold then model const UserActivityEvent::Features& features) = 0;
// will return true for this function. Both |inactive_probability_out| and
// |threshold_out| are expected to be in the range of [0, 1.0] so that they
// can be logged as model results.
virtual bool ShouldDim(const UserActivityEvent::Features& features,
float* inactive_probability_out,
float* threshold_out) = 0;
}; };
} // namespace ml } // namespace ml
......
...@@ -13,17 +13,14 @@ SmartDimModelImpl::SmartDimModelImpl() = default; ...@@ -13,17 +13,14 @@ SmartDimModelImpl::SmartDimModelImpl() = default;
SmartDimModelImpl::~SmartDimModelImpl() = default; SmartDimModelImpl::~SmartDimModelImpl() = default;
// TODO(jiameng): add impl. // TODO(jiameng): add impl.
bool SmartDimModelImpl::ShouldDim(const UserActivityEvent::Features& features, UserActivityEvent::ModelPrediction SmartDimModelImpl::ShouldDim(
float* inactive_probability_out, const UserActivityEvent::Features& features) {
float* threshold_out) {
// Let dim go ahead before we have a model implementation in place. // Let dim go ahead before we have a model implementation in place.
if (inactive_probability_out) { UserActivityEvent::ModelPrediction prediction;
*inactive_probability_out = 1.0; prediction.set_decision_threshold(0);
} prediction.set_inactivity_score(100);
if (threshold_out) { prediction.set_response(UserActivityEvent::ModelPrediction::DIM);
*threshold_out = 0.0; return prediction;
}
return true;
} }
} // namespace ml } // namespace ml
......
...@@ -20,9 +20,8 @@ class SmartDimModelImpl : public SmartDimModel { ...@@ -20,9 +20,8 @@ class SmartDimModelImpl : public SmartDimModel {
~SmartDimModelImpl() override; ~SmartDimModelImpl() override;
// chromeos::power::ml::SmartDimModel overrides: // chromeos::power::ml::SmartDimModel overrides:
bool ShouldDim(const UserActivityEvent::Features& features, UserActivityEvent::ModelPrediction ShouldDim(
float* inactive_probability_out, const UserActivityEvent::Features& features) override;
float* threshold_out) override;
private: private:
DISALLOW_COPY_AND_ASSIGN(SmartDimModelImpl); DISALLOW_COPY_AND_ASSIGN(SmartDimModelImpl);
......
...@@ -179,14 +179,33 @@ message UserActivityEvent { ...@@ -179,14 +179,33 @@ message UserActivityEvent {
optional int32 previous_positive_actions_count = 30; optional int32 previous_positive_actions_count = 30;
} // next id = 31 } // next id = 31
// All fields except |model_applied| in ModelPrediction are populated by the
// model. |model_applied| is populated by the UserActivityManager when
// deciding whether to apply the model decision.
message ModelPrediction { message ModelPrediction {
// If |inactivity_score| < |decision_threshold| then dim will be deferred. enum Response {
// Dim should go ahead.
DIM = 0;
// Dim should be deferred.
NO_DIM = 1;
// Model could fail to make a prediction due to various reasons, e.g. it
// could fail to load the preprocessor or process the features for
// inference.
MODEL_ERROR = 2;
}
// Both |inactivity_score| and |decision_threshold| are in the range of
// [0,100]. These values are the quantized versions of actual values used in
// making a model prediction, so that they can be logged later. If
// |inactivity_score| < |decision_threshold| then dim will be deferred.
optional int32 decision_threshold = 1; optional int32 decision_threshold = 1;
// How likely user will remain inactive if screen is dimmed. // How likely user will remain inactive if screen is dimmed.
optional int32 inactivity_score = 2; optional int32 inactivity_score = 2;
// Whether model decision (regardless if dim is to be deferred) is // Whether model decision (regardless if dim is to be deferred) is
// taken by powerd. // taken by powerd. It is false if model response is MODEL_ERROR or if dim
// was deferred last time dim imminent occurred.
optional bool model_applied = 3; optional bool model_applied = 3;
optional Response response = 4;
} }
optional ModelParams params = 1; optional ModelParams params = 1;
......
...@@ -193,30 +193,27 @@ void UserActivityManager::OnIdleEventObserved( ...@@ -193,30 +193,27 @@ void UserActivityManager::OnIdleEventObserved(
ExtractFeatures(activity_data); ExtractFeatures(activity_data);
if (base::FeatureList::IsEnabled(features::kUserActivityPrediction) && if (base::FeatureList::IsEnabled(features::kUserActivityPrediction) &&
smart_dim_model_) { smart_dim_model_) {
float inactivity_probability = -1; // Decide whether to defer the imminent screen dim.
float threshold = -1; UserActivityEvent::ModelPrediction model_prediction =
const bool should_dim = smart_dim_model_->ShouldDim( smart_dim_model_->ShouldDim(features_);
features_, &inactivity_probability, &threshold);
DCHECK(inactivity_probability >= 0 && inactivity_probability <= 1.0)
<< inactivity_probability;
DCHECK(threshold >= 0 && threshold <= 1.0) << threshold;
UserActivityEvent::ModelPrediction model_prediction;
// If previous dim was deferred, then model decision will not be applied
// to this event.
model_prediction.set_model_applied(!dim_deferred_);
model_prediction.set_decision_threshold(round(threshold * 100));
model_prediction.set_inactivity_score(round(inactivity_probability * 100));
model_prediction_ = model_prediction;
// Only defer the dim if the model predicts so and also if the dim was not // Only defer the dim if the model predicts so and also if the dim was not
// previously deferred. // previously deferred.
if (should_dim || dim_deferred_) { if (model_prediction.response() ==
dim_deferred_ = false; UserActivityEvent::ModelPrediction::NO_DIM &&
} else { !dim_deferred_) {
power_manager_client_->DeferScreenDim(); power_manager_client_->DeferScreenDim();
dim_deferred_ = true; dim_deferred_ = true;
model_prediction.set_model_applied(true);
} else {
// Either model predicts dim or model fails, or it was previously dimmed.
dim_deferred_ = false;
model_prediction.set_model_applied(
model_prediction.response() ==
UserActivityEvent::ModelPrediction::DIM &&
!dim_deferred_);
} }
model_prediction_ = model_prediction;
} }
waiting_for_final_action_ = true; waiting_for_final_action_ = true;
} }
......
...@@ -156,9 +156,16 @@ void UserActivityUkmLoggerImpl::LogActivity(const UserActivityEvent& event) { ...@@ -156,9 +156,16 @@ void UserActivityUkmLoggerImpl::LogActivity(const UserActivityEvent& event) {
if (event.has_model_prediction()) { if (event.has_model_prediction()) {
const UserActivityEvent::ModelPrediction& model_prediction = const UserActivityEvent::ModelPrediction& model_prediction =
event.model_prediction(); event.model_prediction();
user_activity.SetModelApplied(model_prediction.model_applied()) user_activity.SetModelResponse(model_prediction.response())
.SetModelDecisionThreshold(model_prediction.decision_threshold()) .SetModelApplied(model_prediction.model_applied());
.SetModelInactivityScore(model_prediction.inactivity_score()); if (model_prediction.response() ==
UserActivityEvent::ModelPrediction::DIM ||
model_prediction.response() ==
UserActivityEvent::ModelPrediction::NO_DIM) {
user_activity
.SetModelDecisionThreshold(model_prediction.decision_threshold())
.SetModelInactivityScore(model_prediction.inactivity_score());
}
} }
user_activity.Record(ukm_recorder_); user_activity.Record(ukm_recorder_);
......
...@@ -64,6 +64,7 @@ class UserActivityUkmLoggerTest : public testing::Test { ...@@ -64,6 +64,7 @@ class UserActivityUkmLoggerTest : public testing::Test {
prediction->set_decision_threshold(50); prediction->set_decision_threshold(50);
prediction->set_inactivity_score(60); prediction->set_inactivity_score(60);
prediction->set_model_applied(true); prediction->set_model_applied(true);
prediction->set_response(UserActivityEvent::ModelPrediction::NO_DIM);
user_activity_logger_delegate_ukm_.ukm_recorder_ = &recorder_; user_activity_logger_delegate_ukm_.ukm_recorder_ = &recorder_;
} }
...@@ -99,6 +100,7 @@ class UserActivityUkmLoggerTest : public testing::Test { ...@@ -99,6 +100,7 @@ class UserActivityUkmLoggerTest : public testing::Test {
UserActivity::kModelDecisionThresholdName, 50); UserActivity::kModelDecisionThresholdName, 50);
recorder_.ExpectEntryMetric(entry, UserActivity::kModelInactivityScoreName, recorder_.ExpectEntryMetric(entry, UserActivity::kModelInactivityScoreName,
60); 60);
recorder_.ExpectEntryMetric(entry, UserActivity::kModelResponseName, 1);
recorder_.ExpectEntryMetric(entry, UserActivity::kMouseEventsInLastHourName, recorder_.ExpectEntryMetric(entry, UserActivity::kMouseEventsInLastHourName,
89); 89);
EXPECT_FALSE(recorder_.EntryHasMetric(entry, UserActivity::kOnBatteryName)); EXPECT_FALSE(recorder_.EntryHasMetric(entry, UserActivity::kOnBatteryName));
...@@ -238,6 +240,11 @@ TEST_F(UserActivityUkmLoggerTest, TwoUserActivityEvents) { ...@@ -238,6 +240,11 @@ TEST_F(UserActivityUkmLoggerTest, TwoUserActivityEvents) {
features->set_dim_to_screen_off_sec(20); features->set_dim_to_screen_off_sec(20);
features->set_time_since_last_mouse_sec(200); features->set_time_since_last_mouse_sec(200);
UserActivityEvent::ModelPrediction* prediction =
user_activity_event2.mutable_model_prediction();
prediction->set_model_applied(false);
prediction->set_response(UserActivityEvent::ModelPrediction::MODEL_ERROR);
LogActivity(user_activity_event_); LogActivity(user_activity_event_);
LogActivity(user_activity_event2); LogActivity(user_activity_event2);
...@@ -277,6 +284,12 @@ TEST_F(UserActivityUkmLoggerTest, TwoUserActivityEvents) { ...@@ -277,6 +284,12 @@ TEST_F(UserActivityUkmLoggerTest, TwoUserActivityEvents) {
recorder_.EntryHasMetric(entry1, UserActivity::kTimeSinceLastKeyName)); recorder_.EntryHasMetric(entry1, UserActivity::kTimeSinceLastKeyName));
recorder_.ExpectEntryMetric(entry1, UserActivity::kTimeSinceLastMouseName, recorder_.ExpectEntryMetric(entry1, UserActivity::kTimeSinceLastMouseName,
200); 200);
recorder_.ExpectEntryMetric(entry1, UserActivity::kModelResponseName, 2);
recorder_.ExpectEntryMetric(entry1, UserActivity::kModelAppliedName, 0);
EXPECT_FALSE(recorder_.EntryHasMetric(
entry1, UserActivity::kModelDecisionThresholdName));
EXPECT_FALSE(recorder_.EntryHasMetric(
entry1, UserActivity::kModelInactivityScoreName));
EXPECT_EQ(0u, recorder_.GetEntriesByName(UserActivityId::kEntryName).size()); EXPECT_EQ(0u, recorder_.GetEntriesByName(UserActivityId::kEntryName).size());
} }
......
...@@ -4212,6 +4212,12 @@ be describing additional metrics about the same event. ...@@ -4212,6 +4212,12 @@ be describing additional metrics about the same event.
dim will be deferred. dim will be deferred.
</summary> </summary>
</metric> </metric>
<metric name="ModelResponse">
<summary>
Whether the model recommends the screen dim should be deferred (NO_DIM) or
allowed (DIM), or encountered an error (MODEL_ERROR).
</summary>
</metric>
<metric name="MouseEventsInLastHour"> <metric name="MouseEventsInLastHour">
<summary> <summary>
The number of mouse events reported as user activity in the last hour. The number of mouse events reported as user activity in the last hour.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment