长沙网站seo公司,国外外贸平台,网站建设好后有些什么资料,开发网站的技术风险在AI技术的发展历史中#xff0c;模式识别模型是最伟大的AI技术之一#xff0c;尤其是从像素图像中读取文本。其中一个是Hopfield网络#xff08;或称为Ising模型的神经网络或Ising–Lenz–Little模型#xff09;#xff0c;这是一种递归神经网络形式#xff0c;由John J…在AI技术的发展历史中模式识别模型是最伟大的AI技术之一尤其是从像素图像中读取文本。其中一个是Hopfield网络或称为Ising模型的神经网络或Ising–Lenz–Little模型这是一种递归神经网络形式由John J. Hopfield博士在1982年发明。Hopfield网络可以应用于模式识别例如从像素图像中识别数字字符。在本文中我们将使用C Builder开发一个简单的Hopfield网络GUI形式它可以从像素模式中学习并且我们可以通过测试一些最接近的模式来回忆它们。
目录
Hopfield网络在AI开发中是什么如何训练Hopfield网络如何在C中开发一个简单的Hopfield网络如何在C Builder中开发一个简单的Hopfield网络如何在C Builder中测试一个简单的Hopfield网络应用C Builder中有关Hopfield网络的完整示例代码
Hopfield网络在AI开发中是什么
Hopfield网络的目的是存储数据模式并根据部分输入回忆完整的数据模式。例如Hopfield网络可以应用于8×8数字字符识别。我们可以在这个网络上训练一些字符然后我们可以询问一个更接近的字符如果它记住了训练过的字符或没有。我们可以使用这个Hopfield网络从图像中提取字符并将它们以ASCII形式放入文本文件中这被称为模式识别。这个网络的良好行为是即使字符的完整形式没有给出它也能记住字符的完整形式。这个例子可以用于从文本中识别光学字符如果字母的一小部分有变形或纸张脏污Hopfield网络可能能记住这种类型的问题。在现代ML和AI应用中有许多更有用的方法基于Hopfield网络如当前的人工神经网络。
Hopfield网络或称为Ising模型的神经网络或Ising–Lenz–Little模型是一种递归神经网络形式由John J. Hopfield博士在1982年发明。它由一个单层组成包含一个或多个完全连接的递归神经元。Hopfield网络常用于自动关联和优化任务。Hopfield网络作为具有二进制阈值节点的内容可寻址存储系统。Hopfield网络还提供了一个基本模型用于理解人脑和记忆如何被人工模拟。
如何训练Hopfield网络
如何在数字字符识别编程中应用这种方法Hopfield网络如何在1和0像素上工作我们可以将每个像素映射到Hopfield网络中的一个节点。我们可以在这个网络上训练正确的字符形式以识别每个字符。Hopfield网络在几次迭代后找到最可能的假设字符并最终以训练的正确形式再现模式。如果我们有N个像素这意味着我们的网络有NxN个权重所以这个问题在计算上非常昂贵可能在某些情况下很慢。例如我们可以训练空白形式空格和这个“A”形式如此进行即可。 Hopfield网络中的所有节点都用作输入和输出并且它们完全相互连接。也就是说每个节点是网络中每个其他节点的输入。我们可以将每个节点到自身的链接视为权重为0的链接。
我们可以轻松地训练Hopfield网络我们只需要二进制数据来训练这个网络。正如我们所知我们可以有二进制输入向量以及双极性输入向量。在Hopfield网络的训练过程中权重在迭代中更新。 例如对于一个由N个元素组成的3节点Hopfield网络数据矩阵和由NxN个元素组成的权重矩阵。以下是这些矩阵的3节点示例 如何在C中开发一个简单的Hopfield网络
让我们创建一个简单的Hopfield网络C Builder示例如下。 按照给定的如下步骤创建一个简单的THopfield_Network类。
class THopfield_Network
{
private:std::vectorstd::vectorint weights;
public:THopfield_Network(int numofNeurons) : weights(numofNeurons, std::vectorint(numNeurons, 0)){}
我们将为这个类添加3个公共方法。首先它将使用learn_pattern()方法从模式向量中学习该方法定义如下
// Learn from a pattern (update weights)
void learn_pattern(const std::vectorint pattern)
{for (int i 0; i pattern.size(); i){for (int j 0; j pattern.size(); j){if (i ! j){weights[i][j] pattern[i] * pattern[j];}}}
}
我们将使用update_neuron()方法更新我们的Hopfield网络神经元该方法定义如下
// Update neuron asynchronously
int update_neuron(const std::vectorint input, int neuronIndex)
{int sum 0;for (int i 0; i input.size(); i){sum weights[neuronIndex][i] * input[i];}return (sum 0) ? 1 : -1;
}
我们可以使用这个update_neuron方法通过以下定义的test()方法测试给定的输入模式
//测试网络
std::vectorint test(const std::vectorint input)
{std::vectorint output(input);for (int i 0; i input.size(); i){output[i] update_neuron(output, i);}return output;
}
作为结果这个简单的Hopfield网络类将如下所示
class THopfield_Network
{ private:std::vectorstd::vectorint weights; public:THopfield_Network(int numofNeurons) : weights(numofNeurons, std::vectorint(numofNeurons, 0)){}// Learn from a pattern (update weights)void learn_pattern(const std::vectorint pattern){for (int i 0; i pattern.size(); i){for (int j 0; j pattern.size(); j){if (i ! j){weights[i][j] pattern[i] * pattern[j];}}}}// Update neuron asynchronouslyint update_neuron(const std::vectorint input, int neuronIndex){int sum 0;for (int i 0; i input.size(); i){sum weights[neuronIndex][i] * input[i];}return (sum 0) ? 1 : -1;}// Test the networkstd::vectorint test(const std::vectorint input){std::vectorint output(input);for (int i 0; i input.size(); i){output[i] update_neuron(output, i);}return output;}
};
现在我们可以全局定义一个Hopfield网络给定宽度和高度像素。例如如果我们有6×6像素模式我们可以定义如下
int W 6, H 6;
THopfield_Network hopfield(W*H);
现在我们可以定义一个模式向量如下 std::vectorint pattern {1, -1, -1, -1, -1, -1,-1, 1, -1, -1, -1, -1,-1, -1, 1, -1, -1, -1,-1, -1, -1, 1, -1, -1,-1, -1, -1, -1, 1, -1,-1, -1, -1, -1, -1, 1};
我们可以训练这个模式如果我们有另一个如上的输入模式我们可以测试它以获得最接近给定输入的结果recovered_pattern。
hopfield.learn_pattern(pattern);std::vectorint recovered_pattern hopfield.test(input_pattern);
现在我们在Cbuilder中完成一个GUI界面的Hopfield网络。
如何在CBuilder中开发一个简单的Hopfield网络
让我们创建一个简单的C Builder中的Hopfield网络示例如下。 首先创建一个新的C Builder FMX应用程序添加一个图像TImage备忘录TMemo和3个按钮TButton它们是“清除”“训练”和“测试”按钮。你可以添加一些布局来安排它们如给定的表单TForm设计如上图。 将我们的THopfield网络类添加到“TForm1 *Form1;”行下面。 在Form单元的头文件中定义bmp和bmp2位图如下其中bmp将用作输入模式bmp2将显示在图像上。 TBitmap* bmp, *bmp2; 这样bmp将用于存储输入模式的像素值而bmp2用于显示处理后的图像。
class TForm1 : public TForm
{
__published: // IDE-managed ComponentsTImage *Image1;TButton *btTrain;TButton *btTest;TButton *btClear;TMemo *Memo1;TLayout *Layout1;TLayout *Layout2;void __fastcall btClearClick(TObject *Sender);void __fastcall Image1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, float X, float Y);void __fastcall btTrainClick(TObject *Sender);void __fastcall btTestClick(TObject *Sender);
private: // User declarations
public: // User declarationsTBitmap *bmp, *bmp2;__fastcall TForm1(TComponent* Owner);}; 4. 现在开始创建这些位图。 __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{bmp new TBitmap(W,H);bmp2 new TBitmap(Image1-Width, Image1-Height);Image1-Bitmap-Assign(bmp2);
}
5. 定义Clear按钮事件。 void __fastcall TForm1::btClearClick(TObject *Sender)
{bmp-Clear(claBlack);Image1-Bitmap-Clear(claBlack);
}
6. 为了允许用户通过点击图像定义自己的模式我们需要处理Image1的的OnMouseDown事件。当用户在Image1上双击时我们可以捕获鼠标点击的像素位置并根据这些位置更新网络的权重。以下是一个处理双击鼠标点击事件的示例
void __fastcall TForm1::Image1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, float X, float Y)
{float w Image1-Width / W; // grid widthfloat h Image1-Height / H; // grid heightint px X / w; // exact pixel X on the bitmap scaled imageint py Y / h; // exact pixel Y on the bitmap of scaled imageTBitmapData bitmapData;TAlphaColorRec acr;if (bmp-Map(TMapAccess::ReadWrite, bitmapData)) // Lock bitmap and retrive bitmap data{ac.Color bitmapData.GetPixel(px, py);if (ac.Color claBlack){bitmapData.SetPixel(px, py, claWhite);Image1-Bitmap-Canvas-BeginScene();Image1-Bitmap-Canvas-Fill-Color claWhite;Image1-Bitmap-Canvas-FillRect(TRectF(px * w, py * h, px * w w, py * h h, 0, 0, AllCorners, 255.0);Image1-Bitmap-Canvas-EndScene();}else{bitmapData.SetPixel(px, py, claBlack);Image1-Bitmap-Canvas-BeginScene();Image1-Bitmap-Canvas-Fill-Color claBlack;Image1-Bitmap-Canvas-FillRect(TRectF(px * w, py * h, px * w w, py * h h, 0, 0, AllCorners, 255.0);Image1-Bitmap-Canvas-EndScene();}bmp-Unmap(bitmapData);
}
在这个事件处理函数中我们首先计算出鼠标点击位置对应的网格宽度w和高度h然后获取该位置的像素颜色。如果像素颜色是黑色我们将其设置为白色并在Image1上绘制一个白色方块。如果不是黑色我们将其设置为黑色并在Image1上绘制一个黑色方块。这样用户就可以在Image1上绘制模式然后训练Hopfield网络。 7.
现在我们可以通过双击“训练”按钮来创建训练方法。在这个方法中我们将从bmp位图中读取像素数据然后在备忘录中显示这些数据然后我们将使用hopfield.learn_pattern(pattern)来学习这个模式。以下是如何实现的示例
void __fastcall TForm1::btTrainClick(TObject *Sender)
{std::vectorint pattern;TBitmapData bitmapData;TAlphaColor acr;if (bmp-Map(TMapAccess::ReadWrite, bitmapData)) // Lock bitmap and retrive bitmap data{for (int j 0; j H; j){for (int i 0; i W; i){ac.Color bitmapData.GetPixel(i, j);if (ac.Color claBlack){pattern.push_back(-1);}else{pattern.push_back(1);}}bmp-Unmap(bitmapData);}Memo1-Lines-Add(Learned Pattern:);for (int j 0; j H; j){String str ;for (int i 0; i W; i){if (pattern[j * W i] 1){str *;}else{str ;}}Memo1-Lines-Add(str);}Memo1-Lines-Add(------------);hopfield.learn_pattern(pattern);
}
在这个btTrainClick事件处理函数中我们首先检查bmp位图是否可以被锁定并获取其数据。然后我们遍历位图的每个像素检查其颜色并根据颜色更新模式向量。最后我们将模式向量传递给hopfield对象调用learn_pattern方法进行训练。训练完成后我们将训练结果添加到备忘录中供后续测试或使用。
8. 最后我们可以通过双击“测试”按钮来创建测试事件。在这个事件处理函数中我们将使用之前训练的模式向量来测试网络检查网络是否能够正确回忆训练的模式。以下是如何实现的示例
void __fastcall TForm1::btTestClick(TObject *Sender)
{std::vectorint pattern;TBitmapData bitmapData;TAlphaColor acr;if (bmp-Map(TMapAccess::ReadWrite, bitmapData)) // Lock bitmap and retrive bitmap data{for (int j 0; j H; j){for (int i 0; i W; i){ac.Color bitmapData.GetPixel(i, j);if (ac.Color claBlack)pattern.push_back(-1);elsepattern.push_back(1);}bmp-Unmap(bitmapData);}std::vectorint recovered_pattern hopfield.test(pattern);float w Image1-Width / W; // grid widthfloat h Image1-Height / H; // grid heightMemo1-Lines-Add(Recovered Pattern:);Image1-Bitmap-Canvas-BeginScene();for (int j 0; j H; j){String str ;for (int i 0; i W; i){if (recovered_pattern[j * W i] 0){Image1-Bitmap-Canvas-Fill-Color claWhite;Image1-Bitmap-Canvas-FillRect(TRectF(i * w, j * h, i * w w, j * h h, 0, 0, AllCorners, 255.0);str * ;}else{Image1-Bitmap-Canvas-Fill-Color claBlack;Image1-Bitmap-Canvas-FillRect(TRectF(i * w, j * h, i * w w, j * h h, 0, 0, AllCorners, 255.0);str ;}}Memo1-Lines-Add(str);Image1-Bitmap-Canvas-EndScene();Memo1-Lines-Add(------------);
}
在这个btTestClick事件处理函数中我们首先检查bmp位图是否可以被锁定并获取其数据。然后我们遍历位图的每个像素检查其颜色并根据颜色更新模式向量。最后我们将模式向量传递给hopfield对象调用test方法进行测试。测试完成后我们将恢复的模式添加到备忘录中供后续查看或使用。这样我们就可以通过测试事件来验证Hopfield网络是否能够正确回忆训练的模式。
如何在C Builder中测试一个简单的Hopfield网络应用
现在我们可以运行我们的应用程序F9。首先我们可以清除然后训练这个空白模式然后我们可以绘制“A”然后我们可以训练这个。你可以训练更多的不同模式。 在此步骤之后我们可以使用“测试”按钮来询问另一个模式这个模式看起来像我们之前训练过的模式之一例如下面的模式
hopfield.learn_pattern(pattern);
std::vectorint recovered_pattern hopfield.test(input_pattern);
通过这种方式我们可以训练不同的模式然后通过测试按钮来验证网络是否能够识别我们训练过的模式。这有助于我们了解网络的性能以及它是否能够准确地回忆训练过的模式。 作为结果你将看到我们的Hopfield网络记住了最接近的模式并恢复了它。这表明网络能够有效地存储和回忆训练过的模式即使输入不完全匹配网络也能够识别出最相似的模式。这种能力在模式识别和图像处理等应用中非常有用。 C Builder中有关Hopfield网络的完整示例代码
以下是C Builder FMX应用程序的完整示例注意头部也在上面给出。
//---------------------------------------------------------------------------#include fmx.h
#include vector#pragma hdrstop#include Hopfield_Network_FMX_Unit1.h
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource *.fmx
TForm1 *Form1;class THopfield_Network
{ private:std::vectorstd::vectorint weights; public:THopfield_Network(int numofNeurons) : weights(numofNeurons, std::vectorint(numofNeurons, 0)){}// Learn from a pattern (update weights)void learn_pattern(const std::vectorint pattern){for (int i 0; i pattern.size(); i){for (int j 0; j pattern.size(); j){if (i ! j){weights[i][j] pattern[i] * pattern[j];}}}}// Update neuron asynchronouslyint update_neuron(const std::vectorint input, int neuronIndex){int sum 0;for (int i 0; i input.size(); i){sum weights[neuronIndex][i] * input[i];}return (sum 0) ? 1 : -1;}// Test the networkstd::vectorint test(const std::vectorint input){std::vectorint output(input);for (int i 0; i input.size(); i){output[i] update_neuron(output, i);}return output;}
};int W 6, H 6;
THopfield_Network hopfield(W*H);//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{bmp new TBitmap(W,H);bmp2 new TBitmap(Image1-Width, Image1-Height);Image1-Bitmap-Assign(bmp2);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btClearClick(TObject *Sender)
{bmp-Clear(claBlack);Image1-Bitmap-Clear(claBlack);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Image1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, float X, float Y)
{float w Image1-Width/W; // grid widthfloat h Image1-Height/H; // grid heightint px X/w; // exact pixel X on the bitmap of scaled imageint py Y/h; // exact pixel Y on the bitmap of scaled imageTBitmapData bitmapData;TAlphaColorRec acr;if( bmp-Map(TMapAccess::ReadWrite, bitmapData)) // Lock bitmap and retrive bitmap data{acr.Color bitmapData.GetPixel( px, py );if(acr.Color claBlack){bitmapData.SetPixel(px,py, claWhite);Image1-Bitmap-Canvas-BeginScene();Image1-Bitmap-Canvas-Fill-Color claWhite;Image1-Bitmap-Canvas-FillRect( TRectF(px*w,py*h, px*ww,py*hh), 0, 0, AllCorners, 255.0);Image1-Bitmap-Canvas-EndScene();}else{bitmapData.SetPixel(px,py, claBlack);Image1-Bitmap-Canvas-BeginScene();Image1-Bitmap-Canvas-Fill-Color claBlack;Image1-Bitmap-Canvas-FillRect( TRectF(px*w,py*h, px*ww,py*hh), 0, 0, AllCorners, 255.0);Image1-Bitmap-Canvas-EndScene();}bmp-Unmap(bitmapData);}}
//---------------------------------------------------------------------------
void __fastcall TForm1::btTrainClick(TObject *Sender)
{std::vectorint pattern;TBitmapData bitmapData;TAlphaColorRec acr;if( bmp-Map(TMapAccess::ReadWrite, bitmapData)) // Lock bitmap and retrive bitmap data{for(int j0; jH; j)for(int i0; iW; i){acr.Color bitmapData.GetPixel( i, j );if(acr.Color claBlack) pattern.push_back(-1);else pattern.push_back(1);}bmp-Unmap(bitmapData);}Memo1-Lines-Add(Learned Pattern:);for(int j0; jH; j){String str ;for(int i0; iW; i){if(pattern[j*Wi]1) str * ;else str ;}Memo1-Lines-Add(str);}Memo1-Lines-Add(------------);hopfield.learn_pattern(pattern);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btTestClick(TObject *Sender)
{std::vectorint pattern;TBitmapData bitmapData;TAlphaColorRec acr;if( bmp-Map(TMapAccess::ReadWrite, bitmapData)) // Lock bitmap and retrive bitmap data{for(int j0; jH; j)for(int i0; iW; i){acr.Color bitmapData.GetPixel( i, j );if(acr.Color claBlack) pattern.push_back(-1);else pattern.push_back(1);}bmp-Unmap(bitmapData);}std::vectorint recoveredpattern hopfield.test(pattern);float w Image1-Width/W; // grid widthfloat h Image1-Height/H; // grid heightMemo1-Lines-Add(Recovered Pattern:);Image1-Bitmap-Canvas-BeginScene();for(int j0; jH; j){String str ;for(int i0; iW; i){if(recoveredpattern[j*Wi]1){Image1-Bitmap-Canvas-Fill-Color claWhite;Image1-Bitmap-Canvas-FillRect( TRectF(i*w, j*h, i*ww, j*hh), 0, 0, AllCorners, 255.0);str * ;}else{Image1-Bitmap-Canvas-Fill-Color claBlack;Image1-Bitmap-Canvas-FillRect( TRectF(i*w, j*h, i*ww, j*hh), 0, 0, AllCorners, 255.0);str ;}}Memo1-Lines-Add(str);}Image1-Bitmap-Canvas-EndScene();Memo1-Lines-Add(------------);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction Action)
{bmp-Free(); bmp2-Free();
}
//---------------------------------------------------------------------------