|
@@ -1,15 +1,15 @@
|
|
|
package com.tzld.piaoquan.recommend.server.service.score;
|
|
|
|
|
|
|
|
|
-
|
|
|
+import com.tzld.piaoquan.recommend.server.common.base.RankItem;
|
|
|
+import com.tzld.piaoquan.recommend.server.common.base.RequestContext;
|
|
|
import com.tzld.piaoquan.recommend.server.common.base.UserFeature;
|
|
|
-import com.tzld.piaoquan.recommend.server.common.base.VideoRankFeature;
|
|
|
import com.tzld.piaoquan.recommend.server.gen.recommend.RecommendRequest;
|
|
|
-import com.tzld.piaoquan.recommend.server.model.Video;
|
|
|
import com.tzld.piaoquan.recommend.server.service.rank.RankParam;
|
|
|
import com.tzld.piaoquan.recommend.server.service.recall.RecallResult;
|
|
|
-import com.tzld.piaoquan.recommend.server.service.score.feature.VlogShareFeatureExtractor;
|
|
|
+import com.tzld.piaoquan.recommend.server.service.score.feature.GBDTFeatureExtractorBase;
|
|
|
import com.tzld.piaoquan.recommend.server.service.score.model.GBDTModel;
|
|
|
+import com.tzld.piaoquan.recommend.server.model.Video;
|
|
|
import org.apache.commons.lang.exception.ExceptionUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
@@ -25,52 +25,127 @@ import java.util.concurrent.Executors;
|
|
|
import java.util.concurrent.Future;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
-
|
|
|
-public class FeedsShareLTRScorer extends BaseGBDTModelScorer{
|
|
|
+public class VlogShareGBDTScorer extends BaseGBDTModelScorer {
|
|
|
|
|
|
private final static int CORE_POOL_SIZE = 64;
|
|
|
private final static int TIME_OUT = 150;
|
|
|
- private final static Logger LOGGER = LoggerFactory.getLogger(FeedsShareLTRScorer.class);
|
|
|
+ private final static Logger LOGGER = LoggerFactory.getLogger(VlogShareGBDTScorer.class);
|
|
|
private final static ExecutorService executorService = Executors.newFixedThreadPool(CORE_POOL_SIZE);
|
|
|
+ private static final String VIMAGE_VIDEO_REC_TAG = "小视频";
|
|
|
|
|
|
- public FeedsShareLTRScorer(ScorerConfigInfo configInfo) {
|
|
|
-
|
|
|
+ public VlogShareGBDTScorer(ScorerConfigInfo configInfo) {
|
|
|
+ super(configInfo);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
private RequestContext getRequestContext(RecommendRequest request) {
|
|
|
|
|
|
+ RequestContext requestContext = new RequestContext();
|
|
|
+ return requestContext;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public List<Video> scoring(final RecommendRequest recommendRequest,
|
|
|
+ public List<RankItem> scoring(final RecommendRequest request,
|
|
|
final RankParam param,
|
|
|
- final RecallResult recallResult,
|
|
|
final UserFeature userFeature,
|
|
|
- final VideoRankFeature videoFeature) {
|
|
|
+ final List<RankItem> rankItems) {
|
|
|
+ RecallResult recallResult = param.getRecallResult();
|
|
|
+ if (recallResult.getData().size() == 0) {
|
|
|
+ return rankItems;
|
|
|
+ }
|
|
|
+
|
|
|
+ long startTime = System.currentTimeMillis();
|
|
|
+
|
|
|
+ GBDTModel model = (GBDTModel) this.getModel();
|
|
|
+ if (model == null) {
|
|
|
+ LOGGER.error("not found model");
|
|
|
+ return rankItems;
|
|
|
+ }
|
|
|
+ RequestContext requestContext = getRequestContext(request);
|
|
|
|
|
|
- feedsShareScore();
|
|
|
- Collections.sort();
|
|
|
- return items;
|
|
|
+ // 多Rank的rank打分
|
|
|
+ multipleGBDTScore(rankItems, model, userFeature, request, requestContext);
|
|
|
+ Collections.sort(rankItems);
|
|
|
+ LOGGER.debug("dwelltime ranker excute time: [{}]", System.currentTimeMillis() - startTime);
|
|
|
+ return rankItems;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 分数转换
|
|
|
+ *
|
|
|
+ * @param oldScore
|
|
|
+ * @param dwelltimeOrCompletion
|
|
|
+ * @param duration
|
|
|
+ * @param itemId
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private double predictMultipleGBDTScore(final double oldScore, final double dwelltimeOrCompletion,
|
|
|
+ final double duration, final String itemId,
|
|
|
+ final RecommendRequest requestData, final UserFeature user) {
|
|
|
+ double ctrScalePower = 0;
|
|
|
+ double dwelltimeScalePower = 0;
|
|
|
+
|
|
|
+ double ctrScore = oldScore;
|
|
|
+ if (oldScore <= 0.0) {
|
|
|
+ ctrScore = 0.01;
|
|
|
+ }
|
|
|
+ double newScore = Math.pow(ctrScore, ctrScalePower) * Math.pow(dwelltimeOrCompletion, dwelltimeScalePower);
|
|
|
+ //值越大压制越弱
|
|
|
+ double alpha = 1.0;
|
|
|
+ double suppressRatio = (1 + alpha) / (Math.max(duration, 300.0) / 300 + alpha);
|
|
|
+ newScore = newScore * suppressRatio;
|
|
|
+ LOGGER.debug("Expected dwell time score [{}]: {} ,{}, {}--> {}", new Object[]{itemId, oldScore, dwelltimeOrCompletion, duration, newScore});
|
|
|
+ return newScore;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void gbdtBaseScore(final Video item,
|
|
|
+ final GBDTModel model,
|
|
|
+ final RequestContext requestContext,
|
|
|
+ final Map<String, Double> userFeatures,
|
|
|
+ final Map<String, Double> contextFeatures,
|
|
|
+ final RecommendRequest requestData, final UserFeature user) {
|
|
|
+ try {
|
|
|
+
|
|
|
+ Map<String, Double> articleFeatures;
|
|
|
+ double freshness;
|
|
|
+ Map<String, Double> features;
|
|
|
+ features = GBDTFeatureExtractorBase.extractUserFeatures(user);
|
|
|
|
|
|
+ if (model != null) {
|
|
|
+ Map<String, Double> featureScoreMap = new HashMap<String, Double>();
|
|
|
+ double pro = model.score(features, featureScoreMap);
|
|
|
+ featureScoreMap.put("TOTAL_SCORE", pro);
|
|
|
+ pro = pro > 1 ? pro : 1;
|
|
|
+ Double rankScore = item.getRankScore();
|
|
|
+ LOGGER.debug("xgb score = {}, lgb score = {}", rankScore, pro);
|
|
|
+ double lgbWeight = 1.0;
|
|
|
+ pro = (rankScore + lgbWeight * pro) / (1.0 + lgbWeight);
|
|
|
+ item.setRankScore(pro);
|
|
|
+ }
|
|
|
|
|
|
- public void feedsShareScore(final List<Video> items,
|
|
|
+ } catch (Exception e) {
|
|
|
+ LOGGER.error("Exception {},{}", requestContext, ExceptionUtils.getFullStackTrace(e));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public void multipleGBDTScore(final List<Video> items,
|
|
|
final GBDTModel model,
|
|
|
final UserFeature user,
|
|
|
- final RecommendRequest requestData) {
|
|
|
+ final RecommendRequest requestData,
|
|
|
+ final RequestContext requestContext) {
|
|
|
final int size = items.size();
|
|
|
if (size == 0) {
|
|
|
return;
|
|
|
}
|
|
|
+
|
|
|
final Map<String, Double> userFeatures;
|
|
|
final Map<String, Double> contextFeatures;
|
|
|
|
|
|
-
|
|
|
// context feature
|
|
|
- contextFeatures = VlogShareFeatureExtractor.extractContextFeatures(requestContext);
|
|
|
+ contextFeatures = GBDTFeatureExtractorBase.extractRequestContextFeatures(requestContext);
|
|
|
// user feature
|
|
|
- userFeatures = VlogShareFeatureExtractor.extractUserFeatures();
|
|
|
+ userFeatures = GBDTFeatureExtractorBase.extractUserFeatures(user);
|
|
|
|
|
|
// score item
|
|
|
List<Callable<Object>> callables = new ArrayList<Callable<Object>>();
|
|
@@ -80,9 +155,9 @@ public class FeedsShareLTRScorer extends BaseGBDTModelScorer{
|
|
|
@Override
|
|
|
public Object call() throws Exception {
|
|
|
try {
|
|
|
- dwelltimeScore(items.get(fIndex), model, requestContext, userFeatures, contextFeatures, requestData, user);
|
|
|
+ gbdtBaseScore(items.get(fIndex), model, requestContext, userFeatures, contextFeatures, requestData, user);
|
|
|
} catch (Exception e) {
|
|
|
- LOGGER.error("dwelltime exception: [{}] [{}]", items.get(fIndex).getId(), ExceptionUtils.getFullStackTrace(e));
|
|
|
+ LOGGER.error("dwelltime exception: [{}] [{}]", items.get(fIndex), ExceptionUtils.getFullStackTrace(e));
|
|
|
}
|
|
|
return new Object();
|
|
|
}
|
|
@@ -103,7 +178,7 @@ public class FeedsShareLTRScorer extends BaseGBDTModelScorer{
|
|
|
try {
|
|
|
if (future != null && future.isDone() && !future.isCancelled() && future.get() != null) {
|
|
|
} else {
|
|
|
- LOGGER.debug("Canceled Dwelltime Score {}", requestContext.getId());
|
|
|
+ LOGGER.debug("Canceled Dwelltime Score {}", requestContext);
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
LOGGER.error("InterruptedException {},{}", ExceptionUtils.getFullStackTrace(e));
|
|
@@ -111,65 +186,5 @@ public class FeedsShareLTRScorer extends BaseGBDTModelScorer{
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // GBDT计算score
|
|
|
- private void shareScore(final RankerItem item,
|
|
|
- final GBDTModel model,
|
|
|
- final RequestContext requestContext,
|
|
|
- final Map<String, Double> userFeatures,
|
|
|
- final Map<String, Double> contextFeatures,
|
|
|
- final int debugLevel,
|
|
|
- final RecommendRequest requestData, final User user) {
|
|
|
- try {
|
|
|
- //judge null
|
|
|
- if (item == null || item.getItemInfo() == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- ArticleInfo articleInfo = (ArticleInfo) item.getItemInfo();
|
|
|
-
|
|
|
- Map<String, Double> articleFeatures;
|
|
|
- double freshness;
|
|
|
- Map<String, Double> features;
|
|
|
- articleFeatures = DurationFeatureExtractor.extractArticleFeatures(articleInfo);
|
|
|
-
|
|
|
-
|
|
|
- if (model != null) {
|
|
|
- Map<String, Double> featureScoreMap = new HashMap<String, Double>();
|
|
|
- double pro = model.score(features, featureScoreMap, debugLevel);
|
|
|
- featureScoreMap.put("TOTAL_SCORE", pro);
|
|
|
-
|
|
|
- pro = pro > 1 ? pro : 1;
|
|
|
- LOGGER.debug("xgb score = {}, lgb score = {}", item.getDwelltimeScore(), pro);
|
|
|
-
|
|
|
- double lgbWeight = Configuration.getDouble("mivideo-recommend-service.dwelltime_ranker.lgb.weight", 1.0);
|
|
|
- pro = (item.getDwelltimeScore() + lgbWeight * pro) / (1.0 + lgbWeight);
|
|
|
- item.setDwelltimeScore(pro);
|
|
|
- double duration = 0;
|
|
|
- if(item.getItemInfo() != null) {
|
|
|
- duration = ((ArticleInfo) item.getItemInfo()).getDuration();
|
|
|
- }
|
|
|
- duration = Math.min(Math.max(duration, 1), 1800);
|
|
|
- item.setScore(predictDwelltimeScore(item.getRecScore(), pro, duration, item.getId(), requestData, user));
|
|
|
- }
|
|
|
-
|
|
|
- } catch (Exception e) {
|
|
|
- LOGGER.error("Exception {},{}", requestContext.getId(), ExceptionUtils.getFullStackTrace(e));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
+
|