using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace BotSharp.MachineLearning.CRFsuite
{
public class Crfutils
{
///
/// Generate features for an item sequence by applying feature templates.
/// A feature template consists of a tuple of (name, offset) pairs,
/// where name and offset specify a field name and offset from which
/// the template extracts a feature valreaditerue. Generated features are stored
/// in the 'F' field of each item in the sequence.
///
/// Token features for a sentence
/// the template which contains what feature to extract
public void ApplyTemplates (List> X, Template templates)
{
foreach (List template in templates.Features)
{
List list = new List();
template.ForEach(t => list.Add($"{t.Field}[{t.Offset}]"));
string name = string.Join("|", list);
for (int t = 0 ; t < X.Count() ; t++) {
List values = new List();
foreach (CRFFeature crffeature in template)
{
string field = crffeature.Field;
int offset = crffeature.Offset;
int p = t + offset;
if (p < 0 || p >= X.Count)
{
values.Clear();
break;
}
values.Add(X[p][field].ToString());
}
if (values != null && values.Count > 0)
{
string value = string.Join("|", values);
((List)X[t]["F"]).Add($"{name}={value}");
}
}
}
}
///
/// Return an iterator for item sequences read from a file object.
/// This function reads a sequence from a file object L{fi}, and
/// yields the sequence as a list of mapping objects. Each line
/// (item) from the file object is split by the separator character
/// L{sep}. Separated values of the item are named by L{names},
/// and stored in a mapping object. Every item has a field 'F' that
/// is reserved for storing features.
///
/// source file which contains crf style training data
/// each attribute name in fields
/// seperate by
public List>> Readiter (string fiPath, List names, string sep = " ")
{
List>> Xs = new List>>();
List> X = new List>();
StreamReader sr = new StreamReader(fiPath, Encoding.Default);
string line;
while ((line = sr.ReadLine()) != null)
{
line = line.Replace("\n","");
if (line == null || line.Length == 0)
{
Xs.Add(new List>(X));
X.Clear();
}
else
{
String[] fields = line.Split(sep);
if (fields.Count() < names.Count)
{
// Error Exception
}
Dictionary item = new Dictionary();
item.Add("F", new List());
for (int i = 0 ; i < names.Count ; i++)
{
item.Add(names[i], fields[i]);
}
X.Add(item);
}
}
return Xs;
}
///
/// Escape colon characters from feature names.
///
/// a feature name
public string Escape(string src)
{
return src.Replace(":", "__COLON__");
}
///
/// Output features (and reference labels) of a sequence in CRFSuite
/// format. For each item in the sequence, this function writes a
/// reference label (if L{field} is a non-empty string) and features.
///
/// destination file stream writer
/// Token features for a sentence
/// one attribute name in fields
public void OutputFeatures (StreamWriter sw, List> X, string field = "")
{
for (int t = 0; t < X.Count; t++)
{
if (field.Length != 0)
{
sw.Write(X[t][field]);
}
foreach (string a in (List)X[t]["F"])
{
sw.Write($"\t{Escape(a)}");
}
sw.Write("\n");
}
sw.Write("\n");
}
///
/// CRFFileGenerator
///
/// an extractor which to do the feature extracting work
/// attributes name seperated by space
/// string whihch seperated by
public void CRFFileGenerator (System.Action>> FeatureExtractor, string fields, string rawFile, string parsedName, string sep= " ")
{
FileStream fs = new FileStream(parsedName, FileMode.Create);
StreamWriter sw = new StreamWriter(fs);
List F = fields.Split(" ").ToList();
List>> Xs = Readiter(rawFile, F, " ");
foreach (List> X in Xs)
{
if (X.Any(x => x["w"].ToString() == ""))
{
}
FeatureExtractor(X);
OutputFeatures(sw, X, "y");
}
sw.Flush();
sw.Close();
fs.Close();
}
}
}