私は、文字 "A"のようなアルファベット1文字に対して複数のデータを受け入れることができるようにプログラムを修正しようとしています。キーボードからの1つのキーだけが1つのデータを保持できるようにする何らかの種類のContainsKey関数がありました。複数のデータを保持する方法を教えてください。複数のデータを保持できる辞書を作成するにはどうすればよいですか?
私はこれを非常に明確にするつもりです。これは、監督されていないニューラルネットワークを使用したオンラインOCRプログラムです。ユーザが描画空間に文字を描くと、学習データに文字を追加して後で訓練するという選択肢があります。彼らが文字を追加するとき、彼らはキーボード上のキーを使用して入力したばかりの文字を定義する必要があります。たとえば、文字 'A'を描き、その文字のキーボードからキーを入力するようにポップアップウィンドウが表示されます。
学習データにすでに文字 'A'がある場合、別の文字 'A'を追加することはできません。そのキーAはすでに前の 'A'を保持しています。私はキーAを複数の文字 'A'を保持することができるようにしたかった。
私はここにプログラムのコード全体を掲載するつもりです。これは私のプログラムではなく、Heaton Researchのもので、私はそれを修正しようとしています。少し早いですがお礼を。
public partial class Form1 : Form
{
/**
* The downsample width for the application.
*/
const int DOWNSAMPLE_WIDTH = 10;
/**
* The down sample height for the application.
*/
const int DOWNSAMPLE_HEIGHT = 12;
private Bitmap entryImage;
private Graphics entryGraphics;
private int entryLastX;
private int entryLastY;
private Pen blackPen;
private bool[] downsampled;
private Dictionary<char, List<bool[]>> letterData = new Dictionary<Char, List<bool[]>>();
private double[][] trainingSet;
private SelfOrganizingMap network;
public Form1()
{
InitializeComponent();
blackPen = new Pen(Color.Black);
entryImage = new Bitmap(entry.Width, entry.Height);
entryGraphics = Graphics.FromImage(entryImage);
downsampled = new bool[Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH];
ClearEntry();
}
private void entry_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawImage(entryImage, 0, 0);
Pen blackPen = new Pen(Color.Black);
g.DrawRectangle(blackPen, 0, 0, entry.Width - 1, entry.Height - 1);
}
private void btnDelete_Click(object sender, EventArgs e)
{
string str = (string)this.letters.Items[this.letters.SelectedIndex];
char ch = str[0];
this.letterData.Remove(ch);
this.letters.Items.Remove(str);
ClearEntry();
}
private void btnLoad_Click(object sender, EventArgs e)
{
try
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.Filter = "Data File (*.dat)|*.dat";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
TextReader f = new StreamReader(openFileDialog1.FileName);
String line;
this.letterData.Clear();
this.letters.Items.Clear();
while ((line = f.ReadLine()) != null)
{
int sampleSize = Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH;
char ch = char.ToUpper(line[0]);
bool[] sample = new bool[sampleSize];
int idx = 2;
for (int i = 0; i < sampleSize; i++)
{
if (line[idx++] == '1')
sample[i] = true;
else
sample[i] = false;
}
this.letterData.Add(ch, sample);
this.letters.Items.Add("" + ch);
}
f.Close();
}
MessageBox.Show(this, "File Loaded");
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
}
}
private void btnSave_Click(object sender, EventArgs e)
{
try
{
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "Data File (*.dat)|*.dat";
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
TextWriter f = new StreamWriter(saveFileDialog1.FileName);
int size = Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH;
for (int i = 0; i < this.letters.Items.Count; i++)
{
char ch = ((string)this.letters.Items[i])[0];
bool[] data = this.letterData[ch];
f.Write(ch + ":");
for (int j = 0; j < size; j++)
{
f.Write(data[j] ? "1" : "0");
}
f.WriteLine("");
}
f.Close();
MessageBox.Show("File Saved");
}
}
catch (Exception e2)
{
MessageBox.Show("Error: " + e2.Message, "Training");
}
}
private void btnBeginTraining_Click(object sender, EventArgs e)
{
int inputCount = Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH;
int letterCount = this.letters.Items.Count;
this.trainingSet = new double[letterCount][];
int index = 0;
foreach (char ch in this.letterData.Keys)
{
this.trainingSet[index] = new double[inputCount];
bool[] data = this.letterData[ch];
for (int i = 0; i < inputCount; i++)
{
this.trainingSet[index][i] = data[i] ? 0.5 : -0.5;
}
index++;
}
network = new SelfOrganizingMap(inputCount, letterCount, NormalizationType.Z_AXIS);
this.ThreadProc();
}
private void btnAdd_Click(object sender, EventArgs e)
{
DownSample ds = new DownSample(this.entryImage);
this.downsampled = ds.downSample(Form1.DOWNSAMPLE_WIDTH, Form1.DOWNSAMPLE_HEIGHT);
this.sample.Invalidate();
String Prompt = "Enter the letter you just draw (from the keyboard)";
String Title = "Letter definition Required";
String Default = " ";
Int32 XPos = ((SystemInformation.WorkingArea.Width/2) - 200);
Int32 YPos = ((SystemInformation.WorkingArea.Height/2) - 100);
bool valid = false;
for (int i = 0; i < this.downsampled.Length; i++)
{
if (this.downsampled[i])
{
valid = true;
}
}
if (!valid)
{
MessageBox.Show("Please draw a letter before adding it.");
return;
}
String Result = Microsoft.VisualBasic.Interaction.InputBox(Prompt, Title, Default, XPos, YPos);
if (Result != null)
{
Result = Result.ToUpper();
if (Result.Length == 0)
{
MessageBox.Show("Please enter a character.");
}
else if (Result.Length < 1)
{
MessageBox.Show("Please enter only a single character.");
}
//else if (this.letterData.ContainsKey(Result[0]))
//{
// MessageBox.Show("That letter is already defined, please delete first.");
//}
else
{
if (this.letterData.ContainsKey(Result[0]))
{
this.letterData[Result[0]].Add(this.downsampled);
}
else
{
this.letterData.Add(Result[0], new List<bool[]>() {this.downsampled});
}
this.letters.Items.Add(Result);
//this.letterData.Add(Result[0], this.downsampled);
this.ClearEntry();
}
}
}
private void btnRecognize_Click(object sender, EventArgs e)
{
DownSample ds = new DownSample(this.entryImage);
this.downsampled = ds.downSample(Form1.DOWNSAMPLE_WIDTH, Form1.DOWNSAMPLE_HEIGHT);
this.sample.Invalidate();
if (this.network == null)
{
MessageBox.Show("The program needs to be trained first");
return;
}
int sampleSize = Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH;
double[] input = new double[sampleSize];
for (int i = 0; i < sampleSize; i++)
{
input[i] = this.downsampled[i] ? 0.5 : -0.5;
}
int best = this.network.Winner(input);
char[] map = mapNeurons();
this.result.Text = " " + map[best];
MessageBox.Show(" " + map[best] + " (Neuron #"
+ best + " fired)", "That Letter You Enter Is");
//ClearEntry();
}
private void btnClear_Click(object sender, EventArgs e)
{
ClearEntry();
}
private void btnSample_Click(object sender, EventArgs e)
{
DownSample ds = new DownSample(this.entryImage);
this.downsampled = ds.downSample(Form1.DOWNSAMPLE_WIDTH, Form1.DOWNSAMPLE_HEIGHT);
this.sample.Invalidate();
}
public void ClearEntry()
{
Brush whiteBrush = new SolidBrush(Color.White);
entryGraphics.FillRectangle(whiteBrush, 0, 0, entry.Width, entry.Height);
entry.Invalidate();
DownSample ds = new DownSample(this.entryImage);
this.downsampled = ds.downSample(Form1.DOWNSAMPLE_WIDTH, Form1.DOWNSAMPLE_HEIGHT);
this.sample.Invalidate();
}
private void entry_MouseDown(object sender, MouseEventArgs e)
{
entry.Capture = true;
entryLastX = e.X;
entryLastY = e.Y;
}
private void entry_MouseUp(object sender, MouseEventArgs e)
{
entryGraphics.DrawLine(blackPen, entryLastX, entryLastY, e.X, e.Y);
entry.Invalidate();
entry.Capture = false;
}
private void entry_MouseMove(object sender, MouseEventArgs e)
{
if (entry.Capture == true)
{
entryGraphics.DrawLine(blackPen, entryLastX, entryLastY, e.X, e.Y);
entry.Invalidate();
entryLastX = e.X;
entryLastY = e.Y;
}
}
private void sample_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
int x, y;
int vcell = sample.Height/Form1.DOWNSAMPLE_HEIGHT;
int hcell = sample.Width/Form1.DOWNSAMPLE_WIDTH;
Brush whiteBrush = new SolidBrush(Color.White);
Brush blackBrush = new SolidBrush(Color.Black);
Pen blackPen = new Pen(Color.Black);
g.FillRectangle(whiteBrush, 0, 0, sample.Width, sample.Height);
for (y = 0; y < Form1.DOWNSAMPLE_HEIGHT; y++)
{
g.DrawLine(blackPen, 0, y * vcell, sample.Width, y * vcell);
}
for (x = 0; x < Form1.DOWNSAMPLE_WIDTH; x++)
{
g.DrawLine(blackPen, x * hcell, 0, x * hcell, sample.Height);
}
int index = 0;
for (y = 0; y < Form1.DOWNSAMPLE_HEIGHT; y++)
{
for (x = 0; x < Form1.DOWNSAMPLE_WIDTH; x++)
{
if (this.downsampled[index++])
{
g.FillRectangle(blackBrush, x * hcell, y * vcell, hcell, vcell);
}
}
}
g.DrawRectangle(blackPen, 0, 0, sample.Width - 1, sample.Height - 1);
}
private void letters_SelectedIndexChanged(object sender, EventArgs e)
{
if (this.letters.SelectedIndex >= 0)
{
string str = (string)this.letters.Items[this.letters.SelectedIndex];
char ch = str[0];
this.downsampled = this.letterData[ch];
this.sample.Invalidate();
}
}
public void ThreadProc()
{
TrainSelfOrganizingMap train = new TrainSelfOrganizingMap(
this.network, this.trainingSet, TrainSelfOrganizingMap.LearningMethod.SUBTRACTIVE, 0.5);
int tries = 1;
do
{
train.Iteration();
this.txtTries.Text = "" + tries;
this.txtBestError.Text = "" + train.BestError;
this.txtLastError.Text = "" + train.TotalError;
tries++;
Application.DoEvents();
} while (train.TotalError > 0.01 && (tries <= 100));
MessageBox.Show("Training complete.");
}
/**
* Used to map neurons to actual letters.
*
* @return The current mapping between neurons and letters as an array.
*/
public char[] mapNeurons()
{
char[] map = new char[this.letters.Items.Count];
for (int i = 0; i < map.Length; i++)
{
map[i] = '?';
}
for (int i = 0; i < this.letters.Items.Count; i++)
{
double[] input = new double[Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH];
char ch = ((string)(this.letters.Items[i]))[0];
bool[] data = this.letterData[ch];
for (int j = 0; j < input.Length; j++)
{
input[j] = data[j] ? 0.5 : -0.5;
}
int best = this.network.Winner(input);
map[best] = ch;
}
return map;
}
}
'valid'を' true'に設定した後、ループから '中断してはいけませんか? – ChaosPandion