removed timestamp from event id
This commit is contained in:
Родитель
d591682f76
Коммит
64cfb9bd25
|
@ -33,6 +33,7 @@
|
|||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<DocumentationFile>..\bin\AnyCPU\Release\Microsoft.Research.MultiWorldTesting.ExploreLibrary.XML</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BaseExplorer.cs" />
|
||||
|
@ -55,12 +56,15 @@
|
|||
<Compile Include="MultiActionHelper.cs" />
|
||||
<Compile Include="TopSlotExplorer.cs" />
|
||||
<Compile Include="UniformRandomExploration.cs" />
|
||||
<Compile Include="UniqueEventID.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="GitLink, Version=2.2.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\gitlink.2.2.0\lib\net45\GitLink.exe</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace Microsoft.Research.MultiWorldTesting.ExploreLibrary
|
|||
/// <param name="uniqueKey">A user-defined identifer for the decision.</param>
|
||||
/// <param name="modelId">Optional; The Id of the model used to make predictions/decisions, if any exists at decision time.</param>
|
||||
/// <param name="isExplore">Optional; Indicates whether the decision was generated purely from exploration (vs. exploitation).</param>
|
||||
void Record(TContext context, TAction value, object explorerState, object mapperState, UniqueEventID uniqueKey);
|
||||
void Record(TContext context, TAction value, object explorerState, object mapperState, string uniqueKey);
|
||||
}
|
||||
|
||||
public interface IExplorer<TAction, TPolicyValue>
|
||||
|
|
|
@ -111,6 +111,13 @@ namespace Microsoft.Research.MultiWorldTesting.ExploreLibrary
|
|||
}
|
||||
}
|
||||
|
||||
public TAction ChooseAction(string uniqueKey, TContext context, IContextMapper<TContext, TPolicyValue> defaultPolicy)
|
||||
{
|
||||
var policy = this.Policy;
|
||||
var policyDecision = (policy ?? defaultPolicy).MapContext(context);
|
||||
return ChooseActionInternal(uniqueKey, context, policyDecision);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Choose an action (or decision to take) given the exploration algorithm and context.
|
||||
/// </summary>
|
||||
|
@ -119,46 +126,35 @@ namespace Microsoft.Research.MultiWorldTesting.ExploreLibrary
|
|||
/// <param name="context">The context upon which a decision is made. See SimpleContext above for an example.</param>
|
||||
/// <param name="numActionsVariable">Optional; Number of actions available which may be variable across decisions.</param>
|
||||
/// <returns>An unsigned 32-bit integer representing the 1-based chosen action.</returns>
|
||||
public TAction ChooseAction(UniqueEventID uniqueKey, TContext context, TAction initialAction)
|
||||
public TAction ChooseAction(string uniqueKey, TContext context, TPolicyValue defaultPolicyDecision)
|
||||
{
|
||||
// Note: thread-safe atomic reference access
|
||||
var policy = this.Policy;
|
||||
if (policy == null)
|
||||
{
|
||||
// policy not ready & initial action provided
|
||||
this.Log(uniqueKey,
|
||||
context,
|
||||
ExplorerDecision.Create(initialAction, new GenericExplorerState { Probability = 1 }, true));
|
||||
|
||||
return initialAction;
|
||||
}
|
||||
|
||||
ulong saltedSeed = MurMurHash3.ComputeIdHash(uniqueKey.Key) + this.appId;
|
||||
PRG random = new PRG(saltedSeed);
|
||||
|
||||
var policyDecision = policy.MapContext(context);
|
||||
var explorerDecision = this.Explorer.MapContext(random, policyDecision.Value, this.numActionsProvider.GetNumberOfActions(context));
|
||||
|
||||
this.Log(uniqueKey, context, explorerDecision, policyDecision);
|
||||
|
||||
return explorerDecision.Value;
|
||||
var policyDecision = (policy != null) ? policy.MapContext(context) : defaultPolicyDecision;
|
||||
return ChooseActionInternal(uniqueKey, context, policyDecision);
|
||||
}
|
||||
|
||||
public TAction ChooseAction(UniqueEventID uniqueKey, TContext context)
|
||||
public TAction ChooseAction(string uniqueKey, TContext context)
|
||||
{
|
||||
ulong saltedSeed = MurMurHash3.ComputeIdHash(uniqueKey.Key) + this.appId;
|
||||
ulong saltedSeed = MurMurHash3.ComputeIdHash(uniqueKey) + this.appId;
|
||||
PRG random = new PRG(saltedSeed);
|
||||
|
||||
var policy = this.Policy;
|
||||
ExplorerDecision<TAction> explorerDecision;
|
||||
PolicyDecision<TPolicyValue> policyDecision = null;
|
||||
|
||||
int numActionsVariable = this.numActionsProvider.GetNumberOfActions(context);
|
||||
if (numActionsVariable <= 0)
|
||||
{
|
||||
throw new Exception("Could not determine number of actions from the provided context.");
|
||||
}
|
||||
|
||||
if (policy == null)
|
||||
explorerDecision = this.InitialExplorer.Explore(random, this.numActionsProvider.GetNumberOfActions(context));
|
||||
explorerDecision = this.InitialExplorer.Explore(random, numActionsVariable);
|
||||
else
|
||||
{
|
||||
policyDecision = policy.MapContext(context);
|
||||
explorerDecision = this.Explorer.MapContext(random, policyDecision.Value, this.numActionsProvider.GetNumberOfActions(context));
|
||||
explorerDecision = this.Explorer.MapContext(random, policyDecision.Value, numActionsVariable);
|
||||
}
|
||||
|
||||
this.Log(uniqueKey, context, explorerDecision, policyDecision != null ? policyDecision.MapperState : null);
|
||||
|
@ -166,14 +162,6 @@ namespace Microsoft.Research.MultiWorldTesting.ExploreLibrary
|
|||
return explorerDecision.Value;
|
||||
}
|
||||
|
||||
private void Log(UniqueEventID uniqueKey, TContext context, ExplorerDecision<TAction> explorerDecision, object policyState = null)
|
||||
{
|
||||
if (explorerDecision.ShouldRecord)
|
||||
{
|
||||
this.recorder.Record(context, explorerDecision.Value, explorerDecision.ExplorerState, policyState, uniqueKey);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
|
@ -183,6 +171,32 @@ namespace Microsoft.Research.MultiWorldTesting.ExploreLibrary
|
|||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private TAction ChooseActionInternal(string uniqueKey, TContext context, PolicyDecision<TPolicyValue> policyDecision)
|
||||
{
|
||||
ulong saltedSeed = MurMurHash3.ComputeIdHash(uniqueKey) + this.appId;
|
||||
PRG random = new PRG(saltedSeed);
|
||||
|
||||
int numActionsVariable = this.numActionsProvider.GetNumberOfActions(context);
|
||||
if (numActionsVariable <= 0)
|
||||
{
|
||||
throw new Exception("Could not determine number of actions from the provided context.");
|
||||
}
|
||||
|
||||
var explorerDecision = this.Explorer.MapContext(random, policyDecision.Value, numActionsVariable);
|
||||
|
||||
this.Log(uniqueKey, context, explorerDecision, policyDecision);
|
||||
|
||||
return explorerDecision.Value;
|
||||
}
|
||||
|
||||
private void Log(string uniqueKey, TContext context, ExplorerDecision<TAction> explorerDecision, object policyState = null)
|
||||
{
|
||||
if (explorerDecision.ShouldRecord)
|
||||
{
|
||||
this.recorder.Record(context, explorerDecision.Value, explorerDecision.ExplorerState, policyState, uniqueKey);
|
||||
}
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
|
|
|
@ -26,5 +26,5 @@ using System.Runtime.InteropServices;
|
|||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.3")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.3")]
|
||||
[assembly: AssemblyVersion("1.0.0.4")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.4")]
|
||||
|
|
|
@ -25,11 +25,11 @@ namespace Microsoft.Research.MultiWorldTesting.ExploreLibrary.SingleAction
|
|||
/// <param name="action">Chosen by an exploration algorithm given context.</param>
|
||||
/// <param name="probability">The probability of the chosen action given context.</param>
|
||||
/// <param name="uniqueKey">A user-defined identifer for the decision.</param>
|
||||
public void Record(TContext context, int value, object explorerState, object mapperState, UniqueEventID uniqueKey)
|
||||
public void Record(TContext context, int value, object explorerState, object mapperState, string uniqueKey)
|
||||
{
|
||||
recordingBuilder.Append(value.ToString(CultureInfo.InvariantCulture));
|
||||
recordingBuilder.Append(' ');
|
||||
recordingBuilder.Append(uniqueKey.Key);
|
||||
recordingBuilder.Append(uniqueKey);
|
||||
recordingBuilder.Append(' ');
|
||||
|
||||
recordingBuilder.Append(((GenericExplorerState)explorerState).Probability.ToString("0.00000", CultureInfo.InvariantCulture));
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Microsoft.Research.MultiWorldTesting.ExploreLibrary
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a unique identifier for an event.
|
||||
/// </summary>
|
||||
public class UniqueEventID
|
||||
{
|
||||
/// <summary>
|
||||
/// The key for the event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This key is used as a seed to the randomization, which
|
||||
/// ensures consistent experience within same event, but
|
||||
/// random across events.
|
||||
/// </remarks>
|
||||
public string Key { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The time stamp of the event which, together with the key,
|
||||
/// uniquely identify an event. Events with same key
|
||||
/// must have the same time stamp.
|
||||
/// </summary>
|
||||
public DateTime TimeStamp { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="8.0.2" targetFramework="net45" />
|
||||
<package id="gitlink" version="2.2.0" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net45" />
|
||||
</packages>
|
|
@ -20,7 +20,7 @@ namespace cs_test
|
|||
/// </summary>
|
||||
class MyRecorder : IRecorder<MyContext, int>
|
||||
{
|
||||
public void Record(MyContext context, int value, object explorerState, object mapperState, UniqueEventID uniqueKey)
|
||||
public void Record(MyContext context, int value, object explorerState, object mapperState, string uniqueKey)
|
||||
{
|
||||
// Stores the tuple internally in a vector that could be used later for other purposes.
|
||||
interactions.Add(new Interaction<MyContext>()
|
||||
|
@ -28,7 +28,7 @@ namespace cs_test
|
|||
Context = context,
|
||||
Action = (uint)value,
|
||||
Probability = ((GenericExplorerState)explorerState).Probability,
|
||||
UniqueKey = uniqueKey.Key
|
||||
UniqueKey = uniqueKey
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ namespace cs_test
|
|||
// Performs exploration by passing an instance of the Epsilon-Greedy exploration algorithm into MwtExplorer
|
||||
// using a sample string to uniquely identify this event
|
||||
string uniqueKey = "eventid";
|
||||
int action = mwtt.ChooseAction(new UniqueEventID { Key = uniqueKey, TimeStamp = DateTime.UtcNow }, context);
|
||||
int action = mwtt.ChooseAction(uniqueKey, context);
|
||||
|
||||
Console.WriteLine(recorder.GetRecording());
|
||||
|
||||
|
@ -151,7 +151,7 @@ namespace cs_test
|
|||
//MwtExplorer<MyContext> mwtt = new MwtExplorer<MyContext>("mwt", recorder);
|
||||
var mwtt = MwtExplorer.Create("mwt", numActions, recorder, new TauFirstExplorer(tau), new MyPolicy());
|
||||
|
||||
int action = mwtt.ChooseAction(new UniqueEventID { Key = "key", TimeStamp = DateTime.UtcNow }, new MyContext());
|
||||
int action = mwtt.ChooseAction("key", new MyContext());
|
||||
Console.WriteLine(String.Join(",", recorder.GetAllInteractions().Select(it => it.Action)));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -315,7 +315,7 @@ namespace BlackBoxTests
|
|||
|
||||
for (int i = 0; i < experimentalUnitIdList.Length; i++)
|
||||
{
|
||||
mwt.ChooseAction(new UniqueEventID { Key = experimentalUnitIdList[i] }, contextList[i]);
|
||||
mwt.ChooseAction(experimentalUnitIdList[i], contextList[i]);
|
||||
}
|
||||
|
||||
File.AppendAllText(outputFile, recorder.GetRecording());
|
||||
|
@ -358,7 +358,7 @@ namespace BlackBoxTests
|
|||
for (int i = 0; i < experimentalUnitIdList.Length; i++)
|
||||
{
|
||||
int numActionsVariable = isVariableActionContext ? ((IVariableActionContext)contextList[i]).GetNumberOfActions() : int.MaxValue;
|
||||
mwt.ChooseAction(new UniqueEventID { Key = experimentalUnitIdList[i] }, contextList[i]);
|
||||
mwt.ChooseAction(experimentalUnitIdList[i], contextList[i]);
|
||||
}
|
||||
|
||||
File.AppendAllText(outputFile, recorder.GetRecording());
|
||||
|
@ -401,7 +401,7 @@ namespace BlackBoxTests
|
|||
for (int i = 0; i < experimentalUnitIdList.Length; i++)
|
||||
{
|
||||
int numActionsVariable = isVariableActionContext ? ((IVariableActionContext)contextList[i]).GetNumberOfActions() : int.MaxValue;
|
||||
mwt.ChooseAction(new UniqueEventID { Key = experimentalUnitIdList[i] }, contextList[i]);
|
||||
mwt.ChooseAction(experimentalUnitIdList[i], contextList[i]);
|
||||
}
|
||||
|
||||
File.AppendAllText(outputFile, recorder.GetRecording());
|
||||
|
@ -422,7 +422,7 @@ namespace BlackBoxTests
|
|||
for (int i = 0; i < experimentalUnitIdList.Length; i++)
|
||||
{
|
||||
int numActionsVariable = isVariableActionContext ? ((IVariableActionContext)contextList[i]).GetNumberOfActions() : int.MaxValue;
|
||||
mwt.ChooseAction(new UniqueEventID { Key = experimentalUnitIdList[i] }, contextList[i]);
|
||||
mwt.ChooseAction(experimentalUnitIdList[i], contextList[i]);
|
||||
}
|
||||
|
||||
File.AppendAllText(outputFile, recorder.GetRecording());
|
||||
|
@ -464,7 +464,7 @@ namespace BlackBoxTests
|
|||
for (int i = 0; i < experimentalUnitIdList.Length; i++)
|
||||
{
|
||||
int numActionsVariable = isVariableActionContext ? ((IVariableActionContext)contextList[i]).GetNumberOfActions() : int.MaxValue;
|
||||
mwt.ChooseAction(new UniqueEventID { Key = experimentalUnitIdList[i] }, contextList[i]);
|
||||
mwt.ChooseAction(experimentalUnitIdList[i], contextList[i]);
|
||||
}
|
||||
|
||||
File.AppendAllText(outputFile, recorder.GetRecording());
|
||||
|
@ -486,7 +486,7 @@ namespace BlackBoxTests
|
|||
for (int i = 0; i < experimentalUnitIdList.Length; i++)
|
||||
{
|
||||
int numActionsVariable = isVariableActionContext ? ((IVariableActionContext)contextList[i]).GetNumberOfActions() : int.MaxValue;
|
||||
mwt.ChooseAction(new UniqueEventID { Key = experimentalUnitIdList[i] }, contextList[i]);
|
||||
mwt.ChooseAction(experimentalUnitIdList[i], contextList[i]);
|
||||
}
|
||||
|
||||
File.AppendAllText(outputFile, recorder.GetRecording());
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace ExploreTests.SingleAction
|
|||
where TContext : RegularTestContext
|
||||
{
|
||||
string uniqueKey = "ManagedTestId";
|
||||
var uniqueId = new UniqueEventID { Key = uniqueKey, TimeStamp = DateTime.UtcNow };
|
||||
var uniqueId = uniqueKey;
|
||||
TestRecorder<TContext> recorder = new TestRecorder<TContext>();
|
||||
//MwtExplorer<TContext> mwtt = new MwtExplorer<TContext>("mwt", recorder);
|
||||
var mwtt = MwtExplorer.Create("mwt", numActions, recorder, explorer, policy);
|
||||
|
@ -98,7 +98,7 @@ namespace ExploreTests.SingleAction
|
|||
where TContext : RegularTestContext
|
||||
{
|
||||
string uniqueKey = "ManagedTestId";
|
||||
var uniqueId = new UniqueEventID { Key = uniqueKey, TimeStamp = DateTime.UtcNow };
|
||||
var uniqueId = uniqueKey;
|
||||
|
||||
var recorder = new TestRecorder<TContext>();
|
||||
|
||||
|
@ -240,7 +240,7 @@ namespace ExploreTests.SingleAction
|
|||
Random rand = new Random();
|
||||
for (uint i = 0; i < contexts.Length; i++)
|
||||
{
|
||||
var uniqueId = new UniqueEventID { Key = rand.NextDouble().ToString(), TimeStamp = DateTime.UtcNow };
|
||||
var uniqueId = rand.NextDouble().ToString();
|
||||
int chosenAction = mwtt.ChooseAction(uniqueId, contexts[i]);
|
||||
actions[chosenAction - 1]++; // action id is one-based
|
||||
}
|
||||
|
@ -273,9 +273,9 @@ namespace ExploreTests.SingleAction
|
|||
var mwtt = MwtExplorer.Create("mwt", numActions, recorder, explorer, scorer);
|
||||
|
||||
Random rand = new Random();
|
||||
mwtt.ChooseAction(new UniqueEventID { Key = rand.NextDouble().ToString() }, new RegularTestContext() { Id = 100 });
|
||||
mwtt.ChooseAction(new UniqueEventID { Key = rand.NextDouble().ToString() }, new RegularTestContext() { Id = 101 });
|
||||
mwtt.ChooseAction(new UniqueEventID { Key = rand.NextDouble().ToString() }, new RegularTestContext() { Id = 102 });
|
||||
mwtt.ChooseAction(rand.NextDouble().ToString(), new RegularTestContext() { Id = 100 });
|
||||
mwtt.ChooseAction(rand.NextDouble().ToString(), new RegularTestContext() { Id = 101 });
|
||||
mwtt.ChooseAction(rand.NextDouble().ToString(), new RegularTestContext() { Id = 102 });
|
||||
|
||||
var interactions = recorder.GetAllInteractions();
|
||||
|
||||
|
@ -305,7 +305,7 @@ namespace ExploreTests.SingleAction
|
|||
explorer.EnableExplore(false);
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
int chosenAction = mwtt.ChooseAction(new UniqueEventID { Key = rand.NextDouble().ToString() }, new RegularTestContext() { Id = (int)i });
|
||||
int chosenAction = mwtt.ChooseAction(rand.NextDouble().ToString(), new RegularTestContext() { Id = (int)i });
|
||||
Assert.AreEqual(highestScoreAction, chosenAction);
|
||||
}
|
||||
}
|
||||
|
@ -339,7 +339,7 @@ namespace ExploreTests.SingleAction
|
|||
//var mwtt = new MwtExplorer<TContext>("mwt", recorder);
|
||||
var mwtt = MwtExplorer.Create("mwt", numActions, recorder, explorer, scorer);
|
||||
|
||||
int chosenAction = mwtt.ChooseAction(new UniqueEventID { Key = uniqueKey }, testContext);
|
||||
int chosenAction = mwtt.ChooseAction(uniqueKey, testContext);
|
||||
|
||||
var interactions = recorder.GetAllInteractions();
|
||||
Assert.AreEqual(1, interactions.Count);
|
||||
|
@ -367,14 +367,14 @@ namespace ExploreTests.SingleAction
|
|||
|
||||
class TestRecorder<Ctx> : IRecorder<Ctx, int>
|
||||
{
|
||||
public void Record(Ctx context, int value, object explorerState, object mapperState, UniqueEventID uniqueKey)
|
||||
public void Record(Ctx context, int value, object explorerState, object mapperState, string uniqueKey)
|
||||
{
|
||||
interactions.Add(new TestInteraction<Ctx>()
|
||||
{
|
||||
Context = context,
|
||||
Action = (uint)value,
|
||||
Probability = ((GenericExplorerState)explorerState).Probability,
|
||||
UniqueKey = uniqueKey.Key
|
||||
UniqueKey = uniqueKey
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче