Commit 558a9191 authored by Charles Zhao's avatar Charles Zhao Committed by Commit Bot

cros: Add SerializedMrfuAppLaunchPredictor for AppSearchResultRanker

(1) Add SerializedMrfuAppLaunchPredictor with unit test.
SerializedMrfuAppLaunchPredictor is basically MrfuAppLaunchPredictor
with extra serialization and deserialization logic.

Bug: 871674
Change-Id: I95bcb2599557ef9f7a860b74814dc4307da109a2
Reviewed-on: https://chromium-review.googlesource.com/1223716
Commit-Queue: Charles . <charleszhao@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#591917}
parent 052bac3d
......@@ -78,6 +78,64 @@ void MrfuAppLaunchPredictor::UpdateScore(Score* score) {
}
}
SerializedMrfuAppLaunchPredictor::SerializedMrfuAppLaunchPredictor()
: MrfuAppLaunchPredictor(), last_save_timestamp_(base::Time::Now()) {}
SerializedMrfuAppLaunchPredictor::~SerializedMrfuAppLaunchPredictor() = default;
const char SerializedMrfuAppLaunchPredictor::kPredictorName[] =
"SerializedMrfuAppLaunchPredictor";
const char* SerializedMrfuAppLaunchPredictor::GetPredictorName() const {
return kPredictorName;
}
bool SerializedMrfuAppLaunchPredictor::ShouldSave() {
const base::Time now = base::Time::Now();
if (now - last_save_timestamp_ >= kSaveInternal) {
last_save_timestamp_ = now;
return true;
}
return false;
}
AppLaunchPredictorProto SerializedMrfuAppLaunchPredictor::ToProto() const {
AppLaunchPredictorProto output;
auto& predictor_proto =
*output.mutable_serialized_mrfu_app_launch_predictor();
predictor_proto.set_num_of_trains(num_of_trains_);
for (const auto& pair : scores_) {
auto& score_item = (*predictor_proto.mutable_scores())[pair.first];
score_item.set_last_score(pair.second.last_score);
score_item.set_num_of_trains_at_last_update(
pair.second.num_of_trains_at_last_update);
}
return output;
}
bool SerializedMrfuAppLaunchPredictor::FromProto(
const AppLaunchPredictorProto& proto) {
if (proto.predictor_case() !=
AppLaunchPredictorProto::kSerializedMrfuAppLaunchPredictor) {
return false;
}
const auto& predictor_proto = proto.serialized_mrfu_app_launch_predictor();
num_of_trains_ = predictor_proto.num_of_trains();
scores_.clear();
for (const auto& pair : predictor_proto.scores()) {
// Skip the case where the last_score has already dropped to 0.0f.
if (pair.second.last_score() == 0.0f)
continue;
auto& score_item = scores_[pair.first];
score_item.last_score = pair.second.last_score();
score_item.num_of_trains_at_last_update =
pair.second.num_of_trains_at_last_update();
}
return true;
}
HourAppLaunchPredictor::HourAppLaunchPredictor()
: last_save_timestamp_(base::Time::Now()) {}
......
......@@ -57,9 +57,7 @@ class MrfuAppLaunchPredictor : public AppLaunchPredictor {
// Name of the predictor;
static const char kPredictorName[];
private:
FRIEND_TEST_ALL_PREFIXES(AppLaunchPredictorTest, MrfuAppLaunchPredictor);
protected:
// Records last updates of the Score for an app.
struct Score {
int32_t num_of_trains_at_last_update = 0;
......@@ -68,6 +66,14 @@ class MrfuAppLaunchPredictor : public AppLaunchPredictor {
// Updates the Score to now.
void UpdateScore(Score* score);
// Map from app_id to its Score.
base::flat_map<std::string, Score> scores_;
// Increment 1 for each Train() call.
int32_t num_of_trains_ = 0;
private:
FRIEND_TEST_ALL_PREFIXES(AppLaunchPredictorTest, MrfuAppLaunchPredictor);
friend class SerializedMrfuAppLaunchPredictorTest;
// Controls how much the score decays for each Train() call.
// This decay_coeff_ should be within [0.5f, 1.0f]. Setting it as 0.5f means
......@@ -76,14 +82,33 @@ class MrfuAppLaunchPredictor : public AppLaunchPredictor {
// (1) Set a better initial value based on real user data.
// (2) Dynamically change this coeff instead of setting it as constant.
static constexpr float decay_coeff_ = 0.8f;
// Map from app_id to its Score.
base::flat_map<std::string, Score> scores_;
// Increment 1 for each Train() call.
int32_t num_of_trains_ = 0;
DISALLOW_COPY_AND_ASSIGN(MrfuAppLaunchPredictor);
};
// SerializedMrfuAppLaunchPredictor is MrfuAppLaunchPredictor with supporting of
// AppLaunchPredictor::ToProto and AppLaunchPredictor::FromProto.
class SerializedMrfuAppLaunchPredictor : public MrfuAppLaunchPredictor {
public:
SerializedMrfuAppLaunchPredictor();
~SerializedMrfuAppLaunchPredictor() override;
// AppLaunchPredictor:
const char* GetPredictorName() const override;
bool ShouldSave() override;
AppLaunchPredictorProto ToProto() const override;
bool FromProto(const AppLaunchPredictorProto& proto) override;
// Name of the predictor;
static const char kPredictorName[];
private:
// Last time the predictor was saved.
base::Time last_save_timestamp_;
DISALLOW_COPY_AND_ASSIGN(SerializedMrfuAppLaunchPredictor);
};
// HourAppLaunchPredictor is a AppLaunchPredictor that uses hour of the day as
// bins, and uses app-launch frequency of in each bin as the Rank score.
// For example, if it's 8:30 am right now, then only app-launches between 8am to
......
......@@ -8,6 +8,18 @@ option optimize_for = LITE_RUNTIME;
package app_list;
message SerializedMrfuAppLaunchPredictorProto {
// Records last updates of the Score for an app.
message Score {
optional int32 num_of_trains_at_last_update = 1;
optional float last_score = 2;
}
// Map from app_id to its Score.
map<string, Score> scores = 1;
// Increment 1 for each Train() call.
optional int32 num_of_trains = 2;
}
// HourAppLaunchPredictorProto is used for materializing HourAppLaunchPredictor.
message HourAppLaunchPredictorProto {
// A frequency table records app launches that happened in a particular bin.
......@@ -32,5 +44,7 @@ message AppLaunchPredictorProto {
oneof predictor {
FakeAppLaunchPredictorProto fake_app_launch_predictor = 1;
HourAppLaunchPredictorProto hour_app_launch_predictor = 2;
SerializedMrfuAppLaunchPredictorProto serialized_mrfu_app_launch_predictor =
3;
}
}
......@@ -42,6 +42,52 @@ TEST(AppLaunchPredictorTest, MrfuAppLaunchPredictor) {
Pair(kTarget2, FloatEq(score_1))));
}
// Test Serialization logic of SerializedMrfuAppLaunchPredictor.
class SerializedMrfuAppLaunchPredictorTest : public testing::Test {
protected:
void SetUp() override {
score1_ = (1.0f - decay) * decay + (1.0f - decay);
score2_ = 1.0f - decay;
auto& predictor_proto =
*proto_.mutable_serialized_mrfu_app_launch_predictor();
predictor_proto.set_num_of_trains(3);
auto& item1 = (*predictor_proto.mutable_scores())[kTarget1];
item1.set_last_score(score1_);
item1.set_num_of_trains_at_last_update(2);
auto& item2 = (*predictor_proto.mutable_scores())[kTarget2];
item2.set_last_score(score2_);
item2.set_num_of_trains_at_last_update(3);
}
float score1_ = 0.0f;
float score2_ = 0.0f;
static constexpr float decay = MrfuAppLaunchPredictor::decay_coeff_;
AppLaunchPredictorProto proto_;
};
TEST_F(SerializedMrfuAppLaunchPredictorTest, ToProto) {
SerializedMrfuAppLaunchPredictor predictor;
predictor.Train(kTarget1);
predictor.Train(kTarget1);
predictor.Train(kTarget2);
EXPECT_EQ(predictor.ToProto().SerializeAsString(),
proto_.SerializeAsString());
}
TEST_F(SerializedMrfuAppLaunchPredictorTest, FromProto) {
SerializedMrfuAppLaunchPredictor predictor;
EXPECT_TRUE(predictor.FromProto(proto_));
EXPECT_THAT(predictor.Rank(),
UnorderedElementsAre(Pair(kTarget1, FloatEq(score1_ * decay)),
Pair(kTarget2, FloatEq(score2_))));
}
class HourAppLaunchPredictorTest : public testing::Test {
protected:
// Sets local time according to |day_of_week| and |hour_of_day|.
......
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