学習 API の例
このセクションには、ILearningInterface の実装例が含まれています。 この実装は単なる例であり、実稼働環境で使用するためのものではないことに注意してください。
以下の例では、受け入れおよびコンタクトの件数をトラッキングし、特定のオファーの受け入れとコンタクトの比率をオファーの受け入れ確立比として使用します。例には示されていませんが、より優先度の高い推奨オファーがあります。少なくとも 1 つのコンタクトを含むオファーが、降順の受け入れ確立比に基づいて配列されています。
以下の例では、すべての件数がメモリー内に保持されています。これは、ランタイム・サーバーでメモリー不足が発生するため、現実的なシナリオではありません。現実の実動シナリオでは、カウントをデータベース内に保持しなければなりません。
package com.unicacorp.interact.samples.learning.v2;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.unicacorp.interact.samples.learning.SampleOptimizer.MyOfferSorter;
import com.unicacorp.interact.treatment.optimization.IClientArgs;
import com.unicacorp.interact.treatment.optimization.IInteractSession;
import com.unicacorp.interact.treatment.optimization.ILearningConfig;
import com.unicacorp.interact.treatment.optimization.ILearningContext;
import com.unicacorp.interact.treatment.optimization.IOffer;
import com.unicacorp.interact.treatment.optimization.LearningException;
import com.unicacorp.interact.treatment.optimization.v2.ILearning;
import com.unicacorp.interact.treatment.optimization.v2.ITreatment;

/**
* This is a sample implementation of the learning optimizer.
* The interface ILearning may be found in the interact.jar library.
*
* To actually use this implementation, select ExternalLearning as the optimizationType in the offerServing node
* of the Interact application within the Platform configuration. Within the offerserving node there is also
* an External Learning config category - within there you must set the name of the class to this:
* com.unicacorp.interact.samples.learning.v2.SampleLearning. Please note however, this implementation is just a sample
* and was not designed to be used in a production environment.
*
*
* This example keeps track of accept and contact counts and uses the ratio of accept to contacts
* for a particular offer as the acceptance probability rate for the offer.
*
*
* Offers not presented will get higher priority for recommending.
* Offers with at least one contact will be ordered based on descending acceptance probability rate.
*
* Note: all counts are kept in memory. This is not a realistic scenario since you would run out of memory sooner or
* later. In a real production scenario, the counts should be persisted into a database.
*
*/

public class SampleLearning implements ILearning
{

// A map of offer ids to contact count for the offer id
private Map<Long,Integer> _offerToContactCount = new HashMap<Long, Integer>();

// A map of offer ids to contact count for the offer id
private Map<Long,Integer> _offerToAcceptCount = new HashMap<Long, Integer>();


/* (non-Javadoc)
* @see com.unicacorp.interact.treatment.optimization.v2.ILearning#initialize
* (com.unicacorp.interact.treatment.optimization.v2.ILearningConfig, boolean)
*/
public void initialize(ILearningConfig config, boolean debug) throws LearningException
{
// If any remote connections are required, this is a good place to initialize those connections as this
// method is called once at the start of the interact runtime webapp.
// This example does not have any remote connections and prints for debugging purposes that this method will
// be called
System.out.println("Calling initialize for SampleLearning");
}

/* (non-Javadoc)
* @see com.unicacorp.interact.treatment.optimization.v2.ILearning#reinitialize
* (com.unicacorp.interact.treatment.optimization.v2.ILearningConfig, boolean)
*/
public void reinitialize(ILearningConfig config, boolean debug) throws LearningException
{
// If an IC is deployed, this reinitialize method is called to allow the implementation to
// refresh any updated configuration settings
System.out.println("Calling reinitialize for SampleLearning");
}


/* (non-Javadoc)
* @see com.unicacorp.interact.treatment.optimization.v2.ILearning#logEvent
* (com.unicacorp.interact.treatment.optimization.v2.ILearningContext,
* com.unicacorp.interact.treatment.optimization.v2.IOffer,
* com.unicacorp.interact.treatment.optimization.v2.IClientArgs,
* com.unicacorp.interact.treatment.optimization.IInteractSession, boolean)
*/
public void logEvent(ILearningContext context, IOffer offer, IClientArgs clientArgs,
IInteractSession session, boolean debug) throws LearningException
{
System.out.println("Calling logEvent for SampleLearning");


if(context.getLearningContext()==ILearningContext.LOG_AS_CONTACT)
{
System.out.println("adding contact");

// Keep track of all contacts in memory
synchronized(_offerToAcceptCount)
{
Integer count = _offerToAcceptCount.get(offer.getOfferId());
if(count == null)
count = new Integer(1);
else
count++;
_offerToAcceptCount.put(offer.getOfferId(), ++count);
}

}
else if(context.getLearningContext()==ILearningContext.LOG_AS_ACCEPT)
{
System.out.println("adding accept");
// Keep track of all accept counts in memory by adding to the map
synchronized(_offerToAcceptCount)
{
Integer count = _offerToAcceptCount.get(offer.getOfferId());
if(count == null)
count = new Integer(1);
else
count++;
_offerToAcceptCount.put(offer.getOfferId(), ++count);
}
}

}

/* (non-Javadoc)
* @see com.unicacorp.interact.treatment.optimization.v2.ILearning#optimizeRecommendList
* (java.util.List, com.unicacorp.interact.treatment.optimization.v2.IClientArgs,
* com.unicacorp.interact.treatment.optimization.IInteractSession, boolean)
*/
public List<ITreatment> optimizeRecommendList(List<ITreatment> recList,
IClientArgs clientArgs, IInteractSession session, boolean debug)
throws LearningException
{
System.out.println("Calling optimizeRecommendList for SampleLearning");

// Sort the candidate treatments by calling the sorter defined in this class and return the sorted list
Collections.sort(recList,new MyOfferSorter());

// now just return what was asked for via "numberRequested" variable
List<ITreatment> result = new ArrayList<ITreatment>();

for(int x=0;x<(Integer)clientArgs.getValue(IClientArgs.NUMBER_OF_OFFERS_REQUESTED) && x<recList.size();x++)
{
result.add(recList.get(x));
}
return result;
}

/* (non-Javadoc)
* @see com.unicacorp.interact.treatment.optimization.v2.ILearning#shutdown
* (com.unicacorp.interact.treatment.optimization.v2.ILearningConfig, boolean)
*/
public void shutdown(ILearningConfig config, boolean debug) throws LearningException
{
// If any remote connections exist, this would be a good place to gracefully
// disconnect from them as this method is called at the shutdown of the Interact runtime
// webapp. For this example, there is nothing really to do
// except print out a statement for debugging.
System.out.println("Calling shutdown for SampleLearning");

}
// Sort by:
// 1. offers with zero contacts - for ties, order is based on original input
// 2. descending accept probability rate - for ties, order is based on original input

public class MyOfferSorter implements Comparator<ITreatment>
{
private static final long serialVersionUID = 1L;

/* (non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
public int compare(ITreatment treatment1, ITreatment treatment2)
{

// get contact count for both treatments
Integer contactCount1 = _offerToContactCount.get(treatment1.getOffer().getOfferId());
Integer contactCount2 = _offerToContactCount.get(treatment2.getOffer().getOfferId());

// if treatment hasn't been contacted, then that wins
if(contactCount1 == null || contactCount1 == 0)
return -1;

if(contactCount2 == null || contactCount2 == 0)
return 1;

// get accept counts
Integer acceptCount1 = _offerToAcceptCount.get(treatment1.getOffer().getOfferId());
Integer acceptCount2 = _offerToAcceptCount.get(treatment2.getOffer().getOfferId());

float acceptProbability1 = (float) acceptCount1 / (float) contactCount1;
float acceptProbability2 = (float) acceptCount2 / (float) contactCount2;

// descending order
return (int) (acceptProbability2 - acceptProbability1);

}
}

}