weka.classifiers.timeseries.gui.SimpleConfigPanel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of timeseriesForecasting Show documentation
Show all versions of timeseriesForecasting Show documentation
Provides a time series forecasting environment for Weka. Includes a wrapper for Weka regression schemes that automates the process of creating lagged variables and date-derived periodic variables and provides the ability to do closed-loop forecasting. New evaluation routines are provided by a special evaluation module and graphing of predictions/forecasts are provided via the JFreeChart library. Includes both command-line and GUI user interfaces. Sample time series data can be found in ${WEKA_HOME}/packages/timeseriesForecasting/sample-data.
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License
* along with this program. If not, see .
*/
/*
* SimpleConfigPanel.java
* Copyright (C) 2010-2016 University of Waikato, Hamilton, New Zealand
*/
package weka.classifiers.timeseries.gui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import weka.classifiers.timeseries.WekaForecaster;
import weka.filters.supervised.attribute.TSLagMaker;
import weka.classifiers.timeseries.eval.TSEvaluation;
import weka.core.Attribute;
import weka.core.Instances;
import weka.filters.Filter;
import weka.filters.unsupervised.attribute.Remove;
import weka.gui.AttributeSelectionPanel;
/**
* Class that renders a simple configuration panel for configuring a time series
* forecaster.
*
* @author Mark Hall (mhall{[at]}pentaho{[dot]}com)
* @version $Revision: 52593 $
*/
public class SimpleConfigPanel extends JPanel {
/**
* For serialization
*/
private static final long serialVersionUID = 4339062970124604791L;
/** The training instances to operate on */
protected Instances m_instances;
/** The forecaster to configure */
protected WekaForecaster m_forecaster;
/**
* Holds the header of the training instances after all but numeric attributes
* are removed (for target selection purposes
*/
protected Instances m_targetHeader;
/** Combo box for selecting the time stamp attribute */
protected JComboBox m_timeStampCombo = new JComboBox();
/** Combo box for selecting the periodicity */
protected JComboBox m_periodicityCombo = new JComboBox();
/** Panel for selecting targets to forecast */
protected AttributeSelectionPanel m_targetPanel =
new AttributeSelectionPanel();
/** Checkbox for computing confidence intervals */
protected JCheckBox m_computeConfidence = new JCheckBox();
/** Spinner for selecting the number of steps to forecast */
protected JSpinner m_horizonSpinner;
/** Spinner for selecting the confidence interval */
protected JSpinner m_confidenceLevelSpinner;
/** Checkbox for selecting whether to perform evaluation */
protected JCheckBox m_performEvaluation = new JCheckBox();
/** A reference to the advanced config panel */
protected AdvancedConfigPanel m_advancedConfig;
/**
* Text field for entering date time stamp values that should be "skipped" -
* i.e. not considered as a time step
*/
protected JTextField m_skipText = new JTextField(18);
/** A reference to the parent panel */
protected ForecastingPanel m_parentPanel;
/**
* Constructor
*
* @param parent the parent ForecastingPanel
*/
public SimpleConfigPanel(ForecastingPanel parent) {
m_parentPanel = parent;
setLayout(new BorderLayout());
JPanel colSelect = new JPanel();
colSelect.setLayout(new BorderLayout());
colSelect.setBorder(BorderFactory.createTitledBorder("Target Selection"));
JPanel tempHolder1 = new JPanel();
tempHolder1.setLayout(new BorderLayout());
tempHolder1.add(m_targetPanel, BorderLayout.NORTH);
colSelect.add(tempHolder1, BorderLayout.NORTH);
m_targetPanel.setPreferredScrollableViewportSize(new Dimension(250, 80));
SpinnerNumberModel snm = new SpinnerNumberModel();
snm.setValue(1);
snm.setMinimum(1);
m_horizonSpinner = new JSpinner(snm);
Dimension spinD = m_horizonSpinner.getPreferredSize();
spinD = new Dimension((int) (spinD.getWidth() * 1.5),
(int) spinD.getHeight());
m_horizonSpinner.setPreferredSize(spinD);
JPanel spinnerHolder = new JPanel();
spinnerHolder.setBorder(BorderFactory.createEmptyBorder(0, 0, 1, 0));
spinnerHolder.setLayout(new BorderLayout());
spinnerHolder.add(m_horizonSpinner, BorderLayout.EAST);
spinnerHolder.add(new JLabel("Number of time units to forecast ",
JLabel.LEFT), BorderLayout.CENTER);
// tempHolder1.add(spinnerHolder, BorderLayout.CENTER);
// JPanel spacer = new JPanel();
// spacer.setMinimumSize(spinD);
// tempHolder1.add(spacer, BorderLayout.SOUTH);
add(colSelect, BorderLayout.CENTER);
Box comboHolder = new Box(BoxLayout.PAGE_AXIS);
comboHolder.add(spinnerHolder);
JPanel timeHolder = new JPanel();
timeHolder.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 0));
timeHolder.setLayout(new BorderLayout());
// timeHolder.setBorder(BorderFactory.createTitledBorder("Time stamp"));
timeHolder.add(new JLabel("Time stamp ", JLabel.RIGHT), BorderLayout.WEST);
timeHolder.add(m_timeStampCombo, BorderLayout.EAST);
comboHolder.add(timeHolder);
JPanel periodicityHolder = new JPanel();
periodicityHolder.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 0));
periodicityHolder.setLayout(new BorderLayout());
// periodicityHolder.setBorder(BorderFactory.createTitledBorder("Periodicity"));
periodicityHolder.add(new JLabel("Periodicity", JLabel.RIGHT),
BorderLayout.WEST);
periodicityHolder.add(m_periodicityCombo, BorderLayout.EAST);
comboHolder.add(periodicityHolder);
m_periodicityCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
checkSkipEnabledStatus();
checkPeriodicity(null);
}
});
//
JPanel skipPanel = new JPanel();
skipPanel.setLayout(new BorderLayout());
skipPanel.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 0));
String skipTipText =
"Set date time stamp values that should be 'skipped'
"
+ "i.e. times that shouldn't count as a time step increment.
"
+ "E.g. financial trading does not occur on the weekend, so the
"
+ "difference between Friday and the following Monday is actually one
"
+ "time step (not three).
Examples:
"
+ "\"sat,weekend,aug,2011-01-11@yyyy-MM-dd\"";
JLabel skipLab = new JLabel("Skip list", JLabel.RIGHT);
skipLab.setToolTipText(skipTipText);
skipPanel.add(skipLab, BorderLayout.WEST);
skipPanel.add(m_skipText, BorderLayout.EAST);
m_skipText.setToolTipText(skipTipText);
comboHolder.add(skipPanel);
m_computeConfidence.setHorizontalTextPosition(SwingConstants.LEFT);
JPanel confHolder = new JPanel();
confHolder.setLayout(new BorderLayout());
confHolder.add(new JLabel("Confidence intervals", JLabel.RIGHT),
BorderLayout.WEST);
confHolder.add(m_computeConfidence, BorderLayout.EAST);
comboHolder.add(confHolder);
JPanel confLevHolder = new JPanel();
confLevHolder.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 0));
confLevHolder.setLayout(new BorderLayout());
final JLabel levelLab = new JLabel("Level (%) ", JLabel.RIGHT);
levelLab.setEnabled(false);
snm = new SpinnerNumberModel();
snm.setValue(95);
snm.setMinimum(1);
snm.setMaximum(99);
m_confidenceLevelSpinner = new JSpinner(snm);
m_confidenceLevelSpinner.setEnabled(false);
confLevHolder.add(m_confidenceLevelSpinner, BorderLayout.EAST);
confLevHolder.add(levelLab, BorderLayout.CENTER);
comboHolder.add(confLevHolder);
m_computeConfidence.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
boolean enable = m_computeConfidence.isSelected();
levelLab.setEnabled(enable);
m_confidenceLevelSpinner.setEnabled(enable);
}
});
JPanel evalHolder = new JPanel();
evalHolder.setLayout(new BorderLayout());
evalHolder.add(new JLabel("Perform evaluation", JLabel.RIGHT),
BorderLayout.WEST);
m_performEvaluation.setHorizontalAlignment(SwingConstants.LEFT);
evalHolder.add(m_performEvaluation, BorderLayout.EAST);
comboHolder.add(evalHolder);
m_performEvaluation.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
m_advancedConfig.m_trainingCheckBox.setSelected(m_performEvaluation
.isSelected());
// don't enable test set evaluation, only disable
if (!m_performEvaluation.isSelected()) {
m_advancedConfig.m_holdoutCheckBox.setSelected(false);
}
}
});
// comboHolder.add(m_horizon);
JPanel temp = new JPanel();
temp.setLayout(new BorderLayout());
temp.setBorder(BorderFactory.createTitledBorder("Parameters"));
temp.add(comboHolder, BorderLayout.NORTH);
add(temp, BorderLayout.EAST);
m_timeStampCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (m_advancedConfig != null) {
m_advancedConfig.updateDateDerivedPanel();
checkSkipEnabledStatus();
}
}
});
/*
* m_periodicityCombo.addActionListener(new ActionListener() { public void
* actionPerformed(ActionEvent e) { if (m_forecaster != null) {
*
* } } });
*/
// m_targetPanel
/*
* Dimension d = tempHolder1.getPreferredSize(); Dimension d2 =
* spinnerHolder.getPreferredSize(); tempHolder1.setMinimumSize(new
* Dimension(tempHolder1.getPreferredSize().width, d.height + d2.height));
* tempHolder1.setPreferredSize(new
* Dimension(tempHolder1.getPreferredSize().width, d.height + d2.height));
*/
}
private void checkSkipEnabledStatus() {
boolean enable = false;
if (m_instances != null) {
if (m_timeStampCombo.getSelectedItem() != null) {
String timeName = m_timeStampCombo.getSelectedItem().toString();
Attribute timeAtt = m_instances.attribute(timeName);
if (timeAtt != null) {
if (m_periodicityCombo.getSelectedItem() != null) {
String periodicity = m_periodicityCombo.getSelectedItem()
.toString();
enable =
(timeAtt.isDate() && !periodicity.equals("") && !periodicity
.equals(""));
}
}
}
}
m_skipText.setEnabled(enable);
}
/**
* Get the title for this panel suitable for displaying in a tab.
*
* @return the title for this panel.
*/
public String getTabTitle() {
return "Basic configuration";
}
/**
* Get the tool tip for this panel.
*
* @return the tool tip for this panel.
*/
public String getTabTitleToolTip() {
return "Basic configuration";
}
/**
* Get the value in the horizon spinner (i.e. the number of steps to forecast)
*
* @return the number of steps to forecast.
*/
public int getHorizonValue() {
SpinnerNumberModel snm = (SpinnerNumberModel) m_horizonSpinner.getModel();
return snm.getNumber().intValue();
}
/**
* Set a reference to the advanced configuration panel.
*
* @param adv a reference to the advanced configuration panel.
*/
public void setAdvancedConfig(AdvancedConfigPanel adv) {
m_advancedConfig = adv;
}
/**
* Set the WekaForecaster that is to be configured by this panel.
*
* @param forecaster the WekaForecaster that is to be configured by this
* panel.
*/
public void setForecaster(WekaForecaster forecaster) {
m_forecaster = forecaster;
if (m_instances != null) {
if (!m_forecaster.getTSLagMaker().getAdjustForTrends()) {
m_timeStampCombo.setSelectedItem("");
m_periodicityCombo.setSelectedIndex(0);
} else {
if (m_forecaster.getTSLagMaker().isUsingAnArtificialTimeIndex()) {
m_timeStampCombo.setSelectedItem("