Predict user model based on genus


前言

To create an agent, four tasks need to be completed: predicting the opponent model, predicting the user model, how to bid, and accep the offer


1、preference elicitation

在这里插入图片描述

The Agent does not know the specific preferences of the User. We need to judge User’s preference by asking User what you like. Of course, User himself cannot tell you exactly which attribute he prefers and how much the corresponding evaluation is. For User, he can only tell you an “an ordinal ranking of outcomes”. It is User who gave you a bunch of offers. Assuming 10 offers, he can tell you the order of the utility of these 10 offers from small to large. But we don’t know what the specific user’s Utility space is.

2、Elicitation cost

At the beginning of each negotiation, you will get a bunch of offer rankings through the built-in API (through the getBidRanking() method, an index of 0 is the lowest bid.). The number of this ranking is limited. According to different scenarios, different numbers of bids can be obtained.

So, what if you want to get more bid rankings (some people have these needs, because the more bids, the more accurate your prediction of the User model will be)? You can additionally query a certain number of bids through the elicitRank method. But there will be a corresponding cost, which is called an elicitation cost, or a bother cost. The more you ask, the corresponding “consultation fee” will be deducted from your utility.

Personally, we basically do not need to conduct additional consultation. There are several reasons.

First of all, for many advanced algorithms, for example, you use machine learning algorithms or evolutionary algorithms, because the amount of calculation is relatively large. In many cases, the more bids you give me, the greater the amount of calculation. But the system basically only gives you one minute to calculate the User model. This creates a problem: in some cases where the domain is relatively large, the number of bids may be very large, close to 1500 (you can check the evaluation manual of agent negotiation, which mentions the upper limit of the highest number of bids ). Faced with so many bids ranking, in order to ensure that the calculation can be completed within the time frame set by the system, you may choose to remove many bids. In other words, I think the rink ranking obtained in the first consultation is sufficient, and there is no need to consult additional information, which will increase the cost.

Secondly, I think an algorithm like agent GG without additional consultation, despite its time complexity of 01, is still so robust. It is also explained on the side that there may be no need for additional consultation.

All in all, it’s not necessary to be able to use elicitRank.

3,loss function

The quality of the loss function determines the effect of your model. Sometimes, if you change the parameters a little bit, you will find that the result can be a qualitative leap. The parameter of this function is an AbstractUtilitySpace

First, we get a list of bids sorted by Utility from small to large through userModel.

In order to prevent userModel from giving too many bids, such as 1500, we need to filter some of them. I used a more common method, using the quantity range to filter out a part of bids. (As mentioned before, any algorithm that eats computing power may encounter this situation and cause the calculation to time out)

Now we assume that there are a total of 600 bids. We will use the getUtility(bid) method of the incoming AbstractUtilitySpace to calculate the predictive utility of these 600 bids.

Because these 600 bids have a new utility, we can sort them in ascending order. This way we get a new sort.

The new sorting and the sorting consulted from users will be obviously misaligned. For example, where the index is 0, it should be 100 originally, but the actual situation is that 100 is at the index 40, so the error is (0-40 ), at this time, you can choose to square the error and accumulate these errors to become the total error (MSE)

You can print the error of each iteration to judge whether the model is good, whether it converges fast or not, and even draw (I am trying)

Finally, iteratively optimize this loss function, the goal is to reduce the error.

 private double lossfunction(AbstractUtilitySpace abstractUtilitySpace){
    
    
        BidRanking bidRanking = userModel.getBidRanking();   //1. First take out the bidRanking list from userModel

        //First store bidRanking in a list. Otherwise, you can't get the value by index later.
        List<Bid> bidRankingStore=new ArrayList<>();
        for(Bid bid:bidRanking){
    
    
            bidRankingStore.add(bid);
        }

        //2. We need to write a bidList separately to store bidRanking to prevent excessive calculation.
        List<Bid> bidList =new ArrayList<>();

        //If the bid amount is less than 500
        if(bidRanking.getSize()<=500){
    
    
            for(Bid bid:bidRanking){
    
    
                bidList.add(bid);
            }
        }

        //if the bid amount between 500 and 2000
        else if(bidRanking.getSize()>500&&bidRanking.getSize()<2000){
    
    
            for(int i=0;i<bidRanking.getSize();i+=2){
    
    
                bidList.add(bidRankingStore.get(i));
            }
        }


        List<Double> utilityList=new ArrayList<>();
        for(Bid bid:bidList){
    
    
            utilityList.add(abstractUtilitySpace.getUtility(bid));  //Calculate the actual utility of each bidRanking in the current space. And put it in the utilityList.
        }                                                       //Note that the index of the utility list and the index of bidRanking are the same at this time. We need to use this to store in TreeMap



        TreeMap<Integer,Double> utilityRank=new TreeMap<>();   //Create a treeMap, one to store the current index, and one to store the corresponding index utility.

        for(int i=0;i<utilityList.size();i++){
    
       //Here we traverse the utility program, and store the index and utility in the TreeMap.
            utilityRank.put(i,utilityList.get(i));
        }

        // 4. At this time we need to sort according to the value of the TreeMap (the value is stored in the utility value)
        Comparator<Map.Entry<Integer,Double>> valueComparator = Comparator.comparingDouble(Map.Entry::getValue);
		 // map is converted to list for sorting
        List<Map.Entry<Integer,Double>> listRank = new ArrayList<>(utilityRank.entrySet());
        // sort
        Collections.sort(listRank, valueComparator);

        //Using the above method, TreeMap is now converted to List.
        //list look like this:[100=0.3328030236029489, 144=0.33843867914476017, 82=0.35366230775310603, 68=0.39994535024458255, 25=0.4407324473062739, 119=0.45895568095691974,
       
        int error=0;
        for(int i=0;i<listRank.size();i++){
    
    
            int gap=Math.abs(listRank.get(i).getKey()-i); 
            error+=gap*gap;
        }                                             

        System.out.println("Error:"+error);  //Monitor the size of the error in each iteration
        return error
    }

4,Randomly generate a UtilitySpace (weight set)

AdditiveUtilitySpaceFactory, generates a new UtilitySpace. Because the weights in these UtilitySpaces are all default, we need to randomly change these weights to ensure better initialization of the algorithm.

//Generate a random utility space
    private AbstractUtilitySpace Randominitial(){
    
    
        AdditiveUtilitySpaceFactory additiveUtilitySpaceFactory=new AdditiveUtilitySpaceFactory(userModel.getDomain());  //Get the domain under the current utilitySpace directly.
        List<Issue> issues=additiveUtilitySpaceFactory.getDomain().getIssues();
        for(Issue issue:issues){
    
    
            additiveUtilitySpaceFactory.setWeight(issue,random.nextDouble());    //Set the weight of each issue
            IssueDiscrete values=(IssueDiscrete) issue;       //Cast the issue to a collection of values
            for (Value value:values.getValues()){
    
                //Get each value through the values collection.
                additiveUtilitySpaceFactory.setUtility(issue,(ValueDiscrete)value,random.nextDouble());   //Because now is the cumulative utility space, after setting a weight randomly, you can set a utility to the current value, and the utility is random.
            }                                                                                            //When the utility is determined, the current value itself is also determined.

        }
        additiveUtilitySpaceFactory.normalizeWeights(); //Because the calculation of the utility value for each value was random before, at this time, it needs to be normalized.
        return  additiveUtilitySpaceFactory.getUtilitySpace();  //After generating a utility space, return to this utility space.
    }

5,梯度下降

猜你喜欢

转载自blog.csdn.net/qq_39297053/article/details/110007819
今日推荐