闵老师的文章链接: 日撸 Java 三百行(总述)_minfanphd的博客-CSDN博客
自己也把手敲的代码放在了github上维护:https://github.com/fulisha-ok/sampledata
我是copy代码直接运行了GUI的一个总体代码,最后运行的界面如下,这个界面实现了灵活输入参数(神经层数,激活函数,训练次数等。点击OK即可完成一次)再执行神经网络的训练和测试(其中训练的方式以及前向传播函数和后向传播函数都是调用的通用神经网络的方法)
在看了一个整体的思路,在来详细看代码类。
package machinelearing.gui;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
/**
* @author: fulisha
* @date: 2023/7/17 15:39
* @description:
*/
public class ApplicationShutdown implements WindowListener, ActionListener {
/**
* Only one instance.
*/
public static ApplicationShutdown applicationShutdown = new ApplicationShutdown();
private ApplicationShutdown() {
}
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
@Override
public void windowClosed(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
}
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
package machinelearing.gui;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/**
* @author: fulisha
* @date: 2023/7/17 15:41
* @description:
*/
public class DialogCloser extends WindowAdapter implements ActionListener {
/**
* The dialog under control.
*/
private Dialog currentDialog;
/**
* The first constructor.
*/
public DialogCloser() {
super();
}
/**
* The second constructor.
*
* @param paraDialog the dialog under control
*/
public DialogCloser(Dialog paraDialog) {
currentDialog = paraDialog;
}
/**
* Close the dialog which clicking the cross at the up-right corner of the window.
* @param paraWindowEvent From it we can obtain which window sent the message because X was used.
*/
@Override
public void windowClosing(WindowEvent paraWindowEvent) {
paraWindowEvent.getWindow().dispose();
}
/**
* Close the dialog while pushing an "OK" or "Cancel" button.
* @param paraEvent Not considered.
*/
@Override
public void actionPerformed(ActionEvent paraEvent) {
currentDialog.dispose();
}
}
package machinelearing.gui;
import java.awt.*;
/**
* @author: fulisha
* @date: 2023/7/17 16:04
* @description:
*/
public class ErrorDialog extends Dialog{
/**
* Serial uid. Not quite useful.
*/
private static final long serialVersionUID = 124535235L;
/**
* The ONLY ErrorDialog.
*/
public static ErrorDialog errorDialog = new ErrorDialog();
/**
* The label containing the message to display.
*/
private TextArea messageTextArea;
/**
***************************
* Display an error dialog and respective error message. Like other dialogs,
* this constructor is private, such that users can use only one dialog,
* i.e., ErrorDialog.errorDialog to display message. This is helpful for
* saving space (only one dialog) since we may need "many" dialogs.
***************************
*/
private ErrorDialog(){
// This dialog is module.
super(GUICommon.mainFrame, "Error", true);
// Prepare for the dialog.
messageTextArea = new TextArea();
Button okButton = new Button("OK");
okButton.setSize(20, 10);
okButton.addActionListener(new DialogCloser(this));
Panel okPanel = new Panel();
okPanel.setLayout(new FlowLayout());
okPanel.add(okButton);
// Add TextArea and Button
setLayout(new BorderLayout());
add(BorderLayout.CENTER, messageTextArea);
add(BorderLayout.SOUTH, okPanel);
setLocation(200, 200);
setSize(500, 200);
addWindowListener(new DialogCloser());
setVisible(false);
}
/**
* set message.
* @param paramMessage the new message
*/
public void setMessageAndShow(String paramMessage) {
messageTextArea.setText(paramMessage);
setVisible(true);
}
}
package machinelearing.gui;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* @author: fulisha
* @date: 2023/7/17 15:44
* @description:
*/
public class HelpDialog extends Dialog implements ActionListener {
/**
* Serial uid. Not quite useful.
*/
private static final long serialVersionUID = 3869415040299264995L;
/**
* Display the help dialog.
*
* @param paraTitle the title of the dialog.
* @param paraFilename the help file.
*/
public HelpDialog(String paraTitle, String paraFilename) {
super(GUICommon.mainFrame, paraTitle, true);
setBackground(GUICommon.MY_COLOR);
TextArea displayArea = new TextArea("", 10, 10, TextArea.SCROLLBARS_VERTICAL_ONLY);
displayArea.setEditable(false);
String textToDisplay = "";
try {
RandomAccessFile helpFile = new RandomAccessFile(paraFilename, "r");
String tempLine = helpFile.readLine();
while (tempLine != null) {
textToDisplay = textToDisplay + tempLine + "\n";
tempLine = helpFile.readLine();
}
helpFile.close();
} catch (IOException ee) {
dispose();
ErrorDialog.errorDialog.setMessageAndShow(ee.toString());
}
// Use this if you need to display Chinese. Consult the author for this
// method.
// textToDisplay = SimpleTools.GB2312ToUNICODE(textToDisplay);
displayArea.setText(textToDisplay);
displayArea.setFont(new Font("Times New Romans", Font.PLAIN, 14));
Button okButton = new Button("OK");
okButton.setSize(20, 10);
okButton.addActionListener(new DialogCloser(this));
Panel okPanel = new Panel();
okPanel.setLayout(new FlowLayout());
okPanel.add(okButton);
// OK Button
setLayout(new BorderLayout());
add(BorderLayout.CENTER, displayArea);
add(BorderLayout.SOUTH, okPanel);
setLocation(120, 70);
setSize(500, 400);
addWindowListener(new DialogCloser());
setVisible(false);
}
/**
* Simply set it visible.
*/
@Override
public void actionPerformed(ActionEvent ee) {
setVisible(true);
}
}
package machinelearing.gui;
import javax.swing.*;
import java.awt.*;
/**
* @author: fulisha
* @date: 2023/7/17 15:43
* @description:
*/
public class GUICommon {
/**
* Only one main frame.
*/
public static Frame mainFrame = null;
/**
* Only one main pane.
*/
public static JTabbedPane mainPane = null;
/**
* For default project number.
*/
public static int currentProjectNumber = 0;
/**
* Default font.
*/
public static final Font MY_FONT = new Font("Times New Romans", Font.PLAIN, 12);
/**
* Default color
*/
public static final Color MY_COLOR = Color.lightGray;
/**
* Set the main frame. This can be done only once at the initialzing stage.
* @param paraFrame the main frame of the GUI.
* @throws Exception If the main frame is set more than once.
*/
public static void setFrame(Frame paraFrame) throws Exception {
if (mainFrame == null) {
mainFrame = paraFrame;
} else {
throw new Exception("The main frame can be set only ONCE!");
}
}
/**
* Set the main pane. This can be done only once at the initialzing stage.
* @param paramPane the main pane of the GUI.
* @throws Exception If the main panel is set more than once.
*/
public static void setPane(JTabbedPane paramPane) throws Exception {
if (mainPane == null) {
mainPane = paramPane;
} else {
throw new Exception("The main panel can be set only ONCE!");
}
}
}
package machinelearing.gui;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
/**
* @author: fulisha
* @date: 2023/7/17 16:10
* @description:
*/
public class DoubleField extends TextField implements FocusListener {
/**
* Serial uid. Not quite useful.
*/
private static final long serialVersionUID = 363634723L;
/**
* The value
*/
protected double doubleValue;
/**
* Give it default values.
*/
public DoubleField() {
this("5.13", 10);
}
/**
* Only specify the content.
* @param paraString The content of the field.
*/
public DoubleField(String paraString) {
this(paraString, 10);
}
/**
* Only specify the width.
* @param paraWidth The width of the field.
*/
public DoubleField(int paraWidth) {
this("5.13", paraWidth);
}
/**
* Specify the content and the width.
* @param paraString The content of the field.
* @param paraWidth The width of the field.
*/
public DoubleField(String paraString, int paraWidth) {
super(paraString, paraWidth);
addFocusListener(this);
}
/**
* Implement FocusListener.
* @param paraEvent The event is unimportant.
*/
@Override
public void focusGained(FocusEvent paraEvent) {
}
/**
* Implement FocusListener.
* @param paraEvent The event is unimportant.
*/
@Override
public void focusLost(FocusEvent paraEvent) {
try {
doubleValue = Double.parseDouble(getText());
} catch (Exception ee) {
ErrorDialog.errorDialog
.setMessageAndShow("\"" + getText() + "\" Not a double. Please check.");
requestFocus();
}
}
/**
* Get the double value.
* @return the double value.
*/
public double getValue() {
try {
doubleValue = Double.parseDouble(getText());
} catch (Exception ee) {
ErrorDialog.errorDialog
.setMessageAndShow("\"" + getText() + "\" Not a double. Please check.");
requestFocus();
}
return doubleValue;
}
}
和DoubleField同理
package machinelearing.gui;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
/**
* @author: fulisha
* @date: 2023/7/17 16:12
* @description:
*/
public class IntegerField extends TextField implements FocusListener {
/**
* Serial uid. Not quite useful.
*/
private static final long serialVersionUID = -2462338973265150779L;
/**
* Only specify the content.
*/
public IntegerField() {
this("513");
}
/**
* Specify the content and the width.
* @param paraString The default value of the content.
* @param paraWidth The width of the field.
*/
public IntegerField(String paraString, int paraWidth) {
super(paraString, paraWidth);
addFocusListener(this);
}
/**
* Only specify the content.
* @param paraString The given default string.
*/
public IntegerField(String paraString) {
super(paraString);
addFocusListener(this);
}
/**
* Only specify the width.
* @param paraWidth The width of the field.
*/
public IntegerField(int paraWidth) {
super(paraWidth);
setText("513");
addFocusListener(this);
}
/**
* Implement FocusListenter.
* @param paraEvent The event is unimportant.
*/
@Override
public void focusGained(FocusEvent paraEvent) {
}
/**
* Implement FocusListenter.
* @param paraEvent The event is unimportant.
*/
@Override
public void focusLost(FocusEvent paraEvent) {
try {
Integer.parseInt(getText());
// System.out.println(tempInt);
} catch (Exception ee) {
ErrorDialog.errorDialog.setMessageAndShow("\"" + getText()
+ "\"Not an integer. Please check.");
requestFocus();
}
}
/**
* Get the int value. Show error message if the content is not an int.
* @return the int value.
*/
public int getValue() {
int tempInt = 0;
try {
tempInt = Integer.parseInt(getText());
} catch (Exception ee) {
ErrorDialog.errorDialog.setMessageAndShow("\"" + getText()
+ "\" Not an int. Please check.");
requestFocus();
}
return tempInt;
}
}
package machinelearing.gui;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.io.File;
/**
* @author: fulisha
* @date: 2023/7/17 16:14
* @description:一个带有文件选择功能的文本输入框,用于方便用户选择文件路径,并将选择的文件路径显示在文本输入框中。它还具有一些对文本内容的处理,如检查文件是否存在并显示错误消息等。
*/
public class FilenameField extends TextField implements ActionListener,
FocusListener{
/**
* Serial uid. Not quite useful.
*/
private static final long serialVersionUID = 4572287941606065298L;
/**
* No special initialization..
*/
public FilenameField() {
super();
setText("");
addFocusListener((FocusListener) this);
}
/**
* No special initialization.
* @param paraWidth The width of the .
*/
public FilenameField(int paraWidth) {
super(paraWidth);
setText("");
addFocusListener(this);
}// Of constructor
/**
* No special initialization.
* @param paraWidth The width of the .
* @param paraText The given initial text
*/
public FilenameField(int paraWidth, String paraText) {
super(paraWidth);
setText(paraText);
addFocusListener(this);
}
/**
* No special initialization.
* @param paraWidth The width of the .
* @param paraText The given initial text
*/
public FilenameField(String paraText, int paraWidth) {
super(paraWidth);
setText(paraText);
addFocusListener(this);
}
/**
* Avoid setting null or empty string.
* @param paraText The given text.
*/
@Override
public void setText(String paraText) {
if (paraText.trim().equals("")) {
super.setText("unspecified");
} else {
super.setText(paraText.replace('\\', '/'));
}
}
/**
* Implement ActionListenter.
* @param paraEvent The event is unimportant.
*/
@Override
public void actionPerformed(ActionEvent paraEvent) {
FileDialog tempDialog = new FileDialog(GUICommon.mainFrame,
"Select a file");
tempDialog.setVisible(true);
if (tempDialog.getDirectory() == null) {
setText("");
return;
}
String directoryName = tempDialog.getDirectory();
String tempFilename = directoryName + tempDialog.getFile();
//System.out.println("tempFilename = " + tempFilename);
setText(tempFilename);
}
/**
* Implement FocusListenter.
* @param paraEvent The event is unimportant.
*/
@Override
public void focusGained(FocusEvent paraEvent) {
}
/**
* Implement FocusListenter.
* @param paraEvent The event is unimportant.
*/
@Override
public void focusLost(FocusEvent paraEvent) {
// System.out.println("Focus lost exists.");
String tempString = getText();
if ((tempString.equals("unspecified"))
|| (tempString.equals("")))
return;
File tempFile = new File(tempString);
if (!tempFile.exists()) {
ErrorDialog.errorDialog.setMessageAndShow("File \"" + tempString
+ "\" not exists. Please check.");
requestFocus();
setText("");
}
}
}
package machinelearing.gui;
import machinelearing.ann.FullAnn;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
/**
* @author: fulisha
* @date: 2023/7/18 16:02
* @description:
*/
public class AnnMain implements ActionListener {
/**
* Select the arff file.
*/
private FilenameField arffFilenameField;
/**
* The setting of alpha.
*/
private DoubleField alphaField;
/**
* The setting of alpha.
*/
private DoubleField betaField;
/**
* The setting of alpha.
*/
private DoubleField gammaField;
/**
* Layer nodes, such as "4, 8, 8, 3".
*/
private TextField layerNodesField;
/**
* Activators, such as "ssa".
*/
private TextField activatorField;
/**
* The number of training rounds.
*/
private IntegerField roundsField;
/**
* The learning rate.
*/
private DoubleField learningRateField;
/**
* The mobp.
*/
private DoubleField mobpField;
/**
* The message area.
*/
private TextArea messageTextArea;
/**
* The only constructor.
*/
public AnnMain() {
// A simple frame to contain dialogs.
Frame mainFrame = new Frame();
mainFrame.setTitle("ANN");
// The top part: select arff file.
arffFilenameField = new FilenameField(30);
arffFilenameField.setText("D:/sampledata/sampledata/src/data/iris.arff");
Button browseButton = new Button(" Browse ");
browseButton.addActionListener(arffFilenameField);
Panel sourceFilePanel = new Panel();
sourceFilePanel.add(new Label("The .arff file:"));
sourceFilePanel.add(arffFilenameField);
sourceFilePanel.add(browseButton);
// Setting panel.
Panel settingPanel = new Panel();
settingPanel.setLayout(new GridLayout(3, 6));
settingPanel.add(new Label("alpha"));
alphaField = new DoubleField("0.01");
settingPanel.add(alphaField);
settingPanel.add(new Label("beta"));
betaField = new DoubleField("0.02");
settingPanel.add(betaField);
settingPanel.add(new Label("gamma"));
gammaField = new DoubleField("0.03");
settingPanel.add(gammaField);
settingPanel.add(new Label("layer nodes"));
layerNodesField = new TextField("4, 8, 8, 3");
settingPanel.add(layerNodesField);
settingPanel.add(new Label("activators"));
activatorField = new TextField("sss");
settingPanel.add(activatorField);
settingPanel.add(new Label("training rounds"));
roundsField = new IntegerField("5000");
settingPanel.add(roundsField);
settingPanel.add(new Label("learning rate"));
learningRateField = new DoubleField("0.01");
settingPanel.add(learningRateField);
settingPanel.add(new Label("mobp"));
mobpField = new DoubleField("0.5");
settingPanel.add(mobpField);
Panel topPanel = new Panel();
topPanel.setLayout(new BorderLayout());
topPanel.add(BorderLayout.NORTH, sourceFilePanel);
topPanel.add(BorderLayout.CENTER, settingPanel);
messageTextArea = new TextArea(80, 40);
// The bottom part: ok and exit
Button okButton = new Button(" OK ");
okButton.addActionListener(this);
// DialogCloser dialogCloser = new DialogCloser(this);
Button exitButton = new Button(" Exit ");
// cancelButton.addActionListener(dialogCloser);
exitButton.addActionListener(ApplicationShutdown.applicationShutdown);
Button helpButton = new Button(" Help ");
helpButton.setSize(20, 10);
helpButton.addActionListener(new HelpDialog("ANN", "D:/sampledata/sampledata/src/data/help.txt"));
Panel okPanel = new Panel();
okPanel.add(okButton);
okPanel.add(exitButton);
okPanel.add(helpButton);
mainFrame.setLayout(new BorderLayout());
mainFrame.add(BorderLayout.NORTH, topPanel);
mainFrame.add(BorderLayout.CENTER, messageTextArea);
mainFrame.add(BorderLayout.SOUTH, okPanel);
mainFrame.setSize(600, 500);
mainFrame.setLocation(100, 100);
mainFrame.addWindowListener(ApplicationShutdown.applicationShutdown);
mainFrame.setBackground(GUICommon.MY_COLOR);
mainFrame.setVisible(true);
}
/**
* Read the arff file.
*/
@Override
public void actionPerformed(ActionEvent ae) {
String tempFilename = arffFilenameField.getText();
// Read the layers nodes.
String tempString = layerNodesField.getText().trim();
int[] tempLayerNodes = null;
try {
tempLayerNodes = stringToIntArray(tempString);
} catch (Exception ee) {
ErrorDialog.errorDialog.setMessageAndShow(ee.toString());
return;
}
double tempLearningRate = learningRateField.getValue();
double tempMobp = mobpField.getValue();
String tempActivators = activatorField.getText().trim();
FullAnn tempNetwork = new FullAnn(tempFilename, tempLayerNodes, tempLearningRate, tempMobp,
tempActivators);
int tempRounds = roundsField.getValue();
long tempStartTime = new Date().getTime();
for (int i = 0; i < tempRounds; i++) {
tempNetwork.train();
}
long tempEndTime = new Date().getTime();
messageTextArea.append("\r\nSummary:\r\n");
messageTextArea.append("Trainng time: " + (tempEndTime - tempStartTime) + "ms.\r\n");
double tempAccuray = tempNetwork.test();
messageTextArea.append("Accuracy: " + tempAccuray + "\r\n");
messageTextArea.append("End.");
}
/**
* Convert a string with commas into an int array.
* @param paraString The source string
* @return An int array.
* @throws Exception Exception for illegal data.
*/
public static int[] stringToIntArray(String paraString) throws Exception {
int tempCounter = 1;
for (int i = 0; i < paraString.length(); i++) {
if (paraString.charAt(i) == ',') {
tempCounter++;
}
}
int[] resultArray = new int[tempCounter];
String tempRemainingString = new String(paraString) + ",";
String tempString;
for (int i = 0; i < tempCounter; i++) {
tempString = tempRemainingString.substring(0, tempRemainingString.indexOf(",")).trim();
if (tempString.equals("")) {
throw new Exception("Blank is unsupported");
}
resultArray[i] = Integer.parseInt(tempString);
tempRemainingString = tempRemainingString
.substring(tempRemainingString.indexOf(",") + 1);
}
return resultArray;
}
/**
* The entrance method.
* @param args The parameters.
*/
public static void main(String args[]) {
new AnnMain();
}
}
AnnMain构造方法,是程序的入口方法,他初始化 GUI 界面并添加监听事件。所以从这个构造方法去了解这些代码
今天学习的GUI 是 创建了一个包含输入和输出界面的 GUI 窗口,并为界面上的按钮注册了相应的事件监听器,当用户输入参数后,点击 OK 按钮可以神经网络训练和测试(这里的方法都是FullAnn里面的),点击 Exit 按钮可以退出程序,点击 Help 按钮可以查看帮助信息。今天的代码主要是学习的GUI布局,而关于神经网络学习是之前已经学习的知识(FullAnn类),可再巩固。