Переглянути джерело

feat:广告人群选择实验迭代

zhaohaipeng 4 місяців тому
батько
коміт
3405d65855

+ 21 - 0
ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/util/NumUtil.java

@@ -1,5 +1,9 @@
 package com.tzld.piaoquan.ad.engine.commons.util;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Arrays;
+
 public class NumUtil {
 
     public static double div(double d1, double d2) {
@@ -28,6 +32,23 @@ public class NumUtil {
         return 1 / (1 + Math.exp(-x));
     }
 
+    public static double round(double value, int newScale){
+        return new BigDecimal(value).setScale(newScale, RoundingMode.HALF_UP).doubleValue();
+    }
+
+    public static double[] softmax(double[] inputs) {
+        double max = Arrays.stream(inputs).max().orElse(0);
+        double[] expValues = Arrays.stream(inputs)
+                .map(x -> Math.exp(x - max)) // Subtract max to stabilize
+                .toArray();
+
+        double sum = Arrays.stream(expValues).sum();
+
+        return Arrays.stream(expValues)
+                .map(x -> x / sum)
+                .toArray();
+    }
+
     @SafeVarargs
     public static <T extends Comparable<T>> T min(T... values) {
         if (values == null || values.length == 0) {

+ 1 - 1
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/log/impl/LogHubServiceImpl.java

@@ -136,7 +136,7 @@ public class LogHubServiceImpl implements LogHubService {
                 logMap.put("allfeature", JSON.toJSONString(context.getLogParam().getAllFeature()));
                 logMap.put("metafeature", JSON.toJSONString(context.getLogParam().getMetaFeature()));
                 logMap.put("scoremap", JSON.toJSONString(context.getLogParam().getScoreMap()));
-
+                logMap.put("isNewUser", context.getLogParam().isBIsNewUser());
                 aliyunLogManager.sendLog(project, crowdChooseStatisticsLogStore, "", logMap);
             }
         });

+ 2 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/v2/PredictLogParam.java

@@ -25,4 +25,6 @@ public class PredictLogParam {
     private Map<String, Double> scoreMap = new HashMap<>();
 
     private boolean aIsShowAd;
+
+    private boolean bIsNewUser;
 }

+ 61 - 44
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/v2/PredictServiceV2.java

@@ -5,9 +5,11 @@ import com.tzld.piaoquan.ad.engine.commons.util.NumUtil;
 import com.tzld.piaoquan.ad.engine.service.feature.Feature;
 import com.tzld.piaoquan.ad.engine.service.feature.FeatureService;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.MapUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.text.DecimalFormat;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -25,31 +27,59 @@ public class PredictServiceV2 {
         Feature feature = featureService.getPredictFeature(context);
         Map<String, Map<String, String>> userFeature = feature.getUserFeature();
         Map<String, String> featureMap = userFeature.getOrDefault("alg_ad_crowd_choose_feature_v2", new HashMap<>());
-
-        double adViewCnt = Double.parseDouble(featureMap.getOrDefault("ad_view_cnt", "0"));
-        double adClick = Double.parseDouble(featureMap.getOrDefault("ad_click", "0"));
-        double adConver = Double.parseDouble(featureMap.getOrDefault("ad_conver", "0"));
-        double hasAdClick = Double.parseDouble(featureMap.getOrDefault("has_ad_click", "0"));
-        double hasAdShare = Double.parseDouble(featureMap.getOrDefault("has_ad_share", "0"));
-        double hasAdReturnCnt = Double.parseDouble(featureMap.getOrDefault("has_ad_return_cnt", "0"));
-        double noAdClick = Double.parseDouble(featureMap.getOrDefault("no_ad_click", "0"));
-        double noAdShare = Double.parseDouble(featureMap.getOrDefault("no_ad_share", "0"));
-        double noAdReturnCnt = Double.parseDouble(featureMap.getOrDefault("no_ad_return_cnt", "0"));
-
-        // 计算出回流出广告时的收益
-        double adClickValue = NumUtil.div(adClick, adViewCnt) * NumUtil.log10(adClick);
-        double adConverValue = NumUtil.div(adConver, adViewCnt) * NumUtil.log10(adConver);
-        double hasAdShareValue = NumUtil.div(hasAdShare, hasAdClick) * NumUtil.log10(hasAdShare);
-        double hasAdReturnValue = NumUtil.div(hasAdReturnCnt, hasAdClick) * NumUtil.log10(hasAdReturnCnt);
-        double hasAdValue = NumUtil.sigmoid(adClickValue + adConverValue + hasAdShareValue + hasAdReturnValue);
-
-        // 计算回流不出广告时的收益
-        double noAdShareValue = NumUtil.div(noAdShare, noAdClick) * NumUtil.log10(noAdShare);
-        double noAdReturnValue = NumUtil.div(noAdReturnCnt, noAdClick) * NumUtil.log10(noAdReturnCnt + hasAdReturnCnt);
-        double noAdValue = NumUtil.sigmoid(noAdShareValue + noAdReturnValue);
-
-        // 计算最终的收益
-        double score = NumUtil.div(hasAdValue, (hasAdValue + noAdValue));
+        double score = 0.8;
+
+        context.getLogParam().setBIsNewUser(true);
+
+        if (MapUtils.isNotEmpty(featureMap)) {
+
+            double noAdShareMin = exp713Config.getOrDefault((Object) "noAdShareMin", 5d);
+            double noShareReturnMin = exp713Config.getOrDefault("noShareReturnMin", 25d);
+
+            double adViewCnt = Double.parseDouble(featureMap.getOrDefault("ad_view_cnt", "0"));
+            double adClick = Double.parseDouble(featureMap.getOrDefault("ad_click", "0"));
+            double adConver = Double.parseDouble(featureMap.getOrDefault("ad_conver", "0"));
+            double hasAdClick = Double.parseDouble(featureMap.getOrDefault("has_ad_click", "0"));
+            double hasAdShare = Double.parseDouble(featureMap.getOrDefault("has_ad_share", "0"));
+            double hasAdReturnCnt = Double.parseDouble(featureMap.getOrDefault("has_ad_return_cnt", "0"));
+            double noAdClick = Double.parseDouble(featureMap.getOrDefault("no_ad_click", "0"));
+            double noAdShare = Double.parseDouble(featureMap.getOrDefault("no_ad_share", "0"));
+            double noAdReturnCnt = Double.parseDouble(featureMap.getOrDefault("no_ad_return_cnt", "0"));
+
+            // 计算出回流出广告时的收益
+            double adClickValue = NumUtil.div(adClick, adViewCnt) * NumUtil.log10(adClick);
+            double adConverValue = NumUtil.div(adConver, adViewCnt) * NumUtil.log10(adConver);
+            double hasAdShareValue = NumUtil.div(hasAdShare, hasAdClick) * NumUtil.log10(hasAdShare);
+            double hasAdReturnValue = NumUtil.div(hasAdReturnCnt, hasAdClick) * NumUtil.log10(hasAdReturnCnt);
+            double hasAdValue = adClickValue + adConverValue + hasAdShareValue + hasAdReturnValue;
+
+            // 计算回流不出广告时的收益
+            double noAdShareValue = NumUtil.div(noAdShare, noAdClick) * NumUtil.log10(noAdShare);
+            double noAdReturnValue = NumUtil.div(noAdReturnCnt, noAdClick) * NumUtil.log10(noAdReturnCnt + hasAdReturnCnt);
+            double noAdValue = noAdShareValue + noAdReturnValue;
+
+            // 计算最终的收益
+            score = NumUtil.softmax(new double[]{hasAdValue, noAdValue})[0];
+
+
+            context.getLogParam().setScore(score);
+            context.getLogParam().setExpId("713");
+            context.getLogParam().getMetaFeature().putAll(feature.getUserFeature());
+            for (Map.Entry<String, String> entry : featureMap.entrySet()) {
+                context.getLogParam().getAllFeature().put(entry.getKey(), Double.parseDouble(entry.getValue()));
+            }
+            context.getLogParam().getScoreMap().put("adClickValue", NumUtil.round(adClickValue, 6));
+            context.getLogParam().getScoreMap().put("adConverValue", NumUtil.round(adConverValue, 6));
+            context.getLogParam().getScoreMap().put("hasAdShareValue", NumUtil.round(hasAdShareValue, 6));
+            context.getLogParam().getScoreMap().put("hasAdReturnValue", NumUtil.round(hasAdReturnValue, 6));
+            context.getLogParam().getScoreMap().put("hasAdValue", NumUtil.round(hasAdValue, 6));
+            context.getLogParam().getScoreMap().put("noAdShareValue", NumUtil.round(noAdShareValue, 6));
+            context.getLogParam().getScoreMap().put("noAdReturnValue", NumUtil.round(noAdReturnValue, 6));
+            context.getLogParam().getScoreMap().put("noAdValue", NumUtil.round(noAdValue, 6));
+            context.getLogParam().getScoreMap().put("score", NumUtil.round(score, 6));
+
+            context.getLogParam().setBIsNewUser(false);
+        }
 
         // 分数截断,避免过长或过短
         double minScore = exp713Config.getOrDefault("minScore", 0.1d);
@@ -62,34 +92,20 @@ public class PredictServiceV2 {
 
         double random = Math.random();
         boolean isShowAd = random < score;
-
-        context.getLogParam().setScore(score);
-        context.getLogParam().setExpId("713");
-        context.getLogParam().getMetaFeature().putAll(feature.getUserFeature());
-        for (Map.Entry<String, String> entry : featureMap.entrySet()) {
-            context.getLogParam().getAllFeature().put(entry.getKey(), Double.parseDouble(entry.getValue()));
-        }
-        context.getLogParam().getScoreMap().put("adClickValue", adClickValue);
-        context.getLogParam().getScoreMap().put("adConverValue", adConverValue);
-        context.getLogParam().getScoreMap().put("hasAdShareValue", hasAdShareValue);
-        context.getLogParam().getScoreMap().put("hasAdReturnValue", hasAdReturnValue);
-        context.getLogParam().getScoreMap().put("hasAdValue", hasAdValue);
-        context.getLogParam().getScoreMap().put("noAdShareValue", noAdShareValue);
-        context.getLogParam().getScoreMap().put("noAdReturnValue", noAdReturnValue);
-        context.getLogParam().getScoreMap().put("noAdValue", noAdValue);
-        context.getLogParam().getScoreMap().put("score", score);
+        context.getLogParam().setAIsShowAd(isShowAd);
         context.getLogParam().getScoreMap().put("minScore", minScore);
         context.getLogParam().getScoreMap().put("maxScore", maxScore);
         context.getLogParam().getScoreMap().put("random", random);
-        context.getLogParam().setAIsShowAd(isShowAd);
 
-        return isShowAd ? rtnAdPredict(context) : rtnNoAdPredict();
+
+        return isShowAd ? rtnAdPredict(context) : rtnNoAdPredict(context);
     }
 
 
-    private Map<String, Object> rtnNoAdPredict() {
+    private Map<String, Object> rtnNoAdPredict(PredictContext context) {
         Map<String, Object> rtnMap = new HashMap<>();
         rtnMap.put("ad_predict", 1);
+        rtnMap.put("pqtid", context.getPqtId());
         rtnMap.put("no_ad_strategy", "713_exp");
         return rtnMap;
     }
@@ -97,6 +113,7 @@ public class PredictServiceV2 {
     private Map<String, Object> rtnAdPredict(PredictContext context) {
         Map<String, Object> rtnMap = new HashMap<>();
         rtnMap.put("ad_predict", 2);
+        rtnMap.put("pqtid", context.getPqtId());
         rtnMap.putAll(context.getLogParam().getScoreMap());
         return rtnMap;
     }