add information entropy
This commit is contained in:
parent
535854df1f
commit
6f1ea96289
|
|
@ -8,4 +8,10 @@
|
|||
<Folder Include="Fasttext\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Data.Sqlite">
|
||||
<HintPath>..\..\..\..\..\..\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.data.sqlite.core\2.1.0\lib\netstandard2.0\Microsoft.Data.Sqlite.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
230
BotSharp.MachineLearning/Entropy/AbstractDataIndexer.cs
Normal file
230
BotSharp.MachineLearning/Entropy/AbstractDataIndexer.cs
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
// Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the AbstractDataIndexer.java source file found in the
|
||||
//original java implementation of MaxEnt.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract base for DataIndexer implementations.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Tom Morton
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
public abstract class AbstractDataIndexer : ITrainingDataIndexer
|
||||
{
|
||||
private int[][] mContexts;
|
||||
private int[] mOutcomeList;
|
||||
private int[] mNumTimesEventsSeen;
|
||||
private string[] mPredicateLabels;
|
||||
private string[] mOutcomeLabels;
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array of context data calculated from the training data.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Array of integer arrays, each containing the context data for an event.
|
||||
/// </returns>
|
||||
public virtual int[][] GetContexts()
|
||||
{
|
||||
return mContexts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the array of context data calculated from the training data.
|
||||
/// </summary>
|
||||
/// <param name="newContexts">
|
||||
/// Array of integer arrays, each containing the context data for an event.
|
||||
/// </param>
|
||||
protected internal void SetContexts(int[][] newContexts)
|
||||
{
|
||||
mContexts = newContexts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array indicating how many times each event is seen.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Integer array with event frequencies.
|
||||
/// </returns>
|
||||
public virtual int[] GetNumTimesEventsSeen()
|
||||
{
|
||||
return mNumTimesEventsSeen;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets an array indicating how many times each event is seen.
|
||||
/// </summary>
|
||||
/// <param name="newNumTimesEventsSeen">
|
||||
/// Integer array with event frequencies.
|
||||
/// </param>
|
||||
protected internal void SetNumTimesEventsSeen(int[] newNumTimesEventsSeen)
|
||||
{
|
||||
mNumTimesEventsSeen = newNumTimesEventsSeen;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an outcome list.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Integer array of outcomes.
|
||||
/// </returns>
|
||||
public virtual int[] GetOutcomeList()
|
||||
{
|
||||
return mOutcomeList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets an outcome list.
|
||||
/// </summary>
|
||||
/// <param name="newOutcomeList">
|
||||
/// Integer array of outcomes.
|
||||
/// </param>
|
||||
protected internal void SetOutcomeList(int[] newOutcomeList)
|
||||
{
|
||||
mOutcomeList = newOutcomeList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array of predicate labels.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Array of predicate labels.
|
||||
/// </returns>
|
||||
public virtual string[] GetPredicateLabels()
|
||||
{
|
||||
return mPredicateLabels;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets an array of predicate labels.
|
||||
/// </summary>
|
||||
/// <param name="newPredicateLabels">
|
||||
/// Array of predicate labels.
|
||||
/// </param>
|
||||
protected internal void SetPredicateLabels(string[] newPredicateLabels)
|
||||
{
|
||||
mPredicateLabels = newPredicateLabels;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array of outcome labels.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Array of outcome labels.
|
||||
/// </returns>
|
||||
public virtual string[] GetOutcomeLabels()
|
||||
{
|
||||
return mOutcomeLabels;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets an array of outcome labels.
|
||||
/// </summary>
|
||||
/// <param name="newOutcomeLabels">
|
||||
/// Array of outcome labels.
|
||||
/// </param>
|
||||
protected internal void SetOutcomeLabels(string[] newOutcomeLabels)
|
||||
{
|
||||
mOutcomeLabels = newOutcomeLabels;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sorts and uniques the array of comparable events. This method
|
||||
/// will alter the eventsToCompare array -- it does an in place
|
||||
/// sort, followed by an in place edit to remove duplicates.
|
||||
/// </summary>
|
||||
/// <param name="eventsToCompare">
|
||||
/// a List of <code>ComparableEvent</code> values
|
||||
/// </param>
|
||||
protected internal virtual void SortAndMerge(List<ComparableEvent> eventsToCompare)
|
||||
{
|
||||
eventsToCompare.Sort();
|
||||
int eventCount = eventsToCompare.Count;
|
||||
int uniqueEventCount = 1; // assertion: eventsToCompare.length >= 1
|
||||
|
||||
if (eventCount <= 1)
|
||||
{
|
||||
return; // nothing to do; edge case (see assertion)
|
||||
}
|
||||
|
||||
ComparableEvent comparableEvent = eventsToCompare[0];
|
||||
for (int currentEvent = 1; currentEvent < eventCount; currentEvent++)
|
||||
{
|
||||
ComparableEvent eventToCompare = eventsToCompare[currentEvent];
|
||||
|
||||
if (comparableEvent.Equals(eventToCompare))
|
||||
{
|
||||
comparableEvent.SeenCount++; // increment the seen count
|
||||
eventsToCompare[currentEvent] = null; // kill the duplicate
|
||||
}
|
||||
else
|
||||
{
|
||||
comparableEvent = eventToCompare; // a new champion emerges...
|
||||
uniqueEventCount++; // increment the # of unique events
|
||||
}
|
||||
}
|
||||
|
||||
//NotifyProgress("done. Reduced " + eventCount + " events to " + uniqueEventCount + ".");
|
||||
|
||||
mContexts = new int[uniqueEventCount][];
|
||||
mOutcomeList = new int[uniqueEventCount];
|
||||
mNumTimesEventsSeen = new int[uniqueEventCount];
|
||||
|
||||
for (int currentEvent = 0, currentStoredEvent = 0; currentEvent < eventCount; currentEvent++)
|
||||
{
|
||||
ComparableEvent eventToStore = eventsToCompare[currentEvent];
|
||||
if (null == eventToStore)
|
||||
{
|
||||
continue; // this was a dupe, skip over it.
|
||||
}
|
||||
mNumTimesEventsSeen[currentStoredEvent] = eventToStore.SeenCount;
|
||||
mOutcomeList[currentStoredEvent] = eventToStore.Outcome;
|
||||
mContexts[currentStoredEvent] = eventToStore.GetPredicateIndexes();
|
||||
++currentStoredEvent;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Utility method for creating a string[] array from a dictionary whose
|
||||
/// keys are labels (strings) to be stored in the array and whose
|
||||
/// values are the indices (integers) at which the corresponding
|
||||
/// labels should be inserted.
|
||||
/// </summary>
|
||||
/// <param name="labelToIndexMap">
|
||||
/// a <code>Dictionary</code> value
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// a <code>string[]</code> value
|
||||
/// </returns>
|
||||
protected internal static string[] ToIndexedStringArray(Dictionary<string, int> labelToIndexMap)
|
||||
{
|
||||
string[] indexedArray = new string[labelToIndexMap.Count];
|
||||
int[] indices = new int[labelToIndexMap.Count];
|
||||
labelToIndexMap.Keys.CopyTo(indexedArray, 0);
|
||||
labelToIndexMap.Values.CopyTo(indices, 0);
|
||||
Array.Sort(indices, indexedArray);
|
||||
return indexedArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
70
BotSharp.MachineLearning/Entropy/BasicContextGenerator.cs
Normal file
70
BotSharp.MachineLearning/Entropy/BasicContextGenerator.cs
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the BasicContextGenerator.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// Generate contexts for maxent decisions, assuming that the input
|
||||
/// given to the GetContext() method is a string containing contextual
|
||||
/// predicates separated by spaces, e.g:
|
||||
/// <p>
|
||||
/// cp_1 cp_2 ... cp_n
|
||||
/// </p>
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>based on BasicContextGenerator.java, $Revision: 1.2 $, $Date: 2002/04/30 08:48:35 $
|
||||
/// </version>
|
||||
public class BasicContextGenerator : IContextGenerator<string>
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds up the list of contextual predicates given a string.
|
||||
/// </summary>
|
||||
/// <param name="input">
|
||||
/// string with contextual predicates separated by spaces.
|
||||
/// </param>
|
||||
/// <returns>string array of contextual predicates.</returns>
|
||||
public virtual string[] GetContext(string input)
|
||||
{
|
||||
return input.Split(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
125
BotSharp.MachineLearning/Entropy/BasicEventReader.cs
Normal file
125
BotSharp.MachineLearning/Entropy/BasicEventReader.cs
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the BasicEventStream.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// An object which can deliver a stream of training events assuming
|
||||
/// that each event is represented as a space separated list containing
|
||||
/// all the contextual predicates, with the last item being the
|
||||
/// outcome, e.g.:
|
||||
///
|
||||
/// <p> cp_1 cp_2 ... cp_n outcome</p>
|
||||
/// </summary>
|
||||
public class BasicEventReader : ITrainingEventReader
|
||||
{
|
||||
private IContextGenerator<string> mContext;
|
||||
private ITrainingDataReader<string> mDataReader;
|
||||
private TrainingEvent mNextEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor sets up the training event reader based on a stream of training data.
|
||||
/// </summary>
|
||||
/// <param name="dataReader">
|
||||
/// Stream of training data.
|
||||
/// </param>
|
||||
public BasicEventReader(ITrainingDataReader<string> dataReader)
|
||||
{
|
||||
mContext = new BasicContextGenerator();
|
||||
|
||||
mDataReader = dataReader;
|
||||
if (mDataReader.HasNext())
|
||||
{
|
||||
mNextEvent = CreateEvent(mDataReader.NextToken());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the next Event object held in this EventReader. Each call to ReadNextEvent advances the EventReader.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// the Event object which is next in this EventReader
|
||||
/// </returns>
|
||||
public virtual TrainingEvent ReadNextEvent()
|
||||
{
|
||||
while (mNextEvent == null && mDataReader.HasNext())
|
||||
{
|
||||
mNextEvent = CreateEvent(mDataReader.NextToken());
|
||||
}
|
||||
|
||||
TrainingEvent currentEvent = mNextEvent;
|
||||
if (mDataReader.HasNext())
|
||||
{
|
||||
mNextEvent = CreateEvent(mDataReader.NextToken());
|
||||
}
|
||||
else
|
||||
{
|
||||
mNextEvent = null;
|
||||
}
|
||||
return currentEvent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether there are any Events remaining in this EventReader.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// true if this EventReader has more Events
|
||||
/// </returns>
|
||||
public virtual bool HasNext()
|
||||
{
|
||||
while (mNextEvent == null && mDataReader.HasNext())
|
||||
{
|
||||
mNextEvent = CreateEvent(mDataReader.NextToken());
|
||||
}
|
||||
return mNextEvent != null;
|
||||
}
|
||||
|
||||
private TrainingEvent CreateEvent(string observation)
|
||||
{
|
||||
int lastSpace = observation.LastIndexOf((char)' ');
|
||||
if (lastSpace == -1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new TrainingEvent(observation.Substring(lastSpace + 1), mContext.GetContext(observation.Substring(0, (lastSpace) - (0))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
220
BotSharp.MachineLearning/Entropy/ComparableEvent.cs
Normal file
220
BotSharp.MachineLearning/Entropy/ComparableEvent.cs
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the ComparableEvent.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// A Maximum Entropy event representation which we can use to sort based on the
|
||||
/// predicates indexes contained in the events.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on ComparableEvent.java, $Revision: 1.2 $, $Date: 2001/12/27 19:20:26 $
|
||||
/// </version>
|
||||
public class ComparableEvent : IComparable<ComparableEvent>
|
||||
{
|
||||
private int mOutcome;
|
||||
private int[] mPredicateIndexes ;
|
||||
private int mSeenCount = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The outcome ID of this event.
|
||||
/// </summary>
|
||||
public int Outcome
|
||||
{
|
||||
get
|
||||
{
|
||||
return mOutcome;
|
||||
}
|
||||
set
|
||||
{
|
||||
mOutcome = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array containing the indexes of the predicates in this event.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Integer array of predicate indexes.
|
||||
/// </returns>
|
||||
public int[] GetPredicateIndexes()
|
||||
{
|
||||
return mPredicateIndexes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the array containing the indices of the predicates in this event.
|
||||
/// </summary>
|
||||
/// <param name="predicateIndexes">
|
||||
/// Integer array of predicate indexes.
|
||||
/// </param>
|
||||
public void SetPredicateIndexes(int[] predicateIndexes)
|
||||
{
|
||||
mPredicateIndexes = predicateIndexes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of times this event
|
||||
/// has been seen.
|
||||
/// </summary>
|
||||
public int SeenCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return mSeenCount;
|
||||
}
|
||||
set
|
||||
{
|
||||
mSeenCount = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for the ComparableEvent.
|
||||
/// </summary>
|
||||
/// <param name="outcome">
|
||||
/// The ID of the outcome for this event.
|
||||
/// </param>
|
||||
/// <param name="predicateIndexes">
|
||||
/// Array of indexes for the predicates in this event.
|
||||
/// </param>
|
||||
public ComparableEvent(int outcome, int[] predicateIndexes)
|
||||
{
|
||||
mOutcome = outcome;
|
||||
System.Array.Sort(predicateIndexes);
|
||||
mPredicateIndexes = predicateIndexes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of the IComparable interface.
|
||||
/// </summary>
|
||||
/// <param name="eventToCompare">
|
||||
/// ComparableEvent to compare this event to.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A value indicating if the compared object is smaller, greater or the same as this event.
|
||||
/// </returns>
|
||||
public virtual int CompareTo(ComparableEvent eventToCompare)
|
||||
{
|
||||
if (mOutcome < eventToCompare.Outcome)
|
||||
{
|
||||
return - 1;
|
||||
}
|
||||
else if (mOutcome > eventToCompare.Outcome)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int smallerLength = (mPredicateIndexes .Length > eventToCompare.GetPredicateIndexes().Length ? eventToCompare.GetPredicateIndexes().Length : GetPredicateIndexes().Length);
|
||||
|
||||
for (int currentIndex = 0; currentIndex < smallerLength; currentIndex++)
|
||||
{
|
||||
if (mPredicateIndexes [currentIndex] < eventToCompare.GetPredicateIndexes()[currentIndex])
|
||||
{
|
||||
return - 1;
|
||||
}
|
||||
else if (mPredicateIndexes [currentIndex] > eventToCompare.GetPredicateIndexes()[currentIndex])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (mPredicateIndexes .Length < eventToCompare.GetPredicateIndexes().Length)
|
||||
{
|
||||
return - 1;
|
||||
}
|
||||
else if (mPredicateIndexes .Length > eventToCompare.GetPredicateIndexes().Length)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests if this event is equal to another object.
|
||||
/// </summary>
|
||||
/// <param name="o">
|
||||
/// Object to test against.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// True if the objects are equal.
|
||||
/// </returns>
|
||||
public override bool Equals (object o)
|
||||
{
|
||||
if (!(o is ComparableEvent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return (this.CompareTo(o as ComparableEvent)== 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides a hashcode for storing events in a dictionary or hashtable.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A hashcode value.
|
||||
/// </returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.ToString().GetHashCode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to provide a succint summary of the ComparableEvent object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// string representation of the ComparableEvent object.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (int currentIndex = 0; currentIndex < mPredicateIndexes.Length; currentIndex++)
|
||||
{
|
||||
stringBuilder.Append(" ").Append(mPredicateIndexes [currentIndex]);
|
||||
}
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
308
BotSharp.MachineLearning/Entropy/GisModel.cs
Normal file
308
BotSharp.MachineLearning/Entropy/GisModel.cs
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the GISModel.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// A maximum entropy model which has been trained using the Generalized
|
||||
/// Iterative Scaling procedure.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Tom Morton and Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on GISModel.java, $Revision: 1.13 $, $Date: 2004/06/11 20:51:44 $
|
||||
/// </version>
|
||||
public sealed class GisModel : IMaximumEntropyModel
|
||||
{
|
||||
|
||||
private readonly IO.IGisModelReader _reader;
|
||||
|
||||
private readonly string[] _outcomeNames;
|
||||
|
||||
private readonly int _outcomeCount;
|
||||
private readonly double _initialProbability;
|
||||
private readonly double _correctionConstantInverse;
|
||||
|
||||
private readonly int[] _featureCounts;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for a maximum entropy model trained using the
|
||||
/// Generalized Iterative Scaling procedure.
|
||||
/// </summary>
|
||||
/// <param name="reader">
|
||||
/// A reader providing the data for the model.
|
||||
/// </param>
|
||||
public GisModel(IO.IGisModelReader reader)
|
||||
{
|
||||
this._reader = reader;
|
||||
_outcomeNames = reader.GetOutcomeLabels();
|
||||
CorrectionConstant = reader.CorrectionConstant;
|
||||
CorrectionParameter = reader.CorrectionParameter;
|
||||
|
||||
_outcomeCount = _outcomeNames.Length;
|
||||
_initialProbability = Math.Log(1.0 / _outcomeCount);
|
||||
_correctionConstantInverse = 1.0 / CorrectionConstant;
|
||||
_featureCounts = new int[_outcomeCount];
|
||||
}
|
||||
|
||||
// implementation of IMaxentModel -------
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of outcomes for this model.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The number of outcomes.
|
||||
/// </returns>
|
||||
public int OutcomeCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_outcomeCount);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates a context.
|
||||
/// </summary>
|
||||
/// <param name="context">
|
||||
/// A list of string names of the contextual predicates
|
||||
/// which are to be evaluated together.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// An array of the probabilities for each of the different
|
||||
/// outcomes, all of which sum to 1.
|
||||
/// </returns>
|
||||
public double[] Evaluate(string[] context)
|
||||
{
|
||||
return Evaluate(context, new double[_outcomeCount]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this model to evaluate a context and return an array of the
|
||||
/// likelihood of each outcome given that context.
|
||||
/// </summary>
|
||||
/// <param name="context">
|
||||
/// The names of the predicates which have been observed at
|
||||
/// the present decision point.
|
||||
/// </param>
|
||||
/// <param name="outcomeSums">
|
||||
/// This is where the distribution is stored.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The normalized probabilities for the outcomes given the
|
||||
/// context. The indexes of the double[] are the outcome
|
||||
/// ids, and the actual string representation of the
|
||||
/// outcomes can be obtained from the method
|
||||
/// GetOutcome(int outcomeIndex).
|
||||
/// </returns>
|
||||
public double[] Evaluate(string[] context, double[] outcomeSums)
|
||||
{
|
||||
for (int outcomeIndex = 0; outcomeIndex < _outcomeCount; outcomeIndex++)
|
||||
{
|
||||
outcomeSums[outcomeIndex] = _initialProbability;
|
||||
_featureCounts[outcomeIndex] = 0;
|
||||
}
|
||||
|
||||
foreach (string con in context)
|
||||
{
|
||||
_reader.GetPredicateData(con, _featureCounts, outcomeSums);
|
||||
}
|
||||
|
||||
double normal = 0.0;
|
||||
for (int outcomeIndex = 0;outcomeIndex < _outcomeCount; outcomeIndex++)
|
||||
{
|
||||
outcomeSums[outcomeIndex] = Math.Exp((outcomeSums[outcomeIndex] * _correctionConstantInverse) + ((1.0 - (_featureCounts[outcomeIndex] / CorrectionConstant)) * CorrectionParameter));
|
||||
normal += outcomeSums[outcomeIndex];
|
||||
}
|
||||
|
||||
for (int outcomeIndex = 0; outcomeIndex < _outcomeCount;outcomeIndex++)
|
||||
{
|
||||
outcomeSums[outcomeIndex] /= normal;
|
||||
}
|
||||
return outcomeSums;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the name of the outcome corresponding to the highest likelihood
|
||||
/// in the parameter outcomes.
|
||||
/// </summary>
|
||||
/// <param name="outcomes">
|
||||
/// A double[] as returned by the Evaluate(string[] context)
|
||||
/// method.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The name of the most likely outcome.
|
||||
/// </returns>
|
||||
public string GetBestOutcome(double[] outcomes)
|
||||
{
|
||||
int bestOutcomeIndex = 0;
|
||||
for (int currentOutcome = 1; currentOutcome < outcomes.Length; currentOutcome++)
|
||||
if (outcomes[currentOutcome] > outcomes[bestOutcomeIndex])
|
||||
{
|
||||
bestOutcomeIndex = currentOutcome;
|
||||
}
|
||||
return _outcomeNames[bestOutcomeIndex];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a string matching all the outcome names with all the
|
||||
/// probabilities produced by the <code>Evaluate(string[] context)</code>
|
||||
/// method.
|
||||
/// </summary>
|
||||
/// <param name="outcomes">
|
||||
/// A <code>double[]</code> as returned by the
|
||||
/// <code>eval(string[] context)</code>
|
||||
/// method.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// string containing outcome names paired with the normalized
|
||||
/// probability (contained in the <code>double[] outcomes</code>)
|
||||
/// for each one.
|
||||
/// </returns>
|
||||
public string GetAllOutcomes(double[] outcomes)
|
||||
{
|
||||
if (outcomes.Length != _outcomeNames.Length)
|
||||
{
|
||||
throw new ArgumentException("The double array sent as a parameter to GisModel.GetAllOutcomes() must not have been produced by this model.");
|
||||
}
|
||||
else
|
||||
{
|
||||
var outcomeInfo = new StringBuilder(outcomes.Length * 2);
|
||||
outcomeInfo.Append(_outcomeNames[0]).Append("[").Append(outcomes[0].ToString("0.0000", System.Globalization.CultureInfo.CurrentCulture)).Append("]");
|
||||
for (int currentOutcome = 1; currentOutcome < outcomes.Length; currentOutcome++)
|
||||
{
|
||||
outcomeInfo.Append(" ").Append(_outcomeNames[currentOutcome]).Append("[").Append(outcomes[currentOutcome].ToString("0.0000", System.Globalization.CultureInfo.CurrentCulture)).Append("]");
|
||||
}
|
||||
return outcomeInfo.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the name of an outcome corresponding to an integer ID value.
|
||||
/// </summary>
|
||||
/// <param name="outcomeIndex">
|
||||
/// An outcome ID.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The name of the outcome associated with that ID.
|
||||
/// </returns>
|
||||
public string GetOutcomeName(int outcomeIndex)
|
||||
{
|
||||
return _outcomeNames[outcomeIndex];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index associated with the string name of the given outcome.
|
||||
/// </summary>
|
||||
/// <param name="outcome">
|
||||
/// the string name of the outcome for which the
|
||||
/// index is desired
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// the index if the given outcome label exists for this
|
||||
/// model, -1 if it does not.
|
||||
/// </returns>
|
||||
public int GetOutcomeIndex(string outcome)
|
||||
{
|
||||
for (int iCurrentOutcomeName = 0; iCurrentOutcomeName < _outcomeNames.Length; iCurrentOutcomeName++)
|
||||
{
|
||||
if (_outcomeNames[iCurrentOutcomeName] == outcome)
|
||||
{
|
||||
return iCurrentOutcomeName;
|
||||
}
|
||||
}
|
||||
return - 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides the predicates data structure which is part of the encoding of the maxent model
|
||||
/// information. This method will usually only be needed by
|
||||
/// GisModelWriters.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Dictionary containing PatternedPredicate objects.
|
||||
/// </returns>
|
||||
public Dictionary<string, PatternedPredicate> GetPredicates()
|
||||
{
|
||||
return _reader.GetPredicates();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides the list of outcome patterns used by the predicates. This method will usually
|
||||
/// only be needed by GisModelWriters.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Array of outcome patterns.
|
||||
/// </returns>
|
||||
public int[][] GetOutcomePatterns()
|
||||
{
|
||||
return _reader.GetOutcomePatterns();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides the outcome names data structure which is part of the encoding of the maxent model
|
||||
/// information. This method will usually only be needed by
|
||||
/// GisModelWriters.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Array containing the outcome names.
|
||||
/// </returns>
|
||||
public string[] GetOutcomeNames()
|
||||
{
|
||||
return _outcomeNames;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides the model's correction constant.
|
||||
/// This property will usually only be needed by GisModelWriters.
|
||||
/// </summary>
|
||||
public int CorrectionConstant { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Provides the model's correction parameter.
|
||||
/// This property will usually only be needed by GisModelWriters.
|
||||
/// </summary>
|
||||
public double CorrectionParameter { get; private set; }
|
||||
|
||||
}
|
||||
}
|
||||
886
BotSharp.MachineLearning/Entropy/GisTrainer.cs
Normal file
886
BotSharp.MachineLearning/Entropy/GisTrainer.cs
Normal file
|
|
@ -0,0 +1,886 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the GISTrainer.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// An implementation of Generalized Iterative Scaling. The reference paper
|
||||
/// for this implementation was Adwait Ratnaparkhi's tech report at the
|
||||
/// University of Pennsylvania's Institute for Research in Cognitive Science,
|
||||
/// and is available at <a href ="ftp://ftp.cis.upenn.edu/pub/ircs/tr/97-08.ps.Z"><code>ftp://ftp.cis.upenn.edu/pub/ircs/tr/97-08.ps.Z</code></a>.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J, Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on GISTrainer.java, $Revision: 1.15 $, $Date: 2004/06/14 20:52:41 $
|
||||
/// </version>
|
||||
public class GisTrainer : IO.IGisModelReader
|
||||
{
|
||||
private int mTokenCount; // # of event tokens
|
||||
private int mPredicateCount; // # of predicates
|
||||
private int mOutcomeCount; // # of mOutcomes
|
||||
private int mTokenID; // global index variable for Tokens
|
||||
private int mPredicateId; // global index variable for Predicates
|
||||
private int mOutcomeId; // global index variable for Outcomes
|
||||
|
||||
// records the array of predicates seen in each event
|
||||
private int[][] mContexts;
|
||||
|
||||
// records the array of outcomes seen in each event
|
||||
private int[] mOutcomes;
|
||||
|
||||
// records the num of times an event has been seen, paired to
|
||||
// int[][] mContexts
|
||||
private int[] mNumTimesEventsSeen;
|
||||
|
||||
// stores the string names of the outcomes. The GIS only tracks outcomes
|
||||
// as ints, and so this array is needed to save the model to disk and
|
||||
// thereby allow users to know what the outcome was in human
|
||||
// understandable terms.
|
||||
private string[] mOutcomeLabels;
|
||||
|
||||
// stores the string names of the predicates. The GIS only tracks
|
||||
// predicates as ints, and so this array is needed to save the model to
|
||||
// disk and thereby allow users to know what the outcome was in human
|
||||
// understandable terms.
|
||||
private string[] mPredicateLabels;
|
||||
|
||||
// stores the observed expections of each of the events
|
||||
private double[][] mObservedExpections;
|
||||
|
||||
// stores the estimated parameter value of each predicate during iteration
|
||||
private double[][] mParameters;
|
||||
|
||||
// Stores the expected values of the features based on the current models
|
||||
private double[][] mModelExpections;
|
||||
|
||||
//The maximum number of features fired in an event. Usually referred to as C.
|
||||
private int mMaximumFeatureCount;
|
||||
|
||||
// stores inverse of constant, 1/C.
|
||||
private double mMaximumFeatureCountInverse;
|
||||
|
||||
// the correction parameter of the model
|
||||
private double mCorrectionParameter;
|
||||
|
||||
// observed expectation of correction feature
|
||||
private double mCorrectionFeatureObservedExpectation;
|
||||
|
||||
// a global variable to help compute the amount to modify the correction
|
||||
// parameter
|
||||
private double mCorrectionFeatureModifier;
|
||||
|
||||
private const double mNearZero = 0.01;
|
||||
private const double mLLThreshold = 0.0001;
|
||||
|
||||
// Stores the output of the current model on a single event durring
|
||||
// training. This will be reset for every event for every iteration.
|
||||
private double[] mModelDistribution;
|
||||
|
||||
// Stores the number of features that get fired per event
|
||||
private int[] mFeatureCounts;
|
||||
|
||||
// initial probability for all outcomes.
|
||||
private double mInitialProbability;
|
||||
|
||||
private Dictionary<string, PatternedPredicate> mPredicates;
|
||||
private int[][] mOutcomePatterns;
|
||||
|
||||
// smoothing algorithm (unused) --------
|
||||
|
||||
// internal class UpdateParametersWithSmoothingProcedure : Trove.IIntDoubleProcedure
|
||||
// {
|
||||
|
||||
// private double mdSigma = 2.0;
|
||||
|
||||
// public UpdateParametersWithSmoothingProcedure(GisTrainer enclosingInstance)
|
||||
// {
|
||||
// moEnclosingInstance = enclosingInstance;
|
||||
// }
|
||||
//
|
||||
// private GisTrainer moEnclosingInstance;
|
||||
//
|
||||
// public virtual bool Execute(int outcomeID, double input)
|
||||
// {
|
||||
// double x = 0.0;
|
||||
// double x0 = 0.0;
|
||||
// double tmp;
|
||||
// double f;
|
||||
// double fp;
|
||||
// for (int i = 0; i < 50; i++)
|
||||
// {
|
||||
// // check what domain these parameters are in
|
||||
// tmp = moEnclosingInstance.maoModelExpections[moEnclosingInstance.miPredicateID][outcomeID] * System.Math.Exp(moEnclosingInstance.miConstant * x0);
|
||||
// f = tmp + (input + x0) / moEnclosingInstance.mdSigma - moEnclosingInstance.maoObservedExpections[moEnclosingInstance.miPredicateID][outcomeID];
|
||||
// fp = tmp * moEnclosingInstance.miConstant + 1 / moEnclosingInstance.mdSigma;
|
||||
// if (fp == 0)
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
// x = x0 - f / fp;
|
||||
// if (System.Math.Abs(x - x0) < 0.000001)
|
||||
// {
|
||||
// x0 = x;
|
||||
// break;
|
||||
// }
|
||||
// x0 = x;
|
||||
// }
|
||||
// moEnclosingInstance.maoParameters[moEnclosingInstance.miPredicateID].Put(outcomeID, input + x0);
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// training progress event -----------
|
||||
|
||||
/// <summary>
|
||||
/// Used to provide informational messages regarding the
|
||||
/// progress of the training algorithm.
|
||||
/// </summary>
|
||||
public event TrainingProgressEventHandler TrainingProgress;
|
||||
|
||||
/// <summary>
|
||||
/// Used to raise events providing messages with information
|
||||
/// about training progress.
|
||||
/// </summary>
|
||||
/// <param name="e">
|
||||
/// Contains the message with information about the progress of
|
||||
/// the training algorithm.
|
||||
/// </param>
|
||||
protected virtual void OnTrainingProgress(TrainingProgressEventArgs e)
|
||||
{
|
||||
if (TrainingProgress != null)
|
||||
{
|
||||
TrainingProgress(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void NotifyProgress(string message)
|
||||
{
|
||||
OnTrainingProgress(new TrainingProgressEventArgs(message));
|
||||
}
|
||||
|
||||
|
||||
// training options --------------
|
||||
|
||||
/// <summary>
|
||||
/// Sets whether this trainer will use smoothing while training the model.
|
||||
/// This can improve model accuracy, though training will potentially take
|
||||
/// longer and use more memory. Model size will also be larger.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Initial testing indicates improvements for models built on small data sets and
|
||||
/// few outcomes, but performance degradation for those with large data
|
||||
/// sets and lots of outcomes.
|
||||
/// </remarks>
|
||||
public bool Smoothing { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets whether this trainer will use slack parameters while training the model.
|
||||
/// </summary>
|
||||
public bool UseSlackParameter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If smoothing is in use, this value indicates the "number" of
|
||||
/// times we want the trainer to imagine that it saw a feature that it
|
||||
/// actually didn't see. Defaulted to 0.1.
|
||||
/// </summary>
|
||||
public double SmoothingObservation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <code>GisTrainer</code> instance.
|
||||
/// </summary>
|
||||
public GisTrainer()
|
||||
{
|
||||
Smoothing = false;
|
||||
UseSlackParameter = false;
|
||||
SmoothingObservation = 0.1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <code>GisTrainer</code> instance.
|
||||
/// </summary>
|
||||
/// <param name="useSlackParameter">
|
||||
/// Sets whether this trainer will use slack parameters while training the model.
|
||||
/// </param>
|
||||
public GisTrainer(bool useSlackParameter)
|
||||
{
|
||||
Smoothing = false;
|
||||
UseSlackParameter = useSlackParameter;
|
||||
SmoothingObservation = 0.1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <code>GisTrainer</code> instance.
|
||||
/// </summary>
|
||||
/// <param name="smoothingObservation">
|
||||
/// If smoothing is in use, this value indicates the "number" of
|
||||
/// times we want the trainer to imagine that it saw a feature that it
|
||||
/// actually didn't see. Defaulted to 0.1.
|
||||
/// </param>
|
||||
public GisTrainer(double smoothingObservation)
|
||||
{
|
||||
Smoothing = true;
|
||||
UseSlackParameter = false;
|
||||
SmoothingObservation = smoothingObservation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <code>GisTrainer</code> instance.
|
||||
/// </summary>
|
||||
/// <param name="useSlackParameter">
|
||||
/// Sets whether this trainer will use slack parameters while training the model.
|
||||
/// </param>
|
||||
/// <param name="smoothingObservation">
|
||||
/// If smoothing is in use, this value indicates the "number" of
|
||||
/// times we want the trainer to imagine that it saw a feature that it
|
||||
/// actually didn't see. Defaulted to 0.1.
|
||||
/// </param>
|
||||
public GisTrainer(bool useSlackParameter, double smoothingObservation)
|
||||
{
|
||||
Smoothing = true;
|
||||
UseSlackParameter = useSlackParameter;
|
||||
SmoothingObservation = smoothingObservation;
|
||||
}
|
||||
|
||||
|
||||
// alternative TrainModel signatures --------------
|
||||
|
||||
/// <summary>
|
||||
/// Train a model using the GIS algorithm.
|
||||
/// </summary>
|
||||
/// <param name="eventReader">
|
||||
/// The ITrainingEventReader holding the data on which this model
|
||||
/// will be trained.
|
||||
/// </param>
|
||||
public virtual void TrainModel(ITrainingEventReader eventReader)
|
||||
{
|
||||
TrainModel(eventReader, 100, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Train a model using the GIS algorithm.
|
||||
/// </summary>
|
||||
/// <param name="eventReader">
|
||||
/// The ITrainingEventReader holding the data on which this model will be trained
|
||||
/// </param>
|
||||
/// <param name="iterations">The number of GIS iterations to perform</param>
|
||||
/// <param name="cutoff">
|
||||
/// The number of times a predicate must be seen in order
|
||||
/// to be relevant for training.
|
||||
/// </param>
|
||||
public virtual void TrainModel(ITrainingEventReader eventReader, int iterations, int cutoff)
|
||||
{
|
||||
TrainModel(iterations, new OnePassDataIndexer(eventReader, cutoff));
|
||||
}
|
||||
|
||||
|
||||
// training algorithm -----------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Train a model using the GIS algorithm.
|
||||
/// </summary>
|
||||
/// <param name="iterations">
|
||||
/// The number of GIS iterations to perform.
|
||||
/// </param>
|
||||
/// <param name="dataIndexer">
|
||||
/// The data indexer used to compress events in memory.
|
||||
/// </param>
|
||||
public virtual void TrainModel(int iterations, ITrainingDataIndexer dataIndexer)
|
||||
{
|
||||
int[] outcomeList;
|
||||
|
||||
//incorporate all of the needed info
|
||||
NotifyProgress("Incorporating indexed data for training...");
|
||||
mContexts = dataIndexer.GetContexts();
|
||||
mOutcomes = dataIndexer.GetOutcomeList();
|
||||
mNumTimesEventsSeen = dataIndexer.GetNumTimesEventsSeen();
|
||||
mTokenCount = mContexts.Length;
|
||||
|
||||
// determine the correction constant and its inverse
|
||||
mMaximumFeatureCount = mContexts[0].Length;
|
||||
for (mTokenID = 1; mTokenID < mContexts.Length; mTokenID++)
|
||||
{
|
||||
if (mContexts[mTokenID].Length > mMaximumFeatureCount)
|
||||
{
|
||||
mMaximumFeatureCount = mContexts[mTokenID].Length;
|
||||
}
|
||||
}
|
||||
mMaximumFeatureCountInverse = 1.0 / mMaximumFeatureCount;
|
||||
|
||||
NotifyProgress("done.");
|
||||
|
||||
mOutcomeLabels = dataIndexer.GetOutcomeLabels();
|
||||
outcomeList = dataIndexer.GetOutcomeList();
|
||||
mOutcomeCount = mOutcomeLabels.Length;
|
||||
mInitialProbability = Math.Log(1.0 / mOutcomeCount);
|
||||
|
||||
mPredicateLabels = dataIndexer.GetPredicateLabels();
|
||||
mPredicateCount = mPredicateLabels.Length;
|
||||
|
||||
NotifyProgress("\tNumber of Event Tokens: " + mTokenCount);
|
||||
NotifyProgress("\t Number of Outcomes: " + mOutcomeCount);
|
||||
NotifyProgress("\t Number of Predicates: " + mPredicateCount);
|
||||
|
||||
// set up feature arrays
|
||||
var predicateCounts = new int[mPredicateCount][];
|
||||
for (mPredicateId = 0; mPredicateId < mPredicateCount; mPredicateId++)
|
||||
{
|
||||
predicateCounts[mPredicateId] = new int[mOutcomeCount];
|
||||
}
|
||||
for (mTokenID = 0; mTokenID < mTokenCount; mTokenID++)
|
||||
{
|
||||
for (int currentContext = 0; currentContext < mContexts[mTokenID].Length; currentContext++)
|
||||
{
|
||||
predicateCounts[mContexts[mTokenID][currentContext]][outcomeList[mTokenID]] += mNumTimesEventsSeen[mTokenID];
|
||||
}
|
||||
}
|
||||
|
||||
// A fake "observation" to cover features which are not detected in
|
||||
// the data. The default is to assume that we observed "1/10th" of a
|
||||
// feature during training.
|
||||
double smoothingObservation = SmoothingObservation;
|
||||
|
||||
// Get the observed expectations of the features. Strictly speaking,
|
||||
// we should divide the counts by the number of Tokens, but because of
|
||||
// the way the model's expectations are approximated in the
|
||||
// implementation, this is cancelled out when we compute the next
|
||||
// iteration of a parameter, making the extra divisions wasteful.
|
||||
mOutcomePatterns = new int[mPredicateCount][];
|
||||
mParameters = new double[mPredicateCount][];
|
||||
mModelExpections = new double[mPredicateCount][];
|
||||
mObservedExpections = new double[mPredicateCount][];
|
||||
|
||||
for (mPredicateId = 0; mPredicateId < mPredicateCount; mPredicateId++)
|
||||
{
|
||||
int activeOutcomeCount;
|
||||
if (Smoothing)
|
||||
{
|
||||
activeOutcomeCount = mOutcomeCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
activeOutcomeCount = 0;
|
||||
for (mOutcomeId = 0; mOutcomeId < mOutcomeCount; mOutcomeId++)
|
||||
{
|
||||
if (predicateCounts[mPredicateId][mOutcomeId] > 0)
|
||||
{
|
||||
activeOutcomeCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mOutcomePatterns[mPredicateId] = new int[activeOutcomeCount];
|
||||
mParameters[mPredicateId] = new double[activeOutcomeCount];
|
||||
mModelExpections[mPredicateId] = new double[activeOutcomeCount];
|
||||
mObservedExpections[mPredicateId] = new double[activeOutcomeCount];
|
||||
|
||||
int currentOutcome = 0;
|
||||
for (mOutcomeId = 0; mOutcomeId < mOutcomeCount; mOutcomeId++)
|
||||
{
|
||||
if (predicateCounts[mPredicateId][mOutcomeId] > 0)
|
||||
{
|
||||
mOutcomePatterns[mPredicateId][currentOutcome] = mOutcomeId;
|
||||
mObservedExpections[mPredicateId][currentOutcome] = Math.Log(predicateCounts[mPredicateId][mOutcomeId]);
|
||||
currentOutcome++;
|
||||
}
|
||||
else if (Smoothing)
|
||||
{
|
||||
mOutcomePatterns[mPredicateId][currentOutcome] = mOutcomeId;
|
||||
mObservedExpections[mPredicateId][currentOutcome] = Math.Log(smoothingObservation);
|
||||
currentOutcome++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// compute the expected value of correction
|
||||
if (UseSlackParameter)
|
||||
{
|
||||
int correctionFeatureValueSum = 0;
|
||||
for (mTokenID = 0; mTokenID < mTokenCount; mTokenID++)
|
||||
{
|
||||
for (int currentContext = 0; currentContext < mContexts[mTokenID].Length; currentContext++)
|
||||
{
|
||||
mPredicateId = mContexts[mTokenID][currentContext];
|
||||
|
||||
if ((!Smoothing) && predicateCounts[mPredicateId][mOutcomes[mTokenID]] == 0)
|
||||
{
|
||||
correctionFeatureValueSum += mNumTimesEventsSeen[mTokenID];
|
||||
}
|
||||
}
|
||||
correctionFeatureValueSum += (mMaximumFeatureCount - mContexts[mTokenID].Length) * mNumTimesEventsSeen[mTokenID];
|
||||
}
|
||||
if (correctionFeatureValueSum == 0)
|
||||
{
|
||||
mCorrectionFeatureObservedExpectation = Math.Log(mNearZero); //nearly zero so log is defined
|
||||
}
|
||||
else
|
||||
{
|
||||
mCorrectionFeatureObservedExpectation = Math.Log(correctionFeatureValueSum);
|
||||
}
|
||||
|
||||
mCorrectionParameter = 0.0;
|
||||
}
|
||||
|
||||
NotifyProgress("...done.");
|
||||
|
||||
mModelDistribution = new double[mOutcomeCount];
|
||||
mFeatureCounts = new int[mOutcomeCount];
|
||||
|
||||
//Find the parameters
|
||||
NotifyProgress("Computing model parameters...");
|
||||
FindParameters(iterations);
|
||||
|
||||
NotifyProgress("Converting to new predicate format...");
|
||||
ConvertPredicates();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Estimate and return the model parameters.
|
||||
/// </summary>
|
||||
/// <param name="iterations">
|
||||
/// Number of iterations to run through.
|
||||
/// </param>
|
||||
private void FindParameters(int iterations)
|
||||
{
|
||||
double previousLogLikelihood = 0.0;
|
||||
NotifyProgress("Performing " + iterations + " iterations.");
|
||||
for (int currentIteration = 1; currentIteration <= iterations; currentIteration++)
|
||||
{
|
||||
if (currentIteration < 10)
|
||||
{
|
||||
NotifyProgress(" " + currentIteration + ": ");
|
||||
}
|
||||
else if (currentIteration < 100)
|
||||
{
|
||||
NotifyProgress(" " + currentIteration + ": ");
|
||||
}
|
||||
else
|
||||
{
|
||||
NotifyProgress(currentIteration + ": ");
|
||||
}
|
||||
double currentLogLikelihood = NextIteration();
|
||||
if (currentIteration > 1)
|
||||
{
|
||||
if (previousLogLikelihood > currentLogLikelihood)
|
||||
{
|
||||
throw new SystemException("Model Diverging: loglikelihood decreased");
|
||||
}
|
||||
if (currentLogLikelihood - previousLogLikelihood < mLLThreshold)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
previousLogLikelihood = currentLogLikelihood;
|
||||
}
|
||||
|
||||
// kill a bunch of these big objects now that we don't need them
|
||||
mObservedExpections = null;
|
||||
mModelExpections = null;
|
||||
mNumTimesEventsSeen = null;
|
||||
mContexts = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this model to evaluate a context and return an array of the
|
||||
/// likelihood of each outcome given that context.
|
||||
/// </summary>
|
||||
/// <param name="context">
|
||||
/// The integers of the predicates which have been
|
||||
/// observed at the present decision point.
|
||||
/// </param>
|
||||
/// <param name="outcomeSums">
|
||||
/// The normalized probabilities for the outcomes given the
|
||||
/// context. The indexes of the double[] are the outcome
|
||||
/// ids.
|
||||
/// </param>
|
||||
protected virtual void Evaluate(int[] context, double[] outcomeSums)
|
||||
{
|
||||
for (int outcomeIndex = 0; outcomeIndex < mOutcomeCount; outcomeIndex++)
|
||||
{
|
||||
outcomeSums[outcomeIndex] = mInitialProbability;
|
||||
mFeatureCounts[outcomeIndex] = 0;
|
||||
}
|
||||
int[] activeOutcomes;
|
||||
int outcomeId;
|
||||
int predicateId;
|
||||
int currentActiveOutcome;
|
||||
|
||||
for (int currentContext = 0; currentContext < context.Length; currentContext++)
|
||||
{
|
||||
predicateId = context[currentContext];
|
||||
activeOutcomes = mOutcomePatterns[predicateId];
|
||||
for (currentActiveOutcome = 0; currentActiveOutcome < activeOutcomes.Length; currentActiveOutcome++)
|
||||
{
|
||||
outcomeId = activeOutcomes[currentActiveOutcome];
|
||||
mFeatureCounts[outcomeId]++;
|
||||
outcomeSums[outcomeId] += mMaximumFeatureCountInverse * mParameters[predicateId][currentActiveOutcome];
|
||||
}
|
||||
}
|
||||
|
||||
double sum = 0.0;
|
||||
for (int currentOutcomeId = 0; currentOutcomeId < mOutcomeCount; currentOutcomeId++)
|
||||
{
|
||||
outcomeSums[currentOutcomeId] = System.Math.Exp(outcomeSums[currentOutcomeId]);
|
||||
if (UseSlackParameter)
|
||||
{
|
||||
outcomeSums[currentOutcomeId] += ((1.0 - ((double) mFeatureCounts[currentOutcomeId] / mMaximumFeatureCount)) * mCorrectionParameter);
|
||||
}
|
||||
sum += outcomeSums[currentOutcomeId];
|
||||
}
|
||||
|
||||
for (int currentOutcomeId = 0; currentOutcomeId < mOutcomeCount; currentOutcomeId++)
|
||||
{
|
||||
outcomeSums[currentOutcomeId] /= sum;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute one iteration of GIS and retutn log-likelihood.
|
||||
/// </summary>
|
||||
/// <returns>The log-likelihood.</returns>
|
||||
private double NextIteration()
|
||||
{
|
||||
// compute contribution of p(a|b_i) for each feature and the new
|
||||
// correction parameter
|
||||
double logLikelihood = 0.0;
|
||||
mCorrectionFeatureModifier = 0.0;
|
||||
int eventCount = 0;
|
||||
int numCorrect = 0;
|
||||
int outcomeId;
|
||||
|
||||
for (mTokenID = 0; mTokenID < mTokenCount; mTokenID++)
|
||||
{
|
||||
Evaluate(mContexts[mTokenID], mModelDistribution);
|
||||
for (int currentContext = 0; currentContext < mContexts[mTokenID].Length; currentContext++)
|
||||
{
|
||||
mPredicateId = mContexts[mTokenID][currentContext];
|
||||
for (int currentActiveOutcome = 0; currentActiveOutcome < mOutcomePatterns[mPredicateId].Length; currentActiveOutcome++)
|
||||
{
|
||||
outcomeId = mOutcomePatterns[mPredicateId][currentActiveOutcome];
|
||||
mModelExpections[mPredicateId][currentActiveOutcome] += (mModelDistribution[outcomeId] * mNumTimesEventsSeen[mTokenID]);
|
||||
|
||||
if (UseSlackParameter)
|
||||
{
|
||||
mCorrectionFeatureModifier += mModelDistribution[mOutcomeId] * mNumTimesEventsSeen[mTokenID];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (UseSlackParameter)
|
||||
{
|
||||
mCorrectionFeatureModifier += (mMaximumFeatureCount - mContexts[mTokenID].Length) * mNumTimesEventsSeen[mTokenID];
|
||||
}
|
||||
|
||||
logLikelihood += System.Math.Log(mModelDistribution[mOutcomes[mTokenID]]) * mNumTimesEventsSeen[mTokenID];
|
||||
eventCount += mNumTimesEventsSeen[mTokenID];
|
||||
|
||||
//calculation solely for the information messages
|
||||
int max = 0;
|
||||
for (mOutcomeId = 1; mOutcomeId < mOutcomeCount; mOutcomeId++)
|
||||
{
|
||||
if (mModelDistribution[mOutcomeId] > mModelDistribution[max])
|
||||
{
|
||||
max = mOutcomeId;
|
||||
}
|
||||
}
|
||||
if (max == mOutcomes[mTokenID])
|
||||
{
|
||||
numCorrect += mNumTimesEventsSeen[mTokenID];
|
||||
}
|
||||
}
|
||||
NotifyProgress(".");
|
||||
|
||||
// compute the new parameter values
|
||||
for (mPredicateId = 0; mPredicateId < mPredicateCount; mPredicateId++)
|
||||
{
|
||||
for (int currentActiveOutcome = 0; currentActiveOutcome < mOutcomePatterns[mPredicateId].Length; currentActiveOutcome++)
|
||||
{
|
||||
outcomeId = mOutcomePatterns[mPredicateId][currentActiveOutcome];
|
||||
mParameters[mPredicateId][currentActiveOutcome] += (mObservedExpections[mPredicateId][currentActiveOutcome] - Math.Log(mModelExpections[mPredicateId][currentActiveOutcome]));
|
||||
mModelExpections[mPredicateId][currentActiveOutcome] = 0.0;// re-initialize to 0.0's
|
||||
}
|
||||
}
|
||||
|
||||
if (mCorrectionFeatureModifier > 0.0 && UseSlackParameter)
|
||||
{
|
||||
mCorrectionParameter += (mCorrectionFeatureObservedExpectation - Math.Log(mCorrectionFeatureModifier));
|
||||
}
|
||||
|
||||
NotifyProgress(". logLikelihood=" + logLikelihood + "\t" + ((double) numCorrect / eventCount));
|
||||
return (logLikelihood);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the predicate data into the outcome pattern / patterned predicate format used by the GIS models.
|
||||
/// </summary>
|
||||
private void ConvertPredicates()
|
||||
{
|
||||
var predicates = new PatternedPredicate[mParameters.Length];
|
||||
|
||||
for (mPredicateId = 0; mPredicateId < mPredicateCount; mPredicateId++)
|
||||
{
|
||||
double[] parameters = mParameters[mPredicateId];
|
||||
predicates[mPredicateId] = new PatternedPredicate(mPredicateLabels[mPredicateId], parameters);
|
||||
}
|
||||
|
||||
var comparer = new OutcomePatternComparer();
|
||||
Array.Sort(mOutcomePatterns, predicates, comparer);
|
||||
|
||||
List<int[]> outcomePatterns = new List<int[]>();
|
||||
int currentPatternId = 0;
|
||||
int predicatesInPattern = 0;
|
||||
int[] currentPattern = mOutcomePatterns[0];
|
||||
|
||||
for (mPredicateId = 0; mPredicateId < mPredicateCount; mPredicateId++)
|
||||
{
|
||||
if (comparer.Compare(currentPattern, mOutcomePatterns[mPredicateId]) == 0)
|
||||
{
|
||||
predicates[mPredicateId].OutcomePattern = currentPatternId;
|
||||
predicatesInPattern++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int[] pattern = new int[currentPattern.Length + 1];
|
||||
pattern[0] = predicatesInPattern;
|
||||
currentPattern.CopyTo(pattern, 1);
|
||||
outcomePatterns.Add(pattern);
|
||||
currentPattern = mOutcomePatterns[mPredicateId];
|
||||
currentPatternId++;
|
||||
predicates[mPredicateId].OutcomePattern = currentPatternId;
|
||||
predicatesInPattern = 1;
|
||||
}
|
||||
}
|
||||
int[] finalPattern = new int[currentPattern.Length + 1];
|
||||
finalPattern[0] = predicatesInPattern;
|
||||
currentPattern.CopyTo(finalPattern, 1);
|
||||
outcomePatterns.Add(finalPattern);
|
||||
|
||||
mOutcomePatterns = outcomePatterns.ToArray();
|
||||
mPredicates = new Dictionary<string, PatternedPredicate>(predicates.Length);
|
||||
for (mPredicateId = 0; mPredicateId < mPredicateCount; mPredicateId++)
|
||||
{
|
||||
mPredicates.Add(predicates[mPredicateId].Name, predicates[mPredicateId]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// IGisModelReader implementation --------------------
|
||||
|
||||
/// <summary>
|
||||
/// The correction constant for the model produced as a result of training.
|
||||
/// </summary>
|
||||
public int CorrectionConstant
|
||||
{
|
||||
get
|
||||
{
|
||||
return mMaximumFeatureCount;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The correction parameter for the model produced as a result of training.
|
||||
/// </summary>
|
||||
public double CorrectionParameter
|
||||
{
|
||||
get
|
||||
{
|
||||
return mCorrectionParameter;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtains the outcome labels for the model produced as a result of training.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Array of outcome labels.
|
||||
/// </returns>
|
||||
public string[] GetOutcomeLabels()
|
||||
{
|
||||
return mOutcomeLabels;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtains the outcome patterns for the model produced as a result of training.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Array of outcome patterns.
|
||||
/// </returns>
|
||||
public int[][] GetOutcomePatterns()
|
||||
{
|
||||
return mOutcomePatterns;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtains the predicate data for the model produced as a result of training.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Dictionary containing PatternedPredicate objects.
|
||||
/// </returns>
|
||||
public Dictionary<string, PatternedPredicate> GetPredicates()
|
||||
{
|
||||
return mPredicates;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns trained model information for a predicate, given the predicate label.
|
||||
/// </summary>
|
||||
/// <param name="predicateLabel">
|
||||
/// The predicate label to fetch information for.
|
||||
/// </param>
|
||||
/// <param name="featureCounts">
|
||||
/// Array to be passed in to the method; it should have a length equal to the number of outcomes
|
||||
/// in the model. The method increments the count of each outcome that is active in the specified
|
||||
/// predicate.
|
||||
/// </param>
|
||||
/// <param name="outcomeSums">
|
||||
/// Array to be passed in to the method; it should have a length equal to the number of outcomes
|
||||
/// in the model. The method adds the parameter values for each of the active outcomes in the
|
||||
/// predicate.
|
||||
/// </param>
|
||||
public void GetPredicateData(string predicateLabel, int[] featureCounts, double[] outcomeSums)
|
||||
{
|
||||
if (mPredicates.ContainsKey(predicateLabel))
|
||||
{
|
||||
PatternedPredicate predicate = mPredicates[predicateLabel];
|
||||
if (predicate != null)
|
||||
{
|
||||
int[] activeOutcomes = mOutcomePatterns[predicate.OutcomePattern];
|
||||
|
||||
for (int currentActiveOutcome = 1; currentActiveOutcome < activeOutcomes.Length; currentActiveOutcome++)
|
||||
{
|
||||
int outcomeIndex = activeOutcomes[currentActiveOutcome];
|
||||
featureCounts[outcomeIndex]++;
|
||||
outcomeSums[outcomeIndex] += predicate.GetParameter(currentActiveOutcome - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class OutcomePatternComparer : IComparer<int[]>
|
||||
{
|
||||
|
||||
internal OutcomePatternComparer()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two outcome patterns and determines which comes first,
|
||||
/// based on the outcome ids (lower outcome ids first)
|
||||
/// </summary>
|
||||
/// <param name="firstPattern">
|
||||
/// First outcome pattern to compare.
|
||||
/// </param>
|
||||
/// <param name="secondPattern">
|
||||
/// Second outcome pattern to compare.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public virtual int Compare(int[] firstPattern, int[] secondPattern)
|
||||
{
|
||||
int smallerLength = (firstPattern.Length > secondPattern.Length ? secondPattern.Length : firstPattern.Length);
|
||||
|
||||
for (int currentOutcome = 0; currentOutcome < smallerLength; currentOutcome++)
|
||||
{
|
||||
if (firstPattern[currentOutcome] < secondPattern[currentOutcome])
|
||||
{
|
||||
return - 1;
|
||||
}
|
||||
else if (firstPattern[currentOutcome] > secondPattern[currentOutcome])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstPattern.Length < secondPattern.Length)
|
||||
{
|
||||
return - 1;
|
||||
}
|
||||
else if (firstPattern.Length > secondPattern.Length)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event arguments class for training progress events.
|
||||
/// </summary>
|
||||
public class TrainingProgressEventArgs : EventArgs
|
||||
{
|
||||
private string mMessage;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for the training progress event arguments.
|
||||
/// </summary>
|
||||
/// <param name="message">
|
||||
/// Information message about the progress of training.
|
||||
/// </param>
|
||||
public TrainingProgressEventArgs(string message)
|
||||
{
|
||||
mMessage = message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Information message about the progress of training.
|
||||
/// </summary>
|
||||
public string Message
|
||||
{
|
||||
get
|
||||
{
|
||||
return mMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler delegate for the training progress event.
|
||||
/// </summary>
|
||||
public delegate void TrainingProgressEventHandler(object sender, TrainingProgressEventArgs e);
|
||||
|
||||
|
||||
}
|
||||
71
BotSharp.MachineLearning/Entropy/IContextGenerator.cs
Normal file
71
BotSharp.MachineLearning/Entropy/IContextGenerator.cs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the ContextGenerator.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// Generate contexts for maximum entropy decisions.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on ContextGenerator.java, $Revision: 1.1.1.1 $, $Date: 2001/10/23 14:06:53 $
|
||||
/// </version>
|
||||
public interface IContextGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds up the list of contextual predicates given an object.
|
||||
/// </summary>
|
||||
string[] GetContext(object input);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate contexts for maximum entropy decisions.
|
||||
/// </summary>
|
||||
public interface IContextGenerator<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds up the list of contextual predicates given an object of type T.
|
||||
/// </summary>
|
||||
string[] GetContext(T input);
|
||||
}
|
||||
|
||||
}
|
||||
151
BotSharp.MachineLearning/Entropy/IMaximumEntropyModel.cs
Normal file
151
BotSharp.MachineLearning/Entropy/IMaximumEntropyModel.cs
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the MaxentModel.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for maximum entropy models.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on MaxentModel.java, $Revision: 1.4 $, $Date: 2003/12/09 23:13:53 $
|
||||
/// </version>
|
||||
public interface IMaximumEntropyModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the number of outcomes for this model.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The number of outcomes.
|
||||
/// </returns>
|
||||
int OutcomeCount
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates a context.
|
||||
/// </summary>
|
||||
/// <param name="context">
|
||||
/// A list of string names of the contextual predicates
|
||||
/// which are to be evaluated together.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// An array of the probabilities for each of the different
|
||||
/// outcomes, all of which sum to 1.
|
||||
/// </returns>
|
||||
double[] Evaluate(string[] context);
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates a context.
|
||||
/// </summary>
|
||||
/// <param name="context">
|
||||
/// A list of string names of the contextual predicates
|
||||
/// which are to be evaluated together.
|
||||
/// </param>
|
||||
/// <param name="probabilities">
|
||||
/// An array which is populated with the probabilities for each of the different
|
||||
/// outcomes, all of which sum to 1.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// an array of the probabilities for each of the different
|
||||
/// outcomes, all of which sum to 1. The <code>probabilities</code> array is returned if it is appropiately sized.
|
||||
/// </returns>
|
||||
double[] Evaluate(string[] context, double[] probabilities);
|
||||
|
||||
/// <summary>
|
||||
/// Simple function to return the outcome associated with the index
|
||||
/// containing the highest probability in the double[].
|
||||
/// </summary>
|
||||
/// <param name="outcomes">
|
||||
/// A <code>double[]</code> as returned by the
|
||||
/// <code>Evaluate(string[] context)</code>
|
||||
/// method.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// the string name of the best outcome
|
||||
/// </returns>
|
||||
string GetBestOutcome(double[] outcomes);
|
||||
|
||||
/// <summary>
|
||||
/// Return a string matching all the outcome names with all the
|
||||
/// probabilities produced by the <code>eval(string[]
|
||||
/// context)</code> method.
|
||||
/// </summary>
|
||||
/// <param name="outcomes">
|
||||
/// A <code>double[]</code> as returned by the
|
||||
/// <code>eval(string[] context)</code>
|
||||
/// method.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// string containing outcome names paired with the normalized
|
||||
/// probability (contained in the <code>double[] ocs</code>)
|
||||
/// for each one.
|
||||
/// </returns>
|
||||
string GetAllOutcomes(double[] outcomes);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the string name of the outcome associated with the supplied index
|
||||
/// </summary>
|
||||
/// <param name="index">
|
||||
/// the index for which the name of the associated outcome is desired.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// the string name of the outcome
|
||||
/// </returns>
|
||||
string GetOutcomeName(int index);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index associated with the string name of the given
|
||||
/// outcome.
|
||||
/// </summary>
|
||||
/// <param name="outcome">
|
||||
/// the string name of the outcome for which the
|
||||
/// index is desired
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// the index if the given outcome label exists for this
|
||||
/// model, -1 if it does not.
|
||||
/// </returns>
|
||||
int GetOutcomeIndex(string outcome);
|
||||
}
|
||||
}
|
||||
175
BotSharp.MachineLearning/Entropy/IO/BinaryGisModelReader.cs
Normal file
175
BotSharp.MachineLearning/Entropy/IO/BinaryGisModelReader.cs
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the BinaryGISModelReader.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.MachineLearning.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// A reader for GIS models stored in a binary format. This format is not the one
|
||||
/// used by the <see cref="SharpEntropy.IO.JavaBinaryGisModelReader">java version of MaxEnt</see>.
|
||||
/// It has two main differences, designed for performance when loading the data
|
||||
/// from file: first, it uses big endian data values, which is native for C#, and secondly it
|
||||
/// encodes the outcome patterns and values in a more efficient manner.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on BinaryGISModelReader.java, $Revision: 1.1.1.1 $, $Date: 2001/10/23 14:06:53 $
|
||||
/// </version>
|
||||
public class BinaryGisModelReader : GisModelReader
|
||||
{
|
||||
private readonly Stream _input;
|
||||
private readonly byte[] _buffer;
|
||||
private int _stringLength = 0;
|
||||
private readonly Encoding _encoding = Encoding.UTF8;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor which directly instantiates the Stream containing
|
||||
/// the model contents.
|
||||
/// </summary>
|
||||
/// <param name="dataInputStream">
|
||||
/// The Stream containing the model information.
|
||||
/// </param>
|
||||
public BinaryGisModelReader(Stream dataInputStream)
|
||||
{
|
||||
using (_input = dataInputStream)
|
||||
{
|
||||
_buffer = new byte[256];
|
||||
base.ReadModel();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor which takes a filename and creates a reader for it.
|
||||
/// </summary>
|
||||
/// <param name="fileName">
|
||||
/// The full path and name of the file in which the model is stored.
|
||||
/// </param>
|
||||
public BinaryGisModelReader(string fileName)
|
||||
{
|
||||
using (_input = new FileStream(fileName, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
_buffer = new byte[256];
|
||||
base.ReadModel();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 32-bit signed integer from the model file.
|
||||
/// </summary>
|
||||
protected override int ReadInt32()
|
||||
{
|
||||
_input.Read(_buffer, 0, 4);
|
||||
return BitConverter.ToInt32(_buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a double-precision floating point number from the model file.
|
||||
/// </summary>
|
||||
protected override double ReadDouble()
|
||||
{
|
||||
_input.Read(_buffer, 0, 8);
|
||||
return BitConverter.ToDouble(_buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a UTF-8 encoded string from the model file.
|
||||
/// </summary>
|
||||
protected override string ReadString()
|
||||
{
|
||||
_stringLength = _input.ReadByte();
|
||||
_input.Read(_buffer, 0, _stringLength);
|
||||
return _encoding.GetString(_buffer, 0, _stringLength);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the predicate data from the file in a more efficient format to that implemented by
|
||||
/// GisModelReader.
|
||||
/// </summary>
|
||||
/// <param name="outcomePatterns">
|
||||
/// Jagged 2-dimensional array of integers that will contain the outcome patterns for the model
|
||||
/// after this method is called.
|
||||
/// </param>
|
||||
/// <param name="predicates">
|
||||
/// Dictionary that will contain the predicate information for the model
|
||||
/// after this method is called.
|
||||
/// </param>
|
||||
protected override void ReadPredicates(out int[][] outcomePatterns, out Dictionary<string, PatternedPredicate> predicates)
|
||||
{
|
||||
//read from the model how many outcome patterns there are
|
||||
int outcomePatternCount = ReadInt32();
|
||||
outcomePatterns = new int[outcomePatternCount][];
|
||||
//read from the model how many predicates there are
|
||||
predicates = new Dictionary<string, PatternedPredicate>(ReadInt32());
|
||||
|
||||
//for each outcome pattern in the model
|
||||
for (int currentOutcomePattern = 0; currentOutcomePattern < outcomePatternCount; currentOutcomePattern++)
|
||||
{
|
||||
//read the number of outcomes in this pattern. This number is 1 greater than the real number of outcomes
|
||||
//in the pattern, because the 0th value contains the number of predicates that use this pattern.
|
||||
var currentOutcomePatternLength = ReadInt32();
|
||||
outcomePatterns[currentOutcomePattern] = new int[currentOutcomePatternLength];
|
||||
//read in the outcomes for this pattern
|
||||
for (int currentOutcome = 0; currentOutcome <currentOutcomePatternLength; currentOutcome++)
|
||||
{
|
||||
outcomePatterns[currentOutcomePattern][currentOutcome] = ReadInt32();
|
||||
}
|
||||
//read in the details of the predicates in this pattern
|
||||
for (int currentPredicate = 0; currentPredicate < outcomePatterns[currentOutcomePattern][0]; currentPredicate++)
|
||||
{
|
||||
string predicateName = ReadString();
|
||||
//we know that the number of parameters in this predicate will be the number of outcomes in the pattern
|
||||
double[] parameters = new double[currentOutcomePatternLength - 1];
|
||||
//read in the parameters for this predicate
|
||||
for (int currentParameter = 0; currentParameter < currentOutcomePatternLength - 1; currentParameter++)
|
||||
{
|
||||
parameters[currentParameter] = ReadDouble();
|
||||
}
|
||||
predicates.Add(predicateName, new PatternedPredicate(currentOutcomePattern, parameters));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
186
BotSharp.MachineLearning/Entropy/IO/BinaryGisModelWriter.cs
Normal file
186
BotSharp.MachineLearning/Entropy/IO/BinaryGisModelWriter.cs
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the BinaryGISModelWriter.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace BotSharp.MachineLearning.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// A writer for GIS models that saves models in a binary format. This format is not the one
|
||||
/// used by the <see cref="SharpEntropy.IO.JavaBinaryGisModelWriter">java version of MaxEnt</see>.
|
||||
/// It has two main differences, designed for performance when loading the data
|
||||
/// from file: first, it uses big endian data values, which is native for C#, and secondly it
|
||||
/// encodes the outcome patterns and values in a more efficient manner.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on BinaryGISModelWriter.java $Revision: 1.1.1.1 $, $Date: 2001/10/23 14:06:53 $
|
||||
/// </version>
|
||||
public class BinaryGisModelWriter : GisModelWriter
|
||||
{
|
||||
private Stream _output;
|
||||
private byte[] _buffer = new byte[7];
|
||||
private readonly System.Text.Encoding _encoding = System.Text.Encoding.UTF8;
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public BinaryGisModelWriter(){}
|
||||
|
||||
/// <summary>
|
||||
/// Takes a GIS model and a file and
|
||||
/// writes the model to that file.
|
||||
/// </summary>
|
||||
/// <param name="model">
|
||||
/// The GisModel which is to be persisted.
|
||||
/// </param>
|
||||
/// <param name="fileName">
|
||||
/// The full path and name of the file in which the model is to be persisted.
|
||||
/// </param>
|
||||
public void Persist(GisModel model, string fileName)
|
||||
{
|
||||
using (_output = new FileStream(fileName, FileMode.Create))
|
||||
{
|
||||
base.Persist(model);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes a GIS model and a Stream and
|
||||
/// writes the model to that Stream.
|
||||
/// </summary>
|
||||
/// <param name="model">
|
||||
/// The GIS model which is to be persisted.
|
||||
/// </param>
|
||||
/// <param name="dataOutputStream">
|
||||
/// The Stream which will be used to persist the model.
|
||||
/// </param>
|
||||
public void Persist(GisModel model, Stream dataOutputStream)
|
||||
{
|
||||
using (_output = dataOutputStream)
|
||||
{
|
||||
base.Persist(model);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a UTF-8 encoded string to the model file.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// The string data to be persisted.
|
||||
/// </param>
|
||||
protected override void WriteString(string data)
|
||||
{
|
||||
_output.WriteByte((byte)_encoding.GetByteCount(data));
|
||||
_output.Write(_encoding.GetBytes(data), 0, _encoding.GetByteCount(data));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 32-bit signed integer to the model file.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// The integer data to be persisted.
|
||||
/// </param>
|
||||
protected override void WriteInt32(int data)
|
||||
{
|
||||
_buffer = BitConverter.GetBytes(data);
|
||||
_output.Write(_buffer, 0, 4);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a double-precision floating point number to the model file.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// The floating point data to be persisted.
|
||||
/// </param>
|
||||
protected override void WriteDouble(double data)
|
||||
{
|
||||
_buffer = BitConverter.GetBytes(data);
|
||||
_output.Write(_buffer, 0, 8);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the predicate data to the file in a more efficient format to that implemented by
|
||||
/// GisModelWriter.
|
||||
/// </summary>
|
||||
/// <param name="model">
|
||||
/// The GIS model containing the predicate data to be persisted.
|
||||
/// </param>
|
||||
protected override void WritePredicates(GisModel model)
|
||||
{
|
||||
int[][] outcomePatterns = model.GetOutcomePatterns();
|
||||
PatternedPredicate[] predicates = GetPredicates();
|
||||
|
||||
//write the number of outcome patterns
|
||||
WriteInt32(outcomePatterns.Length);
|
||||
|
||||
//write the number of predicates
|
||||
WriteInt32(predicates.Length);
|
||||
|
||||
int currentPredicate = 0;
|
||||
|
||||
for (int currentOutcomePattern = 0; currentOutcomePattern < outcomePatterns.Length; currentOutcomePattern++)
|
||||
{
|
||||
//write how many outcomes in this pattern
|
||||
WriteInt32(outcomePatterns[currentOutcomePattern].Length);
|
||||
|
||||
//write the outcomes in this pattern (the first value contains the number of predicates in the pattern
|
||||
//rather than an outcome)
|
||||
for (int currentOutcome = 0; currentOutcome < outcomePatterns[currentOutcomePattern].Length; currentOutcome++)
|
||||
{
|
||||
WriteInt32(outcomePatterns[currentOutcomePattern][currentOutcome]);
|
||||
}
|
||||
|
||||
//write predicates for this pattern
|
||||
while (currentPredicate < predicates.Length && predicates[currentPredicate].OutcomePattern == currentOutcomePattern)
|
||||
{
|
||||
WriteString(predicates[currentPredicate].Name);
|
||||
for (int currentParameter = 0; currentParameter < predicates[currentPredicate].ParameterCount; currentParameter++)
|
||||
{
|
||||
WriteDouble(predicates[currentPredicate].GetParameter(currentParameter));
|
||||
}
|
||||
currentPredicate++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
347
BotSharp.MachineLearning/Entropy/IO/GisModelReader.cs
Normal file
347
BotSharp.MachineLearning/Entropy/IO/GisModelReader.cs
Normal file
|
|
@ -0,0 +1,347 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the GISModelReader.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BotSharp.MachineLearning.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract parent class for readers of GIS models.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on GISModelReader.java, $Revision: 1.5 $, $Date: 2004/06/11 20:51:36 $
|
||||
/// </version>
|
||||
public abstract class GisModelReader : IGisModelReader
|
||||
{
|
||||
private char[] _spaces;
|
||||
private int _correctionConstant;
|
||||
private double _correctionParameter;
|
||||
private string[] _outcomeLabels;
|
||||
private int[][] _outcomePatterns;
|
||||
private int _predicateCount;
|
||||
private Dictionary<string, PatternedPredicate> _predicates;
|
||||
|
||||
/// <summary>
|
||||
/// The number of predicates contained in the model.
|
||||
/// </summary>
|
||||
protected int PredicateCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return _predicateCount;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a model from disk.
|
||||
///
|
||||
/// <p>This method delegates to worker methods for each part of this
|
||||
/// sequence. If you are creating a reader that conforms largely to this
|
||||
/// sequence but varies at one or more points, override the relevant worker
|
||||
/// method(s) to achieve the required format.</p>
|
||||
///
|
||||
/// <p>If you are creating a reader for a format which does not follow this
|
||||
/// sequence at all, override this method and ignore the
|
||||
/// other ReadX methods provided in this abstract class.</p>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Thie method assumes that models are saved in the
|
||||
/// following sequence:
|
||||
///
|
||||
/// <p>GIS (model type identifier)</p>
|
||||
/// <p>1. the correction constant (int)</p>
|
||||
/// <p>2. the correction constant parameter (double)</p>
|
||||
/// <p>3. outcomes</p>
|
||||
/// <p>3a. number of outcomes (int)</p>
|
||||
/// <p>3b. outcome names (string array - length specified in 3a)</p>
|
||||
/// <p>4. predicates</p>
|
||||
/// <p>4a. outcome patterns</p>
|
||||
/// <p>4ai. number of outcome patterns (int)</p>
|
||||
/// <p>4aii. outcome pattern values (each stored in a space delimited string)</p>
|
||||
/// <p>4b. predicate labels</p>
|
||||
/// <p>4bi. number of predicates (int)</p>
|
||||
/// <p>4bii. predicate names (string array - length specified in 4bi)</p>
|
||||
/// <p>4c. predicate parameters (double values)</p>
|
||||
/// </remarks>
|
||||
protected virtual void ReadModel()
|
||||
{
|
||||
_spaces = new char[] {' '}; //cached constant to improve performance
|
||||
CheckModelType();
|
||||
_correctionConstant = ReadCorrectionConstant();
|
||||
_correctionParameter = ReadCorrectionParameter();
|
||||
_outcomeLabels = ReadOutcomes();
|
||||
ReadPredicates(out _outcomePatterns, out _predicates);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks the model file being read from begins with the sequence of characters
|
||||
/// "GIS".
|
||||
/// </summary>
|
||||
protected virtual void CheckModelType()
|
||||
{
|
||||
string modelType = ReadString();
|
||||
if (modelType != "GIS")
|
||||
{
|
||||
throw new ApplicationException("Error: attempting to load a " + modelType + " model as a GIS model." + " You should expect problems.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the correction constant from the model file.
|
||||
/// </summary>
|
||||
protected virtual int ReadCorrectionConstant()
|
||||
{
|
||||
return ReadInt32();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the correction constant parameter from the model file.
|
||||
/// </summary>
|
||||
protected virtual double ReadCorrectionParameter()
|
||||
{
|
||||
return ReadDouble();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the outcome names from the model file.
|
||||
/// </summary>
|
||||
protected virtual string[] ReadOutcomes()
|
||||
{
|
||||
int outcomeCount = ReadInt32();
|
||||
var outcomeLabels = new string[outcomeCount];
|
||||
for (int currentLabel = 0; currentLabel < outcomeCount; currentLabel++)
|
||||
{
|
||||
outcomeLabels[currentLabel] = ReadString();
|
||||
}
|
||||
return outcomeLabels;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the predicate information from the model file, placing the data in two
|
||||
/// structures - an array of outcome patterns, and a Dictionary of predicates
|
||||
/// keyed by predicate name.
|
||||
/// </summary>
|
||||
protected virtual void ReadPredicates(out int[][] outcomePatterns, out Dictionary<string, PatternedPredicate> predicates)
|
||||
{
|
||||
outcomePatterns = ReadOutcomePatterns();
|
||||
string[] asPredicateLabels = ReadPredicateLabels();
|
||||
predicates = ReadParameters(outcomePatterns, asPredicateLabels);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the outcome pattern information from the model file.
|
||||
/// </summary>
|
||||
protected virtual int[][] ReadOutcomePatterns()
|
||||
{
|
||||
//get the number of outcome patterns (that is, the number of unique combinations of outcomes in the model)
|
||||
int outcomePatternCount = ReadInt32();
|
||||
//initialize an array of outcome patterns. Each outcome pattern is itself an array of integers
|
||||
var outcomePatterns = new int[outcomePatternCount][];
|
||||
//for each outcome pattern
|
||||
for (int currentOutcomePattern = 0; currentOutcomePattern < outcomePatternCount; currentOutcomePattern++)
|
||||
{
|
||||
//read a space delimited string from the model file containing the information for the integer array.
|
||||
//The first value in the integer array is the number of predicates related to this outcome pattern; the
|
||||
//other values make up the outcome IDs for this pattern.
|
||||
string[] tokens = ReadString().Split(_spaces);
|
||||
//convert this string to the array of integers required for the pattern
|
||||
var patternData = new int[tokens.Length];
|
||||
for (int currentPatternValue = 0; currentPatternValue < tokens.Length; currentPatternValue++)
|
||||
{
|
||||
patternData[currentPatternValue] = int.Parse(tokens[currentPatternValue], System.Globalization.CultureInfo.InvariantCulture);
|
||||
}
|
||||
outcomePatterns[currentOutcomePattern] = patternData;
|
||||
}
|
||||
return outcomePatterns;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the outcome labels from the model file.
|
||||
/// </summary>
|
||||
protected virtual string[] ReadPredicateLabels()
|
||||
{
|
||||
_predicateCount = ReadInt32();
|
||||
var predicateLabels = new string[_predicateCount];
|
||||
for (int currentPredicate = 0; currentPredicate < _predicateCount; currentPredicate++)
|
||||
{
|
||||
predicateLabels[currentPredicate] = ReadString();
|
||||
}
|
||||
return predicateLabels;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the predicate parameter information from the model file.
|
||||
/// </summary>
|
||||
protected virtual Dictionary<string, PatternedPredicate> ReadParameters(int[][] outcomePatterns, string[] predicateLabels)
|
||||
{
|
||||
var predicates = new Dictionary<string, PatternedPredicate>(predicateLabels.Length);
|
||||
int parameterIndex = 0;
|
||||
|
||||
for (int currentOutcomePattern = 0; currentOutcomePattern < outcomePatterns.Length; currentOutcomePattern++)
|
||||
{
|
||||
for (int currentOutcomeInfo = 0; currentOutcomeInfo < outcomePatterns[currentOutcomePattern][0]; currentOutcomeInfo++)
|
||||
{
|
||||
var parameters = new double[outcomePatterns[currentOutcomePattern].Length - 1];
|
||||
for (int currentParameter = 0; currentParameter < outcomePatterns[currentOutcomePattern].Length - 1; currentParameter++)
|
||||
{
|
||||
parameters[currentParameter] = ReadDouble();
|
||||
}
|
||||
predicates.Add(predicateLabels[parameterIndex], new PatternedPredicate(currentOutcomePattern, parameters));
|
||||
parameterIndex++;
|
||||
}
|
||||
}
|
||||
return predicates;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implement as needed for the format the model is stored in.
|
||||
/// </summary>
|
||||
protected abstract int ReadInt32();
|
||||
|
||||
/// <summary>
|
||||
/// Implement as needed for the format the model is stored in.
|
||||
/// </summary>
|
||||
protected abstract double ReadDouble();
|
||||
|
||||
/// <summary>
|
||||
/// Implement as needed for the format the model is stored in.
|
||||
/// </summary>
|
||||
protected abstract string ReadString();
|
||||
|
||||
/// <summary>
|
||||
/// The model's correction constant.
|
||||
/// </summary>
|
||||
public int CorrectionConstant
|
||||
{
|
||||
get
|
||||
{
|
||||
return _correctionConstant;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The model's correction constant parameter.
|
||||
/// </summary>
|
||||
public double CorrectionParameter
|
||||
{
|
||||
get
|
||||
{
|
||||
return _correctionParameter;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the labels for all the outcomes in the model.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// string array containing outcome labels.
|
||||
/// </returns>
|
||||
public string[] GetOutcomeLabels()
|
||||
{
|
||||
return _outcomeLabels;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the outcome patterns in the model.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Array of integer arrays containing the information for
|
||||
/// each outcome pattern in the model.
|
||||
/// </returns>
|
||||
public int[][] GetOutcomePatterns()
|
||||
{
|
||||
return _outcomePatterns;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the predicates in the model.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Dictionary containing PatternedPredicate objects keyed
|
||||
/// by predicate label.
|
||||
/// </returns>
|
||||
public Dictionary<string, PatternedPredicate> GetPredicates()
|
||||
{
|
||||
return _predicates;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns model information for a predicate, given the predicate label.
|
||||
/// </summary>
|
||||
/// <param name="predicateLabel">
|
||||
/// The predicate label to fetch information for.
|
||||
/// </param>
|
||||
/// <param name="featureCounts">
|
||||
/// Array to be passed in to the method; it should have a length equal to the number of outcomes
|
||||
/// in the model. The method increments the count of each outcome that is active in the specified
|
||||
/// predicate.
|
||||
/// </param>
|
||||
/// <param name="outcomeSums">
|
||||
/// Array to be passed in to the method; it should have a length equal to the number of outcomes
|
||||
/// in the model. The method adds the parameter values for each of the active outcomes in the
|
||||
/// predicate.
|
||||
/// </param>
|
||||
public virtual void GetPredicateData(string predicateLabel, int[] featureCounts, double[] outcomeSums)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (predicateLabel != null && _predicates.ContainsKey(predicateLabel))
|
||||
{
|
||||
PatternedPredicate predicate = _predicates[predicateLabel];
|
||||
int[] activeOutcomes = _outcomePatterns[predicate.OutcomePattern];
|
||||
|
||||
for (int currentActiveOutcome = 1; currentActiveOutcome < activeOutcomes.Length; currentActiveOutcome++)
|
||||
{
|
||||
int outcomeIndex = activeOutcomes[currentActiveOutcome];
|
||||
featureCounts[outcomeIndex]++;
|
||||
outcomeSums[outcomeIndex] += predicate.GetParameter(currentActiveOutcome - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
throw new ArgumentException(string.Format("Try to find key '{0}' in predicates dictionary ({1} entries)", predicateLabel, _predicates.Count), ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
313
BotSharp.MachineLearning/Entropy/IO/GisModelWriter.cs
Normal file
313
BotSharp.MachineLearning/Entropy/IO/GisModelWriter.cs
Normal file
|
|
@ -0,0 +1,313 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the GISModeWriter.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.MachineLearning.IO
|
||||
{
|
||||
/// <summary> Abstract parent class for GIS model writers that save data to a single
|
||||
/// file. It provides the persist method which takes care of the structure of a stored
|
||||
/// document, and requires an extending class to define precisely how the data should
|
||||
/// be stored.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on GISModelWriter.java, $Revision: 1.5 $, $Date: 2004/06/11 20:51:36 $
|
||||
/// </version>
|
||||
public abstract class GisModelWriter
|
||||
{
|
||||
private PatternedPredicate[] mPredicates;
|
||||
|
||||
/// <summary>
|
||||
/// Implement as needed for the format the model is stored in.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// string data to be written to storage.
|
||||
/// </param>
|
||||
protected abstract void WriteString(string data);
|
||||
|
||||
/// <summary>
|
||||
/// Implement as needed for the format the model is stored in.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// Integer data to be written to storage.
|
||||
/// </param>
|
||||
protected abstract void WriteInt32(int data);
|
||||
|
||||
/// <summary>
|
||||
/// Implement as needed for the format the model is stored in.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// Double precision floating point data to be written to storage.
|
||||
/// </param>
|
||||
protected abstract void WriteDouble(double data);
|
||||
|
||||
/// <summary>
|
||||
/// Obtains a list of the predicates in the model to be written to storage.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Array of PatternedPredicate objects containing the predicate data for the model.
|
||||
/// </returns>
|
||||
protected PatternedPredicate[] GetPredicates()
|
||||
{
|
||||
return mPredicates;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the list of predicates to be written to storage.
|
||||
/// </summary>
|
||||
/// <param name="predicates">
|
||||
/// Array of PatternedPredicate objects to be persisted.
|
||||
/// </param>
|
||||
protected void SetPredicates(PatternedPredicate[] predicates)
|
||||
{
|
||||
mPredicates = predicates;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the model to persistent storage, using the <code>writeX()</code> methods
|
||||
/// provided by extending classes.
|
||||
///
|
||||
/// <p>This method delegates to worker methods for each part of this
|
||||
/// sequence. If you are creating a writer that conforms largely to this
|
||||
/// sequence but varies at one or more points, override the relevant worker
|
||||
/// method(s) to achieve the required format.</p>
|
||||
///
|
||||
/// <p>If you are creating a writer for a format which does not follow this
|
||||
/// sequence at all, override this method and ignore the
|
||||
/// other WriteX methods provided in this abstract class.</p>
|
||||
/// </summary>
|
||||
/// <param name="model">
|
||||
/// GIS model whose data is to be persisted.
|
||||
/// </param>
|
||||
protected void Persist(GisModel model)
|
||||
{
|
||||
Initialize(model);
|
||||
WriteModelType("GIS");
|
||||
WriteCorrectionConstant(model.CorrectionConstant);
|
||||
WriteCorrectionParameter(model.CorrectionParameter);
|
||||
WriteOutcomes(model.GetOutcomeNames());
|
||||
WritePredicates(model);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Organises the data available in the GIS model into a structure that is easier to
|
||||
/// persist from.
|
||||
/// </summary>
|
||||
/// <param name="model">
|
||||
/// The GIS model to be persisted.
|
||||
///</param>
|
||||
protected virtual void Initialize(GisModel model)
|
||||
{
|
||||
//read the predicates from the model
|
||||
Dictionary<string, PatternedPredicate> predicates = model.GetPredicates();
|
||||
//build arrays of predicates and predicate names from the dictionary
|
||||
mPredicates = new PatternedPredicate[predicates.Count];
|
||||
var predicateNames = new string[predicates.Count];
|
||||
predicates.Values.CopyTo(mPredicates, 0);
|
||||
predicates.Keys.CopyTo(predicateNames, 0);
|
||||
//give each PatternedPredicate in the array the name taken from the dictionary keys
|
||||
for (int currentPredicate = 0; currentPredicate < predicates.Count; currentPredicate++)
|
||||
{
|
||||
mPredicates[currentPredicate].Name = predicateNames[currentPredicate];
|
||||
}
|
||||
//sort the PatternedPredicate array based on the outcome pattern that each predicate uses
|
||||
Array.Sort(mPredicates, new OutcomePatternIndexComparer());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the model type identifier at the beginning of the file.
|
||||
/// </summary>
|
||||
/// <param name="modelType">string identifying the model type.</param>
|
||||
protected virtual void WriteModelType(string modelType)
|
||||
{
|
||||
WriteString(modelType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the value of the correction constant
|
||||
/// </summary>
|
||||
/// <param name="correctionConstant">the model's correction constant value.</param>
|
||||
protected virtual void WriteCorrectionConstant(int correctionConstant)
|
||||
{
|
||||
WriteInt32(correctionConstant);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the value of the correction constant parameter.
|
||||
/// </summary>
|
||||
/// <param name="correctionParameter">the model's correction constant parameter.</param>
|
||||
protected virtual void WriteCorrectionParameter(double correctionParameter)
|
||||
{
|
||||
WriteDouble(correctionParameter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the outcome labels to the file.
|
||||
/// </summary>
|
||||
/// <param name="outcomeLabels">string array of outcome labels.</param>
|
||||
protected virtual void WriteOutcomes(string[] outcomeLabels)
|
||||
{
|
||||
//write the number of outcomes
|
||||
WriteInt32(outcomeLabels.Length);
|
||||
|
||||
//write each label
|
||||
foreach (string label in outcomeLabels)
|
||||
{
|
||||
WriteString(label);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the predicate information to the model file.
|
||||
/// </summary>
|
||||
/// <param name="model">The GIS model to write the data from.</param>
|
||||
protected virtual void WritePredicates(GisModel model)
|
||||
{
|
||||
WriteOutcomePatterns(model.GetOutcomePatterns());
|
||||
WritePredicateNames();
|
||||
WriteParameters();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the outcome pattern data to the file.
|
||||
/// </summary>
|
||||
/// <param name="outcomePatterns">
|
||||
/// Array of outcome patterns, each an integer array containing
|
||||
/// the number of predicates using the pattern, and then the list of
|
||||
/// outcome IDs in the pattern.
|
||||
/// </param>
|
||||
protected void WriteOutcomePatterns(int[][] outcomePatterns)
|
||||
{
|
||||
//write the number of outcome patterns
|
||||
WriteInt32(outcomePatterns.Length);
|
||||
|
||||
//for each pattern
|
||||
foreach (int[] pattern in outcomePatterns)
|
||||
{
|
||||
//build a string with the pattern values separated by spaces
|
||||
var outcomePatternBuilder = new StringBuilder();
|
||||
for (int currentOutcome = 0; currentOutcome < pattern.Length; currentOutcome++)
|
||||
{
|
||||
if (currentOutcome > 0)
|
||||
{
|
||||
outcomePatternBuilder.Append(" ");
|
||||
}
|
||||
outcomePatternBuilder.Append(pattern[currentOutcome]);
|
||||
}
|
||||
//write the string containing pattern values to the file
|
||||
WriteString(outcomePatternBuilder.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the names of the predicates to the model file.
|
||||
/// </summary>
|
||||
protected void WritePredicateNames()
|
||||
{
|
||||
//write the number of predicates
|
||||
WriteInt32(mPredicates.Length);
|
||||
|
||||
//for each predicate, write its name to the file
|
||||
foreach (PatternedPredicate predicate in mPredicates)
|
||||
{
|
||||
WriteString(predicate.Name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes out the parameter values for all the predicates to the model file.
|
||||
/// </summary>
|
||||
protected void WriteParameters()
|
||||
{
|
||||
foreach (PatternedPredicate predicate in mPredicates)
|
||||
{
|
||||
for (int currentParameter = 0; currentParameter < predicate.ParameterCount; currentParameter++)
|
||||
{
|
||||
WriteDouble(predicate.GetParameter(currentParameter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class to enable sorting PatternedPredicates into order based on the
|
||||
/// outcome pattern index.
|
||||
/// </summary>
|
||||
private class OutcomePatternIndexComparer : IComparer<PatternedPredicate>
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
internal OutcomePatternIndexComparer(){}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of the IComparer interface.
|
||||
/// Compares two PatternedPredicate objects and returns a value indicating whether
|
||||
/// one is less than, equal to or greater than the other.
|
||||
/// </summary>
|
||||
/// <param name="firstPredicate">
|
||||
/// First object to compare.
|
||||
/// </param>
|
||||
/// <param name="secondPredicate">
|
||||
/// Second object to compare.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// -1 if the first PatternedPredicate has a lower outcome pattern index;
|
||||
/// 1 if the second PatternedPredicate has a lower outcome pattern index;
|
||||
/// 0 if they both have the same outcome pattern index.
|
||||
/// </returns>
|
||||
public virtual int Compare(PatternedPredicate firstPredicate, PatternedPredicate secondPredicate)
|
||||
{
|
||||
if (firstPredicate.OutcomePattern < secondPredicate.OutcomePattern)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (firstPredicate.OutcomePattern > secondPredicate.OutcomePattern)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
87
BotSharp.MachineLearning/Entropy/IO/IGisModelReader.cs
Normal file
87
BotSharp.MachineLearning/Entropy/IO/IGisModelReader.cs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file has no equivalent in the java MaxEnt library, because the link
|
||||
//between GISModel and GISModelReader is implemented differently there. This
|
||||
//interface is designed so that GIS model reader classes can hold some or all of
|
||||
//their data in persistent storage rather than in memory.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BotSharp.MachineLearning.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for readers of GIS models.
|
||||
/// </summary>
|
||||
public interface IGisModelReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the value of the model's correction constant. This property should
|
||||
/// usually only be accessed by GIS model writer classes via the GisModel class.
|
||||
/// </summary>
|
||||
int CorrectionConstant
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the value of the model's correction constant parameter. This property should
|
||||
/// usually only be accessed by GIS model writer classes via the GisModel class.
|
||||
/// </summary>
|
||||
double CorrectionParameter
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the model's outcome labels as a string array. This method should
|
||||
/// usually only be accessed by GIS model writer classes via the GisModel class.
|
||||
/// </summary>
|
||||
string[] GetOutcomeLabels();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the model's outcome patterns. This method should
|
||||
/// usually only be accessed by GIS model writer classes via the GisModel class.
|
||||
/// </summary>
|
||||
int[][] GetOutcomePatterns();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the model's predicates. This method should
|
||||
/// usually only be accessed by GIS model writer classes via the GisModel class.
|
||||
/// </summary>
|
||||
Dictionary<string, PatternedPredicate> GetPredicates();
|
||||
|
||||
/// <summary>
|
||||
/// Returns model information for a predicate, given the predicate label.
|
||||
/// </summary>
|
||||
/// <param name="predicateLabel">
|
||||
/// The predicate label to fetch information for.
|
||||
/// </param>
|
||||
/// <param name="featureCounts">
|
||||
/// Array to be passed in to the method; it should have a length equal to the number of outcomes
|
||||
/// in the model. The method increments the count of each outcome that is active in the specified
|
||||
/// predicate.
|
||||
/// </param>
|
||||
/// <param name="outcomeSums">
|
||||
/// Array to be passed in to the method; it should have a length equal to the number of outcomes
|
||||
/// in the model. The method adds the parameter values for each of the active outcomes in the
|
||||
/// predicate.
|
||||
/// </param>
|
||||
void GetPredicateData(string predicateLabel, int[] featureCounts, double[] outcomeSums);
|
||||
|
||||
}
|
||||
}
|
||||
123
BotSharp.MachineLearning/Entropy/IO/JavaBinaryGisModelReader.cs
Normal file
123
BotSharp.MachineLearning/Entropy/IO/JavaBinaryGisModelReader.cs
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the BinaryGISModelReader.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace BotSharp.MachineLearning.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// A reader for GIS models stored in the binary format produced by the java version
|
||||
/// of MaxEnt. This binary format stores data using big-endian values, which means
|
||||
/// that the C# version must reverse the byte order of each value in turn, making it
|
||||
/// less efficient. Use only for compatibility with the java MaxEnt library.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on BinaryGISModelReader.java, $Revision: 1.1.1.1 $, $Date: 2001/10/23 14:06:53 $
|
||||
/// </version>
|
||||
public class JavaBinaryGisModelReader : GisModelReader
|
||||
{
|
||||
private readonly Stream _input;
|
||||
private readonly byte[] _buffer;
|
||||
private int _stringLength = 0;
|
||||
private readonly System.Text.Encoding _encoding = System.Text.Encoding.UTF8;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor which directly instantiates the Stream containing
|
||||
/// the model contents.
|
||||
/// </summary>
|
||||
/// <param name="dataInputStream">The Stream containing the model information.
|
||||
/// </param>
|
||||
public JavaBinaryGisModelReader(Stream dataInputStream)
|
||||
{
|
||||
using (_input = dataInputStream)
|
||||
{
|
||||
_buffer = new byte[256];
|
||||
base.ReadModel();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor which takes a filename and creates a reader for it.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The full path and name of the file in which the model is stored.
|
||||
/// </param>
|
||||
public JavaBinaryGisModelReader(string fileName)
|
||||
{
|
||||
using (_input = new FileStream(fileName, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
_buffer = new byte[256];
|
||||
base.ReadModel();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 32-bit signed integer from the model file.
|
||||
/// </summary>
|
||||
protected override int ReadInt32()
|
||||
{
|
||||
_input.Read(_buffer, 0, 4);
|
||||
Array.Reverse(_buffer, 0, 4);
|
||||
return BitConverter.ToInt32(_buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a double-precision floating point number from the model file.
|
||||
/// </summary>
|
||||
protected override double ReadDouble()
|
||||
{
|
||||
_input.Read(_buffer, 0, 8);
|
||||
Array.Reverse(_buffer, 0, 8);
|
||||
return BitConverter.ToDouble(_buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a UTF-8 encoded string from the model file.
|
||||
/// </summary>
|
||||
protected override string ReadString()
|
||||
{
|
||||
//read string from binary file with UTF8 encoding
|
||||
_stringLength = (_input.ReadByte() * 256) + _input.ReadByte();
|
||||
_input.Read(_buffer, 0, _stringLength);
|
||||
return _encoding.GetString(_buffer, 0, _stringLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
140
BotSharp.MachineLearning/Entropy/IO/JavaBinaryGisModelWriter.cs
Normal file
140
BotSharp.MachineLearning/Entropy/IO/JavaBinaryGisModelWriter.cs
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the BinaryGISModelWriter.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace BotSharp.MachineLearning.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// A writer for GIS models that saves models in the binary format used by the java
|
||||
/// version of MaxEnt. This binary format stores data using big-endian values, which means
|
||||
/// that the C# version must reverse the byte order of each value in turn, making it
|
||||
/// less efficient. Use only for compatibility with the java MaxEnt library.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on BinaryGISModelWriter.java $Revision: 1.1.1.1 $, $Date: 2001/10/23 14:06:53 $
|
||||
/// </version>
|
||||
public class JavaBinaryGisModelWriter : GisModelWriter
|
||||
{
|
||||
private Stream mOutput;
|
||||
private byte[] mBuffer = new byte[7];
|
||||
private System.Text.Encoding mEncoding = System.Text.Encoding.UTF8;
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public JavaBinaryGisModelWriter()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary> Takes a GisModel and a File and
|
||||
/// writes the model to that file.
|
||||
/// </summary>
|
||||
/// <param name="model">The GisModel which is to be persisted.
|
||||
/// </param>
|
||||
/// <param name="fileName">The name of the file in which the model is to be persisted.
|
||||
/// </param>
|
||||
public void Persist(GisModel model, string fileName)
|
||||
{
|
||||
using (mOutput = new FileStream(fileName, FileMode.Create))
|
||||
{
|
||||
base.Persist(model);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes a GisModel and a Stream and writes the model to that stream.
|
||||
/// </summary>
|
||||
/// <param name="model">
|
||||
/// The GIS model which is to be persisted.
|
||||
/// </param>
|
||||
/// <param name="dataOutputStream">
|
||||
/// The Stream which will be used to persist the model.
|
||||
/// </param>
|
||||
public void Persist(GisModel model, Stream dataOutputStream)
|
||||
{
|
||||
using (mOutput = dataOutputStream)
|
||||
{
|
||||
base.Persist(model);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a UTF-8 encoded string to the model file.
|
||||
/// </summary>
|
||||
/// /// <param name="data">
|
||||
/// The string data to be persisted.
|
||||
/// </param>
|
||||
protected override void WriteString(string data)
|
||||
{
|
||||
mOutput.WriteByte((byte)(mEncoding.GetByteCount(data) / 256));
|
||||
mOutput.WriteByte((byte)(mEncoding.GetByteCount(data) % 256));
|
||||
mOutput.Write(mEncoding.GetBytes(data), 0, mEncoding.GetByteCount(data));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 32-bit signed integer to the model file.
|
||||
/// </summary>
|
||||
/// /// <param name="data">
|
||||
/// The integer data to be persisted.
|
||||
/// </param>
|
||||
protected override void WriteInt32(int data)
|
||||
{
|
||||
mBuffer = BitConverter.GetBytes(data);
|
||||
Array.Reverse(mBuffer);
|
||||
mOutput.Write(mBuffer, 0, 4);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a double-precision floating point number to the model file.
|
||||
/// </summary>
|
||||
/// /// <param name="data">
|
||||
/// The floating point data to be persisted.
|
||||
/// </param>
|
||||
protected override void WriteDouble(double data)
|
||||
{
|
||||
mBuffer = BitConverter.GetBytes(data);
|
||||
Array.Reverse(mBuffer);
|
||||
mOutput.Write(mBuffer, 0, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
111
BotSharp.MachineLearning/Entropy/IO/PlainTextGisModelReader.cs
Normal file
111
BotSharp.MachineLearning/Entropy/IO/PlainTextGisModelReader.cs
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the PlainTextGISModelReader.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace BotSharp.MachineLearning.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// A reader for GIS models stored in plain text format.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on PlainTextGISModelReader.java, $Revision: 1.1.1.1 $, $Date: 2001/10/23 14:06:53 $
|
||||
/// </version>
|
||||
public class PlainTextGisModelReader : GisModelReader
|
||||
{
|
||||
private StreamReader mInput;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor which directly instantiates the StreamReader containing
|
||||
/// the model contents.
|
||||
/// </summary>
|
||||
/// <param name="reader">
|
||||
/// The StreamReader containing the model information.
|
||||
/// </param>
|
||||
public PlainTextGisModelReader(StreamReader reader)
|
||||
{
|
||||
using (mInput = reader)
|
||||
{
|
||||
base.ReadModel();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor which takes a file and creates a reader for it.
|
||||
/// </summary>
|
||||
/// <param name="fileName">
|
||||
/// The full path and file name in which the model is stored.
|
||||
/// </param>
|
||||
public PlainTextGisModelReader(string fileName)
|
||||
{
|
||||
using (mInput = new StreamReader(fileName, System.Text.Encoding.UTF7))
|
||||
{
|
||||
base.ReadModel();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 32-bit signed integer from the model file.
|
||||
/// </summary>
|
||||
protected override int ReadInt32()
|
||||
{
|
||||
return int.Parse(mInput.ReadLine(), System.Globalization.CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a double-precision floating point number from the model file.
|
||||
/// </summary>
|
||||
protected override double ReadDouble()
|
||||
{
|
||||
return double.Parse(mInput.ReadLine(), System.Globalization.CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a string from the model file.
|
||||
/// </summary>
|
||||
protected override string ReadString()
|
||||
{
|
||||
return mInput.ReadLine();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
134
BotSharp.MachineLearning/Entropy/IO/PlainTextGisModelWriter.cs
Normal file
134
BotSharp.MachineLearning/Entropy/IO/PlainTextGisModelWriter.cs
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
// Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the PlainTextGISModelReader.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace BotSharp.MachineLearning.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// Model writer that saves models in plain text format.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on PlainTextGISModelWriter.java, $Revision: 1.1.1.1 $, $Date: 2001/10/23 14:06:53 $
|
||||
/// </version>
|
||||
public class PlainTextGisModelWriter : GisModelWriter
|
||||
{
|
||||
private StreamWriter mOutput;
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public PlainTextGisModelWriter()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes a GIS model and a file and writes the model to that file.
|
||||
/// </summary>
|
||||
/// <param name="model">
|
||||
/// The GisModel which is to be persisted.
|
||||
/// </param>
|
||||
/// <param name="fileName">
|
||||
/// The name of the file in which the model is to be persisted.
|
||||
/// </param>
|
||||
public void Persist(GisModel model, string fileName)
|
||||
{
|
||||
using (mOutput = new StreamWriter(fileName, false, System.Text.Encoding.UTF7))
|
||||
{
|
||||
base.Persist(model);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes a GisModel and a stream and writes the model to that stream.
|
||||
/// </summary>
|
||||
/// <param name="model">
|
||||
/// The GisModel which is to be persisted.
|
||||
/// </param>
|
||||
/// <param name="writer">
|
||||
/// The StreamWriter which will be used to persist the model.
|
||||
/// </param>
|
||||
public void Persist(GisModel model, StreamWriter writer)
|
||||
{
|
||||
using (mOutput = writer)
|
||||
{
|
||||
base.Persist(model);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a string to the model file.
|
||||
/// </summary>
|
||||
/// /// <param name="data">
|
||||
/// The string data to be persisted.
|
||||
/// </param>
|
||||
protected override void WriteString(string data)
|
||||
{
|
||||
mOutput.Write(data);
|
||||
mOutput.WriteLine();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 32-bit signed integer to the model file.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// The integer data to be persisted.
|
||||
/// </param>
|
||||
protected override void WriteInt32(int data)
|
||||
{
|
||||
mOutput.Write(data.ToString(System.Globalization.CultureInfo.InvariantCulture));
|
||||
mOutput.WriteLine();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a double-precision floating point number to the model file.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// The floating point data to be persisted.
|
||||
/// </param>
|
||||
protected override void WriteDouble(double data)
|
||||
{
|
||||
mOutput.Write(data.ToString(System.Globalization.CultureInfo.InvariantCulture));
|
||||
mOutput.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
86
BotSharp.MachineLearning/Entropy/ITrainingDataIndexer.cs
Normal file
86
BotSharp.MachineLearning/Entropy/ITrainingDataIndexer.cs
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the DataIndexer.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
//Copyright (C) 2003 Thomas Morton
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//GNU General Public License for more details.
|
||||
//
|
||||
//You should have received a copy of the GNU Lesser General Public
|
||||
//License along with this program; if not, write to the Free Software
|
||||
//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// Object that compresses events in memory and performs feature selection.
|
||||
/// </summary>
|
||||
public interface ITrainingDataIndexer
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array of context data calculated from the training data.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Array of integer arrays, each containing the context data for an event.
|
||||
/// </returns>
|
||||
int[][] GetContexts();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array indicating how many times each event is seen.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Integer array with event frequencies.
|
||||
/// </returns>
|
||||
int[] GetNumTimesEventsSeen();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an outcome list.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Integer array of outcomes.
|
||||
/// </returns>
|
||||
int[] GetOutcomeList();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array of predicate labels.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Array of predicate labels.
|
||||
/// </returns>
|
||||
string[] GetPredicateLabels();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array of outcome labels.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Array of outcome labels.
|
||||
/// </returns>
|
||||
string[] GetOutcomeLabels();
|
||||
}
|
||||
}
|
||||
74
BotSharp.MachineLearning/Entropy/ITrainingDataReader.cs
Normal file
74
BotSharp.MachineLearning/Entropy/ITrainingDataReader.cs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the DataStream.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// A interface for objects which can deliver a stream of training data to be
|
||||
/// supplied to an ITrainingEventReader. It is not necessary to use a ITrainingDataReader in a
|
||||
/// SharpEntropy application, but it can be used to support a wider variety of formats
|
||||
/// in which your training data can be held.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on DataStream.java, $Revision: 1.1.1.1 $, $Date: 2001/10/23 14:06:53 $
|
||||
/// </version>
|
||||
public interface ITrainingDataReader<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the next slice of data held in this ITrainingDataReader.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// the object representing the data which is next in this
|
||||
/// ITrainingDataReader
|
||||
/// </returns>
|
||||
T NextToken();
|
||||
|
||||
/// <summary>
|
||||
/// Test whether there are any training data items remaining in this ITrainingDataReader.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// true if this ITrainingDataReader has more data tokens
|
||||
/// </returns>
|
||||
bool HasNext();
|
||||
}
|
||||
}
|
||||
66
BotSharp.MachineLearning/Entropy/ITrainingEventReader.cs
Normal file
66
BotSharp.MachineLearning/Entropy/ITrainingEventReader.cs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the EventStream.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// An object which can deliver a stream of training events for the GIS
|
||||
/// procedure (or others such as IIS if and when they are implemented).
|
||||
/// TrainingEventReaders don't need to use SharpEntropy.ITrainingDataReader, but doing so
|
||||
/// would provide greater flexibility for producing events from data stored in
|
||||
/// different formats.
|
||||
/// </summary>
|
||||
public interface ITrainingEventReader
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Returns the next TrainingEvent object held in this TrainingEventReader.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// the TrainingEvent object which is next in this TrainingEventReader
|
||||
/// </returns>
|
||||
TrainingEvent ReadNextEvent();
|
||||
|
||||
/// <summary>
|
||||
/// Test whether there are any TrainingEvents remaining in this TrainingEventReader.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// true if this TrainingEventReader has more TrainingEvents
|
||||
/// </returns>
|
||||
bool HasNext();
|
||||
}
|
||||
}
|
||||
212
BotSharp.MachineLearning/Entropy/OnePassDataIndexer.cs
Normal file
212
BotSharp.MachineLearning/Entropy/OnePassDataIndexer.cs
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the OnePassDataIndexer.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// An indexer for maxent model data which handles cutoffs for uncommon
|
||||
/// contextual predicates and provides a unique integer index for each of the
|
||||
/// predicates. The data structures built in the constructor of this class are
|
||||
/// used by the GIS trainer.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on OnePassDataIndexer.java, $Revision: 1.1 $, $Date: 2003/12/13 16:41:29 $
|
||||
/// </version>
|
||||
public class OnePassDataIndexer : AbstractDataIndexer
|
||||
{
|
||||
/// <summary>
|
||||
/// One argument constructor for OnePassDataIndexer which calls the two argument
|
||||
/// constructor assuming no cutoff.
|
||||
/// </summary>
|
||||
/// <param name="eventReader">
|
||||
/// An ITrainingEventReader which contains the a list of all the Events
|
||||
/// seen in the training data.
|
||||
/// </param>
|
||||
public OnePassDataIndexer(ITrainingEventReader eventReader) : this(eventReader, 0)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Two argument constructor for OnePassDataIndexer.
|
||||
/// </summary>
|
||||
/// <param name="eventReader">
|
||||
/// An ITrainingEventReader which contains the a list of all the Events
|
||||
/// seen in the training data.
|
||||
/// </param>
|
||||
/// <param name="cutoff">
|
||||
/// The minimum number of times a predicate must have been
|
||||
/// observed in order to be included in the model.
|
||||
/// </param>
|
||||
public OnePassDataIndexer(ITrainingEventReader eventReader, int cutoff)
|
||||
{
|
||||
Dictionary<string, int> predicateIndex;
|
||||
List<TrainingEvent> events;
|
||||
List<ComparableEvent> eventsToCompare;
|
||||
|
||||
predicateIndex = new Dictionary<string, int>();
|
||||
//NotifyProgress("Indexing events using cutoff of " + cutoff + "\n");
|
||||
|
||||
//NotifyProgress("\tComputing event counts... ");
|
||||
events = ComputeEventCounts(eventReader, predicateIndex, cutoff);
|
||||
//NotifyProgress("done. " + events.Count + " events");
|
||||
|
||||
//NotifyProgress("\tIndexing... ");
|
||||
eventsToCompare = Index(events, predicateIndex);
|
||||
|
||||
//NotifyProgress("done.");
|
||||
|
||||
//NotifyProgress("Sorting and merging oEvents... ");
|
||||
SortAndMerge(eventsToCompare);
|
||||
//NotifyProgress("Done indexing.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads events from <tt>eventReader</tt> into a List<TrainingEvent>. The
|
||||
/// predicates associated with each event are counted and any which
|
||||
/// occur at least <tt>cutoff</tt> times are added to the
|
||||
/// <tt>predicatesInOut</tt> dictionary along with a unique integer index.
|
||||
/// </summary>
|
||||
/// <param name="eventReader">
|
||||
/// an <code>ITrainingEventReader</code> value
|
||||
/// </param>
|
||||
/// <param name="predicatesInOut">
|
||||
/// a <code>Dictionary</code> value
|
||||
/// </param>
|
||||
/// <param name="cutoff">
|
||||
/// an <code>int</code> value
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// an <code>List of TrainingEvents</code> value
|
||||
/// </returns>
|
||||
private List<TrainingEvent> ComputeEventCounts(ITrainingEventReader eventReader, Dictionary<string, int> predicatesInOut, int cutoff)
|
||||
{
|
||||
var counter = new Dictionary<string, int>();
|
||||
var events = new List<TrainingEvent>();
|
||||
int predicateIndex = 0;
|
||||
while (eventReader.HasNext())
|
||||
{
|
||||
TrainingEvent trainingEvent = eventReader.ReadNextEvent();
|
||||
events.Add(trainingEvent);
|
||||
string[] eventContext = trainingEvent.Context;
|
||||
for (int currentEventContext = 0; currentEventContext < eventContext.Length; currentEventContext++)
|
||||
{
|
||||
if (!predicatesInOut.ContainsKey(eventContext[currentEventContext]))
|
||||
{
|
||||
if (counter.ContainsKey(eventContext[currentEventContext]))
|
||||
{
|
||||
counter[eventContext[currentEventContext]]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
counter.Add(eventContext[currentEventContext], 1);
|
||||
}
|
||||
if (counter[eventContext[currentEventContext]] >= cutoff)
|
||||
{
|
||||
predicatesInOut.Add(eventContext[currentEventContext], predicateIndex++);
|
||||
counter.Remove(eventContext[currentEventContext]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
private List<ComparableEvent> Index(List<TrainingEvent> events, Dictionary<string, int> predicateIndex)
|
||||
{
|
||||
var map = new Dictionary<string, int>();
|
||||
|
||||
int eventCount = events.Count;
|
||||
int outcomeCount = 0;
|
||||
|
||||
var eventsToCompare = new List<ComparableEvent>(eventCount);
|
||||
var indexedContext = new List<int>();
|
||||
|
||||
for (int eventIndex = 0; eventIndex < eventCount; eventIndex++)
|
||||
{
|
||||
TrainingEvent currentTrainingEvent = events[eventIndex];
|
||||
string[] eventContext = currentTrainingEvent.Context;
|
||||
ComparableEvent comparableEvent;
|
||||
|
||||
int outcomeIndex;
|
||||
|
||||
string outcome = currentTrainingEvent.Outcome;
|
||||
|
||||
if (map.ContainsKey(outcome))
|
||||
{
|
||||
outcomeIndex = map[outcome];
|
||||
}
|
||||
else
|
||||
{
|
||||
outcomeIndex = outcomeCount++;
|
||||
map.Add(outcome, outcomeIndex);
|
||||
}
|
||||
|
||||
for (int currentEventContext = 0; currentEventContext < eventContext.Length; currentEventContext++)
|
||||
{
|
||||
string predicate = eventContext[currentEventContext];
|
||||
if (predicateIndex.ContainsKey(predicate))
|
||||
{
|
||||
indexedContext.Add(predicateIndex[predicate]);
|
||||
}
|
||||
}
|
||||
|
||||
// drop events with no active features
|
||||
if (indexedContext.Count > 0)
|
||||
{
|
||||
comparableEvent = new ComparableEvent(outcomeIndex, indexedContext.ToArray());
|
||||
eventsToCompare.Add(comparableEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
//"Dropped event " + oEvent.Outcome + ":" + oEvent.Context);
|
||||
}
|
||||
// recycle the list
|
||||
indexedContext.Clear();
|
||||
}
|
||||
SetOutcomeLabels(ToIndexedStringArray(map));
|
||||
SetPredicateLabels(ToIndexedStringArray(predicateIndex));
|
||||
return eventsToCompare;
|
||||
}
|
||||
}
|
||||
}
|
||||
118
BotSharp.MachineLearning/Entropy/PatternedPredicate.cs
Normal file
118
BotSharp.MachineLearning/Entropy/PatternedPredicate.cs
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// Object containing predicate data, where the parameters are matched to
|
||||
/// the outcomes in an outcome pattern.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
public class PatternedPredicate
|
||||
{
|
||||
private int mOutcomePattern;
|
||||
private double[] mParameters;
|
||||
private string mName;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a PatternedPredicate object.
|
||||
/// </summary>
|
||||
/// <param name="outcomePattern">
|
||||
/// Index into the outcome pattern array, specifying which outcome pattern relates to
|
||||
/// this predicate.
|
||||
/// </param>
|
||||
/// <param name="parameters">
|
||||
/// Array of parameters for this predicate.
|
||||
/// </param>
|
||||
protected internal PatternedPredicate(int outcomePattern, double[] parameters)
|
||||
{
|
||||
mOutcomePattern = outcomePattern;
|
||||
mParameters = parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a PatternedPredicate object.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// The predicate name.
|
||||
/// </param>
|
||||
/// <param name="parameters">
|
||||
/// Array of parameters for this predicate.
|
||||
/// </param>
|
||||
protected internal PatternedPredicate(string name, double[] parameters)
|
||||
{
|
||||
mName = name;
|
||||
mParameters = parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Index into array of outcome patterns.
|
||||
/// </summary>
|
||||
public int OutcomePattern
|
||||
{
|
||||
get
|
||||
{
|
||||
return mOutcomePattern;
|
||||
}
|
||||
set // for trainer
|
||||
{
|
||||
mOutcomePattern = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of a parameter from this predicate.
|
||||
/// </summary>
|
||||
/// <param name="index">
|
||||
/// index into the parameter array.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public double GetParameter(int index)
|
||||
{
|
||||
return mParameters[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Number of parameters associated with this predicate.
|
||||
/// </summary>
|
||||
public int ParameterCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return mParameters.Length;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name of the predicate.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
set
|
||||
{
|
||||
mName = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the PlainTextByLineDataStream.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// This ITrainingDataReader implementation will take care of reading a plain text file
|
||||
/// and returning the strings between each new line character, which is what
|
||||
/// many SharpEntropy applications need in order to create ITrainingEventReaders.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on PlainTextByLineDataStream.java, $Revision: 1.1.1.1 $, $Date: 2001/10/23 14:06:53 $
|
||||
/// </version>
|
||||
public class PlainTextByLineDataReader : ITrainingDataReader<string>
|
||||
{
|
||||
private readonly StreamReader _dataReader;
|
||||
private string _nextLine;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a training data reader for reading text lines from a file or other text stream
|
||||
/// </summary>
|
||||
/// <param name="dataSource">StreamReader containing the source of the training data</param>
|
||||
public PlainTextByLineDataReader(StreamReader dataSource)
|
||||
{
|
||||
_dataReader = dataSource;
|
||||
_nextLine = _dataReader.ReadLine();
|
||||
}
|
||||
|
||||
/// <summary>Gets the next text line from the training data</summary>
|
||||
/// <returns>Next text line from the training data</returns>
|
||||
public virtual string NextToken()
|
||||
{
|
||||
string currentLine = _nextLine;
|
||||
_nextLine = _dataReader.ReadLine();
|
||||
return currentLine;
|
||||
}
|
||||
|
||||
/// <summary>Checks if there is any more training data</summary>
|
||||
/// <returns>true if there is more training data to be read</returns>
|
||||
public virtual bool HasNext()
|
||||
{
|
||||
return (_nextLine != null);
|
||||
}
|
||||
}
|
||||
}
|
||||
94
BotSharp.MachineLearning/Entropy/TrainingEvent.cs
Normal file
94
BotSharp.MachineLearning/Entropy/TrainingEvent.cs
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the Event.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// The context of a decision point during training. This includes
|
||||
/// contextual predicates and an outcome.
|
||||
/// </summary>
|
||||
/// <author>
|
||||
/// Jason Baldridge
|
||||
/// </author>
|
||||
/// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
/// <version>
|
||||
/// based on Event.java, $Revision: 1.3 $, $Date: 2003/12/09 23:13:08 $
|
||||
/// </version>
|
||||
public class TrainingEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// The outcome label for this training event.
|
||||
/// </summary>
|
||||
public string Outcome { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The context for this training event.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A string array of context values for this training event.
|
||||
/// </returns>
|
||||
public string[] Context { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for a training event.
|
||||
/// </summary>
|
||||
/// <param name="outcome">
|
||||
/// the outcome label
|
||||
/// </param>
|
||||
/// <param name="context">
|
||||
/// array containing context values
|
||||
/// </param>
|
||||
public TrainingEvent(string outcome, string[] context)
|
||||
{
|
||||
Outcome = outcome;
|
||||
Context = context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override providing text summary of the training event.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Summary of the training event.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return Outcome + " " + string.Join(", ", Context);
|
||||
}
|
||||
}
|
||||
}
|
||||
282
BotSharp.MachineLearning/Entropy/TwoPassDataIndexer.cs
Normal file
282
BotSharp.MachineLearning/Entropy/TwoPassDataIndexer.cs
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
//Copyright (C) 2005 Richard J. Northedge
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
//This file is based on the TwoPassDataIndexer.java source file found in the
|
||||
//original java implementation of MaxEnt. That source file contains the following header:
|
||||
|
||||
//Copyright (C) 2003 Thomas Morton
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//GNU General Public License for more details.
|
||||
//
|
||||
//You should have received a copy of the GNU Lesser General Public
|
||||
//License along with this program; if not, write to the Free Software
|
||||
//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// Collecting event and context counts by making two passes over the events.
|
||||
/// The first pass determines which contexts will be used by the model, and the second
|
||||
/// pass creates the events in memory containing only the contexts which will be used.
|
||||
/// This greatly reduces the amount of memory required for storing the events.
|
||||
/// During the first pass a temporary event file is created which is read during the second pass.
|
||||
/// </summary>
|
||||
/// /// <author>
|
||||
/// Tom Morton
|
||||
/// </author>
|
||||
/// /// /// <author>
|
||||
/// Richard J. Northedge
|
||||
/// </author>
|
||||
public class TwoPassDataIndexer : AbstractDataIndexer
|
||||
{
|
||||
/// <summary>
|
||||
/// One argument constructor for DataIndexer which calls the two argument
|
||||
/// constructor assuming no cutoff.
|
||||
/// </summary>
|
||||
/// <param name="eventReader">
|
||||
/// An ITrainingEventReader which contains the list of all the events
|
||||
/// seen in the training data.
|
||||
/// </param>
|
||||
public TwoPassDataIndexer(ITrainingEventReader eventReader): this(eventReader, 0){}
|
||||
|
||||
/// <summary>
|
||||
/// Two argument constructor for TwoPassDataIndexer.
|
||||
/// </summary>
|
||||
/// <param name="eventReader">
|
||||
/// An ITrainingEventReader which contains the a list of all the events
|
||||
/// seen in the training data.
|
||||
/// </param>
|
||||
/// <param name="cutoff">
|
||||
/// The minimum number of times a predicate must have been
|
||||
/// observed in order to be included in the model.
|
||||
/// </param>
|
||||
public TwoPassDataIndexer(ITrainingEventReader eventReader, int cutoff)
|
||||
{
|
||||
List<ComparableEvent> eventsToCompare;
|
||||
|
||||
var predicateIndex = new Dictionary<string, int>();
|
||||
//NotifyProgress("Indexing events using cutoff of " + cutoff + "\n");
|
||||
|
||||
//NotifyProgress("\tComputing event counts... ");
|
||||
|
||||
string tempFile = new FileInfo(Path.GetTempFileName()).FullName;
|
||||
|
||||
int eventCount = ComputeEventCounts(eventReader, tempFile, predicateIndex, cutoff);
|
||||
//NotifyProgress("done. " + eventCount + " events");
|
||||
|
||||
//NotifyProgress("\tIndexing... ");
|
||||
|
||||
using (var fileEventReader = new FileEventReader(tempFile))
|
||||
{
|
||||
eventsToCompare = Index(eventCount, fileEventReader, predicateIndex);
|
||||
}
|
||||
|
||||
if (File.Exists(tempFile))
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
|
||||
//NotifyProgress("done.");
|
||||
|
||||
//NotifyProgress("Sorting and merging events... ");
|
||||
SortAndMerge(eventsToCompare);
|
||||
//NotifyProgress("Done indexing.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads events from <tt>eventStream</tt> into a dictionary. The
|
||||
/// predicates associated with each event are counted and any which
|
||||
/// occur at least <tt>cutoff</tt> times are added to the
|
||||
/// <tt>predicatesInOut</tt> map along with a unique integer index.
|
||||
/// </summary>
|
||||
/// <param name="eventReader">
|
||||
/// an <code>ITrainingEventReader</code> value
|
||||
/// </param>
|
||||
/// <param name="eventStoreFile">
|
||||
/// a file name to which the events are written to for later processing.
|
||||
/// </param>
|
||||
/// <param name="predicatesInOut">
|
||||
/// a <code>Dictionary</code> value
|
||||
/// </param>
|
||||
/// <param name="cutoff">
|
||||
/// an <code>int</code> value
|
||||
/// </param>
|
||||
private int ComputeEventCounts(ITrainingEventReader eventReader, string eventStoreFile, Dictionary<string, int> predicatesInOut, int cutoff)
|
||||
{
|
||||
var counter = new Dictionary<string, int>();
|
||||
int predicateIndex = 0;
|
||||
int eventCount = 0;
|
||||
|
||||
using (var eventStoreWriter = new StreamWriter(eventStoreFile))
|
||||
{
|
||||
while (eventReader.HasNext())
|
||||
{
|
||||
TrainingEvent currentTrainingEvent = eventReader.ReadNextEvent();
|
||||
eventCount++;
|
||||
eventStoreWriter.Write(FileEventReader.ToLine(currentTrainingEvent));
|
||||
string[] eventContext = currentTrainingEvent.Context;
|
||||
for (int currentPredicate = 0; currentPredicate < eventContext.Length; currentPredicate++)
|
||||
{
|
||||
if (!predicatesInOut.ContainsKey(eventContext[currentPredicate]))
|
||||
{
|
||||
if (counter.ContainsKey(eventContext[currentPredicate]))
|
||||
{
|
||||
counter[eventContext[currentPredicate]]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
counter.Add(eventContext[currentPredicate], 1);
|
||||
}
|
||||
if (counter[eventContext[currentPredicate]] >= cutoff)
|
||||
{
|
||||
predicatesInOut.Add(eventContext[currentPredicate], predicateIndex++);
|
||||
counter.Remove(eventContext[currentPredicate]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return eventCount;
|
||||
}
|
||||
|
||||
private List<ComparableEvent> Index(int eventCount, ITrainingEventReader eventReader, Dictionary<string, int> predicateIndex)
|
||||
{
|
||||
var outcomeMap = new Dictionary<string, int>();
|
||||
int outcomeCount = 0;
|
||||
var eventsToCompare = new List<ComparableEvent>(eventCount);
|
||||
var indexedContext = new List<int>();
|
||||
while (eventReader.HasNext())
|
||||
{
|
||||
TrainingEvent currentTrainingEvent = eventReader.ReadNextEvent();
|
||||
string[] eventContext = currentTrainingEvent.Context;
|
||||
ComparableEvent comparableEvent;
|
||||
|
||||
int outcomeId;
|
||||
string outcome = currentTrainingEvent.Outcome;
|
||||
|
||||
if (outcomeMap.ContainsKey(outcome))
|
||||
{
|
||||
outcomeId = outcomeMap[outcome];
|
||||
}
|
||||
else
|
||||
{
|
||||
outcomeId = outcomeCount++;
|
||||
outcomeMap.Add(outcome, outcomeId);
|
||||
}
|
||||
|
||||
for (int currentPredicate = 0; currentPredicate < eventContext.Length; currentPredicate++)
|
||||
{
|
||||
string predicate = eventContext[currentPredicate];
|
||||
if (predicateIndex.ContainsKey(predicate))
|
||||
{
|
||||
indexedContext.Add(predicateIndex[predicate]);
|
||||
}
|
||||
}
|
||||
|
||||
// drop events with no active features
|
||||
if (indexedContext.Count > 0)
|
||||
{
|
||||
comparableEvent = new ComparableEvent(outcomeId, indexedContext.ToArray());
|
||||
eventsToCompare.Add(comparableEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
//"Dropped event " + currentTrainingEvent.Outcome + ":" + currentTrainingEvent.Context);
|
||||
}
|
||||
// recycle the list
|
||||
indexedContext.Clear();
|
||||
}
|
||||
SetOutcomeLabels(ToIndexedStringArray(outcomeMap));
|
||||
SetPredicateLabels(ToIndexedStringArray(predicateIndex));
|
||||
return eventsToCompare;
|
||||
}
|
||||
}
|
||||
|
||||
class FileEventReader : ITrainingEventReader, IDisposable
|
||||
{
|
||||
private StreamReader mReader;
|
||||
private string mCurrentLine;
|
||||
|
||||
private char[] mWhitespace;
|
||||
|
||||
public FileEventReader(string fileName)
|
||||
{
|
||||
mReader = new StreamReader(fileName, Encoding.UTF7);
|
||||
mWhitespace = new char[] {'\t', '\n', '\r', ' '};
|
||||
}
|
||||
|
||||
public virtual bool HasNext()
|
||||
{
|
||||
mCurrentLine = mReader.ReadLine();
|
||||
return (mCurrentLine != null);
|
||||
}
|
||||
|
||||
public virtual TrainingEvent ReadNextEvent()
|
||||
{
|
||||
string[] tokens = mCurrentLine.Split(mWhitespace);
|
||||
string outcome = tokens[0];
|
||||
var context = new string[tokens.Length - 1];
|
||||
Array.Copy(tokens, 1, context, 0, tokens.Length - 1);
|
||||
|
||||
return (new TrainingEvent(outcome, context));
|
||||
}
|
||||
|
||||
public static string ToLine(TrainingEvent eventToConvert)
|
||||
{
|
||||
var lineBuilder = new StringBuilder();
|
||||
lineBuilder.Append(eventToConvert.Outcome);
|
||||
string[] context = eventToConvert.Context;
|
||||
for (int contextIndex = 0, contextLength = context.Length; contextIndex < contextLength; contextIndex++)
|
||||
{
|
||||
lineBuilder.Append(" " + context[contextIndex]);
|
||||
}
|
||||
lineBuilder.Append(System.Environment.NewLine);
|
||||
return lineBuilder.ToString();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
mReader.Close();
|
||||
}
|
||||
}
|
||||
|
||||
~FileEventReader()
|
||||
{
|
||||
Dispose (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@ using System;
|
|||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SharpWordNet
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for DataFileEngine.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace SharpWordNet
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for IndexWord.
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpWordNet.Morph
|
||||
namespace BotSharp.MachineLearning.Morph
|
||||
{
|
||||
public abstract class AbstractDelegatingOperation : IOperation
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpWordNet.Morph
|
||||
namespace BotSharp.MachineLearning.Morph
|
||||
{
|
||||
/// <summary>
|
||||
/// Remove all applicable suffixes from the word(s) and do a look-up.
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpWordNet.Morph
|
||||
namespace BotSharp.MachineLearning.Morph
|
||||
{
|
||||
public interface IOperation
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpWordNet.Morph
|
||||
namespace BotSharp.MachineLearning.Morph
|
||||
{
|
||||
/// <summary>Lookup the word in the exceptions file of the given part-of-speech. </summary>
|
||||
public class LookupExceptionsOperation : IOperation
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpWordNet.Morph
|
||||
namespace BotSharp.MachineLearning.Morph
|
||||
{
|
||||
public class LookupIndexWordOperation : IOperation
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ using System.Collections.Generic;
|
|||
using System.Text;
|
||||
using System.Collections;
|
||||
|
||||
namespace SharpWordNet.Morph
|
||||
namespace BotSharp.MachineLearning.Morph
|
||||
{
|
||||
public class TokenizerOperation : AbstractDelegatingOperation
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ using System.Collections;
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpWordNet.Morph
|
||||
namespace BotSharp.MachineLearning.Morph
|
||||
{
|
||||
public class Util
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
using System;
|
||||
|
||||
namespace SharpWordNet
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for Relation.
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
using System;
|
||||
|
||||
namespace SharpWordNet
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for RelationType.
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
using System;
|
||||
|
||||
namespace SharpWordNet
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for Synset.
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
using System;
|
||||
|
||||
namespace SharpWordNet
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for Tokenizer.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SharpWordNet
|
||||
namespace BotSharp.MachineLearning
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for WordNetEngine.
|
||||
|
|
|
|||
Loading…
Reference in a new issue