Exemple d'API d'apprentissage
Cette section contient un exemple d'implémentation d'ILearningInterface. Notez que cette implémentation est un simple exemple et n'est pas conçue pour être utilisée dans un environnement de production.
Cet exemple effectue le suivi des décomptes des acceptations et des contacts et utilise le ratio acceptations/contacts correspondant à une offre particulière pour calculer le taux de probabilité d'acceptation de l'offre. Les offres non présentées bénéficient d'une priorité de recommandation plus élevée. Les offres ayant au moins un contact doivent être classées en fonction du taux décroissant de probabilité d'acceptation.
Dans cet exemple, tous les décomptes sont conservés en mémoire. Il ne s'agit pas d'un scénario réaliste, car le serveur d'exécution n'aura pas assez de mémoire. Dans un scénario de production réel, les décomptes doivent être conservés dans une base de données.
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;

/**
* Ceci est un exemple d'implémentation de l'optimiseur d'apprentissage.
* L'interface ILearning se trouve dans la bibliothèque interact.jar.
*
* Pour utiliser cette implémentation, sélectionnez ExternalLearning comme optimizationType dans le noeud offerServing
* de l'application Interact dans la configuration Platform. Le noeud offerserving comporte aussi
* une catégorie de configuration External Learning dans laquelle vous devez définir le nom de la classe comme suit :
* com.unicacorp.interact.samples.learning.v2.SampleLearning. Veuillez noter toutefois que cette implémentation est un simple exemple
* n'est pas conçue pour être utilisée dans un environnement de production.
*
*
* Cet exemple effectue le suivi des décomptes des acceptations et des contacts et utilise le ratio acceptations/contacts
* correspondant à une offre particulière pour calculer le taux de probabilité d'acceptation de l'offre.
*
*
* Les offres non présentées bénéficient d'une priorité de recommandation plus élevée.
* Les offres ayant au moins un contact doivent être classées en fonction du taux décroissant de probabilité d'acceptation.
*
* Remarque : tous les décomptes sont conservés en mémoire. Il ne s'agit pas d'un scénario réaliste car la mémoire sera insuffisante
* à un moment donné. Dans un scénario de production réel, les décomptes doivent être conservés dans une base de données.
*
*/

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);

}
}

}