diff --git a/BioPatRec.m b/BioPatRec.m index b393c9c..88b9d90 100644 --- a/BioPatRec.m +++ b/BioPatRec.m @@ -24,6 +24,7 @@ % ------------------------- Updates & Contributors ------------------------ % 2009-04-02 / Max Ortiz / Creation of EMG_AQ % 2011-22-06 / Max Ortiz / Software name changed from EMG_AQ to BioPatRec +% 20XX-XX-XX / Author / Comments close all; clear all; diff --git a/Comm/AFE/Acquire_tWs.m b/Comm/AFE/Acquire_tWs.m index f706ea5..16c53d9 100644 --- a/Comm/AFE/Acquire_tWs.m +++ b/Comm/AFE/Acquire_tWs.m @@ -23,46 +23,84 @@ % SetDeviceStartAcquisition(), % Acquire_tWs(), StopAcquisition(). This functions % has been moved to COMM/AFE folder, into this new script. - +% 2015-1-19 / Enzo Mastinu / The ADS1299 part has been modified in way to be + % compatible with the new ADS1299 acquisition mode (DSP + FPU) +% 2015-4-10 / Enzo Mastinu / The ADS1299_DSP acquisition has been optimized, only desired + % channels are transmitted to PC, not all as before +% 2016-7-08 / Enzo Mastinu / The ADS_DSP/Neuromotus acquisition has been + % optimized introducing the re-synchronization + % in case the signal got lost % 20xx-xx-xx / Author / Comment % It acquire tWs samples from the selected device -function cData = Acquire_tWs(deviceName, obj, nCh, tWs) +function [cData, error] = Acquire_tWs(deviceName, obj, nCh, tWs) - cData = zeros(tWs,nCh); % this is the data structure that the function must return - ampPP = 0.0005; - offVector = 0:nCh-1; - offVector = offVector .* ampPP; - + error = 0; + cData = zeros(tWs,nCh); % this is the data structure that the function must return - %%%%% ADS1299 %%%%% - if strcmp(deviceName, 'ADS1299') - LSBweight = double(4.5/(24*8388607)); % ADS1299: if gain is set on 24 V/V - for sampleNr = 1:tWs - % 27bytes package mode - byteData = fread(obj,27,'char'); % Acquire 27 bytes packet from Tiva (and from ADS1299), 3 status bytes + 3 byte (24bit) for each channel - value = [65536 256 1]*reshape(byteData(4:end), 3, 8); % all channels data are now available on value vector, byteData(4:end) means throw away status bytes - for k = 1:nCh - if value(k) > 8388607 % the data must be converted from 2's complement - value(k) = value(k) - 2^24; + % Set warnings to temporarily issue error (exceptions) + s = warning('error', 'instrument:fread:unsuccessfulRead'); + try + %%%%% ADS1299 %%%%% + if strcmp(deviceName, 'ADS1299') + % LSBweight = double(4.5/(24*8388607)); % ADS1299: we always use the gain of 24 V/V + LSBweight = double(4.5/(8388607)); % It is better to plot data with gain scaling effect + for sampleNr = 1:tWs + % 27bytes package mode + byteData = fread(obj,27,'char'); % Acquire 27 bytes packet from Tiva (and from ADS1299), 3 status bytes + 3 byte (24bit) for each channel + value = [65536 256 1]*reshape(byteData(4:end), 3, 8); % all channels data are now available on value vector, byteData(4:end) means throw away status bytes + for k = 1:nCh + if value(k) > 8388607 % the data must be converted from 2's complement + value(k) = value(k) - 2^24; + end + cData(sampleNr,k) = value(k) * LSBweight; + end + end + end + if strcmp(deviceName, 'ADS_BP') + for sampleNr = 1:tWs + go = 0; + while go == 0 + % nCh*4 bytes (float) mode + byteData = fread(obj,nCh,'float32'); % float data mode (4bytes X nCh channels) + if byteData < 10 + go = 1; + else + % Synchronize the device again + fwrite(obj,'T','char'); + % Read available data and discard it + if obj.BytesAvailable > 1 + fread(obj,obj.BytesAvailable,'uint8'); + end + fwrite(obj,'G','char'); + fwrite(obj,nCh,'char'); + fread(obj,1,'char'); + go = 0; + end end - cData(sampleNr,k) = value(k) * LSBweight; - end + cData(sampleNr,:) = byteData(1:nCh,:)'; + end end - end + + %%%%% INTAN RHA2216 %%%%% + if strcmp(deviceName, 'RHA2216') + % LSBweight = double(2.5/(200*65535)); % Intan differential gain is 200 V/V + LSBweight = double(2.5/(65535)); % It is better to plot data with gain scaling effect + for sampleNr = 1:tWs + value16 = fread(obj,nCh,'uint16'); + for k = 1:nCh + % cData(sampleNr,k) = value16(k) - 16384; % Centers data and scales it to fit the graphs + cData(sampleNr,k) = value16(k)*LSBweight; % Convert data into volt + end + end + end - %%%%% INTAN RHA2216 %%%%% - if strcmp(deviceName, 'RHA2216') - LSBweight = double(2.5/(200*65535)); % Intan differential gain is 200 V/V - for sampleNr = 1:tWs - value16 = fread(obj,nCh,'uint16'); - for k = 1:nCh -% cData(sampleNr,k) = value16(k) - 16384; % Centers data and scales it to fit the graphs - cData(sampleNr,k) = value16(k)*LSBweight; % Convert data into volt - end - end - end + catch exception + error = 1; + end + %Set warning back to normal state + warning(s); end diff --git a/Comm/AFE/ConnectDevice.m b/Comm/AFE/ConnectDevice.m index a5fddc1..a239af8 100644 --- a/Comm/AFE/ConnectDevice.m +++ b/Comm/AFE/ConnectDevice.m @@ -23,6 +23,8 @@ % SetDeviceStartAcquisition(), % Acquire_tWs(), StopAcquisition(). This functions % has been moved to COMM/AFE folder, into this new script. +% 2015-1-19 / Enzo Mastinu / The ADS1299 part has been modified in way to be + % compatible with the new ADS1299 acquisition mode (DSP + FPU) % 20xx-xx-xx / Author / Comment @@ -41,23 +43,17 @@ sT = handles.sT; nCh = handles.nCh; sTall = handles.sTall; - - % Delete previous connection objects - if exist('obj') - fclose(obj); - delete(obj); - end %%%%% WiFi %%%%% if strcmp(ComPortType, 'WiFi') %%%%% TI ADS1299 %%%%% - if strcmp(deviceName, 'ADS1299') - obj = tcpip('192.168.100.10',65100,'NetworkRole','client'); % WIICOM - obj.InputBufferSize = sTall*sF*27; % 27bytes data package + if strcmp(deviceName, 'ADS_BP') + obj = tcpip('192.168.100.10',65100,'NetworkRole','client'); % ADS1299 + obj.InputBufferSize = sTall*sF*nCh*4; end %%%%% INTAN RHA2216 %%%%% if strcmp(deviceName, 'RHA2216') - obj = tcpip('192.168.100.10',65100,'NetworkRole','client'); % WIICOM + obj = tcpip('192.168.100.10',65100,'NetworkRole','client'); % WIICOM obj.InputBufferSize = sT*sF*nCh*2; end end @@ -66,8 +62,12 @@ if strcmp(ComPortType, 'COM') %%%%% TI ADS1299 %%%%% if strcmp(deviceName, 'ADS1299') - obj = serial (ComPortName, 'baudrate', 2500000, 'databits', 8, 'byteorder', 'bigEndian'); - obj.InputBufferSize = sTall*sF*27; % 27bytes data package + obj = serial (ComPortName, 'baudrate', 2000000, 'databits', 8, 'byteorder', 'bigEndian'); + obj.InputBufferSize = sTall*sF*27; % 27bytes data package + end + if strcmp(deviceName, 'ADS_BP') + obj = serial (ComPortName, 'baudrate', 460800, 'databits', 8, 'byteorder', 'bigEndian'); + obj.InputBufferSize = sTall*sF*nCh*4; end %%%%% INTAN RHA2216 %%%%% if strcmp(deviceName, 'RHA2216') diff --git a/Comm/AFE/SBI/InitSBI_NI.m b/Comm/AFE/SBI/InitSBI_NI.m index aa68605..abdd15b 100644 --- a/Comm/AFE/SBI/InitSBI_NI.m +++ b/Comm/AFE/SBI/InitSBI_NI.m @@ -28,13 +28,16 @@ % job % 2012-05-29 / Max Ortiz / Removed the routine for sequentially adding % channels to a loop. +% 2016-02-10 / Max Ortiz / Modifed routine to use chAI directly as a +% string of numbers identifying each channels +% as in the GUI % 20xx-xx-xx / Author / Comment on update function [s] = InitSBI_NI(sF, sT, chAI, chAO) % Auxiliar variables -nChAI = size(chAI,2); -chAIidx = find(chAI); +% nChAI = size(chAI,2); +% chAIidx = find(chAI); % Close possible daq objects running if (~isempty(daqfind)) @@ -50,8 +53,8 @@ % Add channels in a loop -for i = 1 : size(chAIidx,2) - chID = ['ai' num2str(chAIidx(i)-1)]; +for i = 1 : size(chAI,2) + chID = ['ai' num2str(chAI(i)-1)]; s.addAnalogInputChannel(dev.ID,chID,'Voltage'); s.Channels(i).InputType ='SingleEnded'; s.Channels(i).Range = [-5 5]; diff --git a/Comm/AFE/SetDeviceStartAcquisition.m b/Comm/AFE/SetDeviceStartAcquisition.m index 3d550b4..5d57df4 100644 --- a/Comm/AFE/SetDeviceStartAcquisition.m +++ b/Comm/AFE/SetDeviceStartAcquisition.m @@ -23,7 +23,16 @@ % SetDeviceStartAcquisition(), % Acquire_tWs(), StopAcquisition(). This functions % has been moved to COMM/AFE folder, into this new script. - +% 2015-1-19 / Enzo Mastinu / The ADS1299 part has been modified in way to be + % compatible with the new ADS1299 acquisition mode (DSP + FPU) +% 2015-4-10 / Enzo Mastinu / The ADS1299_DSP acquisition has been optimized, only desired + % channels are transmitted to PC, not all as + % before. To do that PC sends start command + % followed by the number of channels requested +% 2016-5-9 / Enzo Mastinu / The ADS_BP acquisition has been optimized. Now +% % sF will be set before starting the recording. +% % Only some values of sF are allowed. + % 20xx-xx-xx / Author / Comment @@ -35,13 +44,12 @@ function SetDeviceStartAcquisition(handles, obj) nCh = handles.nCh; sTall = handles.sTall; sF = handles.sF; - - + %%%%% INTAN RHA2216 %%%%% if strcmp(deviceName, 'RHA2216') % Setup the selected channels - vCh = 0:nCh'-1; % Vector of channels + vCh = 0:nCh'-1; fwrite(obj,'C','char'); fwrite(obj,nCh,'uint8'); for i = 1 : nCh @@ -97,5 +105,58 @@ function SetDeviceStartAcquisition(handles, obj) return end end + if strcmp(deviceName, 'ADS_BP') + % Set the ADS_BP datarate output + if(sF~=500 && sF~=1000 && sF~=2000) + disp('The selected sampling frequency is not valid for the ADS_BP. Errors may occur!'); + errordlg('The selected sampling frequency is not valid for the ADS_BP. Errors may occur!','Erroneous sampling frequency'); + end + fwrite(obj,'T','char'); + % Read available data and discard it + if obj.BytesAvailable > 1 + fread(obj,obj.BytesAvailable,'uint8'); + end + fwrite(obj,'r','char'); + replay = char(fread(obj,1,'char')); + if strcmp(replay,'r') + fwrite(obj,sF,'uint32'); + replay = char(fread(obj,1,'char')); + if strcmp(replay,'r'); + set(handles.t_msg,'String','sampling frequency set'); + else + set(handles.t_msg,'String','Error Setting sampling frequency'); + fclose(obj); + return + end + else + set(handles.t_msg,'String','Error Setting sampling frequency'); + fclose(obj); + return + end + % Send the START command + fwrite(obj,'G','char'); + fwrite(obj,nCh,'char'); + replay = char(fread(obj,1,'char')); + switch replay + case 'G' + set(handles.t_msg,'String','EMG Start'); + case 'L' + set(handles.t_msg,'String','Error: Neuromotus locked'); + fclose(obj); + return + case 'B' + set(handles.t_msg,'String','Error: Battery Low!'); + fclose(obj); + return + end + % the digital filtering introduce a transient not needed in recording + % session. To avoid that transient we can just skip the first + % samples coming from the device + settlingTime = 1; + settlingSamples = settlingTime*sF; + for sampleNr = 1:settlingSamples + fread(obj,nCh,'float32'); + end + end end diff --git a/Comm/AFE/StopAcquisition.m b/Comm/AFE/StopAcquisition.m index 62f46be..385f84e 100644 --- a/Comm/AFE/StopAcquisition.m +++ b/Comm/AFE/StopAcquisition.m @@ -42,5 +42,9 @@ function StopAcquisition(deviceName, obj) fwrite(obj,'G','char'); % Stop the aquisition ´ fclose(obj); % Close connection end + if strcmp(deviceName, 'ADS_BP') + fwrite(obj,'T','char'); % Stop the aquisition ´ + fclose(obj); % Close connection + end end \ No newline at end of file diff --git a/Comm/ALC/VCP_Piccolo/Connect_ALC.m b/Comm/ALC/VCP_Piccolo/Connect_ALC.m deleted file mode 100644 index 211fcd4..0000000 --- a/Comm/ALC/VCP_Piccolo/Connect_ALC.m +++ /dev/null @@ -1,39 +0,0 @@ -% ---------------------------- Copyright Notice --------------------------- -% This file is part of BioPatRec © which is open and free software under -% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for -% the full license governing this code and copyrights. -% -% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and -% Chalmers University of Technology. All authors’ contributions must be kept -% acknowledged below in the section "Updates % Contributors". -% -% Would you like to contribute to science and sum efforts to improve -% amputees’ quality of life? Join this project! or, send your comments to: -% maxo@chalmers.se. -% -% The entire copyright notice must be kept in this or any source file -% linked to BioPatRec. This will ensure communication with all authors and -% acknowledge contributions here and in the project web page (optional). -% ------------------- Function Description ------------------ -% Function to create the communicatio object - -% --------------------------Updates-------------------------- -% 2011-11-09 / Max Ortiz / Creation -% 20xx-xx-xx / Author / Comment - - - -function obj = Connect_ALC(conn) - %conn, Connection String - %Find serial port objects with specified property values - obj.io=instrfind('Status','open'); - if isempty(obj.io) - obj.io=serial(conn, 'BaudRate', 14400); - pause(1) - % Open io for read and write access - set(obj.io,'InputBuffer',1024*64) - fopen(obj.io) - pause(1) - end - -end diff --git a/Comm/ALC/VCP_Piccolo/GUI_TestPWMs.fig b/Comm/ALC/VCP_Piccolo/GUI_TestPWMs.fig deleted file mode 100644 index a8976df..0000000 Binary files a/Comm/ALC/VCP_Piccolo/GUI_TestPWMs.fig and /dev/null differ diff --git a/Comm/ALC/VCP_Piccolo/GUI_TestPWMs.m b/Comm/ALC/VCP_Piccolo/GUI_TestPWMs.m deleted file mode 100644 index e4e7683..0000000 --- a/Comm/ALC/VCP_Piccolo/GUI_TestPWMs.m +++ /dev/null @@ -1,472 +0,0 @@ -% ---------------------------- Copyright Notice --------------------------- -% This file is part of BioPatRec © which is open and free software under -% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for -% the full license governing this code and copyrights. -% -% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and -% Chalmers University of Technology. All authors’ contributions must be kept -% acknowledged below in the section "Updates % Contributors". -% -% Would you like to contribute to science and sum efforts to improve -% amputees’ quality of life? Join this project! or, send your comments to: -% maxo@chalmers.se. -% -% The entire copyright notice must be kept in this or any source file -% linked to BioPatRec. This will ensure communication with all authors and -% acknowledge contributions here and in the project web page (optional). -% -% -------------------------- Function Description ------------------------- -% [Give a short summary about the principle of your function here.] -% -% ------------------------- Updates & Contributors ------------------------ -% [Contributors are welcome to add their email] -% 20xx-xx-xx / Max Ortiz / Creation -% 20xx-xx-xx / Author / Comment on update - -function varargout = GUI_TestPWMs(varargin) -% GUI_TESTPWMS M-file for GUI_TestPWMs.fig -% GUI_TESTPWMS, by itself, creates a new GUI_TESTPWMS or raises the existing -% singleton*. -% -% H = GUI_TESTPWMS returns the handle to a new GUI_TESTPWMS or the handle to -% the existing singleton*. -% -% GUI_TESTPWMS('CALLBACK',hObject,eventData,handles,...) calls the local -% function named CALLBACK in GUI_TESTPWMS.M with the given input arguments. -% -% GUI_TESTPWMS('Property','Value',...) creates a new GUI_TESTPWMS or raises the -% existing singleton*. Starting from the left, property value pairs are -% applied to the GUI before GUI_TestPWMs_OpeningFcn gets called. An -% unrecognized property name or invalid value makes property application -% stop. All inputs are passed to GUI_TestPWMs_OpeningFcn via varargin. -% -% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one -% instance to run (singleton)". -% -% See also: GUIDE, GUIDATA, GUIHANDLES - -% Edit the above text to modify the response to help GUI_TestPWMs - -% Last Modified by GUIDE v2.5 07-Nov-2011 17:59:15 - -% Begin initialization code - DO NOT EDIT -gui_Singleton = 1; -gui_State = struct('gui_Name', mfilename, ... - 'gui_Singleton', gui_Singleton, ... - 'gui_OpeningFcn', @GUI_TestPWMs_OpeningFcn, ... - 'gui_OutputFcn', @GUI_TestPWMs_OutputFcn, ... - 'gui_LayoutFcn', [] , ... - 'gui_Callback', []); -if nargin && ischar(varargin{1}) - gui_State.gui_Callback = str2func(varargin{1}); -end - -if nargout - [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); -else - gui_mainfcn(gui_State, varargin{:}); -end -% End initialization code - DO NOT EDIT - - -% --- Executes just before GUI_TestPWMs is made visible. -function GUI_TestPWMs_OpeningFcn(hObject, eventdata, handles, varargin) -% This function has no output args, see OutputFcn. -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -% varargin command line arguments to GUI_TestPWMs (see VARARGIN) - -% Choose default command line output for GUI_TestPWMs -handles.output = hObject; - -% Update handles structure -guidata(hObject, handles); - -% UIWAIT makes GUI_TestPWMs wait for user response (see UIRESUME) -% uiwait(handles.figure1); - - -% --- Outputs from this function are returned to the command line. -function varargout = GUI_TestPWMs_OutputFcn(hObject, eventdata, handles) -% varargout cell array for returning output args (see VARARGOUT); -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Get default command line output from handles structure -varargout{1} = handles.output; - - - -function et_pwm1a_Callback(hObject, eventdata, handles) -% hObject handle to et_pwm1a (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_pwm1a as text -% str2double(get(hObject,'String')) returns contents of et_pwm1a as a double - - -% --- Executes during object creation, after setting all properties. -function et_pwm1a_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_pwm1a (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_pwm1b_Callback(hObject, eventdata, handles) -% hObject handle to et_pwm1b (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_pwm1b as text -% str2double(get(hObject,'String')) returns contents of et_pwm1b as a double - - -% --- Executes during object creation, after setting all properties. -function et_pwm1b_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_pwm1b (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_pwm2a_Callback(hObject, eventdata, handles) -% hObject handle to et_pwm2a (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_pwm2a as text -% str2double(get(hObject,'String')) returns contents of et_pwm2a as a double - - -% --- Executes during object creation, after setting all properties. -function et_pwm2a_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_pwm2a (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_pwm2b_Callback(hObject, eventdata, handles) -% hObject handle to et_pwm2b (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_pwm2b as text -% str2double(get(hObject,'String')) returns contents of et_pwm2b as a double - - -% --- Executes during object creation, after setting all properties. -function et_pwm2b_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_pwm2b (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_pwm3a_Callback(hObject, eventdata, handles) -% hObject handle to et_pwm3a (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_pwm3a as text -% str2double(get(hObject,'String')) returns contents of et_pwm3a as a double - - -% --- Executes during object creation, after setting all properties. -function et_pwm3a_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_pwm3a (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in pb_Connect. -function pb_Connect_Callback(hObject, eventdata, handles) -% hObject handle to pb_Connect (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -compath = get(handles.et_com,'String'); -handles.com = Connect_ALC(compath); -%handles.com = MasterModuleComm(compath); -if TestConnectionALC(handles.com)==1; %Write S to stop program - set(handles.t_msg,'String','Connection established'); - guidata(hObject,handles); -else - set(handles.t_msg,'String','Wrong connection'); - fclose(handles.com); -end - - - -% --- Executes on button press in pb_UpdatePWMs. -function pb_UpdatePWMs_Callback(hObject, eventdata, handles) -% hObject handle to pb_UpdatePWMs (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -com = handles.com; % Get the communication object - -pwms = []; -pwms1 = [pwms 100 - str2double(get(handles.et_pwm1a,'String'))]; -pwms2 = [pwms 100 - str2double(get(handles.et_pwm1b,'String'))]; -pwms3 = [pwms 100 - str2double(get(handles.et_pwm2a,'String'))]; -pwms4 = [pwms 100 - str2double(get(handles.et_pwm2b,'String'))]; -pwms5 = [pwms 100 - str2double(get(handles.et_pwm3a,'String'))]; -pwms6 = [pwms 100 - str2double(get(handles.et_pwm3b,'String'))]; -pwms7 = [pwms 100 - str2double(get(handles.et_pwm4a,'String'))]; -pwms8 = [pwms 100 - str2double(get(handles.et_pwm4b,'String'))]; -pwms9 = [pwms 100 - str2double(get(handles.et_pwm5a,'String'))]; -pwms10 = [pwms 100 - str2double(get(handles.et_pwm5b,'String'))]; -pwms11 = [pwms 100 - str2double(get(handles.et_pwm6a,'String'))]; -pwms12 = [pwms 100 - str2double(get(handles.et_pwm6b,'String'))]; -pwms = [pwms1, pwms2, pwms3, pwms4, pwms5, pwms6, pwms7, pwms8, pwms9, pwms10, pwms11, pwms12]; - - -set(handles.t_msg,'String','Update started'); -if UpdateAllPWMusingSCI(com, pwms) == 1 - set(handles.t_msg,'String','Update succesful'); -else - set(handles.t_msg,'String','Update Bad :('); -end - - -function et_com_Callback(hObject, eventdata, handles) -% hObject handle to et_com (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_com as text -% str2double(get(hObject,'String')) returns contents of et_com as a double - - -% --- Executes during object creation, after setting all properties. -function et_com_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_com (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in pb_Disconnect. -function pb_Disconnect_Callback(hObject, eventdata, handles) -% hObject handle to pb_Disconnect (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -fclose(handles.com.io); -set(handles.t_msg,'String','Disconnected'); - - -% --- Executes on button press in pb_CyclePWM. -function pb_CyclePWM_Callback(hObject, eventdata, handles) -% hObject handle to pb_CyclePWM (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -obj = handles.com; - -set(handles.t_msg,'String','Cycling started'); -if TestPWMusingSCIbyCycling(obj) - set(handles.t_msg,'String','Good'); -else - set(handles.t_msg,'String','Bad :('); -end - - - -function et_pwm3b_Callback(hObject, eventdata, handles) -% hObject handle to et_pwm3b (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_pwm3b as text -% str2double(get(hObject,'String')) returns contents of et_pwm3b as a double - - -% --- Executes during object creation, after setting all properties. -function et_pwm3b_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_pwm3b (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_pwm4a_Callback(hObject, eventdata, handles) -% hObject handle to et_pwm4a (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_pwm4a as text -% str2double(get(hObject,'String')) returns contents of et_pwm4a as a double - - -% --- Executes during object creation, after setting all properties. -function et_pwm4a_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_pwm4a (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_pwm4b_Callback(hObject, eventdata, handles) -% hObject handle to et_pwm4b (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_pwm4b as text -% str2double(get(hObject,'String')) returns contents of et_pwm4b as a double - - -% --- Executes during object creation, after setting all properties. -function et_pwm4b_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_pwm4b (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_pwm5a_Callback(hObject, eventdata, handles) -% hObject handle to et_pwm5a (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_pwm5a as text -% str2double(get(hObject,'String')) returns contents of et_pwm5a as a double - - -% --- Executes during object creation, after setting all properties. -function et_pwm5a_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_pwm5a (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_pwm5b_Callback(hObject, eventdata, handles) -% hObject handle to et_pwm5b (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_pwm5b as text -% str2double(get(hObject,'String')) returns contents of et_pwm5b as a double - - -% --- Executes during object creation, after setting all properties. -function et_pwm5b_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_pwm5b (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -function et_pwm6a_Callback(hObject, eventdata, handles) -% hObject handle to et_pwm6a (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_pwm6a as text -% str2double(get(hObject,'String')) returns contents of et_pwm6a as a double - - -% --- Executes during object creation, after setting all properties. -function et_pwm6a_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_pwm6a (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_pwm6b_Callback(hObject, eventdata, handles) -% hObject handle to et_pwm6b (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_pwm6b as text -% str2double(get(hObject,'String')) returns contents of et_pwm6b as a double - - -% --- Executes during object creation, after setting all properties. -function et_pwm6b_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_pwm6b (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end diff --git a/Comm/ALC/VCP_Piccolo/GUI_Test_Hand.fig b/Comm/ALC/VCP_Piccolo/GUI_Test_Hand.fig deleted file mode 100644 index c2cf58a..0000000 Binary files a/Comm/ALC/VCP_Piccolo/GUI_Test_Hand.fig and /dev/null differ diff --git a/Comm/ALC/VCP_Piccolo/GUI_Test_Hand.m b/Comm/ALC/VCP_Piccolo/GUI_Test_Hand.m deleted file mode 100644 index 52380eb..0000000 --- a/Comm/ALC/VCP_Piccolo/GUI_Test_Hand.m +++ /dev/null @@ -1,601 +0,0 @@ -% ---------------------------- Copyright Notice --------------------------- -% This file is part of BioPatRec © which is open and free software under -% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for -% the full license governing this code and copyrights. -% -% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and -% Chalmers University of Technology. All authors’ contributions must be kept -% acknowledged below in the section "Updates % Contributors". -% -% Would you like to contribute to science and sum efforts to improve -% amputees’ quality of life? Join this project! or, send your comments to: -% maxo@chalmers.se. -% -% The entire copyright notice must be kept in this or any source file -% linked to BioPatRec. This will ensure communication with all authors and -% acknowledge contributions here and in the project web page (optional). -% -% -------------------------- Function Description ------------------------- -% [Give a short summary about the principle of your function here.] -% -% ------------------------- Updates & Contributors ------------------------ -% [Contributors are welcome to add their email] -% 20xx-xx-xx / Max Ortiz / Creation -% 20xx-xx-xx / Author / Comment on update - -function varargout = GUI_Test_Hand(varargin) -% GUI_TEST_HAND M-file for GUI_Test_Hand.fig -% GUI_TEST_HAND, by itself, creates a new GUI_TEST_HAND or raises the existing -% singleton*. -% -% H = GUI_TEST_HAND returns the handle to a new GUI_TEST_HAND or the handle to -% the existing singleton*. -% -% GUI_TEST_HAND('CALLBACK',hObject,eventData,handles,...) calls the local -% function named CALLBACK in GUI_TEST_HAND.M with the given input arguments. -% -% GUI_TEST_HAND('Property','Value',...) creates a new GUI_TEST_HAND or raises the -% existing singleton*. Starting from the left, property value pairs are -% applied to the GUI before GUI_Test_Hand_OpeningFcn gets called. An -% unrecognized property name or invalid value makes property application -% stop. All inputs are passed to GUI_Test_Hand_OpeningFcn via varargin. -% -% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one -% instance to run (singleton)". -% -% See also: GUIDE, GUIDATA, GUIHANDLES - -% Edit the above text to modify the response to help GUI_Test_Hand - -% Last Modified by GUIDE v2.5 15-Aug-2012 12:07:02 - -% Begin initialization code - DO NOT EDIT -gui_Singleton = 1; -gui_State = struct('gui_Name', mfilename, ... - 'gui_Singleton', gui_Singleton, ... - 'gui_OpeningFcn', @GUI_Test_Hand_OpeningFcn, ... - 'gui_OutputFcn', @GUI_Test_Hand_OutputFcn, ... - 'gui_LayoutFcn', [] , ... - 'gui_Callback', []); -if nargin && ischar(varargin{1}) - gui_State.gui_Callback = str2func(varargin{1}); -end - -if nargout - [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); -else - gui_mainfcn(gui_State, varargin{:}); -end -% End initialization code - DO NOT EDIT - - -% --- Executes just before GUI_Test_Hand is made visible. -function GUI_Test_Hand_OpeningFcn(hObject, eventdata, handles, varargin) -% This function has no output args, see OutputFcn. -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -% varargin command line arguments to GUI_Test_Hand (see VARARGIN) - -% Choose default command line output for GUI_Test_Hand -handles.output = hObject; - -% Update handles structure -guidata(hObject, handles); - -% UIWAIT makes GUI_Test_Hand wait for user response (see UIRESUME) -% uiwait(handles.figure1); - - -% --- Outputs from this function are returned to the command line. -function varargout = GUI_Test_Hand_OutputFcn(hObject, eventdata, handles) -% varargout cell array for returning output args (see VARARGOUT); -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Get default command line output from handles structure -varargout{1} = handles.output; - - -% --- Executes on button press in pb_connect. -function pb_connect_Callback(hObject, eventdata, handles) -% hObject handle to pb_connect (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -compath = get(handles.et_connection,'String'); -handles.com = Connect_ALC(compath); -%handles.com = MasterModuleComm(compath); -if TestConnectionALC(handles.com)==1; %Write S to stop program - set(handles.t_msg,'String','Connection established'); - guidata(hObject,handles); -else - set(handles.t_msg,'String','Wrong connection'); - fclose(handles.com.io); -end - - -% --- Executes on button press in pb_testConnection. -function pb_testConnection_Callback(hObject, eventdata, handles) -% hObject handle to pb_testConnection (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -set(handles.t_msg,'String','Testing connection...'); -if TestConnectionALC(handles.com)==1; %Write S to stop program - set(handles.t_msg,'String','Connection established'); - guidata(hObject,handles); -else - set(handles.t_msg,'String','Wrong connection'); - fclose(handles.com.io); -end - -% --- Executes on button press in pb_disconnect. -function pb_disconnect_Callback(hObject, eventdata, handles) -% hObject handle to pb_disconnect (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -fclose(handles.com.io); -set(handles.t_msg,'String','Disconnected'); - - - -function et_connection_Callback(hObject, eventdata, handles) -% hObject handle to et_connection (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_connection as text -% str2double(get(hObject,'String')) returns contents of et_connection as a double - - -% --- Executes during object creation, after setting all properties. -function et_connection_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_connection (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in pb_thumbOpen. -function pb_thumbOpen_Callback(hObject, eventdata, handles) -% hObject handle to pb_thumbOpen (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Unable the botton -set(handles.pb_thumbOpen,'Enable','off'); - -% Get info -obj = handles.com; -pwmID = 'A'; % Referes to DoF, not to PWM - -if get(handles.cb_thumb,'Value') - pwm1 = 0; %Duty cycle - pwm2 = str2double(get(handles.et_pwm,'String')); -else - pwm2 = 0; %Duty cycle - pwm1 = str2double(get(handles.et_pwm,'String')); -end - - -% Send PWM -if Update2PWMusingSCI(obj, pwmID, pwm1, pwm2) - % Wait for a little move to take place - pause(str2double(get(handles.et_length,'String'))); - % Stop the movement - Update2PWMusingSCI(obj, pwmID, 0, 0); - set(handles.t_msg,'String','Moved'); -else - set(handles.t_msg,'String','Failed'); - fclose(handles.com.io); -end - -set(handles.pb_thumbOpen,'Enable','on'); - - -% --- Executes on button press in pb_indexOpen. -function pb_indexOpen_Callback(hObject, eventdata, handles) -% hObject handle to pb_indexOpen (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -% Unable the botton -set(handles.pb_indexOpen,'Enable','off'); - -% Get info -obj = handles.com; -pwmID = 'B'; % Referes to DoF, not to PWM - -if get(handles.cb_index,'Value') - pwm2 = 0; %Duty cycle - pwm1 = str2double(get(handles.et_pwm,'String')); -else - pwm1 = 0; %Duty cycle - pwm2 = str2double(get(handles.et_pwm,'String')); -end - - -% Send PWM -if Update2PWMusingSCI(obj, pwmID, pwm1, pwm2) - % Wait for a little move to take place - pause(str2double(get(handles.et_length,'String'))); - % Stop the movement - Update2PWMusingSCI(obj, pwmID, 0, 0); - set(handles.t_msg,'String','Moved'); -else - set(handles.t_msg,'String','Failed'); - fclose(handles.com.io); -end - -set(handles.pb_indexOpen,'Enable','on'); - -% --- Executes on button press in pb_middleOpen. -function pb_middleOpen_Callback(hObject, eventdata, handles) -% hObject handle to pb_middleOpen (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -% Unable the botton -set(handles.pb_middleOpen,'Enable','off'); - -% Get info -obj = handles.com; -pwmID = 'C'; % Referes to DoF, not to PWM - -if get(handles.cb_middle,'Value') - pwm2 = 0; %Duty cycle - pwm1 = str2double(get(handles.et_pwm,'String')); -else - pwm1 = 0; %Duty cycle - pwm2 = str2double(get(handles.et_pwm,'String')); -end - - -% Send PWM -if Update2PWMusingSCI(obj, pwmID, pwm1, pwm2) - % Wait for a little move to take place - pause(str2double(get(handles.et_length,'String'))); - % Stop the movement - Update2PWMusingSCI(obj, pwmID, 0, 0); - set(handles.t_msg,'String','Moved'); -else - set(handles.t_msg,'String','Failed'); - fclose(handles.com.io); -end - -set(handles.pb_middleOpen,'Enable','on'); - -% --- Executes on button press in pb_ringOpen. -function pb_ringOpen_Callback(hObject, eventdata, handles) -% hObject handle to pb_ringOpen (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -% Unable the botton -set(handles.pb_ringOpen,'Enable','off'); - -% Get info -obj = handles.com; -pwmID = 'D'; % Referes to DoF, not to PWM - -if get(handles.cb_ring,'Value') - pwm2 = 0; %Duty cycle - pwm1 = str2double(get(handles.et_pwm,'String')); -else - pwm1 = 0; %Duty cycle - pwm2 = str2double(get(handles.et_pwm,'String')); -end - - -% Send PWM -if Update2PWMusingSCI(obj, pwmID, pwm1, pwm2) - % Wait for a little move to take place - pause(str2double(get(handles.et_length,'String'))); - % Stop the movement - Update2PWMusingSCI(obj, pwmID, 0, 0); - set(handles.t_msg,'String','Moved'); -else - set(handles.t_msg,'String','Failed'); - fclose(handles.com.io); -end - -set(handles.pb_ringOpen,'Enable','on'); - -% --- Executes on button press in pb_littleOpen. -function pb_littleOpen_Callback(hObject, eventdata, handles) -% hObject handle to pb_littleOpen (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -% Unable the botton -set(handles.pb_littleOpen,'Enable','off'); - -% Get info -obj = handles.com; -pwmID = 'E'; % Referes to DoF, not to PWM - -if get(handles.cb_little,'Value') - pwm2 = 0; %Duty cycle - pwm1 = str2double(get(handles.et_pwm,'String')); -else - pwm1 = 0; %Duty cycle - pwm2 = str2double(get(handles.et_pwm,'String')); -end - - -% Send PWM -if Update2PWMusingSCI(obj, pwmID, pwm1, pwm2) - % Wait for a little move to take place - pause(str2double(get(handles.et_length,'String'))); - % Stop the movement - Update2PWMusingSCI(obj, pwmID, 0, 0); - set(handles.t_msg,'String','Moved'); -else - set(handles.t_msg,'String','Failed'); - fclose(handles.com.io); -end - -set(handles.pb_littleOpen,'Enable','on'); - -% --- Executes on button press in pb_thumbClose. -function pb_thumbClose_Callback(hObject, eventdata, handles) -% hObject handle to pb_thumbClose (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -% Unable the botton -set(handles.pb_thumbClose,'Enable','off'); - -% Get info -obj = handles.com; -pwmID = 'A'; % Referes to DoF, not to PWM - -if get(handles.cb_thumb,'Value') - pwm2 = 0; %Duty cycle - pwm1 = str2double(get(handles.et_pwm,'String')); -else - pwm1 = 0; %Duty cycle - pwm2 = str2double(get(handles.et_pwm,'String')); -end - - -% Send PWM -if Update2PWMusingSCI(obj, pwmID, pwm1, pwm2) - % Wait for a little move to take place - pause(str2double(get(handles.et_length,'String'))); - % Stop the movement - Update2PWMusingSCI(obj, pwmID, 0, 0); - set(handles.t_msg,'String','Moved'); -else - set(handles.t_msg,'String','Failed'); - fclose(handles.com.io); -end - -set(handles.pb_thumbClose,'Enable','on'); - -% --- Executes on button press in pb_indexClose. -function pb_indexClose_Callback(hObject, eventdata, handles) -% hObject handle to pb_indexClose (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -set(handles.pb_indexClose,'Enable','off'); - -% Get info -obj = handles.com; -pwmID = 'B'; % Referes to DoF, not to PWM - -if get(handles.cb_thumb,'Value') - pwm1 = 0; %Duty cycle - pwm2 = str2double(get(handles.et_pwm,'String')); -else - pwm2 = 0; %Duty cycle - pwm1 = str2double(get(handles.et_pwm,'String')); -end - - -% Send PWM -if Update2PWMusingSCI(obj, pwmID, pwm1, pwm2) - % Wait for a little move to take place - pause(str2double(get(handles.et_length,'String'))); - % Stop the movement - Update2PWMusingSCI(obj, pwmID, 0, 0); - set(handles.t_msg,'String','Moved'); -else - set(handles.t_msg,'String','Failed'); - fclose(handles.com.io); -end - -set(handles.pb_indexClose,'Enable','on'); - -% --- Executes on button press in pb_middleClose. -function pb_middleClose_Callback(hObject, eventdata, handles) -% hObject handle to pb_middleClose (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -set(handles.pb_middleClose,'Enable','off'); - -% Get info -obj = handles.com; -pwmID = 'C'; % Referes to DoF, not to PWM - -if get(handles.cb_thumb,'Value') - pwm1 = 0; %Duty cycle - pwm2 = str2double(get(handles.et_pwm,'String')); -else - pwm2 = 0; %Duty cycle - pwm1 = str2double(get(handles.et_pwm,'String')); -end - - -% Send PWM -if Update2PWMusingSCI(obj, pwmID, pwm1, pwm2) - % Wait for a little move to take place - pause(str2double(get(handles.et_length,'String'))); - % Stop the movement - Update2PWMusingSCI(obj, pwmID, 0, 0); - set(handles.t_msg,'String','Moved'); -else - set(handles.t_msg,'String','Failed'); - fclose(handles.com.io); -end - -set(handles.pb_middleClose,'Enable','on'); - -% --- Executes on button press in pb_ringClose. -function pb_ringClose_Callback(hObject, eventdata, handles) -% hObject handle to pb_ringClose (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -set(handles.pb_ringClose,'Enable','off'); - -% Get info -obj = handles.com; -pwmID = 'D'; % Referes to DoF, not to PWM - -if get(handles.cb_thumb,'Value') - pwm1 = 0; %Duty cycle - pwm2 = str2double(get(handles.et_pwm,'String')); -else - pwm2 = 0; %Duty cycle - pwm1 = str2double(get(handles.et_pwm,'String')); -end - - -% Send PWM -if Update2PWMusingSCI(obj, pwmID, pwm1, pwm2) - % Wait for a little move to take place - pause(str2double(get(handles.et_length,'String'))); - % Stop the movement - Update2PWMusingSCI(obj, pwmID, 0, 0); - set(handles.t_msg,'String','Moved'); -else - set(handles.t_msg,'String','Failed'); - fclose(handles.com.io); -end - -set(handles.pb_ringClose,'Enable','on'); - -% --- Executes on button press in pb_littleClose. -function pb_littleClose_Callback(hObject, eventdata, handles) -% hObject handle to pb_littleClose (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -set(handles.pb_littleClose,'Enable','off'); - -% Get info -obj = handles.com; -pwmID = 'E'; % Referes to DoF, not to PWM - -if get(handles.cb_thumb,'Value') - pwm1 = 0; %Duty cycle - pwm2 = str2double(get(handles.et_pwm,'String')); -else - pwm2 = 0; %Duty cycle - pwm1 = str2double(get(handles.et_pwm,'String')); -end - - -% Send PWM -if Update2PWMusingSCI(obj, pwmID, pwm1, pwm2) - % Wait for a little move to take place - pause(str2double(get(handles.et_length,'String'))); - % Stop the movement - Update2PWMusingSCI(obj, pwmID, 0, 0); - set(handles.t_msg,'String','Moved'); -else - set(handles.t_msg,'String','Failed'); - fclose(handles.com.io); -end - -set(handles.pb_littleClose,'Enable','on'); - - -function et_pwm_Callback(hObject, eventdata, handles) -% hObject handle to et_pwm (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_pwm as text -% str2double(get(hObject,'String')) returns contents of et_pwm as a double - - -% --- Executes during object creation, after setting all properties. -function et_pwm_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_pwm (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in cb_thumb. -function cb_thumb_Callback(hObject, eventdata, handles) -% hObject handle to cb_thumb (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_thumb - - -% --- Executes on button press in cb_index. -function cb_index_Callback(hObject, eventdata, handles) -% hObject handle to cb_index (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_index - - -% --- Executes on button press in cb_middle. -function cb_middle_Callback(hObject, eventdata, handles) -% hObject handle to cb_middle (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_middle - - -% --- Executes on button press in cb_ring. -function cb_ring_Callback(hObject, eventdata, handles) -% hObject handle to cb_ring (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_ring - - -% --- Executes on button press in cb_little. -function cb_little_Callback(hObject, eventdata, handles) -% hObject handle to cb_little (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_little - - - -function et_length_Callback(hObject, eventdata, handles) -% hObject handle to et_length (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_length as text -% str2double(get(hObject,'String')) returns contents of et_length as a double - - -% --- Executes during object creation, after setting all properties. -function et_length_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_length (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end diff --git a/Comm/ALC/VCP_Piccolo/GUI_Test_PanTilt.fig b/Comm/ALC/VCP_Piccolo/GUI_Test_PanTilt.fig deleted file mode 100644 index bb3db07..0000000 Binary files a/Comm/ALC/VCP_Piccolo/GUI_Test_PanTilt.fig and /dev/null differ diff --git a/Comm/ALC/VCP_Piccolo/GUI_Test_PanTilt.m b/Comm/ALC/VCP_Piccolo/GUI_Test_PanTilt.m deleted file mode 100644 index 21af217..0000000 --- a/Comm/ALC/VCP_Piccolo/GUI_Test_PanTilt.m +++ /dev/null @@ -1,489 +0,0 @@ -% ---------------------------- Copyright Notice --------------------------- -% This file is part of BioPatRec © which is open and free software under -% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for -% the full license governing this code and copyrights. -% -% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and -% Chalmers University of Technology. All authors’ contributions must be kept -% acknowledged below in the section "Updates % Contributors". -% -% Would you like to contribute to science and sum efforts to improve -% amputees’ quality of life? Join this project! or, send your comments to: -% maxo@chalmers.se. -% -% The entire copyright notice must be kept in this or any source file -% linked to BioPatRec. This will ensure communication with all authors and -% acknowledge contributions here and in the project web page (optional). -% -% -------------------------- Function Description ------------------------- -% [Give a short summary about the principle of your function here.] -% -% ------------------------- Updates & Contributors ------------------------ -% [Contributors are welcome to add their email] -% 20xx-xx-xx / Max Ortiz / Creation -% 20xx-xx-xx / Author / Comment on update - -function varargout = GUI_Test_PanTilt(varargin) -% GUI_TEST_PANTILT M-file for GUI_Test_PanTilt.fig -% GUI_TEST_PANTILT, by itself, creates a new GUI_TEST_PANTILT or raises the existing -% singleton*. -% -% H = GUI_TEST_PANTILT returns the handle to a new GUI_TEST_PANTILT or the handle to -% the existing singleton*. -% -% GUI_TEST_PANTILT('CALLBACK',hObject,eventData,handles,...) calls the local -% function named CALLBACK in GUI_TEST_PANTILT.M with the given input arguments. -% -% GUI_TEST_PANTILT('Property','Value',...) creates a new GUI_TEST_PANTILT or raises the -% existing singleton*. Starting from the left, property value pairs are -% applied to the GUI before GUI_Test_PanTilt_OpeningFcn gets called. An -% unrecognized property name or invalid value makes property application -% stop. All inputs are passed to GUI_Test_PanTilt_OpeningFcn via varargin. -% -% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one -% instance to run (singleton)". -% -% See also: GUIDE, GUIDATA, GUIHANDLES - -% Edit the above text to modify the response to help GUI_Test_PanTilt - -% Last Modified by GUIDE v2.5 04-May-2012 18:48:56 - -% Begin initialization code - DO NOT EDIT -gui_Singleton = 1; -gui_State = struct('gui_Name', mfilename, ... - 'gui_Singleton', gui_Singleton, ... - 'gui_OpeningFcn', @GUI_Test_PanTilt_OpeningFcn, ... - 'gui_OutputFcn', @GUI_Test_PanTilt_OutputFcn, ... - 'gui_LayoutFcn', [] , ... - 'gui_Callback', []); -if nargin && ischar(varargin{1}) - gui_State.gui_Callback = str2func(varargin{1}); -end - -if nargout - [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); -else - gui_mainfcn(gui_State, varargin{:}); -end -% End initialization code - DO NOT EDIT - - -% --- Executes just before GUI_Test_PanTilt is made visible. -function GUI_Test_PanTilt_OpeningFcn(hObject, eventdata, handles, varargin) -% This function has no output args, see OutputFcn. -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -% varargin command line arguments to GUI_Test_PanTilt (see VARARGIN) - -% Choose default command line output for GUI_Test_PanTilt -handles.output = hObject; - -% Update handles structure -guidata(hObject, handles); - -% UIWAIT makes GUI_Test_PanTilt wait for user response (see UIRESUME) -% uiwait(handles.figure1); - - -% --- Outputs from this function are returned to the command line. -function varargout = GUI_Test_PanTilt_OutputFcn(hObject, eventdata, handles) -% varargout cell array for returning output args (see VARARGOUT); -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Get default command line output from handles structure -varargout{1} = handles.output; - - -% --- Executes on button press in pb_connect. -function pb_connect_Callback(hObject, eventdata, handles) -% hObject handle to pb_connect (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -compath = get(handles.et_connection,'String'); -handles.com = Connect_ALC(compath); -%handles.com = MasterModuleComm(compath); -if TestConnectionALC(handles.com)==1; %Write S to stop program - set(handles.t_msg,'String','Connection established'); - guidata(hObject,handles); -else - set(handles.t_msg,'String','Wrong connection'); - fclose(handles.com.io); -end - - -% --- Executes on button press in pb_testConnection. -function pb_testConnection_Callback(hObject, eventdata, handles) -% hObject handle to pb_testConnection (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -set(handles.t_msg,'String','Testing connection...'); -if TestConnectionALC(handles.com)==1; %Write S to stop program - set(handles.t_msg,'String','Connection established'); - guidata(hObject,handles); -else - set(handles.t_msg,'String','Wrong connection'); - fclose(handles.com.io); -end - -% --- Executes on button press in pb_disconnect. -function pb_disconnect_Callback(hObject, eventdata, handles) -% hObject handle to pb_disconnect (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -fclose(handles.com.io); -set(handles.t_msg,'String','Disconnected'); - - - -function et_connection_Callback(hObject, eventdata, handles) -% hObject handle to et_connection (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_connection as text -% str2double(get(hObject,'String')) returns contents of et_connection as a double - - -% --- Executes during object creation, after setting all properties. -function et_connection_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_connection (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in pb_pronate. -function pb_pronate_Callback(hObject, eventdata, handles) -% hObject handle to pb_pronate (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - - set(hObject,'Enable','off'); - - stepP = str2double(get(handles.et_step,'String')); - pos = str2double(get(handles.et_posPan,'String')); - - % Get info - obj = handles.com; - pwmID = 'K'; % Referes to DoF, not to PWM - - if get(handles.cb_pan,'Value') - pwmPer = pos-stepP; - else - pwmPer = pos+stepP; - end - - % If no problems where encountered, the ALC must return 1 - % Send PWM - if UpdatePWMusingSCI_PanTilt(obj, pwmID, pwmPer) - set(handles.t_msg,'String','Moved'); - set(handles.et_posPan,'String',num2str(pwmPer)); - else - set(handles.t_msg,'String','Failed'); - fclose(handles.com.io); - end - - set(hObject,'Enable','on'); - -% --- Executes on button press in pb_supinate. -function pb_supinate_Callback(hObject, eventdata, handles) -% hObject handle to pb_supinate (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -% Unable the botton - set(hObject,'Enable','off'); - - stepP = str2double(get(handles.et_step,'String')); - pos = str2double(get(handles.et_posPan,'String')); - - % Get info - obj = handles.com; - pwmID = 'K'; % Referes to DoF, not to PWM - - if get(handles.cb_pan,'Value') - pwmPer = pos+stepP; - else - pwmPer = pos-stepP; - end - - % If no problems where encountered, the ALC must return 1 - % Send PWM - if UpdatePWMusingSCI_PanTilt(obj, pwmID, pwmPer) - set(handles.t_msg,'String','Moved'); - set(handles.et_posPan,'String',num2str(pwmPer)); - else - set(handles.t_msg,'String','Failed'); - fclose(handles.com.io); - end - - set(hObject,'Enable','on'); - -% --- Executes on button press in pb_flex. -function pb_flex_Callback(hObject, eventdata, handles) -% hObject handle to pb_flex (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -% Unable the botton -% Unable the botton - set(hObject,'Enable','off'); - - stepP = str2double(get(handles.et_step,'String')); - pos = str2double(get(handles.et_posTilt,'String')); - - % Get info - obj = handles.com; - pwmID = 'L'; % Referes to DoF, not to PWM - - if get(handles.cb_tilt,'Value') - pwmPer = pos-stepP; - else - pwmPer = pos+stepP; - end - - % If no problems where encountered, the ALC must return 1 - % Send PWM - if UpdatePWMusingSCI_PanTilt(obj, pwmID, pwmPer) - set(handles.t_msg,'String','Moved'); - set(handles.et_posTilt,'String',num2str(pwmPer)); - else - set(handles.t_msg,'String','Failed'); - fclose(handles.com.io); - end - - set(hObject,'Enable','on'); - - - -% --- Executes on button press in pb_extend. -function pb_extend_Callback(hObject, eventdata, handles) -% hObject handle to pb_extend (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - set(hObject,'Enable','off'); - - stepP = str2double(get(handles.et_step,'String')); - pos = str2double(get(handles.et_posTilt,'String')); - - % Get info - obj = handles.com; - pwmID = 'L'; % Referes to DoF, not to PWM - - if get(handles.cb_tilt,'Value') - pwmPer = pos+stepP; - else - pwmPer = pos-stepP; - end - - % If no problems where encountered, the ALC must return 1 - % Send PWM - if UpdatePWMusingSCI_PanTilt(obj, pwmID, pwmPer) - set(handles.t_msg,'String','Moved'); - set(handles.et_posTilt,'String',num2str(pwmPer)); - else - set(handles.t_msg,'String','Failed'); - fclose(handles.com.io); - end - - set(hObject,'Enable','on'); - - - -function et_step_Callback(hObject, eventdata, handles) -% hObject handle to et_step (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_step as text -% str2double(get(hObject,'String')) returns contents of et_step as a double - - -% --- Executes during object creation, after setting all properties. -function et_step_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_step (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in cb_pan. -function cb_pan_Callback(hObject, eventdata, handles) -% hObject handle to cb_pan (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_pan - - -% --- Executes on button press in cb_tilt. -function cb_tilt_Callback(hObject, eventdata, handles) -% hObject handle to cb_tilt (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_tilt - - -% --- Executes on button press in cb_middle. -function cb_middle_Callback(hObject, eventdata, handles) -% hObject handle to cb_middle (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_middle - - -% --- Executes on button press in cb_ring. -function cb_ring_Callback(hObject, eventdata, handles) -% hObject handle to cb_ring (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_ring - - -% --- Executes on button press in cb_little. -function cb_little_Callback(hObject, eventdata, handles) -% hObject handle to cb_little (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_little - - - -function et_length_Callback(hObject, eventdata, handles) -% hObject handle to et_length (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_length as text -% str2double(get(hObject,'String')) returns contents of et_length as a double - - -% --- Executes during object creation, after setting all properties. -function et_length_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_length (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in pb_panCenter. -function pb_panCenter_Callback(hObject, eventdata, handles) -% hObject handle to pb_panCenter (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - - set(hObject,'Enable','off'); - - % Get info - obj = handles.com; - pwmID = 'K'; % Referes to DoF, not to PWM - pwmPer = 72; - set(handles.et_posPan,'String','72'); - - % If no problems where encountered, the ALC must return 1 - % Send PWM - if UpdatePWMusingSCI_PanTilt(obj, pwmID, pwmPer) - set(handles.t_msg,'String','Moved'); - else - set(handles.t_msg,'String','Failed'); - fclose(handles.com.io); - end - - set(hObject,'Enable','on'); - - - - -% --- Executes on button press in pb_tiltCenter. -function pb_tiltCenter_Callback(hObject, eventdata, handles) -% hObject handle to pb_tiltCenter (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - - set(hObject,'Enable','off'); - - % Get info - obj = handles.com; - pwmID = 'L'; % Referes to DoF, not to PWM - pwmPer = 52; - - set(handles.et_posTilt,'String','52'); - - % If no problems where encountered, the ALC must return 1 - % Send PWM - if UpdatePWMusingSCI_PanTilt(obj, pwmID, pwmPer) - set(handles.t_msg,'String','Moved'); - else - set(handles.t_msg,'String','Failed'); - fclose(handles.com.io); - end - - set(hObject,'Enable','on'); - - - -function et_posPan_Callback(hObject, eventdata, handles) -% hObject handle to et_posPan (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_posPan as text -% str2double(get(hObject,'String')) returns contents of et_posPan as a double - - -% --- Executes during object creation, after setting all properties. -function et_posPan_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_posPan (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_posTilt_Callback(hObject, eventdata, handles) -% hObject handle to et_posTilt (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_posTilt as text -% str2double(get(hObject,'String')) returns contents of et_posTilt as a double - - -% --- Executes during object creation, after setting all properties. -function et_posTilt_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_posTilt (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end diff --git a/Comm/ALC/VCP_Piccolo/TestPWMusingSCIbyCycling.m b/Comm/ALC/VCP_Piccolo/TestPWMusingSCIbyCycling.m deleted file mode 100644 index 7c9fa9d..0000000 --- a/Comm/ALC/VCP_Piccolo/TestPWMusingSCIbyCycling.m +++ /dev/null @@ -1,128 +0,0 @@ -% ---------------------------- Copyright Notice --------------------------- -% This file is part of BioPatRec © which is open and free software under -% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for -% the full license governing this code and copyrights. -% -% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and -% Chalmers University of Technology. All authors’ contributions must be kept -% acknowledged below in the section "Updates % Contributors". -% -% Would you like to contribute to science and sum efforts to improve -% amputees’ quality of life? Join this project! or, send your comments to: -% maxo@chalmers.se. -% -% The entire copyright notice must be kept in this or any source file -% linked to BioPatRec. This will ensure communication with all authors and -% acknowledge contributions here and in the project web page (optional). -% -% ------------------- Function Description ------------------ -% Function to test the i-limb motors. This function will increase and -% decrease the speed as well as to change the motor direction. -% -% The corresponding function in the ACL has the same name. -% -% This fuction is a VERY slow implementation of SCI communication. It waits -% until the ALC acknowledges the comunication, otherwise it exits with a -% failure (result = 0). -% -% The driver are controlled to work in fast decay (see data-sheet DVR8833) -% in order to achieve this, one PWM sets the speed while the other is held -% low -% -% pwmDC = PWM duty cycle is inverse, so 10 = 90% of duty cycle -% -% comObj is the communication objectt required for data transmission -% -% --------------------------Updates-------------------------- -% 2011-11-07 / Max Ortiz / Creation -% 20xx-xx-xx / Author / Comment - - -function result = TestPWMusingSCIbyCycling(comObj) - - % Send the Test routine in the ALC - fwrite(comObj.io,'T') - pause(0.1) - % Send the Test ID - fwrite(comObj.io,'B'); - pause(0.1) - reps = 2; - - % Repeat the cycle "reps" times - for i = 1 : reps; - - % Cycle the PWM until 100 percent to go FORWARD - for pwmDC = 0 : 20 : 100 - - % Update the all PWM - for j = 1 : 2 : 10 - - % First PWM to set the speed - fwrite(comObj.io,pwmDC,'uint8','async') - %pause(0.1) - % Read answer - if fread(comObj.io,1) ~= j - result=0; - return; - end - - % Second PWM held low - fwrite(comObj.io,100,'uint8','async') - %pause(0.1) - % Read answer - if fread(comObj.io,1) ~= j+1 - result=0; - return; - end - - end - - % Continue the transmission - fwrite(comObj.io,'C'); - end - - % Cycle the PWM until 100 percent to go Backwards - for pwmDC = 0 : 20 : 100 - - % Update the all PWM - for j = 1 : 2 : 10 - - % First PWM to set the speed - fwrite(comObj.io,100,'uint8','async') - %pause(0.1) - % Read answer - if fread(comObj.io,1) ~= j - result=0; - return; - end - - % Second PWM held low - fwrite(comObj.io,pwmDC,'uint8','async') - %pause(0.1) - % Read answer - if fread(comObj.io,1) ~= j+1 - result=0; - return; - end - - end - - % Break or continue the repetitions - if i >= reps && pwmDC >= 100 % Break the cycle - fwrite(comObj.io,'B') - %pause(0.1) - else % Continue the cycle - fwrite(comObj.io,'C') - %pause(0.1) - end - end - - end - - % Read confirmation - if fread(comObj.io,1)==1 - result=1; - else - result=0; - end -end \ No newline at end of file diff --git a/Comm/ALC/VCP_Piccolo/Update2PWMusingSCI.m b/Comm/ALC/VCP_Piccolo/Update2PWMusingSCI.m deleted file mode 100644 index 22a0975..0000000 --- a/Comm/ALC/VCP_Piccolo/Update2PWMusingSCI.m +++ /dev/null @@ -1,54 +0,0 @@ -% ---------------------------- Copyright Notice --------------------------- -% This file is part of BioPatRec © which is open and free software under -% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for -% the full license governing this code and copyrights. -% -% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and -% Chalmers University of Technology. All authors’ contributions must be kept -% acknowledged below in the section "Updates % Contributors". -% -% Would you like to contribute to science and sum efforts to improve -% amputees’ quality of life? Join this project! or, send your comments to: -% maxo@chalmers.se. -% -% The entire copyright notice must be kept in this or any source file -% linked to BioPatRec. This will ensure communication with all authors and -% acknowledge contributions here and in the project web page (optional). -% -% ------------------- Function Description ------------------ -% Function to test the i-limb motors per DoF. -% -% The corresponding function in the ACL has the same name. -% -% This fuction is a slow implementation of SCI communication. It waits -% until the ALC acknowledges the comunication, otherwise it exits with a -% failure (result = 0). -% -% --------------------------Updates-------------------------- -% 2011-11-10 / Max Ortiz / Creation -% 20xx-xx-xx / Author / Comment - - -function result = Update2PWMusingSCI(obj, pwmID, pwm1, pwm2) - - % Send the Test routine in the ALC - fwrite(obj.io,'D'); - %pause(0.01); % Delay seems to not be neccesary - % Send PWM ID - fwrite(obj.io,pwmID); - %pause(0.01) % Delay seems to not be neccesary - % Send duty cycle - fwrite(obj.io,100-pwm1,'uint8','sync') - %pause(0.01) % Delay seems to not be neccesary - fwrite(obj.io,100-pwm2,'uint8','sync') - %pause(0.01) % Delay seems to not be neccesary - - % If no problems where encountered, the ALC must return 1 - if fread(obj.io,1)==1 - result=1; - else - result=0; - return; - end - -end diff --git a/Comm/ALC/VCP_Piccolo/UpdateAllPWMusingSCI.m b/Comm/ALC/VCP_Piccolo/UpdateAllPWMusingSCI.m deleted file mode 100644 index 04b5cc4..0000000 --- a/Comm/ALC/VCP_Piccolo/UpdateAllPWMusingSCI.m +++ /dev/null @@ -1,61 +0,0 @@ -% ---------------------------- Copyright Notice --------------------------- -% This file is part of BioPatRec © which is open and free software under -% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for -% the full license governing this code and copyrights. -% -% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and -% Chalmers University of Technology. All authors’ contributions must be kept -% acknowledged below in the section "Updates % Contributors". -% -% Would you like to contribute to science and sum efforts to improve -% amputees’ quality of life? Join this project! or, send your comments to: -% maxo@chalmers.se. -% -% The entire copyright notice must be kept in this or any source file -% linked to BioPatRec. This will ensure communication with all authors and -% acknowledge contributions here and in the project web page (optional). -% -% ------------------- Function Description ------------------ -% Function to test the i-limb motors. This function will update the values -% of the PWM using a PWM ID and then sending the percentage of duty cycle. -% -% The corresponding function in the ACL has the same name. -% -% This fuction is a slow implementation of SCI communication. It waits -% until the ALC acknowledges the comunication, otherwise it exits with a -% failure (result = 0). -% -% --------------------------Updates-------------------------- -% 2011-11-08 / Max Ortiz / Creation -% 2012-05-03 / Pratham D / Added K and L -% 2012-07-08 / Max Ortiz / Update the communication protocol - -function result = UpdateAllPWMusingSCI(obj, pwms) - - % Setup IDs - pwmID = ['A' ; 'B' ; 'C' ; 'D' ; 'E'; 'F' ; 'G' ; 'H' ; 'I' ; 'J'; 'K' ; 'L']; - - for i = 1 : size(pwms,2) - % Send the Test routine in the ALC -% fwrite(obj.io,'T'); -% %pause(0.01); % Delay seems to not be neccesary -% % Send the Test ID -% fwrite(obj.io,'X'); - % Send Single PWM update - fwrite(obj.io,'S'); - %Send ID - fwrite(obj.io,pwmID(i)); - %pause(0.01) % Delay seems to not be neccesary - % Send duty cycle - fwrite(obj.io,pwms(i),'uint8','async') - %pause(0.01) % Delay seems to not be neccesary - - % If no problems where encountered, the ALC must return 1 - if fread(obj.io,1)==1 - result=1; - else - result=0; - return; - end - end -end diff --git a/Comm/ALC/VCP_Piccolo/UpdatePWMusingSCI_PanTilt.m b/Comm/ALC/VCP_Piccolo/UpdatePWMusingSCI_PanTilt.m deleted file mode 100644 index e1fb5af..0000000 --- a/Comm/ALC/VCP_Piccolo/UpdatePWMusingSCI_PanTilt.m +++ /dev/null @@ -1,79 +0,0 @@ -% ---------------------------- Copyright Notice --------------------------- -% This file is part of BioPatRec © which is open and free software under -% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for -% the full license governing this code and copyrights. -% -% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and -% Chalmers University of Technology. All authors’ contributions must be kept -% acknowledged below in the section "Updates % Contributors". -% -% Would you like to contribute to science and sum efforts to improve -% amputees’ quality of life? Join this project! or, send your comments to: -% maxo@chalmers.se. -% -% The entire copyright notice must be kept in this or any source file -% linked to BioPatRec. This will ensure communication with all authors and -% acknowledge contributions here and in the project web page (optional). -% -% ------------------- Function Description ------------------ -% Function to send the PWM for control of the servo motors for the Pan & -% Tilt unit. -% -% --------------------------Updates-------------------------- -% 2012-05-04 / Max Ortiz / Creation -% 2012-06-29 / Max Ortiz / Modified the protocolo for communication with -% the microcontroller, now it will only send a "S" -% before the servo ID, and duty cycle. -% 20xx-xx-xx / Author / - - -function [result pwmPer] = UpdatePWMusingSCI_PanTilt(obj, pwmID, pwmPer) - - %% Safety routine (specifically for the servocity pantilt) - %Tilt - if strcmp(pwmID,'L') - maxP = 85; - minP = 7; - if minP > pwmPer - pwmPer = minP; - end - if maxP < pwmPer - pwmPer = maxP; - end - end - %Pan - if strcmp(pwmID,'K') - maxP = 100; - minP = 1; - if minP > pwmPer - pwmPer = minP; - end - if maxP < pwmPer - pwmPer = maxP; - end - end - - %% Send values to controller - % Send the Test routine in the ALC - % fwrite(obj.io,'T'); - % pause(0.01); % Delay seems to not be neccesary - % Send the Test ID - % fwrite(obj.io,'X'); - - % Send servo indentifier - fwrite(obj.io,'S'); - %Send ID - fwrite(obj.io,pwmID); - %pause(0.01) % Delay seems to not be neccesary - % Send duty cycle - fwrite(obj.io,pwmPer,'uint8','async') - %pause(0.01) % Delay seems to not be neccesary - - if fread(obj.io,1)==1 - result=1; - else - result=0; - return; - end - -end diff --git a/Comm/ConnectVRE.m b/Comm/ConnectVRE.m index 2a02cea..8f7b9d9 100644 --- a/Comm/ConnectVRE.m +++ b/Comm/ConnectVRE.m @@ -22,14 +22,23 @@ % ------------------------- Updates & Contributors ------------------------ % [Contributors are welcome to add their email] % 2013-01-29 / Nichlas Sander / Creation +% 2015-12-01 / Morten Bak Kristoffersen / Added arm/leg selection. function handles = ConnectVRE(handles, program) if ~isfield(handles,'vre_Com') open(program); handles.vre_Com = tcpip('127.0.0.1',23068,'NetworkRole','server'); fopen(handles.vre_Com); + if ~isfield(handles, 'vre_leg') % Default is not using the leg + fwrite(handles.vre_Com,sprintf('%c%c%c%c','c',char(1),char(1),char(1))); + fread(handles.vre_Com,1); + else + fwrite(handles.vre_Com,sprintf('%c%c%c%c','c',char(1),char(2),char(1))); + fread(handles.vre_Com,1); + end end handles = DisableIfExists(handles,'pb_socketConnect'); + handles = DisableIfExists(handles,'pb_VRleg'); handles = DisableIfExists(handles,'pb_socketConnect2'); handles = DisableIfExists(handles,'pb_ARarm'); handles = EnableIfExists(handles,'pb_socketDisconnect'); diff --git a/Comm/DisconnectVRE.m b/Comm/DisconnectVRE.m index 96eb48f..0281c33 100644 --- a/Comm/DisconnectVRE.m +++ b/Comm/DisconnectVRE.m @@ -29,6 +29,7 @@ handles = rmfield(handles,'vre_Com'); end handles = EnableIfExists(handles,'pb_socketConnect'); + handles = EnableIfExists(handles,'pb_VRleg'); handles = EnableIfExists(handles,'pb_socketConnect2'); handles = EnableIfExists(handles,'pb_ARarm'); handles = DisableIfExists(handles,'pb_socketDisconnect'); diff --git a/Comm/SendControls.m b/Comm/SendControls.m new file mode 100644 index 0000000..be45b4e --- /dev/null +++ b/Comm/SendControls.m @@ -0,0 +1,63 @@ +function SendControls(control,savedControls) + +device = digitalio('nidaq', 'Dev1'); +addline(device,0:3,'out'); + + +if control(1) + %for i = 1:length(savedControls) + switch(savedControls(1)) + case 1 + putvalue(device, [1 1 0 0]); + case 2 + putvalue(device, [0 0 1 1]); + case 3 + putvalue(device, [1 0 0 0]); + case 4 + putvalue(device, [0 1 0 0]); + end + %end + +elseif control(2) + switch(savedControls(2)) + case 1 + putvalue(device, [1 1 0 0]); + case 2 + putvalue(device, [0 0 1 1]); + case 3 + putvalue(device, [1 0 0 0]); + case 4 + putvalue(device, [0 1 0 0]); + end + +elseif control(3) + switch(savedControls(3)) + case 1 + putvalue(device, [1 1 0 0]); + case 2 + putvalue(device, [0 0 1 1]); + case 3 + putvalue(device, [1 0 0 0]); + case 4 + putvalue(device, [0 1 0 0]); + end + +elseif control(4) + switch(savedControls(4)) + case 1 + putvalue(device, [1 1 0 0]); + case 2 + putvalue(device, [0 0 1 1]); + case 3 + putvalue(device, [1 0 0 0]); + case 4 + putvalue(device, [0 1 0 0]); + end + +else + putvalue(device, [0 0 0 0]); +end +end + + + \ No newline at end of file diff --git a/Comm/VRE/GUI_Test_VRE.fig b/Comm/VRE/GUI_Test_VRE.fig index a271ace..0206834 100644 Binary files a/Comm/VRE/GUI_Test_VRE.fig and b/Comm/VRE/GUI_Test_VRE.fig differ diff --git a/Comm/VRE/GUI_Test_VRE.m b/Comm/VRE/GUI_Test_VRE.m index 8245356..9555960 100644 --- a/Comm/VRE/GUI_Test_VRE.m +++ b/Comm/VRE/GUI_Test_VRE.m @@ -22,7 +22,7 @@ % Edit the above text to modify the response to help GUI_Test_VRE -% Last Modified by GUIDE v2.5 22-Oct-2013 11:25:20 +% Last Modified by GUIDE v2.5 01-Dec-2015 14:25:55 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; @@ -91,7 +91,10 @@ function pb_startVRE_Callback(hObject, eventdata, handles) % % set(handles.t_msg,'String','Disconnected'); % % set(handles.pb_startVRE,'String','Connect'); % % end -handles = ConnectVRE(handles,'Virtual Reality.exe'); +if isfield(handles,'vre_leg') +handles = rmfield(handles,'vre_leg'); +end +handles = ConnectVRE(handles,'virtual reality.exe'); guidata(hObject,handles); % --- Executes during object creation, after setting all properties. @@ -309,3 +312,13 @@ function pb_startAREARM_Callback(hObject, eventdata, handles) % handles structure with handles and user data (see GUIDATA) handles = ConnectVRE(handles,'Augmented Reality ARM.exe'); guidata(hObject,handles); + + +% --- Executes on button press in pb_startVRELEG. +function pb_startVRELEG_Callback(hObject, eventdata, handles) +% hObject handle to pb_startVRELEG (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles.vre_leg = 1; +handles = ConnectVRE(handles,'virtual reality.exe'); +guidata(hObject,handles); diff --git a/Control/GUI_Sensors.fig b/Control/GUI_Sensors.fig index 2b62b78..50ed97b 100644 Binary files a/Control/GUI_Sensors.fig and b/Control/GUI_Sensors.fig differ diff --git a/Control/GUI_Sensors.m b/Control/GUI_Sensors.m index e50d835..91131ad 100644 --- a/Control/GUI_Sensors.m +++ b/Control/GUI_Sensors.m @@ -62,10 +62,13 @@ function GUI_Sensors_OpeningFcn(hObject, eventdata, handles, varargin) if ~isempty(h) % get handles and other user-defined data associated to Gui1 g1data = guidata(h); - - % handles.sensors = g1data.sensors - handles.sensors = InitSensors(); - handles.com = g1data.Control_obj; + handles.sensors = g1data.sensors; + if isfield(g1data,'Control_obj') + handles.com = g1data.Control_obj; + else + errordlg('Communication object not found. Connect with the device!','Error'); + return + end end % if InitSensors found the "sensors.def" file diff --git a/Control/GUI_SingleMotorTest.fig b/Control/GUI_SingleMotorTest.fig deleted file mode 100644 index c114f9f..0000000 Binary files a/Control/GUI_SingleMotorTest.fig and /dev/null differ diff --git a/Control/GUI_SingleMotorTest.m b/Control/GUI_SingleMotorTest.m deleted file mode 100644 index 2959496..0000000 --- a/Control/GUI_SingleMotorTest.m +++ /dev/null @@ -1,1016 +0,0 @@ -% ---------------------------- Copyright Notice --------------------------- -% This file is part of BioPatRec © which is open and free software under -% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for -% the full license governing this code and copyrights. -% -% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and -% Chalmers University of Technology. All authors’ contributions must be kept -% acknowledged below in the section "Updates % Contributors". -% -% Would you like to contribute to science and sum efforts to improve -% amputees’ quality of life? Join this project! or, send your comments to: -% maxo@chalmers.se. -% -% The entire copyright notice must be kept in this or any source file -% linked to BioPatRec. This will ensure communication with all authors and -% acknowledge contributions here and in the project web page (optional). -% -% -------------------------- Function Description ------------------------- -% [Give a short summary about the principle of your function here.] -% -% ------------------------- Updates & Contributors ------------------------ -% [Contributors are welcome to add their email] -% 20xx-xx-xx / Max Ortiz / Creation -% 20xx-xx-xx / Author / Comment on update - -function varargout = GUI_SingleMotorTest(varargin) -% GUI_SINGLEMOTORTEST M-file for GUI_SingleMotorTest.fig -% GUI_SINGLEMOTORTEST, by itself, creates a new GUI_SINGLEMOTORTEST or raises the existing -% singleton*. -% -% H = GUI_SINGLEMOTORTEST returns the handle to a new GUI_SINGLEMOTORTEST or the handle to -% the existing singleton*. -% -% GUI_SINGLEMOTORTEST('CALLBACK',hObject,eventData,handles,...) calls the local -% function named CALLBACK in GUI_SINGLEMOTORTEST.M with the given input arguments. -% -% GUI_SINGLEMOTORTEST('Property','Value',...) creates a new GUI_SINGLEMOTORTEST or raises the -% existing singleton*. Starting from the left, property value pairs are -% applied to the GUI before GUI_SingleMotorTest_OpeningFcn gets called. An -% unrecognized property name or invalid value makes property application -% stop. All inputs are passed to GUI_SingleMotorTest_OpeningFcn via varargin. -% -% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one -% instance to run (singleton)". -% -% See also: GUIDE, GUIDATA, GUIHANDLES - -% Edit the above text to modify the response to help GUI_SingleMotorTest - -% Last Modified by GUIDE v2.5 15-Sep-2011 12:10:36 - -% Begin initialization code - DO NOT EDIT -gui_Singleton = 1; -gui_State = struct('gui_Name', mfilename, ... - 'gui_Singleton', gui_Singleton, ... - 'gui_OpeningFcn', @GUI_SingleMotorTest_OpeningFcn, ... - 'gui_OutputFcn', @GUI_SingleMotorTest_OutputFcn, ... - 'gui_LayoutFcn', [] , ... - 'gui_Callback', []); -if nargin && ischar(varargin{1}) - gui_State.gui_Callback = str2func(varargin{1}); -end - -if nargout - [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); -else - gui_mainfcn(gui_State, varargin{:}); -end -% End initialization code - DO NOT EDIT - - -% --- Executes just before GUI_SingleMotorTest is made visible. -function GUI_SingleMotorTest_OpeningFcn(hObject, eventdata, handles, varargin) -% This function has no output args, see OutputFcn. -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -% varargin command line arguments to GUI_SingleMotorTest (see VARARGIN) - -% Choose default command line output for GUI_SingleMotorTest -handles.output = hObject; - -% Button Group -set(handles.motordir,'SelectionChangeFcn',@motordir_SelectionChangeFcn); - -% Update handles structure -guidata(hObject, handles); - -% UIWAIT makes GUI_SingleMotorTest wait for user response (see UIRESUME) -% uiwait(handles.fig_one_motor_test_panel); - - -% --- Outputs from this function are returned to the command line. -function varargout = GUI_SingleMotorTest_OutputFcn(hObject, eventdata, handles) -% varargout cell array for returning output args (see VARARGOUT); -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Get default command line output from handles structure -varargout{1} = handles.output; - - -% --- Executes on button press in pb_initDAQ. -function pb_initDAQ_Callback(hObject, eventdata, handles) -% hObject handle to pb_initDAQ (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - sF = str2double(get(handles.et_Fs,'String')); - sT = str2double(get(handles.et_Ts,'String')); - [ai ao dio] = init_DAQ(sF,sT,1:8); - - set(handles.t_ai,'UserData',ai); - set(handles.t_ao,'UserData',ao); - set(handles.t_dio,'UserData',dio); - - % Enable Buttons - set(handles.pb_recordAI,'Enable','on') - set(handles.pb_stopDAQ,'Enable','on') - - -function et_Fs_Callback(hObject, eventdata, handles) - set(handles.pb_recordAI,'Enable','off') - set(handles.pb_stopDAQ,'Enable','off') - - -% --- Executes during object creation, after setting all properties. -function et_Fs_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_Fs (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_Ts_Callback(hObject, eventdata, handles) - set(handles.pb_recordAI,'Enable','off') - set(handles.pb_stopDAQ,'Enable','off') - - -% --- Executes during object creation, after setting all properties. -function et_Ts_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_Ts (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_Tp_Callback(hObject, eventdata, handles) -% hObject handle to et_Tp (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_Tp as text -% str2double(get(hObject,'String')) returns contents of et_Tp as a double - - -% --- Executes during object creation, after setting all properties. -function et_Tp_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_Tp (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in pb_recordAI. -function pb_recordAI_Callback(hObject, eventdata, handles) - - Fs = str2double(get(handles.et_Fs,'String')); - Ts = str2double(get(handles.et_Ts,'String')); - Tp = str2double(get(handles.et_Tp,'String')); - - cIdx = zeros(1,21); - gcIdx = zeros(1,21); - - % Get ANN - if get(handles.cb_ann,'Value') - ANN = get(handles.cb_ann,'UserData'); - if isempty(ANN) - [file, path] = uigetfile('*.mat'); - load([path,file]); - if exist('psoANN','var') - ANN = psoANN; - elseif exist('eaANN','var') - ANN = eaANN; - elseif exist('bpANN','var') - ANN = bpANN; - else - errordlg('File without ANNs','Error'); - return; - end - set(handles.cb_ann,'UserData',ANN) - end - if Tp ~= ANN.tw - errordlg(['Peek time does not match ANN.tw:' num2str(ANN.tw)],'Error'); - return; - elseif Fs ~= ANN.Fs - errordlg(['Fs does not match ANN.Fs:' num2str(ANN.Fs)],'Error'); - return; - end - cIdx(ANN.cIdx) = 1; - treated_data.vdata = []; - treated_data.tdata = []; - treated_data.etrN = 1; - end - ncIdx = get(handles.pm_chrs,'Value'); - gcIdx(ncIdx) = 1; - - % Index - mIIdx = 5; % Index for motor I - PWMIdx = 6; % Index for PWM - - % Init Graphs - nxt = round(Ts/Tp) * 5; % Total samples to peek - nx = Fs*Tp; % samples to peek - axes(handles.a_motorRI); - mRIy = zeros(1,nxt); % Motor RI y (or vector) - p_motorRI = plot(1:nxt,mRIy); - axes(handles.a_motorI); - y = zeros(1,nx); % Motor I and PWM vector - p_motorI = plot(1:nx,y); - axes(handles.a_PWM); - p_PWM = plot(1:nx,y); % PWM plot - axes(handles.a_schr); - pv = [zeros(1,nxt) ; zeros(1,nxt) ; zeros(1,nxt) ; zeros(1,nxt)]; % Plot vector for signal chrs - p_schr = plot(1:nxt,pv); - axes(handles.a_controls); - cv = zeros(1,nxt); % Control Vector - cvA = cv; % Analog Control Vector - p_controls = plot(1:nxt,cv); - axes(handles.a_error); - ev = zeros(1,nxt); % Error Vector - p_error = plot(1:nxt,ev); - - %Scaling - chmin(1) = str2double(get(handles.et_ch0min,'String')); - chmax(1) = str2double(get(handles.et_ch0max,'String')); - chmin(2) = str2double(get(handles.et_ch1min,'String')); - chmax(2) = str2double(get(handles.et_ch1max,'String')); - chmin(3) = str2double(get(handles.et_ch2min,'String')); - chmax(3) = str2double(get(handles.et_ch2max,'String')); - chmin(4) = str2double(get(handles.et_ch3min,'String')); - chmax(4) = str2double(get(handles.et_ch3max,'String')); - Aoutmin = str2double(get(handles.et_Aoutmin,'String')); - Aoutmax = str2double(get(handles.et_Aoutmax,'String')); - errmRImin = str2double(get(handles.et_errmRImin,'String')); - errmRImax = str2double(get(handles.et_errmRImax,'String')); - - % Chanel for control - if get(handles.cb_ch0,'value') - csch = 1; - elseif get(handles.cb_ch1,'value') - csch = 2; - elseif get(handles.cb_ch2,'value') - csch = 3; - elseif get(handles.cb_ch3,'value') - csch = 4; - end - Amin = chmin(csch); - Amax = chmax(csch); - - % DAQ - ai = get(handles.t_ai,'UserData'); - start(ai); - dio = get(handles.t_dio,'UserData'); - ao = get(handles.t_ao,'UserData'); - StopMotor(dio,ao); - - % wait for the first samples to be aquired - while ai.SamplesAcquired < Fs*Tp - end - i=1; - while ai.SamplesAcquired < Fs*Ts - - data = peekdata(ai,Fs*Tp); - datam = data(:,mIIdx); - datapwm = data(:,PWMIdx); - data = data(:,1:4); - - % MOTOR -% data(:,mIIdx) = data(:,mIIdx)./ str2double(get(handles.et_senseR,'String')); % Change from Voltage to Current -% motorRI(i) = trapz(data(:,mIIdx)) / 1000; % Integral of the current per mS - datam = datam ./ str2double(get(handles.et_senseR,'String')); % Change from Voltage to Current - motorRI(i) = trapz(datam) / 1000; % Integral of the current per mS - %motorRI(i) = sum(data(:,mIIdx).^2)/Fs*Tp; - if motorRI(i) >= 0.9 % Safety routing - StopMotor(dio,ao); - end - mRIy(i) = motorRI(i); - set(handles.et_motorRI,'String',num2str(motorRI(i))); - set(p_motorRI,'YData',mRIy); - set(p_motorI,'YData',datam); - set(p_PWM,'YData',datapwm); - drawnow; - - - % Signal Characteristics for Amplitud - treated_data.trdata = analyze_signal(data(:,1:4),Fs,gcIdx); % Only Breakdown the Biosignals - allChrs = fieldnames(treated_data.trdata); - Chr = allChrs(ncIdx); - pv(:,i) = treated_data.trdata.(Chr{1}); - % Graphics - set(p_schr(1),'YData',pv(1,:)); - set(p_schr(2),'YData',pv(2,:)); - set(p_schr(3),'YData',pv(3,:)); - set(p_schr(4),'YData',pv(4,:)); - - if get(handles.cb_ann,'Value') - % filtering - if ANN.filters.PLH - data = BSbutterPLHarmonics(Fs, data); - elseif ANN.filters.BP - data = FilterBP_EMG(Fs, data); - end - treated_data.trdata = analyze_signal(data,Fs,cIdx); - trset = get_Sets(treated_data,ANN.Chrs); - - % Normalize - if ANN.normalize == 1 - allsets = get(handles.t_allsets,'UserData'); - allsets(length(allsets(:,1))+1 : length(allsets(:,1))+length(trset(:,1)),:) = trset; - mn = mean(allsets,1); - vr = var(allsets); - trset = (trset - mn(ones(size(trset,1), 1), :)) ./ vr(ones(size(trset,1), 1), :); - end - - ANN = evaluate_ann(trset, ANN); - - if round(ANN.o(1)) == 1 && round(ANN.o(2)) == 0 - dir = [0 1]; % 1 Open - csch = 2; - set(handles.t_msgdir,'String','Open'); - elseif round(ANN.o(1)) == 0 && round(ANN.o(2)) == 1 - dir = [1 0]; % 2 Close - csch = 1; - set(handles.t_msgdir,'String','Close'); - else - dir = [1 1]; % 2 Close - set(handles.t_msgdir,'String','Do nothing'); - end - - else - % Automatic direction - if get(handles.cb_ch1and2,'Value') % CH 1 and CH 2 Natural - if pv(2,i) > pv(1,i) - dir = [0 1]; % 1 Open - csch = 2; - set(handles.t_msgdir,'String','Open'); - else - dir = [1 0]; % 2 Close - csch = 1; - set(handles.t_msgdir,'String','Close'); - end - elseif get(handles.cb_ch2and3,'Value') % CH 2 and CH 3 Usual - if pv(2,i) > pv(3,i) - dir = [0 1]; % 1 Open - csch = 2; - set(handles.t_msgdir,'String','Open'); - else - dir = [1 0]; % 2 Close - csch = 3; - set(handles.t_msgdir,'String','Close'); - end - end - end - - % Scaling: First range is how you want the output, seconde range is where the raw-data comes - Amin = chmin(csch); - Amax = chmax(csch); - cv(i) = scale(pv(csch,i),0,100,Amin,Amax); - if cv(i) > 0 % Set direction only if there is control planned - putvalue(dio.Line([1 2]), dir); - else - putvalue(dio.Line([1 2]), [1 1]); - end - set(p_controls,'YData',cv); - - % Error - smotorRI = scale(motorRI(i),0,100,errmRImin,errmRImax); - ev(i) = cv(i) - smotorRI; % 1 Amp = 100% - set(p_error,'YData',ev); - - - % Scaling output 1 - 4 V and control signal from 0 - 100; - cvA(i) = scale(cv(i),Aoutmin,Aoutmax,0,100); - if get(handles.cb_linkcontrols,'Value') - putsample(ao,cvA(i)); % Exit according to slider - end - - i=i+1; - end - - [data t] = getdata(ai); - data(:,mIIdx) = data(:,mIIdx)./ str2double(get(handles.et_senseR,'String')); % change from V to I - set(handles.t_t,'UserData',t); - - set(handles.pb_pmotorRI,'UserData',motorRI); - - motorI = data(:,mIIdx); - set(p_motorI,'XData',t); - set(p_motorI,'YData',motorI); - set(handles.pb_pmotorI,'UserData',motorI); - - PWM = data(:,PWMIdx); - set(p_PWM,'XData',t); - set(p_PWM,'YData',PWM); - set(handles.pb_pPWM,'UserData',PWM); - - set(handles.pb_pschr,'UserData',pv); - set(handles.pb_pcontrols,'UserData',cv); - set(handles.pb_pcontrolsA,'UserData',cvA); - set(handles.pb_perror,'UserData',ev); - - StopMotor(dio,ao); % End by stoping the motor - - -% --- Executes on button press in pb_stopDAQ. -function pb_stopDAQ_Callback(hObject, eventdata, handles) -% hObject handle to pb_stopDAQ (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - ai = get(handles.t_ai,'UserData'); - ao = get(handles.t_ao,'UserData'); - dio = get(handles.t_dio,'UserData'); - - stop(ai); - stop(ao); - stop(dio); - - - -% --- Executes on slider movement. -function s_speed_Callback(hObject, eventdata, handles) -% hObject handle to s_speed (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'Value') returns position of slider -% get(hObject,'Min') and get(hObject,'Max') to determine range of slider - - set(handles.et_speed,'String',num2str(get(hObject,'Value'))); - ao = get(handles.t_ao,'UserData'); - putsample(ao,get(hObject,'Value')); % Exit according to slider - - -% --- Executes during object creation, after setting all properties. -function s_speed_CreateFcn(hObject, eventdata, handles) -% hObject handle to s_speed (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: slider controls usually have a light gray background. -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - - - -function et_speed_Callback(hObject, eventdata, handles) -% hObject handle to et_speed (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_speed as text -% str2double(get(hObject,'String')) returns contents of et_speed as a double - - set(handles.s_speed,'Value',str2double(get(hObject,'String'))); - ao = get(handles.t_ao,'UserData'); - putsample(ao,get(handles.s_speed,'Value')); % Exit according to slider - -% --- Executes during object creation, after setting all properties. -function et_speed_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_speed (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_motordir_Callback(hObject, eventdata, handles) -% hObject handle to et_motordir (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_motordir as text -% str2double(get(hObject,'String')) returns contents of et_motordir as a double - - -% --- Executes during object creation, after setting all properties. -function et_motordir_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_motordir (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - -function motordir_SelectionChangeFcn(hObject, eventdata) - -%retrieve GUI data, i.e. the handles structure -handles = guidata(hObject); - -dio = get(handles.t_dio,'UserData'); - -switch get(eventdata.NewValue,'Tag') % Get Tag of selected object - case 'rb_stop' - set(handles.et_motordir,'String','3'); - putvalue(dio.Line([1 2]), [1 1]); % Stop motor - - case 'rb_close' - set(handles.et_motordir,'String','2'); - putvalue(dio.Line([1 2]), [1 0]); - - case 'rb_open' - set(handles.et_motordir,'String','1'); - putvalue(dio.Line([1 2]), [0 1]); - - otherwise - set(handles.et_motordir,'String','3'); - putvalue(dio.Line([1 2]), [1 1]); -end -%updates the handles structure -guidata(hObject, handles); - - -% --- Executes on button press in pb_pmotorI. -function pb_pmotorI_Callback(hObject, eventdata, handles) - figure; - plot(get(handles.t_t,'UserData'),get(handles.pb_pmotorI,'UserData')); - title('Motor Current (I)') - - -% --- Executes on button press in pb_pPWM. -function pb_pPWM_Callback(hObject, eventdata, handles) - figure; - plot(get(handles.t_t,'UserData'),get(handles.pb_pPWM,'UserData')); - title('PWM') - - -% --- Executes on button press in pb_pmotorV. -function pb_pmotorV_Callback(hObject, eventdata, handles) -% hObject handle to pb_pmotorV (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - - - -function et_motorRI_Callback(hObject, eventdata, handles) - - -% --- Executes during object creation, after setting all properties. - -function et_motorRI_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_motorRI (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in pb_pmotorRI. -function pb_pmotorRI_Callback(hObject, eventdata, handles) - figure; - plot(get(handles.pb_pmotorRI,'UserData')); - title('Motor R Current') - - - -function et_senseR_Callback(hObject, eventdata, handles) -% hObject handle to et_senseR (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_senseR as text -% str2double(get(hObject,'String')) returns contents of et_senseR as a double - - -% --- Executes during object creation, after setting all properties. -function et_senseR_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_senseR (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in pb_pcontrols. -function pb_pcontrols_Callback(hObject, eventdata, handles) - figure; - plot(get(handles.pb_pcontrols,'UserData')); - title('Control Signal') - - -% --- Executes on button press in pb_pschr. -function pb_pschr_Callback(hObject, eventdata, handles) - figure; - plot(get(handles.pb_pschr,'UserData')'); - title('Signal Characteristic') - legend('1','2','3','4') - - - -function et_ch0min_Callback(hObject, eventdata, handles) -% hObject handle to et_ch0min (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_ch0min as text -% str2double(get(hObject,'String')) returns contents of et_ch0min as a double - - -% --- Executes during object creation, after setting all properties. -function et_ch0min_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_ch0min (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_ch0max_Callback(hObject, eventdata, handles) -% hObject handle to et_ch0max (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_ch0max as text -% str2double(get(hObject,'String')) returns contents of et_ch0max as a double - - -% --- Executes during object creation, after setting all properties. -function et_ch0max_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_ch0max (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in cb_ch0. -function cb_ch0_Callback(hObject, eventdata, handles) -% hObject handle to cb_ch0 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_ch0 - - -% --- Executes on button press in cb_ch1. -function cb_ch1_Callback(hObject, eventdata, handles) -% hObject handle to cb_ch1 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_ch1 - - -% --- Executes on button press in cb_ch2. -function cb_ch2_Callback(hObject, eventdata, handles) -% hObject handle to cb_ch2 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_ch2 - - -% --- Executes on button press in cb_ch3. -function cb_ch3_Callback(hObject, eventdata, handles) -% hObject handle to cb_ch3 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_ch3 - - -% --- Executes on button press in pb_perror. -function pb_perror_Callback(hObject, eventdata, handles) - figure; - plot(get(handles.pb_perror,'UserData')); - title('Error') - - -% --- Executes on selection change in pm_chrs. -function pm_chrs_Callback(hObject, eventdata, handles) -% hObject handle to pm_chrs (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: contents = get(hObject,'String') returns pm_chrs contents as cell array -% contents{get(hObject,'Value')} returns selected item from pm_chrs - - -% --- Executes during object creation, after setting all properties. -function pm_chrs_CreateFcn(hObject, eventdata, handles) -% hObject handle to pm_chrs (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: popupmenu controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in cb_linkcontrols. -function cb_linkcontrols_Callback(hObject, eventdata, handles) -% hObject handle to cb_linkcontrols (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_linkcontrols - - -% --- Executes on button press in pb_pcontrolsA. -function pb_pcontrolsA_Callback(hObject, eventdata, handles) - figure; - plot(get(handles.pb_pcontrolsA,'UserData')); - title('Analog Control Signal') - - - -function et_Aoutmin_Callback(hObject, eventdata, handles) -% hObject handle to et_Aoutmin (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_Aoutmin as text -% str2double(get(hObject,'String')) returns contents of et_Aoutmin as a double - - -% --- Executes during object creation, after setting all properties. -function et_Aoutmin_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_Aoutmin (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_Aoutmax_Callback(hObject, eventdata, handles) -% hObject handle to et_Aoutmax (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_Aoutmax as text -% str2double(get(hObject,'String')) returns contents of et_Aoutmax as a double - - -% --- Executes during object creation, after setting all properties. -function et_Aoutmax_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_Aoutmax (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_errmRImin_Callback(hObject, eventdata, handles) -% hObject handle to et_errmRImin (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_errmRImin as text -% str2double(get(hObject,'String')) returns contents of et_errmRImin as a double - - -% --- Executes during object creation, after setting all properties. -function et_errmRImin_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_errmRImin (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_errmRImax_Callback(hObject, eventdata, handles) -% hObject handle to et_errmRImax (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_errmRImax as text -% str2double(get(hObject,'String')) returns contents of et_errmRImax as a double - - -% --- Executes during object creation, after setting all properties. -function et_errmRImax_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_errmRImax (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_ch1min_Callback(hObject, eventdata, handles) -% hObject handle to et_ch1min (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_ch1min as text -% str2double(get(hObject,'String')) returns contents of et_ch1min as a double - - -% --- Executes during object creation, after setting all properties. -function et_ch1min_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_ch1min (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_ch1max_Callback(hObject, eventdata, handles) -% hObject handle to et_ch1max (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_ch1max as text -% str2double(get(hObject,'String')) returns contents of et_ch1max as a double - - -% --- Executes during object creation, after setting all properties. -function et_ch1max_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_ch1max (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_ch2min_Callback(hObject, eventdata, handles) -% hObject handle to et_ch2min (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_ch2min as text -% str2double(get(hObject,'String')) returns contents of et_ch2min as a double - - -% --- Executes during object creation, after setting all properties. -function et_ch2min_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_ch2min (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_ch2max_Callback(hObject, eventdata, handles) -% hObject handle to et_ch2max (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_ch2max as text -% str2double(get(hObject,'String')) returns contents of et_ch2max as a double - - -% --- Executes during object creation, after setting all properties. -function et_ch2max_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_ch2max (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_ch3min_Callback(hObject, eventdata, handles) -% hObject handle to et_ch3min (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_ch3min as text -% str2double(get(hObject,'String')) returns contents of et_ch3min as a double - - -% --- Executes during object creation, after setting all properties. -function et_ch3min_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_ch3min (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_ch3max_Callback(hObject, eventdata, handles) -% hObject handle to et_ch3max (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_ch3max as text -% str2double(get(hObject,'String')) returns contents of et_ch3max as a double - - -% --- Executes during object creation, after setting all properties. -function et_ch3max_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_ch3max (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in cb_ch1and2. -function cb_ch1and2_Callback(hObject, eventdata, handles) -% hObject handle to cb_ch1and2 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_ch1and2 - - -% --- Executes on button press in cb_ch2and3. -function cb_ch2and3_Callback(hObject, eventdata, handles) -% hObject handle to cb_ch2and3 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_ch2and3 - - -% --- Executes on button press in cb_ann. -function cb_ann_Callback(hObject, eventdata, handles) -% hObject handle to cb_ann (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_ann diff --git a/Control/IH2Azzurra/ReadSensors.m b/Control/IH2Azzurra/ReadSensors.m new file mode 100644 index 0000000..101f6bb --- /dev/null +++ b/Control/IH2Azzurra/ReadSensors.m @@ -0,0 +1,57 @@ +% ---------------------------- Copyright Notice --------------------------- +% This file is part of BioPatRec © which is open and free software under +% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for +% the full license governing this code and copyrights. +% +% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and +% Chalmers University of Technology. All authors’ contributions must be kept +% acknowledged below in the section "Updates % Contributors". +% +% Would you like to contribute to science and sum efforts to improve +% amputees’ quality of life? Join this project! or, send your comments to: +% maxo@chalmers.se. +% +% The entire copyright notice must be kept in this or any source file +% linked to BioPatRec. This will ensure communication with all authors and +% acknowledge contributions here and in the project web page (optional). +% +% ------------------- Function Description ------------------ +% Function serving as an interface between the control framework +% of BioPatRec © and IH2 Azzurra by Prensilia SRL. The function allows +% to read the External Sensors from the hardware. Please refer +% to the IH2 Azzurra manual for more information about External Sensors +% +% --------------------------Updates-------------------------- +% 2015-07-20 / Francesco Clemente / Creation (ReadSensors) +% +% 20xx-xx-xx / Author / Comment on update + +function data = ReadSensors(obj, SensorsIDs, ExtSensNo) + +% extract IDs of the sensors to be read +ExtSensID = NaN*ones(ExtSensNo,1); +for n = 1:ExtSensNo + ExtSensID(n) = str2double(SensorsIDs(n).id); +end + +% check if IDs are correct +if sum(ExtSensID > 6) || sum(ExtSensID < 0) + warning('IH2:Sensor_OOR',... + ['At least one external sensor address provided is '... + 'out of the allowed range (0:6).'... + 'The closer range limit will be used instead']); + ExtSensID(ExtSensID>6) = 6; + ExtSensID(ExtSensID<0) = 0; +end + +% send reading commands +CMD = 77*ones(2*ExtSensNo,1); +CMD(2:2:end) = ExtSensID; +fwrite(obj, CMD); +read_bytes = fread(obj, 2*ExtSensNo); + +% reconstruct values +data = NaN*ones(1,ExtSensNo); +for n=1:ExtSensNo + data(1,n) = bitand(3,read_bytes(1+(n-1)*2))*256 + read_bytes((2+(n-1)*2)); +end diff --git a/Control/IH2Azzurra/SendMotorCommand.m b/Control/IH2Azzurra/SendMotorCommand.m new file mode 100644 index 0000000..43fb5b6 --- /dev/null +++ b/Control/IH2Azzurra/SendMotorCommand.m @@ -0,0 +1,51 @@ +function result = SendMotorCommand(obj, ctrl_type, motor_address, dir, ctrl_val) + + switch ctrl_type + case 0 %speed control + % the ctrl_val is mapped to the motor PWM + PWM = round(ctrl_val*511/100); + + % the direction is mapped to the 'S' bit + if dir == 0%open + bitS = '0'; + else + bitS = '1'; + end + + % check for correct input values + if PWM > 511 || PWM < 0 + warning('IH2:PWM_OOR',... + ['The provided PWM is out of the allowed range (0:511). '... + 'The closer range limit will be used instead']); + PWM = min(PWM, 511); + PWM = max(PWM, 0); + end + + % build up the command bytes + PWM_bin = dec2bin(PWM,9); + MA_bin = dec2bin(str2double(motor_address),4); + bit8 = PWM_bin(1); + Byte1 = bin2dec(['1' bitS MA_bin '0' bit8]); + Byte2 = bin2dec(PWM_bin(2:end)); + + % send the command + fwrite(obj, [Byte1 Byte2]); + + case 1 %position control + + % the ctrl_val is mapped to the motor position + Pos = round(ctrl_val*255/100); + + if Pos > 255 || Pos < 0 + warning('IH2:POS_OOR', ... + ['The provided position is out of the allowed range (0:255).'... + 'The closer range limit will be used instead']); + Pos = min(Pos, 255); + Pos = max(Pos, 0); + end + + % send the command + fwrite(obj, [68 motor_address Pos]); + end + result = 1; +return \ No newline at end of file diff --git a/Comm/ALC/VCP_Piccolo/TestConnectionALC.m b/Control/IH2Azzurra/TestConnection.m similarity index 77% rename from Comm/ALC/VCP_Piccolo/TestConnectionALC.m rename to Control/IH2Azzurra/TestConnection.m index d1f0d0f..80cd2f8 100644 --- a/Comm/ALC/VCP_Piccolo/TestConnectionALC.m +++ b/Control/IH2Azzurra/TestConnection.m @@ -1,38 +1,40 @@ -% ---------------------------- Copyright Notice --------------------------- -% This file is part of BioPatRec © which is open and free software under -% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for -% the full license governing this code and copyrights. -% -% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and -% Chalmers University of Technology. All authors’ contributions must be kept -% acknowledged below in the section "Updates % Contributors". -% -% Would you like to contribute to science and sum efforts to improve -% amputees’ quality of life? Join this project! or, send your comments to: -% maxo@chalmers.se. -% -% The entire copyright notice must be kept in this or any source file -% linked to BioPatRec. This will ensure communication with all authors and -% acknowledge contributions here and in the project web page (optional). -% -% ------------------- Function Description ------------------ -% Function to test the communicatio object -% --------------------------Updates-------------------------- -% 2011-11-09 / Max Ortiz / Creation -% 20xx-xx-xx / Author / Comment - -%% Test Connection -function result = TestConnectionALC(obj) - %If buffer not empty, - if obj.io.BytesAvailable>0 - fread(obj.io,obj.io.BytesAvailable); - end - %Send connection test - fwrite(obj.io,'C'); - pause(0.5); - if fread(obj.io,1)==1 - result=1; - else - result=0; - end +% ---------------------------- Copyright Notice --------------------------- +% This file is part of BioPatRec © which is open and free software under +% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for +% the full license governing this code and copyrights. +% +% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and +% Chalmers University of Technology. All authors’ contributions must be kept +% acknowledged below in the section "Updates % Contributors". +% +% Would you like to contribute to science and sum efforts to improve +% amputees’ quality of life? Join this project! or, send your comments to: +% maxo@chalmers.se. +% +% The entire copyright notice must be kept in this or any source file +% linked to BioPatRec. This will ensure communication with all authors and +% acknowledge contributions here and in the project web page (optional). +% +% ------------------- Function Description ------------------ +% Function to test the communicatio object +% --------------------------Updates-------------------------- +% 2015-11-09 / Max Ortiz / Creation +% 20xx-xx-xx / Author / Comment + +%% IH2 Azzurra communication test +function result = TestConnection(com) + + % Empty the serial port buffer, if not + if com.BytesAvailable>0 + fread(com,com.BytesAvailable); + end + + % Try to read two motor positions + fwrite(com,[69 1 69 2]); + pos = fread(com,2); + if numel(pos)==2 + result=1; + else + result=0; + end end \ No newline at end of file diff --git a/Control/IH2Azzurra/motors.def b/Control/IH2Azzurra/motors.def new file mode 100644 index 0000000..7210ce2 --- /dev/null +++ b/Control/IH2Azzurra/motors.def @@ -0,0 +1,5 @@ +0,0,30 +1,0,30 +2,0,30 +3,0,30 +4,0,30 \ No newline at end of file diff --git a/Control/IH2Azzurra/movements.def b/Control/IH2Azzurra/movements.def new file mode 100644 index 0000000..9759eb9 --- /dev/null +++ b/Control/IH2Azzurra/movements.def @@ -0,0 +1,25 @@ +0,Rest,0,0,0 0 +1,Open Hand,9,1,1 0 2 0 3 0 4 0 5 0 +2,Close Hand,9,0,1 1 2 1 3 1 4 1 5 1 +3,Flex Hand,7,0,2 0 +4,Extend Hand,7,1,2 1 +5,Pronation,8,0,2 0 +6,Supination,8,1,2 1 +7,Thumb Extend,5,1,0 0 +8,Thumb Flex,5,0,0 0 +9,Index Extend,4,1,0 0 +10,Index Flex,4,0,0 0 +11,Middle Extend,3,1,0 0 +12,Middle Flex,3,0,0 0 +13,Ring Extend,2,1,0 0 +14,Ring Flex,2,0,0 0 +15,Little Extend,1,1,0 0 +16,Little Flex,1,0,0 0 +17,Pointer,10,1,1 1 2 1 3 0 4 1 5 1 +18,Thumb Yaw Flex,6,0,0 0 +19,Thumb Yaw Extend,6,1,0 0 +20,Flex Elbow,15,1,3 0 +21,Extend Elbow,15,0,3 1 +22,Agree,11,1,1 0 2 0 3 1 4 1 5 1 +23,Fine Grip,12,1,1 1 2 1 3 1 4 0 5 0 +24,Side Grip,13,1,1 0 2 1 3 1 4 1 5 1 \ No newline at end of file diff --git a/Control/IH2Azzurra/sensors.def b/Control/IH2Azzurra/sensors.def new file mode 100644 index 0000000..3d90272 --- /dev/null +++ b/Control/IH2Azzurra/sensors.def @@ -0,0 +1,7 @@ +0, AN0 +1, AN1 +2, AN2 +3, AN3 +4, AN4 +5, AN5 +6, AN6 \ No newline at end of file diff --git a/Control/InitMF_Hand_DC_Hardcoded.m b/Control/InitMF_Hand_DC_Hardcoded.m deleted file mode 100644 index 75336cf..0000000 --- a/Control/InitMF_Hand_DC_Hardcoded.m +++ /dev/null @@ -1,57 +0,0 @@ -% ---------------------------- Copyright Notice --------------------------- -% This file is part of BioPatRec © which is open and free software under -% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for -% the full license governing this code and copyrights. -% -% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and -% Chalmers University of Technology. All authors’ contributions must be kept -% acknowledged below in the section "Updates % Contributors". -% -% Would you like to contribute to science and sum efforts to improve -% amputees’ quality of life? Join this project! or, send your comments to: -% maxo@chalmers.se. -% -% The entire copyright notice must be kept in this or any source file -% linked to BioPatRec. This will ensure communication with all authors and -% acknowledge contributions here and in the project web page (optional). -% -% -------------------------- Function Description ------------------------- -% Function to initialize the vector to be used for control of a -% multifuctional prosthetic device using dc motors -% -% ------------------------- Updates & Contributors ------------------------ -% [Contributors are welcome to add their email] -% 2013-04-21 / Max Ortiz / Creation (removed from RealtimePatRec -% 20xx-xx-xx / Author / Comment on update - -function [pwmIDs pwmAs pwmBs] = InitMF_Hand_DC_Hardcoded(handles) - - %Initialize - motorIdx = zeros(1,10); - pwmAs = zeros(1,10); - pwmBs = zeros(1,10); - movSpeeds = zeros(1,10); - - % Get the links to the motors - for i = 1 : size(motorIdx,2) - pmID = ['handles.pm_m' num2str(i)]; - motorIdx(i) = get(eval(pmID),'Value'); - speedID = ['handles.et_speed' num2str(i)]; - movSpeeds(i) = str2double(get(eval(speedID),'String')); - end - - % Init variables for control - pwmIDs = ['A';'A';'B';'B';'C';'C';'D';'D';'E';'E']; - for i = 1 : 2 : size(pwmIDs) - pwmAs(i) = movSpeeds(i); - pwmBs(i) = 0; - pwmAs(i+1) = 0; - pwmBs(i+1) = movSpeeds(i+1); - end; - - % Arrenge according to selection - pwmIDs = pwmIDs(motorIdx); - pwmAs = pwmAs(motorIdx); - pwmBs = pwmBs(motorIdx); - -end \ No newline at end of file diff --git a/Control/InitMotors.m b/Control/InitMotors.m index c49303c..7ccdb10 100644 --- a/Control/InitMotors.m +++ b/Control/InitMotors.m @@ -19,20 +19,31 @@ % Reads the file motors.def and loads the data into motor objects. % --------------------------Updates-------------------------- % 2012-05-29 / Nichlas Sander / Creation -% 2012-07-19 / Max Ortiz / Added fclose which is necessary to prevent -% matlab crashes due to many files open. +% 2012-07-19 / Max Ortiz / Added fclose which is necessary to prevent +% matlab crashes due to many files open. +% 2016-05-19 / Enzo Mastinu / The path of the folder is now passed to the +% function. In case any file name is +% provided, it loads the default def file. % 20xx-xx-xx / Author / Comment on update -function obj = InitMotors -fid = fopen('motors.def'); -tline = fgetl(fid); -i = 1; -while(ischar(tline)) - t = textscan(tline,'%s','delimiter',','); - t = t{1}; - obj(i) = motor(t(1),str2double(t(2)),str2double(t(3))); - tline = fgetl(fid); - i = i + 1; -end +function obj = InitMotors(path) -fclose(fid); + if(nargin) + fid = fopen(strcat(path,'\motors.def')); + if(fid==-1) + errordlg('motors.def file not found in the given folder','Definition File Error'); + return + end + else + fid = fopen('motors_VRE.def'); + end + tline = fgetl(fid); + i = 1; + while(ischar(tline)) + t = textscan(tline,'%s','delimiter',','); + t = t{1}; + obj(i) = motor(t(1),str2double(t(2)),str2double(t(3))); + tline = fgetl(fid); + i = i + 1; + end + fclose(fid); diff --git a/Control/InitMovements.m b/Control/InitMovements.m index 9ac0cc7..ae46bdd 100644 --- a/Control/InitMovements.m +++ b/Control/InitMovements.m @@ -19,33 +19,44 @@ % Reads the file movements.def and loads the data into movement objects. % --------------------------Updates-------------------------- % 2012-05-29 / Nichlas Sander / Creation -% 2015-06-11 / Sebastian Karlsson / The directions of each motor in each -% movement are stored in motors matrix. +% 2015-06-11 / Sebastian Karlsson / The directions of each motor in each +% movement are stored in motors matrix. +% 2016-05-19 / Enzo Mastinu / The path of the folder is now passed to the +% function. In case any file name is +% provided, it loads the default def file. % 20xx-xx-xx / Author / Comment on update -function obj = InitMovements -fid = fopen('movements.def'); -tline = fgetl(fid); -i = 1; -while(ischar(tline)) - %Go through the string - t = textscan(tline,'%s','delimiter',','); - t = t{1}; - - %process t(5) here - m = textscan(cell2mat(t(5)),'%s','delimiter',' '); - j = 1; - k = 1; - clear motors; - motors = zeros(2,size(m{1},1)/2); - while(j <= size(m{1},1)) - motors(1,k) = str2double(m{1}(j)); %Motor ID - motors(2,k) = str2double(m{1}(j+1)); %Motor Direction - j = j + 2; - k = k + 1; +function obj = InitMovements(path) + + if(nargin) + fid = fopen(strcat(path,'\movements.def')); + if(fid==-1) + errordlg('movements.def file not found in the given folder','Definition File Error'); + return + end + else + fid = fopen('movements_VRE.def'); end - obj(i) = movement(str2double(t(1)),t(2),str2double(t(3)),str2double(t(4)),motors); tline = fgetl(fid); - i = i+1; -end -fclose(fid); \ No newline at end of file + i = 1; + while(ischar(tline)) + %Go through the string + t = textscan(tline,'%s','delimiter',','); + t = t{1}; + %process t(5) here + m = textscan(cell2mat(t(5)),'%s','delimiter',' '); + j = 1; + k = 1; + clear motors; + motors = zeros(2,size(m{1},1)/2); + while(j <= size(m{1},1)) + motors(1,k) = str2double(m{1}(j)); %Motor ID + motors(2,k) = str2double(m{1}(j+1)); %Motor Direction + j = j + 2; + k = k + 1; + end + obj(i) = movement(str2double(t(1)),t(2),str2double(t(3)),str2double(t(4)),motors); + tline = fgetl(fid); + i = i+1; + end + fclose(fid); \ No newline at end of file diff --git a/Control/InitSensors.m b/Control/InitSensors.m index 9534fbf..d9af88b 100644 --- a/Control/InitSensors.m +++ b/Control/InitSensors.m @@ -19,20 +19,18 @@ % Reads the file sensors.def and loads the data into sensor objects. % --------------------------Updates-------------------------- % 2015-06-11 / Sebastian Karlsson / Creation +% 2016-05-19 / Enzo Mastinu / The path of the folder must now be passed +% to the function. In case no file name is +% provided, it returns -1. +% 20xx-xx-xx / Author / Comment on update -function obj = InitSensors +function obj = InitSensors(path) -global ctrl_dir - -sensorspath = 'sensors.def'; -if ctrl_dir - sensorspath = [ctrl_dir filesep 'sensors.def']; -end - -fid = fopen(sensorspath); -if fid == -1 - obj = -1; -else + if(nargin<1) + obj = -1; + return + end + fid = fopen(strcat(path,'\sensors.def')); tline = fgetl(fid); i = 1; while(ischar(tline)) @@ -43,4 +41,3 @@ i = i + 1; end fclose(fid); -end diff --git a/Control/MotorsOn.m b/Control/MotorsOn.m index 22f8f5c..01ad588 100644 --- a/Control/MotorsOn.m +++ b/Control/MotorsOn.m @@ -52,6 +52,7 @@ motor_index = cell2mat(motors(movement.motor(1,i)).id); % Extract movement direction (for speed control) mov_dir = movement.motor(2,i); + % Send motor commands if ~SendMotorCommand(com, ctrl_type, motor_index, mov_dir, ctrl_val); diff --git a/Control/SPC/movements.def b/Control/SPC/movements.def index a724d57..4b9851a 100644 --- a/Control/SPC/movements.def +++ b/Control/SPC/movements.def @@ -1,25 +1,7 @@ 0,Rest,0,0,0 0 1,Open Hand,9,1,1 1 2,Close Hand,9,0,1 0 -3,Flex Hand,7,0,0 1 -4,Ext Hand,7,1,0 0 5,Pronation,8,0,2 0 6,Supination,8,1,2 1 -24,Side Grip,13,1,0 0 -23,Fine Grip,12,1,0 0 -22,Agree,11,1,0 0 -17,Point,10,1,0 0 -7,Thumb Ext,5,1,0 0 -8,Thumb Flex,5,0,0 0 -19,Thumb Yaw Ext,6,1,0 0 -18,Thumb Yaw Flex,6,0,0 0 20,Flex Elbow,15,1,3 0 -21,Ext Elbow,15,0,3 1 -9,Index Ext,4,1,0 0 -10,Index Flex,4,0,0 0 -11,Middle Ext,3,1,0 0 -12,Middle Flex,3,0,0 0 -13,Ring Ext,2,1,0 0 -14,Ring Flex,2,0,0 0 -15,Little Ext,1,1,0 0 -16,Little Flex,1,0,0 0 +21,Extend Elbow,15,0,3 1 \ No newline at end of file diff --git a/Control/VPSH/motors.def b/Control/VPSH/motors.def new file mode 100644 index 0000000..0a567fd --- /dev/null +++ b/Control/VPSH/motors.def @@ -0,0 +1 @@ +A,0,50 \ No newline at end of file diff --git a/Control/VPSH/movements.def b/Control/VPSH/movements.def new file mode 100644 index 0000000..4ca0552 --- /dev/null +++ b/Control/VPSH/movements.def @@ -0,0 +1,3 @@ +0,Rest,0,0,0 0 +1,Open Hand,9,1,1 1 +2,Close Hand,9,0,1 0 \ No newline at end of file diff --git a/Control/VPSH/sensors.def b/Control/VPSH/sensors.def new file mode 100644 index 0000000..54456e3 --- /dev/null +++ b/Control/VPSH/sensors.def @@ -0,0 +1,4 @@ +A, Strain +B, Pad1 +C, Pad2 +D, Pad3 \ No newline at end of file diff --git a/Control/VRE/motors_VRE.def b/Control/VRE/motors_VRE.def new file mode 100644 index 0000000..e9def9a --- /dev/null +++ b/Control/VRE/motors_VRE.def @@ -0,0 +1 @@ +A,0,1 \ No newline at end of file diff --git a/Control/VRE/movements_VRE.def b/Control/VRE/movements_VRE.def new file mode 100644 index 0000000..4eba307 --- /dev/null +++ b/Control/VRE/movements_VRE.def @@ -0,0 +1,47 @@ +0,Rest,0,0,0 0 +1,Open Hand,9,1,0 0 +2,Close Hand,9,0,0 0 +3,Flex Hand,7,0,0 0 +4,Extend Hand,7,1,0 0 +5,Pronation,8,0,0 0 +6,Supination,8,1,0 0 +7,Thumb Extend,5,1,0 0 +8,Thumb Flex,5,0,0 0 +9,Index Extend,4,1,0 0 +10,Index Flex,4,0,0 0 +11,Middle Extend,3,1,0 0 +12,Middle Flex,3,0,0 0 +13,Ring Extend,2,1,0 0 +14,Ring Flex,2,0,0 0 +15,Little Extend,1,1,0 0 +16,Little Flex,1,0,0 0 +17,Point,10,1,0 0 +18,Thumb Yaw Flex,6,1,0 0 +19,Thumb Yaw Extend,6,0,0 0 +20,Flex Elbow,15,1,0 0 +21,Extend Elbow,15,0,0 0 +22,Agree,11,1,0 0 +23,Fine Grip,12,1,0 0 +24,Side Grip,13,1,0 0 +1,Ankle Plantarflexion,6,0,0 0 +2,Ankle Dorsiflexion,6,1,0 0 +3,Ankle Inversion,7,0,0 0 +4,Ankle Eversion,7,1,0 0 +5,Flex Knee,8,1,0 0 +6,Extend Knee,8,0,0 0 +7,Tibial Rotation in,9,0,0 0 +8,Tibial Rotation out,9,1,0 0 +9,Femoral Rotation in,10,1,0 0 +10,Femoral Rotation out,10,0,0 0 +11,Curl Toes,11,0,0 0 +12,Stretch Toes,11,1,0 0 +13,Big Extend,5,1,0 0 +14,Big Flex,5,0,0 0 +15,Index Extend,4,1,0 0 +16,Index Flex,4,0,0 0 +17,Middle Extend,3,1,0 0 +18,Middle Flex,3,0,0 0 +19,Ring Extend,2,1,0 0 +20,Ring Flex,2,0,0 0 +21,Little Extend,1,1,0 0 +22,Little Flex,1,0,0 0 \ No newline at end of file diff --git a/Control/iLimbPanTilt/motors.def b/Control/iLimbPanTilt/motors.def new file mode 100644 index 0000000..a410376 --- /dev/null +++ b/Control/iLimbPanTilt/motors.def @@ -0,0 +1,7 @@ +A,0,60 +B,0,60 +C,0,60 +D,0,100 +E,0,100 +K,1,72 +L,1,54 \ No newline at end of file diff --git a/Control/iLimbPanTilt/movements.def b/Control/iLimbPanTilt/movements.def new file mode 100644 index 0000000..3846276 --- /dev/null +++ b/Control/iLimbPanTilt/movements.def @@ -0,0 +1,21 @@ +0,Rest,0,0,0 0 +1,Open Hand,9,1,1 1 2 1 3 1 4 1 5 1 +2,Close Hand,9,0,1 0 2 0 3 0 4 0 5 0 +3,Flex Hand,7,0,7 0 +4,Extend Hand,7,1,7 1 +5,Pronation,8,0,6 0 +6,Supination,8,1,6 1 +7,Thumb Extend,5,1,1 1 +8,Thumb Flex,5,0,1 0 +9,Index Extend,4,1,2 1 +10,Index Flex,4,0,2 0 +11,Middle Extend,3,1,3 1 +12,Middle Flex,3,0,3 0 +13,Ring Extend,2,1,4 1 +14,Ring Flex,2,0,4 0 +15,Little Extend,1,1,5 1 +16,Little Flex,1,0,5 0 +17,Point,10,0,1 0 2 1 3 0 4 0 5 0 +18,Thumb Yaw Flex,6,0,0 0 +19,Thumb Yaw Extend,6,1,0 0 +22,Agree,0,0,1 1 2 0 3 0 4 0 5 0 \ No newline at end of file diff --git a/DataAnalysis/GUI_DataAnalysis.fig b/DataAnalysis/GUI_DataAnalysis.fig new file mode 100644 index 0000000..2311287 Binary files /dev/null and b/DataAnalysis/GUI_DataAnalysis.fig differ diff --git a/DataAnalysis/GUI_DataAnalysis.m b/DataAnalysis/GUI_DataAnalysis.m new file mode 100644 index 0000000..c37a47f --- /dev/null +++ b/DataAnalysis/GUI_DataAnalysis.m @@ -0,0 +1,701 @@ +function varargout = GUI_DataAnalysis(varargin) +% GUI_DATAANALYSIS MATLAB code for GUI_DataAnalysis.fig +% GUI_DATAANALYSIS, by itself, creates a new GUI_DATAANALYSIS or raises the existing +% singleton*. +% +% H = GUI_DATAANALYSIS returns the handle to a new GUI_DATAANALYSIS or the handle to +% the existing singleton*. +% +% GUI_DATAANALYSIS('CALLBACK',hObject,eventData,handles,...) calls the local +% function named CALLBACK in GUI_DATAANALYSIS.M with the given input arguments. +% +% GUI_DATAANALYSIS('Property','Value',...) creates a new GUI_DATAANALYSIS or raises the +% existing singleton*. Starting from the left, property value pairs are +% applied to the GUI before GUI_DataAnalysis_OpeningFcn gets called. An +% unrecognized property name or invalid value makes property application +% stop. All inputs are passed to GUI_DataAnalysis_OpeningFcn via varargin. +% +% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one +% instance to run (singleton)". +% +% See also: GUIDE, GUIDATA, GUIHANDLES + +% Edit the above text to modify the response to help GUI_DataAnalysis + +% Last Modified by GUIDE v2.5 09-May-2016 15:44:14 + +% Begin initialization code - DO NOT EDIT +gui_Singleton = 1; +gui_State = struct('gui_Name', mfilename, ... + 'gui_Singleton', gui_Singleton, ... + 'gui_OpeningFcn', @GUI_DataAnalysis_OpeningFcn, ... + 'gui_OutputFcn', @GUI_DataAnalysis_OutputFcn, ... + 'gui_LayoutFcn', [] , ... + 'gui_Callback', []); +if nargin && ischar(varargin{1}) + gui_State.gui_Callback = str2func(varargin{1}); +end + +if nargout + [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); +else + gui_mainfcn(gui_State, varargin{:}); +end +% End initialization code - DO NOT EDIT + + +% --- Executes just before GUI_DataAnalysis is made visible. +function GUI_DataAnalysis_OpeningFcn(hObject, eventdata, handles, varargin) +% This function has no output args, see OutputFcn. +% hObject handle to figure +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +% varargin command line arguments to GUI_DataAnalysis (see VARARGIN) + +% Choose default command line output for GUI_DataAnalysis +handles.output = hObject; + +% Saving varargin in handles +handles.varargin = varargin; + +if ~isempty(varargin) + % check if in recordingSession + analysis.inRecSes = false; + if length(varargin)>1 + analysis.inRecSes = true; + analysis.recVarargin = varargin{2}; + end + + % Initialization default values + analysis.limit = 90; + set(handles.f_main,'UserData',analysis); + + % Setting GUI for recSession + set(handles.lb_edit,'String',varargin{1}.mov(1:end)); + set(handles.lb_edit,'Max',varargin{1}.nM); + handles = updateRec(handles); + analysis = get(handles.f_main,'UserData'); + recSession = analysis.recSession; + childrens = get(handles.f_main,'Children'); + set(childrens,'FontSize',10,'FontUnits','points'); + set(handles.t_mahalanobis,'FontSize',9,'FontUnits','points'); + + % Loading Features + fID = LoadFeaturesIDs; + set(handles.lb_features,'String',fID,'Max',length(fID)); + + % Setting up lists + set(handles.lb_channels,'String',1:recSession.nCh) + set(handles.lb_channels,'Max',recSession.nCh) + set(handles.lb_channels,'Min',2); + set(handles.lb_channels,'Value',1:recSession.nCh) +end +% Setting enables +set(handles.pm_classifier,'Enable','off'); +set(handles.pm_method,'Enable','off'); +set(handles.pb_setLimit,'Enable','off'); +set(handles.et_accLimit,'Enable','off'); +set(handles.pb_save,'Enable','off'); +set(handles.pb_undo,'Enable','off'); +set(handles.pb_delete,'Enable','off'); +set(handles.pb_replace,'Enable','off'); + +% Update handles structure +guidata(hObject, handles); + +% UIWAIT makes GUI_DataAnalysis wait for user response (see UIRESUME) +% uiwait(handles.f_main); + + +% --- Outputs from this function are returned to the command line. +function varargout = GUI_DataAnalysis_OutputFcn(hObject, eventdata, handles) +% varargout cell array for returning output args (see VARARGOUT); +% hObject handle to figure +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Get default command line output from handles structure +varargout{1} = handles.output; + + +% --- Executes on button press in pb_extractFeatures. +function pb_extractFeatures_Callback(hObject, eventdata, handles) +% hObject handle to pb_extractFeatures (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +analysis = get(handles.f_main,'UserData'); +% Checking if movements are deleted or added +if ~isequal(analysis.recSession.mov(1:end-1),get(handles.lb_edit,'String')) + handles = updateRec(handles); + analysis = get(handles.f_main,'UserData'); +end + +% Settings from GUI +recSession = analysis.recSession; +featuresS = get(handles.lb_features,'String'); +fID = featuresS(get(handles.lb_features,'Value')); +cTpS = get(handles.pm_ctp,'String'); +cTp = str2double(cTpS(get(handles.pm_ctp,'Value'))); % Contraction Time Precentage +sCh = get(handles.lb_channels,'Value'); + +recSession.tdata = recSession.tdata(:,sCh,:); +recSession.nCh = length(sCh); + +analysis.anDataM = GetAnalysisFeatures(recSession,fID,cTp); +analysis.method = ''; % To make sure CCEs are updated +set(handles.f_main,'UserData',analysis); + +handles = updateCCE(handles); +handles = updatePred(handles); +tmpObj = findobj(handles.am_distances(1)); +am_distances_ButtonDownFcn(tmpObj(1), eventdata, handles, 1); + +% Enable GUI +set(handles.pm_classifier,'Enable','on'); +set(handles.pm_method,'Enable','on'); +set(handles.pb_setLimit,'Enable','on'); +set(handles.et_accLimit,'Enable','on'); +set(handles.pb_save,'Enable','on'); +set(handles.pb_undo,'Enable','on'); +set(handles.pb_delete,'Enable','on'); +if analysis.inRecSes + set(handles.pb_replace,'Enable','on'); +end +guidata(hObject, handles); + +% --- Executes on selection change in pm_method. +function pm_method_Callback(hObject, eventdata, handles) +% hObject handle to pm_method (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: contents = cellstr(get(hObject,'String')) returns pm_method contents as cell array +% contents{get(hObject,'Value')} returns selected item from pm_method +handles = updateCCE(handles); +analysis = get(handles.f_main,'UserData'); +tmpObj = findobj(handles.am_distances(analysis.selectedMov)); +am_distances_ButtonDownFcn(tmpObj(1), eventdata, handles, analysis.selectedMov); +handles = updatePred(handles); +guidata(hObject, handles); + + +% --- Executes during object creation, after setting all properties. +function pm_method_CreateFcn(hObject, eventdata, handles) +% hObject handle to pm_method (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: popupmenu controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + +% --- Executes on mouse press over axes background. +function am_distances_ButtonDownFcn(hObject, eventdata, handles, m) +% hObject handle to am_distances (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +analysis = get(handles.f_main,'UserData'); +% Collecting object m +tmpObj = findobj(handles.am_distances(m)); +hObject = tmpObj(1); +recSession = analysis.recSession; +className = recSession.mov{m}; + +% Updating big plot +cla(handles.a_distance); +copyobj(get(hObject,'Children'),handles.a_distance); +axis(handles.a_distance,[get(hObject,'XLim') get(hObject,'YLim')]); +children = get(handles.a_distance,'Children'); +set(children(1),'MarkerSize',20); +set(children(2),'MarkerSize',5,'Marker','o'); +hold(handles.a_distance,'on'); +plot(handles.a_distance,[mean(get(children(1),'XData')) mean(get(children(2),'XData'))],[mean(get(children(1),'YData')) mean(get(children(2),'YData'))],'x-','Color',[0 0 0],'MarkerSize',8,'Linewidth',1.5); +legend(handles.a_distance,{[className ' (Conserned Movement)'],[analysis.neighborName{m} ' (Closest Neighbor)'], [analysis.method ' : ' num2str(analysis.mCCE(m),2)]}); +set(handles.a_distance,'Visible','on','Box','on','XTick',[],'YTick',[]); + +% Updating prediction plot +if isfield(analysis,'predObj'); + delete(analysis.predObj); +end +h = plot(handles.a_prediction,[analysis.mCCE(m) analysis.mCCE(m)],[0 100],'r--'); + +% Updating selected movement +analysis.selectedMov = m; +analysis.predObj = h; +if m ~= analysis.recSession.nM + [~,pos] = ismember(analysis.recSession.mov(m),get(handles.lb_edit,'String')); + set(handles.lb_edit,'Value',pos); +end +set(handles.f_main,'UserData',analysis); +guidata(hObject, handles); + + +% --- Executes on selection change in pm_classifier. +function pm_classifier_Callback(hObject, eventdata, handles) +% hObject handle to pm_classifier (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: contents = cellstr(get(hObject,'String')) returns pm_classifier contents as cell array +% contents{get(hObject,'Value')} returns selected item from pm_classifier +handles = updatePred(handles); +guidata(hObject, handles); + + +% --- Executes during object creation, after setting all properties. +function pm_classifier_CreateFcn(hObject, eventdata, handles) +% hObject handle to pm_classifier (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: popupmenu controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + +% --- Executes on mouse press over axes background. +function a_prediction_ButtonDownFcn(hObject, eventdata, handles) +% hObject handle to a_prediction (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +figure; +a = axes; +copyobj(hObject.Children,a); +axis(a,[hObject.XLim hObject.YLim]); +xlabel(a,'Classification Complexity'); +ylabel(a,'Predicted Accuracy'); +legend(a.Children([5 2 1]),{'Measured Data' 'Line Fitted to Measured Data' 'Classification Complexity of the Selected Movement'}); + +% --- Executes on selection change in lb_edit. +function lb_edit_Callback(hObject, eventdata, handles) +% hObject handle to lb_edit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: contents = cellstr(get(hObject,'String')) returns lb_edit contents as cell array +% contents{get(hObject,'Value')} returns selected item from lb_edit + + +% --- Executes during object creation, after setting all properties. +function lb_edit_CreateFcn(hObject, eventdata, handles) +% hObject handle to lb_edit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: listbox controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + +% --- Executes on button press in pb_replace. +function pb_replace_Callback(hObject, eventdata, handles) +% hObject handle to pb_replace (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +analysis = get(handles.f_main,'UserData'); +repMovV = get(handles.lb_edit,'Value'); +repMovS = get(handles.lb_edit,'String'); + +% Editing varargin to re-record selected movments +analysis.recVarargin{1} = length(repMovV); +analysis.recVarargin{5} = repMovS(repMovV); +analysis.recVarargin{end+1} = false; +recSession = handles.varargin{1}; + +% Updating recSsession +[~,pos] = ismember(repMovS(repMovV),recSession.mov); +recSession.tdata(:,:,pos) = RecordingSession(analysis.recVarargin{:}); +figure(handles.f_main); +handles.varargin{1} = recSession; + +% Updating GUI +pb_undo_Callback(hObject, eventdata, handles); +set(handles.lb_edit,'Value',pos); +handles = updateRec(handles); +pb_extractFeatures_Callback(hObject, eventdata, handles); + +guidata(hObject, handles); + + +% --- Executes on button press in pb_save. +function pb_save_Callback(hObject, eventdata, handles) +% hObject handle to pb_save (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +mov = get(handles.lb_edit,'String'); +recSession = handles.varargin{1}; +recSession.nM = length(mov); +[~,pos] = ismember(mov,recSession.mov); +recSession.tdata = recSession.tdata(:,:,pos); +recSession.mov = mov; +[filename, pathname] = uiputfile({'*.mat','MAT-files (*.mat)'},'Save as', 'Untitled.mat'); +if isequal(filename,0) || isequal(pathname,0) + disp('User pressed cancel') +else + disp(['User selected ', fullfile(pathname, filename)]) + save([pathname,filename],'recSession'); +end +disp(recSession); + + +% --- Executes on button press in pb_cancel. +function pb_cancel_Callback(hObject, eventdata, handles) +% hObject handle to pb_cancel (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +close(GUI_DataAnalysis); + + +% --- Executes on button press in pb_delete. +function pb_delete_Callback(hObject, eventdata, handles) +% hObject handle to pb_delete (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +selected = get(handles.lb_edit,'Value'); +mov = get(handles.lb_edit,'String'); +movInd = 1:length(mov); +movInd = movInd(~ismember(movInd,selected)); +set(handles.lb_edit,'String',mov(movInd)); +set(handles.lb_edit,'Value',1); +if length(movInd) == 0 + set(handles.lb_edit,'String',{'Empty'}); +end + +% --- Executes on button press in pb_undo. +function pb_undo_Callback(hObject, eventdata, handles) +% hObject handle to pb_undo (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +recSession = handles.varargin{1}; +mov = recSession.mov; +set(handles.lb_edit,'String',mov); + + +% --- Executes on selection change in lb_features. +function lb_features_Callback(hObject, eventdata, handles) +% hObject handle to lb_features (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: contents = cellstr(get(hObject,'String')) returns lb_features contents as cell array +% contents{get(hObject,'Value')} returns selected item from lb_features +ch = get(handles.lb_channels,'Value'); +if length(ch)*length(get(hObject,'Value')) == 1 + if ch == 1 + set(handles.lb_channels,'Value',[ch 2]); + else + set(handles.lb_channels,'Value',[ch 1]); + end +end + + +% --- Executes during object creation, after setting all properties. +function lb_features_CreateFcn(hObject, eventdata, handles) +% hObject handle to lb_features (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: listbox controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + +% --- Executes on selection change in pm_ctp. +function pm_ctp_Callback(hObject, eventdata, handles) +% hObject handle to pm_ctp (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: contents = cellstr(get(hObject,'String')) returns pm_ctp contents as cell array +% contents{get(hObject,'Value')} returns selected item from pm_ctp + + + +% --- Executes during object creation, after setting all properties. +function pm_ctp_CreateFcn(hObject, eventdata, handles) +% hObject handle to pm_ctp (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: popupmenu controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + + +function et_accLimit_Callback(hObject, eventdata, handles) +% hObject handle to et_accLimit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of et_accLimit as text +% str2double(get(hObject,'String')) returns contents of et_accLimit as a double +analysis = get(handles.f_main,'UserData'); +limit = str2double(get(hObject,'String')); +if ~isnan(limit) && isreal(limit) && limit >= 0 && limit <= 100 + analysis = get(handles.f_main,'UserData'); + analysis.limit = limit; + set(handles.f_main,'UserData',analysis); + handles = updatePred(handles); + guidata(hObject, handles); +else + set(hObject,'String',num2str(analysis.limit)); +end + + + +% --- Executes during object creation, after setting all properties. +function et_accLimit_CreateFcn(hObject, eventdata, ~) +% hObject handle to et_accLimit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + +% --- Executes on button press in pb_setLimit. +function pb_setLimit_Callback(hObject, eventdata, handles) +% hObject handle to pb_setLimit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +et_accLimit_Callback(handles.et_accLimit, eventdata, handles) + + +% --- Executes on selection change in lb_channels. +function lb_channels_Callback(hObject, eventdata, handles) +% hObject handle to lb_channels (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: contents = cellstr(get(hObject,'String')) returns lb_channels contents as cell array +% contents{get(hObject,'Value')} returns selected item from lb_channels +ch = get(hObject,'Value'); +if length(ch)*length(get(handles.lb_features,'Value')) == 1 + if ch == 1 + set(hObject,'Value',[ch 2]); + else + set(hObject,'Value',[ch 1]); + end +end + +% --- Executes during object creation, after setting all properties. +function lb_channels_CreateFcn(hObject, eventdata, handles) +% hObject handle to lb_channels (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: listbox controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + +% --- Executes on button press in cb_markedMov. +function cb_markedMov_Callback(hObject, eventdata, handles) +% hObject handle to cb_markedMov (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hint: get(hObject,'Value') returns toggle state of cb_markedMov + +function handles = updatePred(handles) +% updating plots of a_prediction acording to the selected methods +load('preData') +% Settings from GUI +classifierV = get(handles.pm_classifier,'Value'); +classifierS = get(handles.pm_classifier,'String'); +classifier = classifierS{classifierV}; +classifier(classifier == ' ') = '_'; +methodV = get(handles.pm_method,'Value'); +if methodV == 3 + def = 'NNS'; +elseif methodV == 1; + def = 'Mahalanobis_Modified'; +elseif methodV == 2; + def = 'Bhattacharyya'; +end +% Getting data from preData +x = preData.(classifier).(def).values; +y = preData.(classifier).acc; +func = preData.(classifier).(def).func; +exclude = isinf(x) | isnan(x); +x = x(~exclude); +y = y(~exclude); +xlim = min(mean(x)+2*std(x),max(x)); +% Updating a_prediction +cla(handles.a_prediction); +hold(handles.a_prediction, 'on'); +plot(handles.a_prediction,x,y,'.','color',[0.9 0.9 0.9]); +axis(handles.a_prediction,[0 xlim 0 100]); +legend(handles.a_prediction,'hide'); +xlabel(handles.a_prediction,''); +ylabel(handles.a_prediction,''); +set(handles.a_prediction,'XTickLabel',{''},'YTickLabel',{''},'XTick',[],'YTick',[],'layer','top'); +analysis = get(handles.f_main,'UserData'); +m = analysis.selectedMov; +v = 0:xlim/100:xlim; +target = analysis.limit; +accPre = eval(func); +accPre = unique(accPre); +vUnique = v(1:length(accPre)); +limit = interp1(accPre,vUnique,target); +if isnan(limit) + limit = max(x)+v(2); +end +lim = plot(handles.a_prediction,[limit limit],[0 100],'-.','color',[1 0.8 0.8]); +plot(handles.a_prediction,[0 xlim],[target target],'-.','color',[1 0.8 0.8]); +plot(handles.a_prediction,v,eval(func),'r'); +pre = plot(handles.a_prediction,[analysis.mCCE(m) analysis.mCCE(m)],[0 100],'r--'); +analysis.predObj = pre; +analysis.limitObj = lim; +set(handles.am_distances(analysis.mCCE < limit),'XColor',[0.8 0 0],'YColor',[0.8 0 0],'Color',[1 0.7 0.7]) +set(handles.am_distances(~(analysis.mCCE < limit)),'XColor',[0 0 0],'YColor',[0 0 0],'Color',[1 1 1]) +set(handles.f_main,'UserData',analysis); +return + +function handles = updateCCE(handles) +% updating the CCEs acording to the selected methods + +% Check if update is needed +analysis = get(handles.f_main,'UserData'); +methodStr = get(handles.pm_method,'String'); +methodV = get(handles.pm_method,'Value'); +method = methodStr{methodV}; + +if ~strcmp(analysis.method,method); + % Initialization + m = analysis.selectedMov; + recSession = analysis.recSession; + className = recSession.mov{m}; + dPm = handles.am_distances; + data = analysis.anDataM; + [~,nD,nM] = size(data); + neighborCount = zeros(nM,1); + mov = recSession.mov; + chComb = combnk(1:nD,2); % All combinations of 2 channels + chDist = zeros(size(chComb,1),1); + + % finding neighbor class for all movements and classification + % complexity estimations + switch methodV + case 1 + [mCCE,NN] = GetSI(analysis.anDataM); + case 2 + [mCCE,NN] = GetSI(analysis.anDataM,'Bhattacharyya'); + case 3 + [mCCE,NN] = GetNNS(analysis.anDataM); + end + + for m = 1:nM + % Finding most separating channel combination + if NN(m) == 0 + set(dPm(m),'ButtonDownFcn','disp(''no nearest neighbor'')'); + cla(dPm(m)); + else + for ch = 1:size(chComb,1) + switch methodV + case 1 + chDist(ch) = GetDist(data(:,chComb(ch,:),m), data(:,chComb(ch,:),NN(m)),'Mahalanobis Modified'); + case 2 + chDist(ch) = GetDist(data(:,chComb(ch,:),m), data(:,chComb(ch,:),NN(m)),'Bhattacharyya'); + case 3 + chDist(ch) = mean(GetNNS(data(:,chComb(ch,:),[m,NN(m)]))); + end + end + [~,chSort] = sort(chDist); + ch1 = chComb(chSort(end),1); + ch2 = chComb(chSort(end),2); + + %Counting number of conflicts + neighborCount(m) = sum(NN == m); + + %ploting + cla(dPm(m)); + hold(dPm(m),'on'); + plot(dPm(m),data(:,ch1,m),data(:,ch2,m),'r.'); + plot(dPm(m),data(:,ch1,NN(m)),data(:,ch2,NN(m)),'b.'); + children = allchild(dPm(m)); + set(dPm(m),'ButtonDownFcn',@(hObject,eventdata)GUI_DataAnalysis('am_distances_ButtonDownFcn',hObject,eventdata,guidata(hObject),m)); + set(children,'ButtonDownFcn',get(dPm(m),'ButtonDownFcn')); + drawnow; + end + end + + % Saving data in handles + NN(NN == 0) = 1; % Fix for situations with no NN + analysis.neighborName = mov(NN); + analysis.neighborCount = neighborCount; + analysis.utContent(:,2) = num2cell(neighborCount); + set(handles.f_main,'UserData',analysis); + analysis.mCCE = mCCE; + analysis.method = method; + + %updating conflict table + analysis.utContent(:,3) = num2cell(mCCE); + [~,nSort] = sort(analysis.neighborCount,'descend'); + set(handles.ut_conflict,'Data',analysis.utContent(nSort,:)); + set(handles.ut_conflict,'RowName',nSort); + legend(handles.a_distance,{[className ' (Conserned Movement)'],[analysis.neighborName{m} ' (Closest Neighbor)'], [method ' : ' num2str(analysis.mCCE(m),2)]}); + set(handles.f_main,'UserData',analysis); +end +return + +function handles = updateRec(handles) + +% Clearing old Data Analysis +if isfield(handles,'am_distances') + delete(handles.am_distances(:)); + handles = rmfield(handles,'am_distances'); +end +cla(handles.a_prediction); +cla(handles.a_distance); +set(handles.a_distance,'Visible','off'); +delete(findall(handles.f_main,'Tag','legend')) + +% initilazing +analysis = get(handles.f_main,'UserData'); +analysis.selectedMov = 1; +if isfield(analysis,'predObj') + analysis = rmfield(analysis,'predObj'); +end + +recSession = handles.varargin{1}; +mov = get(handles.lb_edit,'String'); +recSession.tdata = recSession.tdata(:,:,ismember(mov,recSession.mov)); +recSession.nM = length(mov)+1; +mov{recSession.nM} = 'Rest'; +recSession.mov = mov; +analysis.recSession = recSession; + +% Create movement axes matrix +dim2 = ceil(sqrt(recSession.nM)); +dim1 = ceil(recSession.nM/dim2); +dPm = tight_subplot_inObject(dim1,dim2,[.01 .01],[.01 .01],[.01 .01],handles.up_distances); +delete(dPm(recSession.nM+1:end)); +for m = 1:recSession.nM + set(dPm(m),'XTick',[],'YTick',[],'Box','on','ButtonDownFcn',@(hObject,eventdata)GUI_DataAnalysis('am_distances_ButtonDownFcn',hObject,eventdata,guidata(hObject),m)); + handles.am_distances(m) = dPm(m); +end +utContent = cell(recSession.nM,3); +utContent(1:recSession.nM,1) = mov; +analysis.utContent = utContent; +set(handles.ut_conflict,'Data',utContent); +set(handles.ut_conflict,'RowName',1:recSession.nM); +set(handles.f_main,'UserData',analysis); +return diff --git a/DataAnalysis/GetAnalysisFeatures.m b/DataAnalysis/GetAnalysisFeatures.m new file mode 100644 index 0000000..23a98b3 --- /dev/null +++ b/DataAnalysis/GetAnalysisFeatures.m @@ -0,0 +1,88 @@ +% ---------------------------- Copyright Notice --------------------------- +% This file is part of BioPatRec ? which is open and free software under +% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for +% the full license governing this code and copyrights. +% +% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and +% Chalmers University of Technology. All authors contributions must be kept +% acknowledged below in the section "Updates & Contributors". +% +% Would you like to contribute to science and sum efforts to improve +% amputees? quality of life? Join this project! or, send your comments to: +% maxo@chalmers.se. +% +% The entire copyright notice must be kept in this or any source file +% linked to BioPatRec. This will ensure communication with all authors and +% acknowledge contributions here and in the project web page (optional). +% +% -------------------------- Function Description ------------------------- +% Returns a data package of feature vectors ready for GUI_DataAnalysis given a +% recSession, contraction time presentage (cTp) and a cell array of feature +% names. +% ------------------------- Updates & Contributors ------------------------ +% [Contributors are welcome to add their email] +% 2016-02-18 / Niclas Nilsson / Creation nilsson007@gmail.com +% 20xx-xx-xx / Author / Comment on update + +function anDataM = GetAnalysisFeatures(recSession,fID,cTp) +% Setting parameters + +sF = recSession.sF; +cT = recSession.cT; +rT = recSession.rT; +nR = recSession.nR; +nCh = recSession.nCh; +mov = recSession.mov; +allData = recSession.tdata; +nM = recSession.nM; + +nS = size(allData,1); % number of samples +tWS = round(0.2 * sF); % Time window samples, considering tw of 200 ms +overlapS = round(0.05 * sF); % Overlap samples considering 50 ms +randTW = false; % Random time windows +rSR = 0.3; % Random samples ratio +%% Extracting contraction data +margin = 1 + round((1-cTp)/2*cT*sF); +nonRest = []; +for r = 1:nR + nonRest = [nonRest round(((r-1)*(cT+rT)*sF+margin)):round(((r-1)*(cT+rT)*sF+(cT*sF-margin)))]; +end +trData = allData(nonRest,:,:); +%% Adding rest +tmpTreated.trData = trData; +tmpTreated.nM = nM-1; +tmpSession = recSession; +tmpSession.nM = nM-1; +tmpTreated.mov = mov(1:end-1); +tmpTreated = AddRestAsMovement(tmpTreated, tmpSession); +trData = tmpTreated.trData; +%% Extracting Features +tWStarts = 1 : overlapS : size(trData,1)-tWS; +if randTW + % random windows are selected + nRS = floor(length(tWStarts)*rSR); + rS = randi(length(tWStarts),nRS); + tWStarts = tWStarts(rS); +end +tS = length(tWStarts); +% Starting waitbar -------------------------------------% +h=waitbar(0,'Extracting Features'); +w = 1; +maxW = nM * tS * length(fID) + nCh; +% Movement Analysis Data--------------------------------% +anDataM = zeros(tS,length(fID)*nCh,nM); +%-------------------------------------------------------% +for m = 1:nM + ind = 1; + for i = tWStarts + tmpTreated = GetSigFeatures(trData(i:i+tWS-1,:,m), sF, fID); + for f = 1:length(fID) + tmpF = tmpTreated.(fID{f}); + anDataM(ind,(f-1)*nCh+1:(f-1)*nCh+nCh,m) = tmpF; + waitbar(w/maxW); + w = w + 1; + end + ind = ind + 1; + end +end +close(h); \ No newline at end of file diff --git a/DataAnalysis/GetDist.m b/DataAnalysis/GetDist.m new file mode 100644 index 0000000..f1c3cce --- /dev/null +++ b/DataAnalysis/GetDist.m @@ -0,0 +1,57 @@ +% ---------------------------- Copyright Notice --------------------------- +% This file is part of BioPatRec ? which is open and free software under +% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for +% the full license governing this code and copyrights. +% +% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and +% Chalmers University of Technology. All authors? contributions must be kept +% acknowledged below in the section "Updates % Contributors". +% +% Would you like to contribute to science and sum efforts to improve +% amputees? quality of life? Join this project! or, send your comments to: +% maxo@chalmers.se. +% +% The entire copyright notice must be kept in this or any source file +% linked to BioPatRec. This will ensure communication with all authors and +% acknowledge contributions here and in the project web page (optional). +% +% -------------------------- Function Description ------------------------- +% This function recieves dataM and dataC form two movements and returns +% the distance between the movements according to the statistical +% similarity measure recieves as def. +% ------------------------- Updates & Contributors ------------------------ +% [Contributors are welcome to add their email] +% 2015-09-23 / Niclas Nilsson / Created Feature evaluation +% 20xx-xx-xx / Author / Comment on update +function dist = GetDist(dataM, dataC, def) +load('offsets'); +nD = size(dataM,2); %number of dimensions +switch def + case 'Bhattacharyya' + % Shown to be highly correlated with MLP-accuracy. + tMeans = mean(dataM)-mean(dataC); + tCov = (cov(dataM)+cov(dataC))./2; + dist = sqrt(tMeans/tCov*tMeans'./8 + log(det(tCov)/sqrt(det(cov(dataM))*det(cov(dataC))))/2)-sum(Bhattacharyya(1:nD-1)); + case 'Mahalanobis Modified' + % Shown to be highly correlated with LDA-accuracy. + tMeans = mean(dataM)-mean(dataC); + tCov = (cov(dataM)+cov(dataC))./2; + dist = sqrt(tMeans/tCov*tMeans')/2-sum(MahalanobisModified(1:nD-1)); + case 'Kullback-Leibler' + % Not found very usefull + tMeans = mean(dataM)-mean(dataC); + dist = (trace(cov(dataC)\cov(dataM))+tMeans/cov(dataC)*tMeans'-length(dataM(1,:)+log(det(cov(dataC))/det(cov(dataM)))))/2; + case 'Hellinger' + % Shown to be highly correlated with MLP-accuracy. + % Not compensated for dimenesional dependency. + % Usefull when comparing data with equal dimensionality. + tCov = (cov(dataM)+cov(dataC))./2; + tMeans = mean(dataM)-mean(dataC); + dist = 1-det(cov(dataM))^(1/4)*det(cov(dataC))^(1/4)/(det(tCov)^(1/2))*exp(-(tMeans/tCov*tMeans')/8); + case 'Mahalanobis' + % -0.02 is compensation for dimenesional dependency. + tMeans = mean(dataM)-mean(dataC); + dist = sqrt(tMeans/cov(dataM)*tMeans')/2; + case 'Mutual Information' + dist = log((2*pi*exp(1))^nD*det(cov(dataM)))/2 + log((2*pi*exp(1))^nD*det(cov(dataC)))/2 - log((2*pi*exp(1))^(nD*2)*det(cov([dataM dataC])))/2; +end \ No newline at end of file diff --git a/DataAnalysis/GetNNS.m b/DataAnalysis/GetNNS.m new file mode 100644 index 0000000..2614cc5 --- /dev/null +++ b/DataAnalysis/GetNNS.m @@ -0,0 +1,92 @@ +% ---------------------------- Copyright Notice --------------------------- +% This file is part of BioPatRec ? which is open and free software under +% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for +% the full license governing this code and copyrights. +% +% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and +% Chalmers University of Technology. All authors? contributions must be kept +% acknowledged below in the section "Updates % Contributors". +% +% Would you like to contribute to science and sum efforts to improve +% amputees? quality of life? Join this project! or, send your comments to: +% maxo@chalmers.se. +% +% The entire copyright notice must be kept in this or any source file +% linked to BioPatRec. This will ensure communication with all authors and +% acknowledge contributions here and in the project web page (optional). +% +% -------------------------- Function Description ------------------------- +% Function recieving data and calculates the Nearest Neighbor Seperability for that +% data. +% ------------------------- Updates & Contributors ------------------------ +% [Contributors are welcome to add their email] +% 2015-09-23 / Niclas Nilsson / Created Feature evaluation +% 20xx-xx-xx / Author / Comment on update +function [NNS,NN] = GetNNS(data,varargin) + +%Initialization +[nS,nD,nM] = size(data); +dataR = zeros(nD, nM*nS); +findNN = false; +NNS = zeros(nM,1); % Nearest Neighbor Separability +if nargout > 1 + NNs = zeros(nS*(nS-1),nM); % Nearest Neighbors + NN = zeros(nM,1); % Nearest Neighbor + ind = ones(nM,1); % starts NNs + findNN = true; +end + +if ~isempty(varargin) + k = varargin{1}; +else + k = nS - 1; % maximume number of nearest neighbors from the same class +end + +weights = 1./(1:k); % vector of weights +normFactor = 1/sum(1./(1:k)); % used to normalize result to value between 0-1 + +%Reshaping data to fit purpuse +for m = 1:nM + dataR(:,(((m-1)*nS+1):((m-1)*nS+nS))) = data(:,:,m)'; +end + +% Normalizing +dataR = normr(dataR); + + +%Iterating over feature data point +for p = 1:(nM*nS) + %Producing distance vector + pDist = sum((dataR(:,p)*ones(1,nM*nS)-dataR).^2).^(1/2); + [~,pSort] = sort(pDist); + % Saving value for point p for p's class + mNN = ceil(pSort(2:k+1)./nS); + m = ceil(p/nS); + NNS(m) = NNS(m) + sum((mNN == m).*weights)*normFactor; + if findNN + NNs(ind(m):k+ind(m)-1,m) = mNN; + ind(m) = ind(m) + k; + end +end +NNS = NNS./nS; +if findNN + wNN = repmat(weights',nM*nS,1); % weigth vector for all NNs + [tNNs,indNN] = sort(NNs); + for m = 1:nM + tWNN = wNN(indNN(:,m)); % weigths are connected to movement indecies + [mem,inMem] = unique(tNNs(:,m),'last'); % finding limits for movement groups + oldInd = 0; + nMem = zeros(size(inMem)); + for i = 1:length(inMem) + nMem(i) = sum(tWNN(oldInd+1:inMem(i))); % summing all weights for all movements + oldInd = inMem(i); + end + nMem = nMem(mem ~= m); % Removing movement that is being evaluated + mem = mem(mem ~= m); + if ~isempty(nMem) + [~,mInd] = max(nMem); % Movements with highest sum of weights is selected as NN + NN(m) = mem(mInd); + end + end +end +return \ No newline at end of file diff --git a/DataAnalysis/GetSI.m b/DataAnalysis/GetSI.m new file mode 100644 index 0000000..2789cfa --- /dev/null +++ b/DataAnalysis/GetSI.m @@ -0,0 +1,48 @@ +% ---------------------------- Copyright Notice --------------------------- +% This file is part of BioPatRec ? which is open and free software under +% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for +% the full license governing this code and copyrights. +% +% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and +% Chalmers University of Technology. All authors? contributions must be kept +% acknowledged below in the section "Updates % Contributors". +% +% Would you like to contribute to science and sum efforts to improve +% amputees? quality of life? Join this project! or, send your comments to: +% maxo@chalmers.se. +% +% The entire copyright notice must be kept in this or any source file +% linked to BioPatRec. This will ensure communication with all authors and +% acknowledge contributions here and in the project web page (optional). +% +% -------------------------- Function Description ------------------------- +% Function recieving data and calculates the Separability Index for that +% data. +% ------------------------- Updates & Contributors ------------------------ +% [Contributors are welcome to add their email] +% 2015-09-23 / Niclas Nilsson / Created +% 20xx-xx-xx / Author / Comment on update +function [SI,NN] = GetSI(data,varargin) +if isempty(varargin) + dist = 'Mahalanobis Modified'; +else + dist = varargin{1}; +end +% Initialization +[~,~,nM] = size(data); +SI = zeros(nM,1); +NN = zeros(nM,1); +%iteration over all movements +for m = 1 : nM + tM = 1:nM; + tM = tM(tM ~= m); % list of all movements except the taget movement + tIndex = 1; + SIs = zeros((nM-1),1); + % Listing all distances in SIs + for t = tM + SIs(tIndex) = GetDist(data(:,:,m),data(:,:,t),dist); + tIndex = 1 + tIndex; + end + [SI(m),iMin] = min(SIs); % The minimume value of tSIs is the distance to the closesed movement... + NN(m) = tM(iMin); +end \ No newline at end of file diff --git a/DataAnalysis/offsets.mat b/DataAnalysis/offsets.mat new file mode 100644 index 0000000..529de31 Binary files /dev/null and b/DataAnalysis/offsets.mat differ diff --git a/DataAnalysis/preData.mat b/DataAnalysis/preData.mat new file mode 100644 index 0000000..57ef35a Binary files /dev/null and b/DataAnalysis/preData.mat differ diff --git a/DataAnalysis/tight_subplot_inObject.m b/DataAnalysis/tight_subplot_inObject.m new file mode 100644 index 0000000..803616a --- /dev/null +++ b/DataAnalysis/tight_subplot_inObject.m @@ -0,0 +1,74 @@ +function ha = tight_subplot_inObject(Nh, Nw, gap, marg_h, marg_w, lim_object) + +% tight_subplot creates "subplot" axes with adjustable gaps and margins +% +% ha = tight_subplot(Nh, Nw, gap, marg_h, marg_w) +% +% in: Nh number of axes in hight (vertical direction) +% Nw number of axes in width (horizontaldirection) +% gap gaps between the axes in normalized units (0...1) +% or [gap_h gap_w] for different gaps in height and width +% marg_h margins in height in normalized units (0...1) +% or [lower upper] for different lower and upper margins +% marg_w margins in width in normalized units (0...1) +% or [left right] for different left and right margins +% +% out: ha array of handles of the axes objects +% starting from upper left corner, going row-wise as in +% going row-wise as in +% +% Example: ha = tight_subplot(3,2,[.01 .03],[.1 .01],[.01 .01]) +% for ii = 1:6; axes(ha(ii)); plot(randn(10,ii)); end +% set(ha(1:4),'XTickLabel',''); set(ha,'YTickLabel','') + +% Pekka Kumpulainen 20.6.2010 @tut.fi +% Tampere University of Technology / Automation Science and Engineering + + +if nargin<3; gap = .02; end +if nargin<4 || isempty(marg_h); marg_h = .05; end +if nargin<5; marg_w = .05; end + +if numel(gap)==1; + gap = [gap gap]; +end +if numel(marg_w)==1; + marg_w = [marg_w marg_w]; +end +if numel(marg_h)==1; + marg_h = [marg_h marg_h]; +end + +set(lim_object,'Units','pixels'); +position = get(lim_object,'Position'); +ox = position(1); +oy = position(2); +ow = position(3); +oh = position(4); + +axh = (1-sum(marg_h)-(Nh-1)*gap(1))/Nh; +axw = (1-sum(marg_w)-(Nw-1)*gap(2))/Nw; + +py = 1-marg_h(2)-axh; + +ha = zeros(Nh*Nw,1); +ii = 0; +for ih = 1:Nh + px = marg_w(1); + + for ix = 1:Nw + ii = ii+1; + % ha(ii) = axes('Units','pixels', ... + % 'Position',[ox+px*ow oy+py*oh ow*axw oh*axh], ... + % 'XTickLabel','', ... + % 'YTickLabel',''); + ha(ii) = axes('Units','normalized', ... + 'Position',[px py axw axh], ... + 'XTickLabel','', ... + 'YTickLabel','',... + 'Parent',lim_object); + px = px+axw+gap(2); + end + py = py-axh-gap(1); +end +%lim_object.Visible = 'off'; diff --git a/GUI_BioPatRec.fig b/GUI_BioPatRec.fig index 9193689..6b97637 100644 Binary files a/GUI_BioPatRec.fig and b/GUI_BioPatRec.fig differ diff --git a/Img/Ankle Dorsiflexion.jpg b/Img/Ankle Dorsiflexion.jpg new file mode 100644 index 0000000..672cd24 Binary files /dev/null and b/Img/Ankle Dorsiflexion.jpg differ diff --git a/Img/Ankle Eversion.jpg b/Img/Ankle Eversion.jpg new file mode 100644 index 0000000..00f225d Binary files /dev/null and b/Img/Ankle Eversion.jpg differ diff --git a/Img/Ankle Inversion.jpg b/Img/Ankle Inversion.jpg new file mode 100644 index 0000000..4a11d56 Binary files /dev/null and b/Img/Ankle Inversion.jpg differ diff --git a/Img/Ankle Plantarflexion.jpg b/Img/Ankle Plantarflexion.jpg new file mode 100644 index 0000000..5f60bc9 Binary files /dev/null and b/Img/Ankle Plantarflexion.jpg differ diff --git a/Img/Big Ext.jpg b/Img/Big Ext.jpg new file mode 100644 index 0000000..7fa5b78 Binary files /dev/null and b/Img/Big Ext.jpg differ diff --git a/Img/Big Flex.jpg b/Img/Big Flex.jpg new file mode 100644 index 0000000..67de3bc Binary files /dev/null and b/Img/Big Flex.jpg differ diff --git a/Img/Curl Toes.jpg b/Img/Curl Toes.jpg new file mode 100644 index 0000000..666d962 Binary files /dev/null and b/Img/Curl Toes.jpg differ diff --git a/Img/Extend Knee.jpg b/Img/Extend Knee.jpg new file mode 100644 index 0000000..8f444c0 Binary files /dev/null and b/Img/Extend Knee.jpg differ diff --git a/Img/Femoral Rotation in.jpg b/Img/Femoral Rotation in.jpg new file mode 100644 index 0000000..faa2656 Binary files /dev/null and b/Img/Femoral Rotation in.jpg differ diff --git a/Img/Femoral Rotation out.jpg b/Img/Femoral Rotation out.jpg new file mode 100644 index 0000000..69997dd Binary files /dev/null and b/Img/Femoral Rotation out.jpg differ diff --git a/Img/Flex Knee.jpg b/Img/Flex Knee.jpg new file mode 100644 index 0000000..aaef53a Binary files /dev/null and b/Img/Flex Knee.jpg differ diff --git a/Img/RelaxLeg.jpg b/Img/RelaxLeg.jpg new file mode 100644 index 0000000..41d3385 Binary files /dev/null and b/Img/RelaxLeg.jpg differ diff --git a/Img/Stretch Toes.jpg b/Img/Stretch Toes.jpg new file mode 100644 index 0000000..eb83852 Binary files /dev/null and b/Img/Stretch Toes.jpg differ diff --git a/Img/Tibial Rotation in.jpg b/Img/Tibial Rotation in.jpg new file mode 100644 index 0000000..5e73c4e Binary files /dev/null and b/Img/Tibial Rotation in.jpg differ diff --git a/Img/Tibial Rotation out.jpg b/Img/Tibial Rotation out.jpg new file mode 100644 index 0000000..ced0aef Binary files /dev/null and b/Img/Tibial Rotation out.jpg differ diff --git a/Img/noImage.png b/Img/noImage.png new file mode 100644 index 0000000..2160114 Binary files /dev/null and b/Img/noImage.png differ diff --git a/PatRec/GUI_PatRec.fig b/PatRec/GUI_PatRec.fig index 41cee37..b618366 100644 Binary files a/PatRec/GUI_PatRec.fig and b/PatRec/GUI_PatRec.fig differ diff --git a/PatRec/GUI_PatRec.m b/PatRec/GUI_PatRec.m index f781ab0..3e7df1a 100644 --- a/PatRec/GUI_PatRec.m +++ b/PatRec/GUI_PatRec.m @@ -23,7 +23,8 @@ % 2014-11-07 / Diep Khong / Added SVM % 2014-12-01 / Enzo Mastinu / Added the handling part for the COM port number % information into the parameters -% 20xx-xx-xx / Author / Comment on update +% 2015-04-29 / Cosima P. / Addition of NetLab +% 20xx-xx-xx / Author / Comment on update function varargout = GUI_PatRec(varargin) % GUI_PATREC M-file for GUI_PatRec.fig @@ -49,7 +50,7 @@ % Edit the above text to modify the response to help GUI_PatRec -% Last Modified by GUIDE v2.5 30-Oct-2013 10:35:30 +% Last Modified by GUIDE v2.5 24-Jun-2015 15:57:15 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; @@ -138,6 +139,12 @@ function pb_GetFeatures_Callback(hObject, eventdata, handles) set(handles.rb_top2,'Enable','on'); set(handles.rb_top3,'Enable','on'); set(handles.rb_top4,'Enable','on'); + + elseif (exist('recSessionFeatures','var')) % Get sig_Features + Load_recSessionFeatures(recSessionFeatures, handles); + %Enable algorithm selection + set(handles.pm_SelectAlgorithm,'Enable','on'); + set(handles.pb_RunOfflineTraining,'Enable','on'); elseif (exist('sigFeatures','var')) % Get sig_Features Load_sigFeatures(sigFeatures, handles); @@ -373,7 +380,6 @@ function pb_RunOfflineTraining_Callback(hObject, eventdata, handles) set(handles.et_trTime,'String',num2str(patRec.trTime)); set(handles.et_tTime,'String',num2str(patRec.tTime)); - set(handles.pb_RealtimePatRecGUI,'Enable','on'); set(handles.pb_RealtimePatRecMov2Mov,'Enable','on'); set(handles.t_msg,'String','Off-line Training Completed'); disp(patRec); @@ -448,6 +454,15 @@ function pm_SelectAlgorithm_Callback(hObject, eventdata, handles) set(handles.pm_SelectTraining,'Value',1); set(handles.pb_RunOfflineTraining,'Enable','on'); set(handles.pm_normSets,'Value',4); + + elseif strcmp(alg,'NetLab MLP') || ... % for NetLab MLP + strcmp(alg,'NetLab GLM') % for NetLab GLM + set(handles.pm_SelectTraining,'Enable','on'); + tA = {'Select Out Func','softmax','linear','logistic','proportional','proportional logistic'}; + set(handles.pm_SelectTraining,'String',tA); + set(handles.pb_RunOfflineTraining,'Enable','off'); + set(handles.pm_normSets,'Value',4); + end @@ -2173,3 +2188,27 @@ function et_accTrue_CreateFcn(hObject, eventdata, handles) if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor','white'); end + + +% -------------------------------------------------------------------- +function m_ALC_Callback(hObject, eventdata, handles) +% hObject handle to m_ALC (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + + +% -------------------------------------------------------------------- +function m_ALC_upload_Callback(hObject, eventdata, handles) +% hObject handle to m_ALC_upload (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +if isfield(handles,'patRec') + if strcmp(handles.patRec.patRecTrained.algorithm, 'DA') + UpdateCoefficientsALCD(handles); + else + set(handles.t_msg,'String','No DA found. No data uploaded'); + end +else + set(handles.t_msg,'String','No patRec found. No data uploaded'); +end diff --git a/PatRec/GUI_TacTest.fig b/PatRec/GUI_TacTest.fig index c6075f3..50a4715 100644 Binary files a/PatRec/GUI_TacTest.fig and b/PatRec/GUI_TacTest.fig differ diff --git a/PatRec/GUI_TacTest.m b/PatRec/GUI_TacTest.m index 7b87969..5e7c941 100644 --- a/PatRec/GUI_TacTest.m +++ b/PatRec/GUI_TacTest.m @@ -53,7 +53,7 @@ % Edit the above text to modify the response to help GUI_TacTest -% Last Modified by GUIDE v2.5 18-Jul-2012 14:18:17 +% Last Modified by GUIDE v2.5 03-Dec-2015 15:21:04 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; @@ -86,6 +86,17 @@ function GUI_TacTest_OpeningFcn(hObject, eventdata, handles, varargin) % Choose default command line output for GUI_TacTest handles.output = hObject; +% SMC test support variables +handles.SMCtestEnabled = 0; +if isfield(handles,'cb_enableSMCtest') + handles.SMCtestSerial = []; + handles.SMCTargetStep = 10; % step between targets + handles.SMCMaxVibIdx = 13; + handles.SMCMaxVibInt = 15; + handles.SMCVibduration = 20; % ms/10 + handles.SMCposition = 0; +end + % Update handles structure guidata(hObject, handles); @@ -258,15 +269,29 @@ function pb_start_Callback(hObject, eventdata, handles) handles.dofs = 1; end +% patRec = handles.patRecHandles.patRec; +% handles.vre_Com = handles.patRecHandles.vre_Com; +% handles.movList = handles.patRecHandles.movList; +% set(handles.txt_status,'String','Starting TAC'); +% TACTest(patRec,handles); +% set(handles.txt_status,'String','Finished TAC'); + +% TEST ALCD patRec = handles.patRecHandles.patRec; handles.vre_Com = handles.patRecHandles.vre_Com; handles.movList = handles.patRecHandles.movList; set(handles.txt_status,'String','Starting TAC'); -TACTest(patRec,handles); +if isfield(handles.patRecHandles,'cb_ALCD') + if get(handles.patRecHandles.cb_ALCD,'Value') == 1 + TACTestALCD(patRec, handles); + else + TACTest(patRec,handles); + end +else + TACTest(patRec,handles); +end set(handles.txt_status,'String','Finished TAC'); - - function tb_allowance_Callback(hObject, eventdata, handles) % hObject handle to tb_allowance (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB @@ -309,3 +334,117 @@ function tb_time_CreateFcn(hObject, eventdata, handles) if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor','white'); end + +% --- Executes on selection change in pm_serialsel. +function pm_SMCselectserial_Callback(hObject, eventdata, handles) +% hObject handle to pm_serialsel (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: contents = cellstr(get(hObject,'String')) returns pm_serialsel contents as cell array +% contents{get(hObject,'Value')} returns selected item from pm_serialsel +COMportIdx = get(hObject,'Value'); +COMport = get(hObject,'String'); +COMport = COMport{COMportIdx}; +BitsN = 8; +SBits = 1; +Parity = 'none'; +TimeOut = 0.5; +BaudRate = 19200; +InputBufferSize = 1000; +OutputBufferSize = 500; + +% Open serial port +if ~isempty(handles.SMCtestSerial) % if already opened, close it + fclose(handles.SMCtestSerial); + delete(handles.SMCtestSerial); + handles.SMCtestSerial = []; +end +handles.SMCtestSerial = serial(COMport,'BaudRate', BaudRate,... + 'DataBits', BitsN, 'StopBits', SBits, 'Parity', Parity,... + 'Timeout', TimeOut, 'InputBufferSize', InputBufferSize,... + 'OutputBufferSize', OutputBufferSize); + +fopen(handles.SMCtestSerial); +set(handles.pb_start,'Enable','on'); + +guidata(hObject,handles); + + +% --- Executes during object creation, after setting all properties. +function cb_enableSMCtest_CreateFcn(hObject, eventdata, handles) %#ok<*INUSD> +% hObject handle to pm_serialsel (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: popupmenu controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + +% --- Executes on selection change in pm_serialsel. +function cb_enableSMCtest_Callback(hObject, eventdata, handles) +% hObject handle to pm_serialsel (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: contents = cellstr(get(hObject,'String')) returns pm_serialsel contents as cell array +% contents{get(hObject,'Value')} returns selected item from pm_serialsel + +if(get(hObject,'Value')) + set(handles.pm_SMCselectserial,'Enable','on'); + handles.SMCtestEnabled = 1; + if isempty(handles.SMCtestSerial) + set(handles.pb_start,'Enable','off'); + else + set(handles.pb_start,'Enable','on'); + end +else + set(handles.pm_SMCselectserial,'Enable','off'); + set(handles.pb_start,'Enable','on'); + handles.SMCtestEnabled = 0; +end + +guidata(hObject,handles); + + +% --- Executes during object creation, after setting all properties. +function pm_SMCselectserial_CreateFcn(hObject, eventdata, handles) %#ok<*INUSD> +% hObject handle to pm_serialsel (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: popupmenu controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + +% list all serial ports available +Serial = instrhwinfo('serial'); +if ~isempty(Serial.AvailableSerialPorts) + serialportlist = Serial.SerialPorts; + set(hObject,'String',serialportlist); +else + set(hObject,'String','None Available'); +end + + +% --- Executes when user attempts to close figure1. +function figure1_CloseRequestFcn(hObject, eventdata, handles) +% hObject handle to figure1 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +if ~isempty(handles.SMCtestSerial) + fclose(handles.SMCtestSerial); + delete(handles.SMCtestSerial); + handles.SMCtestSerial = []; +end + +% Hint: delete(hObject) closes the figure +delete(hObject); + +function figure1_DeleteFcn(hObject, eventdata, handles) diff --git a/PatRec/GUI_TestPatRec.fig b/PatRec/GUI_TestPatRec.fig deleted file mode 100644 index 3610961..0000000 Binary files a/PatRec/GUI_TestPatRec.fig and /dev/null differ diff --git a/PatRec/GUI_TestPatRec.m b/PatRec/GUI_TestPatRec.m deleted file mode 100644 index 5f84d39..0000000 --- a/PatRec/GUI_TestPatRec.m +++ /dev/null @@ -1,1774 +0,0 @@ -% ---------------------------- Copyright Notice --------------------------- -% This file is part of BioPatRec © which is open and free software under -% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for -% the full license governing this code and copyrights. -% -% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and -% Chalmers University of Technology. All authors’ contributions must be kept -% acknowledged below in the section "Updates % Contributors". -% -% Would you like to contribute to science and sum efforts to improve -% amputees’ quality of life? Join this project! or, send your comments to: -% maxo@chalmers.se. -% -% The entire copyright notice must be kept in this or any source file -% linked to BioPatRec. This will ensure communication with all authors and -% acknowledge contributions here and in the project web page (optional). -% -% -------------------------- Function Description ------------------------- -% Compute the overal all Accuracy of the patRec algorithm -% -% ------------------------- Updates & Contributors ------------------------ -% 2011-12-07 / Max Ortiz / Created new version from EMG_AQ -% 20xx-xx-xx / Author / Comment on update - -function varargout = GUI_TestPatRec(varargin) -%GUI_TESTPATREC M-file for GUI_TestPatRec.fig -% GUI_TESTPATREC, by itself, creates a new GUI_TESTPATREC or raises the existing -% singleton*. -% -% H = GUI_TESTPATREC returns the handle to a new GUI_TESTPATREC or the handle to -% the existing singleton*. -% -% GUI_TESTPATREC('Property','Value',...) creates a new GUI_TESTPATREC using the -% given property value pairs. Unrecognized properties are passed via -% varargin to GUI_TestPatRec_OpeningFcn. This calling syntax produces a -% warning when there is an existing singleton*. -% -% GUI_TESTPATREC('CALLBACK') and GUI_TESTPATREC('CALLBACK',hObject,...) call the -% local function named CALLBACK in GUI_TESTPATREC.M with the given input -% arguments. -% -% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one -% instance to run (singleton)". -% -% See also: GUIDE, GUIDATA, GUIHANDLES - -% Edit the above text to modify the response to help GUI_TestPatRec - -% Last Modified by GUIDE v2.5 07-Mar-2012 16:35:05 - -% Begin initialization code - DO NOT EDIT -gui_Singleton = 1; -gui_State = struct('gui_Name', mfilename, ... - 'gui_Singleton', gui_Singleton, ... - 'gui_OpeningFcn', @GUI_TestPatRec_OpeningFcn, ... - 'gui_OutputFcn', @GUI_TestPatRec_OutputFcn, ... - 'gui_LayoutFcn', [], ... - 'gui_Callback', []); -if nargin && ischar(varargin{1}) - gui_State.gui_Callback = str2func(varargin{1}); -end - -if nargout - [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); -else - gui_mainfcn(gui_State, varargin{:}); -end -% End initialization code - DO NOT EDIT - - -% --- Executes just before GUI_TestPatRec is made visible. -function GUI_TestPatRec_OpeningFcn(hObject, eventdata, handles, varargin) -% This function has no output args, see OutputFcn. -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -% varargin unrecognized PropertyName/PropertyValue pairs from the -% command line (see VARARGIN) - -% Logo image -backgroundImage2 = importdata('/../Img/BioPatRec.png'); -%select the axes -axes(handles.axes1); -%place image onto the axes -image(backgroundImage2); -%remove the axis tick marks -axis off - -% Choose default command line output for GUI_TestPatRec -handles.output = hObject; -global TAC - -TAC.running = 0; -TAC.ackTimes = 0; -% Update handles structure -guidata(hObject, handles); - -% UIWAIT makes GUI_TestPatRec wait for user response (see UIRESUME) -% uiwait(handles.figure1); - - -% --- Outputs from this function are returned to the command line. -function varargout = GUI_TestPatRec_OutputFcn(hObject, eventdata, handles) -% varargout cell array for returning output args (see VARARGOUT); -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Get default command line output from handles structure -varargout{1} = handles.output; - - - -function pm_SelectAlgorithm_Callback(hObject, eventdata, handles) -% hObject handle to pm_SelectAlgorithm (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of pm_SelectAlgorithm as text -% str2double(get(hObject,'String')) returns contents of pm_SelectAlgorithm as a double - - -% --- Executes during object creation, after setting all properties. -function pm_SelectAlgorithm_CreateFcn(hObject, eventdata, handles) -% hObject handle to pm_SelectAlgorithm (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function pm_SelectTraining_Callback(hObject, eventdata, handles) -% hObject handle to pm_SelectTraining (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of pm_SelectTraining as text -% str2double(get(hObject,'String')) returns contents of pm_SelectTraining as a double - - -% --- Executes during object creation, after setting all properties. -function pm_SelectTraining_CreateFcn(hObject, eventdata, handles) -% hObject handle to pm_SelectTraining (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on selection change in lb_movements. -function lb_movements_Callback(hObject, eventdata, handles) -% hObject handle to lb_movements (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: contents = cellstr(get(hObject,'String')) returns lb_movements contents as cell array -% contents{get(hObject,'Value')} returns selected item from lb_movements - -disp(get(hObject,'Value')); - - - -% --- Executes during object creation, after setting all properties. -function lb_movements_CreateFcn(hObject, eventdata, handles) -% hObject handle to lb_movements (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: listbox controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_accuracy_Callback(hObject, eventdata, handles) -% hObject handle to et_accuracy (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_accuracy as text -% str2double(get(hObject,'String')) returns contents of et_accuracy as a double - - -% --- Executes during object creation, after setting all properties. -function et_accuracy_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_accuracy (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on selection change in lb_accuracy. -function lb_accuracy_Callback(hObject, eventdata, handles) -% hObject handle to lb_accuracy (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: contents = cellstr(get(hObject,'String')) returns lb_accuracy contents as cell array -% contents{get(hObject,'Value')} returns selected item from lb_accuracy - - -% --- Executes during object creation, after setting all properties. -function lb_accuracy_CreateFcn(hObject, eventdata, handles) -% hObject handle to lb_accuracy (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: listbox controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in pb_RealtimePatRec. -function pb_RealtimePatRec_Callback(hObject, eventdata, handles) -% hObject handle to pb_RealtimePatRec (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -%set(hObject,'Enable','off'); - % validation of patRec loaded - if ~isfield(handles,'patRec') - set(handles.t_msg,'String','No patRec to test'); - set(hObject,'Enable','on'); - return - end - - % Run realtime patrec - set(handles.t_msg,'String','Real time PatRec started...'); - drawnow; - RealtimePatRec(handles.patRec, handles); - set(handles.t_msg,'String','Real time PatRec finished'); - -set(hObject,'Enable','on'); - - -function et_testingT_Callback(hObject, eventdata, handles) -% hObject handle to et_testingT (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_testingT as text -% str2double(get(hObject,'String')) returns contents of et_testingT as a double - - -% --- Executes during object creation, after setting all properties. -function et_testingT_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_testingT (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_trials_Callback(hObject, eventdata, handles) -% hObject handle to et_trials (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_trials as text -% str2double(get(hObject,'String')) returns contents of et_trials as a double - - -% --- Executes during object creation, after setting all properties. -function et_trials_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_trials (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_nR_Callback(hObject, eventdata, handles) -% hObject handle to et_nR (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_nR as text -% str2double(get(hObject,'String')) returns contents of et_nR as a double - - -% --- Executes during object creation, after setting all properties. -function et_nR_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_nR (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_timeOut_Callback(hObject, eventdata, handles) -% hObject handle to et_timeOut (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_timeOut as text -% str2double(get(hObject,'String')) returns contents of et_timeOut as a double - - -% --- Executes during object creation, after setting all properties. -function et_timeOut_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_timeOut (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in pb_motionTest. -function pb_motionTest_Callback(hObject, eventdata, handles) -% hObject handle to pb_motionTest (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - patRec = handles.patRec; - - % validation of patRec loaded - if isempty(patRec) - set(handles.t_msg,'String','No patRec to test'); - return - end - - % Run motion test - set(handles.t_msg,'String','Motion Test started...'); - drawnow; - MotionTest(patRec, handles); - set(handles.t_msg,'String','Motion Test finished'); - - -function et_avgProcTime_Callback(hObject, eventdata, handles) -% hObject handle to et_avgProcTime (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_avgProcTime as text -% str2double(get(hObject,'String')) returns contents of et_avgProcTime as a double - - -% --- Executes during object creation, after setting all properties. -function et_avgProcTime_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_avgProcTime (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function pm_normSets_Callback(hObject, eventdata, handles) -% hObject handle to pm_normSets (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of pm_normSets as text -% str2double(get(hObject,'String')) returns contents of pm_normSets as a double - - -% --- Executes during object creation, after setting all properties. -function pm_normSets_CreateFcn(hObject, eventdata, handles) -% hObject handle to pm_normSets (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in pb_RealtimePatRecDev. -function pb_RealtimePatRecDev_Callback(hObject, eventdata, handles) -% hObject handle to pb_RealtimePatRecDev (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - - -% --- Executes on selection change in lb_features. -function lb_features_Callback(hObject, eventdata, handles) -% hObject handle to lb_features (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: contents = cellstr(get(hObject,'String')) returns lb_features contents as cell array -% contents{get(hObject,'Value')} returns selected item from lb_features - - -% --- Executes during object creation, after setting all properties. -function lb_features_CreateFcn(hObject, eventdata, handles) -% hObject handle to lb_features (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: listbox controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% -------------------------------------------------------------------- -function m_Data_Callback(hObject, eventdata, handles) -% hObject handle to m_Data (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - - -% -------------------------------------------------------------------- -function m_Statistics_Callback(hObject, eventdata, handles) -% hObject handle to m_Statistics (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - - -% -------------------------------------------------------------------- -function m_Stats_CurrentD_Callback(hObject, eventdata, handles) -% hObject handle to m_Stats_CurrentD (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - - -% -------------------------------------------------------------------- -function m_Stats_Group_Callback(hObject, eventdata, handles) -% hObject handle to m_Stats_Group (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - - -% -------------------------------------------------------------------- -function m_Open_Callback(hObject, eventdata, handles) -% hObject handle to m_Open (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - disp('%%%%%%%%%%% Loading Data %%%%%%%%%%%%%'); - set(handles.t_msg,'String','Loading Data...'); - - % Dialog box to open a file - [file, path] = uigetfile('*.mat'); - % Check that the loaded file is a "ss" struct - if ~isequal(file, 0) - load([path,file]); - if (exist('patRec','var')) % Get patRec - Load_patRec(patRec, 'GUI_TestPatRec'); - else - disp('That was not a valid training matrix'); - errordlg('That was not a valid training matrix','Error'); - return; - end - end - - -% -------------------------------------------------------------------- -function m_Save_patRec_Callback(hObject, eventdata, handles) -% hObject handle to m_Save_patRec (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - - -% --- Executes on selection change in pm_m1. -function pm_m1_Callback(hObject, eventdata, handles) -% hObject handle to pm_m1 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: contents = cellstr(get(hObject,'String')) returns pm_m1 contents as cell array -% contents{get(hObject,'Value')} returns selected item from pm_m1 - - -% --- Executes during object creation, after setting all properties. -function pm_m1_CreateFcn(hObject, eventdata, handles) -% hObject handle to pm_m1 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: popupmenu controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_speed1_Callback(hObject, eventdata, handles) -% hObject handle to et_speed1 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_speed1 as text -% str2double(get(hObject,'String')) returns contents of et_speed1 as a double - - -% --- Executes during object creation, after setting all properties. -function et_speed1_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_speed1 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on selection change in pm_m2. -function pm_m2_Callback(hObject, eventdata, handles) -% hObject handle to pm_m2 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: contents = cellstr(get(hObject,'String')) returns pm_m2 contents as cell array -% contents{get(hObject,'Value')} returns selected item from pm_m2 - - -% --- Executes during object creation, after setting all properties. -function pm_m2_CreateFcn(hObject, eventdata, handles) -% hObject handle to pm_m2 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: popupmenu controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_speed2_Callback(hObject, eventdata, handles) -% hObject handle to et_speed2 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_speed2 as text -% str2double(get(hObject,'String')) returns contents of et_speed2 as a double - - -% --- Executes during object creation, after setting all properties. -function et_speed2_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_speed2 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on selection change in pm_m3. -function pm_m3_Callback(hObject, eventdata, handles) -% hObject handle to pm_m3 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: contents = cellstr(get(hObject,'String')) returns pm_m3 contents as cell array -% contents{get(hObject,'Value')} returns selected item from pm_m3 - - -% --- Executes during object creation, after setting all properties. -function pm_m3_CreateFcn(hObject, eventdata, handles) -% hObject handle to pm_m3 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: popupmenu controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_speed3_Callback(hObject, eventdata, handles) -% hObject handle to et_speed3 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_speed3 as text -% str2double(get(hObject,'String')) returns contents of et_speed3 as a double - - -% --- Executes during object creation, after setting all properties. -function et_speed3_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_speed3 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on selection change in pm_m4. -function pm_m4_Callback(hObject, eventdata, handles) -% hObject handle to pm_m4 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: contents = cellstr(get(hObject,'String')) returns pm_m4 contents as cell array -% contents{get(hObject,'Value')} returns selected item from pm_m4 - - -% --- Executes during object creation, after setting all properties. -function pm_m4_CreateFcn(hObject, eventdata, handles) -% hObject handle to pm_m4 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: popupmenu controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_speed4_Callback(hObject, eventdata, handles) -% hObject handle to et_speed4 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_speed4 as text -% str2double(get(hObject,'String')) returns contents of et_speed4 as a double - - -% --- Executes during object creation, after setting all properties. -function et_speed4_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_speed4 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on selection change in pm_m5. -function pm_m5_Callback(hObject, eventdata, handles) -% hObject handle to pm_m5 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: contents = cellstr(get(hObject,'String')) returns pm_m5 contents as cell array -% contents{get(hObject,'Value')} returns selected item from pm_m5 - - -% --- Executes during object creation, after setting all properties. -function pm_m5_CreateFcn(hObject, eventdata, handles) -% hObject handle to pm_m5 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: popupmenu controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_speed5_Callback(hObject, eventdata, handles) -% hObject handle to et_speed5 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_speed5 as text -% str2double(get(hObject,'String')) returns contents of et_speed5 as a double - - -% --- Executes during object creation, after setting all properties. -function et_speed5_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_speed5 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on selection change in pm_m6. -function pm_m6_Callback(hObject, eventdata, handles) -% hObject handle to pm_m6 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: contents = cellstr(get(hObject,'String')) returns pm_m6 contents as cell array -% contents{get(hObject,'Value')} returns selected item from pm_m6 - - -% --- Executes during object creation, after setting all properties. -function pm_m6_CreateFcn(hObject, eventdata, handles) -% hObject handle to pm_m6 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: popupmenu controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_speed6_Callback(hObject, eventdata, handles) -% hObject handle to et_speed6 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_speed6 as text -% str2double(get(hObject,'String')) returns contents of et_speed6 as a double - - -% --- Executes during object creation, after setting all properties. -function et_speed6_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_speed6 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on selection change in pm_m7. -function pm_m7_Callback(hObject, eventdata, handles) -% hObject handle to pm_m7 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: contents = cellstr(get(hObject,'String')) returns pm_m7 contents as cell array -% contents{get(hObject,'Value')} returns selected item from pm_m7 - - -% --- Executes during object creation, after setting all properties. -function pm_m7_CreateFcn(hObject, eventdata, handles) -% hObject handle to pm_m7 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: popupmenu controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_speed7_Callback(hObject, eventdata, handles) -% hObject handle to et_speed7 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_speed7 as text -% str2double(get(hObject,'String')) returns contents of et_speed7 as a double - - -% --- Executes during object creation, after setting all properties. -function et_speed7_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_speed7 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on selection change in pm_m8. -function pm_m8_Callback(hObject, eventdata, handles) -% hObject handle to pm_m8 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: contents = cellstr(get(hObject,'String')) returns pm_m8 contents as cell array -% contents{get(hObject,'Value')} returns selected item from pm_m8 - - -% --- Executes during object creation, after setting all properties. -function pm_m8_CreateFcn(hObject, eventdata, handles) -% hObject handle to pm_m8 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: popupmenu controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_speed8_Callback(hObject, eventdata, handles) -% hObject handle to et_speed8 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_speed8 as text -% str2double(get(hObject,'String')) returns contents of et_speed8 as a double - - -% --- Executes during object creation, after setting all properties. -function et_speed8_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_speed8 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on selection change in pm_m9. -function pm_m9_Callback(hObject, eventdata, handles) -% hObject handle to pm_m9 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: contents = cellstr(get(hObject,'String')) returns pm_m9 contents as cell array -% contents{get(hObject,'Value')} returns selected item from pm_m9 - - -% --- Executes during object creation, after setting all properties. -function pm_m9_CreateFcn(hObject, eventdata, handles) -% hObject handle to pm_m9 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: popupmenu controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_speed9_Callback(hObject, eventdata, handles) -% hObject handle to et_speed9 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_speed9 as text -% str2double(get(hObject,'String')) returns contents of et_speed9 as a double - - -% --- Executes during object creation, after setting all properties. -function et_speed9_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_speed9 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on selection change in pm_m10. -function pm_m10_Callback(hObject, eventdata, handles) -% hObject handle to pm_m10 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: contents = cellstr(get(hObject,'String')) returns pm_m10 contents as cell array -% contents{get(hObject,'Value')} returns selected item from pm_m10 - - -% --- Executes during object creation, after setting all properties. -function pm_m10_CreateFcn(hObject, eventdata, handles) -% hObject handle to pm_m10 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: popupmenu controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_speed10_Callback(hObject, eventdata, handles) -% hObject handle to et_speed10 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_speed10 as text -% str2double(get(hObject,'String')) returns contents of et_speed10 as a double - - -% --- Executes during object creation, after setting all properties. -function et_speed10_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_speed10 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in pb_move1. -function pb_move1_Callback(hObject, eventdata, handles) -% hObject handle to pb_move1 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -%Disable the botton -set(hObject,'Enable','off'); - -%Get speed (in percentage) from the corresponding textedit -movSpeed = str2double(get(handles.et_speed1,'String')); -%Get the time more the movemet from the corresponding textedit -movTime = str2double(get(handles.et_length1,'String')); -%Get the selected motor direction from the corresponding popmenu -motorDir = get(handles.pm_m1,'Value'); - -%Check whether to use VRE -if get(handles.cb_VRE,'Value') - global TAC - %Calculate dof, since every 2nd value indicates which dof. (works for - %now) - dof = round(motorDir/2); - dof = 10; - %Calculate which direction to move in. - dir = mod(motorDir,2); - %Moves the VRE some distance. - if VREActivation(handles.vre_Com,movSpeed,movTime,dof,dir,get(handles.cb_moveTAC,'Value')); - %TAC is complete. - TAC.ackTimes = TAC.ackTimes + 1; - end -end -if get(handles.cb_motorCoupling,'Value') - % Get the communication obj - com = handles.com; - %Activate the motor direction for a short moment. - ShortMotorActivation(com, movSpeed, movTime, motorDir) -end -%Enable the botton -set(hObject,'Enable','on'); - -% --- Executes on button press in pb_move2. -function pb_move2_Callback(hObject, eventdata, handles) -% hObject handle to pb_move2 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -%Disable the botton -set(hObject,'Enable','off'); -%Get speed (in percentage) from the corresponding textedit -movSpeed = str2double(get(handles.et_speed2,'String')); -%Get the time more the movemet from the corresponding textedit -movTime = str2double(get(handles.et_length2,'String')); -%Get the selected motor direction from the corresponding popmenu -motorDir = get(handles.pm_m2,'Value'); - -%Check whether to use VRE -if get(handles.cb_VRE,'Value') - %Calculate dof, since every 2nd value indicates which dof. (works for - %now) - dof = round(motorDir/2); - dof = 9; - %Calculate which direction to move in. - dir = mod(motorDir,2); - %Moves the VRE a short distance. - VREActivation(handles.vre_Com,movSpeed,movTime,dof,dir,get(handles.cb_moveTAC,'Value')); -end -if get(handles.cb_motorCoupling,'Value') - % Get the communication obj - com = handles.com; - %Activate the motor direction for a short moment. - ShortMotorActivation(com, movSpeed, movTime, motorDir) -end -%Enable the botton -set(hObject,'Enable','on'); - -% --- Executes on button press in pb_move3. -function pb_move3_Callback(hObject, eventdata, handles) -% hObject handle to pb_move3 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -%Disable the botton -set(hObject,'Enable','off'); - -%Get speed (in percentage) from the corresponding textedit -movSpeed = str2double(get(handles.et_speed3,'String')); -%Get the time more the movemet from the corresponding textedit -movTime = str2double(get(handles.et_length3,'String')); -%Get the selected motor direction from the corresponding popmenu -motorDir = get(handles.pm_m3,'Value'); - -%Check whether to use VRE -if get(handles.cb_VRE,'Value') - %Calculate dof, since every 2nd value indicates which dof. (works for - %now) - dof = round(motorDir/2); - dof = 7; - %Calculate which direction to move in. - dir = mod(motorDir,2); - %Moves the VRE a short distance. - VREActivation(handles.vre_Com,movSpeed,movTime,dof,dir,get(handles.cb_moveTAC,'Value')); -end -if get(handles.cb_motorCoupling,'Value') - % Get the communicatio obj - com = handles.com; - %Activate the motor direction for a short moment. - ShortMotorActivation(com, movSpeed, movTime, motorDir) -end -%Enable the botton -set(hObject,'Enable','on'); - -% --- Executes on button press in pb_move4. -function pb_move4_Callback(hObject, eventdata, handles) -% hObject handle to pb_move4 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -%Disable the botton -set(hObject,'Enable','off'); - -%Get speed (in percentage) from the corresponding textedit -movSpeed = str2double(get(handles.et_speed4,'String')); -%Get the time more the movemet from the corresponding textedit -movTime = str2double(get(handles.et_length4,'String')); -%Get the selected motor direction from the corresponding popmenu -motorDir = get(handles.pm_m4,'Value'); - -%Check whether to use VRE -if get(handles.cb_VRE,'Value') - %Calculate dof, since every 2nd value indicates which dof. (works for - %now) - dof = round(motorDir/2); - dof = 7; - %Calculate which direction to move in. - dir = mod(motorDir,2); - %Moves the VRE a short distance. - VREActivation(handles.vre_Com,movSpeed,movTime,dof,dir,get(handles.cb_moveTAC,'Value')); -end -if get(handles.cb_motorCoupling,'Value') - % Get the communicatio obj - com = handles.com; - %Activate the motor direction for a short moment. - ShortMotorActivation(com, movSpeed, movTime, motorDir) -end -%Enable the botton -set(hObject,'Enable','on'); - -% --- Executes on button press in pb_move5. -function pb_move5_Callback(hObject, eventdata, handles) -% hObject handle to pb_move5 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -%Disable the botton -set(hObject,'Enable','off'); -%Get speed (in percentage) from the corresponding textedit -movSpeed = str2double(get(handles.et_speed5,'String')); -%Get the time more the movemet from the corresponding textedit -movTime = str2double(get(handles.et_length5,'String')); -%Get the selected motor direction from the corresponding popmenu -motorDir = get(handles.pm_m5,'Value'); -%Check whether to use VRE -if get(handles.cb_VRE,'Value') - %Calculate dof, since every 2nd value indicates which dof. (works for - %now) - dof = round(motorDir/2); - dof = 8; - %Calculate which direction to move in. - dir = mod(motorDir,2); - %Moves the VRE a short distance. - VREActivation(handles.vre_Com,movSpeed,movTime,dof,dir,get(handles.cb_moveTAC,'Value')); -end -if get(handles.cb_motorCoupling,'Value') - % Get the communicatio obj - com = handles.com; - %Activate the motor direction for a short moment. - ShortMotorActivation(com, movSpeed, movTime, motorDir) -end -%Enable the botton -set(hObject,'Enable','on'); - -% --- Executes on button press in pb_move6. -function pb_move6_Callback(hObject, eventdata, handles) -% hObject handle to pb_move6 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -%Disable the botton -set(hObject,'Enable','off'); -%Get speed (in percentage) from the corresponding textedit -movSpeed = str2double(get(handles.et_speed6,'String')); -%Get the time more the movemet from the corresponding textedit -movTime = str2double(get(handles.et_length6,'String')); -%Get the selected motor direction from the corresponding popmenu -motorDir = get(handles.pm_m6,'Value'); -%Check whether to use VRE -if get(handles.cb_VRE,'Value') - %Calculate dof, since every 2nd value indicates which dof. (works for - %now) - dof = round(motorDir/2); - dof = 8; - %Calculate which direction to move in. - dir = mod(motorDir,2); - %Moves the VRE a short distance. - VREActivation(handles.vre_Com,movSpeed,movTime,dof,dir,get(handles.cb_moveTAC,'Value')); -end -if get(handles.cb_motorCoupling,'Value') - % Get the communicatio obj - com = handles.com; - %Activate the motor direction for a short moment. - ShortMotorActivation(com, movSpeed, movTime, motorDir) -end -%Enable the botton -set(hObject,'Enable','on'); - -% --- Executes on button press in pb_move10. -function pb_move10_Callback(hObject, eventdata, handles) -% hObject handle to pb_move10 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -%Disable the botton -set(hObject,'Enable','off'); -%Get speed (in percentage) from the corresponding textedit -movSpeed = str2double(get(handles.et_speed10,'String')); -%Get the time more the movemet from the corresponding textedit -movTime = str2double(get(handles.et_length10,'String')); -%Get the selected motor direction from the corresponding popmenu -motorDir = get(handles.pm_m10,'Value'); -%Check whether to use VRE -if get(handles.cb_VRE,'Value') - %Calculate dof, since every 2nd value indicates which dof. (works for - %now) - dof = round(motorDir/2); - %Calculate which direction to move in. - dir = mod(motorDir,2); - %Moves the VRE a short distance. - VREActivation(handles.vre_Com,movSpeed,movTime,dof,dir,get(handles.cb_moveTAC,'Value')); -end -if get(handles.cb_motorCoupling,'Value') - % Get the communicatio obj - com = handles.com; - %Activate the motor direction for a short moment. - ShortMotorActivation(com, movSpeed, movTime, motorDir) -end -%Enable the botton -set(hObject,'Enable','on'); - -% --- Executes on button press in pb_move9. -function pb_move9_Callback(hObject, eventdata, handles) -% hObject handle to pb_move9 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -%Disable the botton -set(hObject,'Enable','off'); -%Get speed (in percentage) from the corresponding textedit -movSpeed = str2double(get(handles.et_speed9,'String')); -%Get the time more the movemet from the corresponding textedit -movTime = str2double(get(handles.et_length9,'String')); -%Get the selected motor direction from the corresponding popmenu -motorDir = get(handles.pm_m9,'Value'); -%Check whether to use VRE -if get(handles.cb_VRE,'Value') - %Calculate dof, since every 2nd value indicates which dof. (works for - %now) - dof = round(motorDir/2); - %Calculate which direction to move in. - dir = mod(motorDir,2); - %Moves the VRE a short distance. - VREActivation(handles.vre_Com,movSpeed,movTime,dof,dir,get(handles.cb_moveTAC,'Value')); -end -if get(handles.cb_motorCoupling,'Value') - % Get the communicatio obj - com = handles.com; - %Activate the motor direction for a short moment. - ShortMotorActivation(com, movSpeed, movTime, motorDir) -end -%Enable the botton -set(hObject,'Enable','on'); - -% --- Executes on button press in pb_move8. -function pb_move8_Callback(hObject, eventdata, handles) -% hObject handle to pb_move8 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -%Disable the botton -set(hObject,'Enable','off'); -%Get speed (in percentage) from the corresponding textedit -movSpeed = str2double(get(handles.et_speed8,'String')); -%Get the time more the movemet from the corresponding textedit -movTime = str2double(get(handles.et_length8,'String')); -%Get the selected motor direction from the corresponding popmenu -motorDir = get(handles.pm_m8,'Value'); -%Check whether to use VRE -if get(handles.cb_VRE,'Value') - %Calculate dof, since every 2nd value indicates which dof. (works for - %now) - dof = round(motorDir/2); - %Calculate which direction to move in. - dir = mod(motorDir,2); - %Moves the VRE a short distance. - VREActivation(handles.vre_Com,movSpeed,movTime,dof,dir,get(handles.cb_moveTAC,'Value')); -end -if get(handles.cb_motorCoupling,'Value') - % Get the communicatio obj - com = handles.com; - %Activate the motor direction for a short moment. - ShortMotorActivation(com, movSpeed, movTime, motorDir) -end -%Enable the botton -set(hObject,'Enable','on'); - -% --- Executes on button press in pb_move7. -function pb_move7_Callback(hObject, eventdata, handles) -% hObject handle to pb_move7 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -%Disable the botton -set(hObject,'Enable','off'); -%Get speed (in percentage) from the corresponding textedit -movSpeed = str2double(get(handles.et_speed7,'String')); -%Get the time more the movemet from the corresponding textedit -movTime = str2double(get(handles.et_length7,'String')); -%Get the selected motor direction from the corresponding popmenu -motorDir = get(handles.pm_m7,'Value'); -%Check whether to use VRE -if get(handles.cb_VRE,'Value') - %Calculate dof, since every 2nd value indicates which dof. (works for - %now) - dof = round(motorDir/2); - %Calculate which direction to move in. - dir = mod(motorDir,2); - %Moves the VRE a short distance. - VREActivation(handles.vre_Com,movSpeed,movTime,dof,dir,get(handles.cb_moveTAC,'Value')); -end -if get(handles.cb_motorCoupling,'Value') - % Get the communicatio obj - com = handles.com; - %Activate the motor direction for a short moment. - ShortMotorActivation(com, movSpeed, movTime, motorDir) -end -%Enable the botton -set(hObject,'Enable','on'); - -% --- Executes on button press in pb_connect. -function pb_connect_Callback(hObject, eventdata, handles) -% hObject handle to pb_connect (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -compath = get(handles.et_connect,'String'); -handles.com = Connect_ALC(compath); -%handles.com = MasterModuleComm(compath); -if TestConnectionALC(handles.com)==1; %Write S to stop program - set(handles.t_msg,'String','Connection established'); - guidata(hObject,handles); -else - set(handles.t_msg,'String','Wrong connection'); - fclose(handles.com.io); -end - -set(handles.pb_testConnection,'Enable','on'); -set(handles.pb_disconnect,'Enable','on'); - -function et_connect_Callback(hObject, eventdata, handles) -% hObject handle to et_connect (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_connect as text -% str2double(get(hObject,'String')) returns contents of et_connect as a double - - -% --- Executes during object creation, after setting all properties. -function et_connect_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_connect (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in pb_disconnect. -function pb_disconnect_Callback(hObject, eventdata, handles) -% hObject handle to pb_disconnect (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -fclose(handles.com.io); -set(handles.t_msg,'String','Disconnected'); -set(handles.pb_testConnection,'Enable','off'); -set(handles.pb_disconnect,'Enable','off'); - -% --- Executes on button press in pb_testConnection. -function pb_testConnection_Callback(hObject, eventdata, handles) -% hObject handle to pb_testConnection (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -set(handles.t_msg,'String','Testing connection...'); -if TestConnectionALC(handles.com)==1; %Write S to stop program - set(handles.t_msg,'String','Connection established'); - guidata(hObject,handles); -else - set(handles.t_msg,'String','Wrong connection'); - fclose(handles.com.io); -end - - - -function et_length1_Callback(hObject, eventdata, handles) -% hObject handle to et_length1 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_length1 as text -% str2double(get(hObject,'String')) returns contents of et_length1 as a double - - -% --- Executes during object creation, after setting all properties. -function et_length1_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_length1 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_length2_Callback(hObject, eventdata, handles) -% hObject handle to et_length2 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_length2 as text -% str2double(get(hObject,'String')) returns contents of et_length2 as a double - - -% --- Executes during object creation, after setting all properties. -function et_length2_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_length2 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_length3_Callback(hObject, eventdata, handles) -% hObject handle to et_length3 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_length3 as text -% str2double(get(hObject,'String')) returns contents of et_length3 as a double - - -% --- Executes during object creation, after setting all properties. -function et_length3_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_length3 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_length4_Callback(hObject, eventdata, handles) -% hObject handle to et_length4 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_length4 as text -% str2double(get(hObject,'String')) returns contents of et_length4 as a double - - -% --- Executes during object creation, after setting all properties. -function et_length4_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_length4 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_length6_Callback(hObject, eventdata, handles) -% hObject handle to et_length6 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_length6 as text -% str2double(get(hObject,'String')) returns contents of et_length6 as a double - - -% --- Executes during object creation, after setting all properties. -function et_length6_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_length6 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_length5_Callback(hObject, eventdata, handles) -% hObject handle to et_length5 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_length5 as text -% str2double(get(hObject,'String')) returns contents of et_length5 as a double - - -% --- Executes during object creation, after setting all properties. -function et_length5_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_length5 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_length7_Callback(hObject, eventdata, handles) -% hObject handle to et_length7 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_length7 as text -% str2double(get(hObject,'String')) returns contents of et_length7 as a double - - -% --- Executes during object creation, after setting all properties. -function et_length7_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_length7 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_length8_Callback(hObject, eventdata, handles) -% hObject handle to et_length8 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_length8 as text -% str2double(get(hObject,'String')) returns contents of et_length8 as a double - - -% --- Executes during object creation, after setting all properties. -function et_length8_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_length8 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_length9_Callback(hObject, eventdata, handles) -% hObject handle to et_length9 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_length9 as text -% str2double(get(hObject,'String')) returns contents of et_length9 as a double - - -% --- Executes during object creation, after setting all properties. -function et_length9_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_length9 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function et_length10_Callback(hObject, eventdata, handles) -% hObject handle to et_length10 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_length10 as text -% str2double(get(hObject,'String')) returns contents of et_length10 as a double - - -% --- Executes during object creation, after setting all properties. -function et_length10_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_length10 (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in cb_motorCoupling. -function cb_motorCoupling_Callback(hObject, eventdata, handles) -% hObject handle to cb_motorCoupling (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_motorCoupling - - % validation of patRec loaded -% if ~isfield(handles,'com') -% set(handles.t_msg,'String','No connection, connect first!'); -% set(hObject,'Value',0); -% return -% end - - -% --- Executes on button press in pb_socketConnect. -function pb_socketConnect_Callback(hObject, eventdata, handles) -% hObject handle to pb_socketConnect (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - set(handles.pb_socketConnect,'Enable','off'); - - % Dialog box to open a file -%[file, path] = uigetfile('*.exe'); -% Check that the loaded file is a "ss" struct -%if ~isequal(file, 0) -% startString = sprintf('start /D%s %s',path,file); -% disp(startString); -% [a,b] = system(startString); -%end - -% This starts the VRE-environment. Add support for different paths? -open('Virtual Reality.exe'); - -%Retrieves specified port. -port = str2double(get(handles.et_port,'String')); - -set(handles.t_msg,'String','Waiting for client connection.'); -guidata(hObject,handles); - -obj = tcpip('127.0.0.1',port,'NetworkRole','server'); - -fopen(obj); -set(handles.t_msg,'String',sprintf('Server established on port %d.',port)); -handles.vre_Com = obj; -guidata(hObject,handles); - -set(handles.pb_socketDisconnect,'Enable','on'); -set(handles.pb_Camera,'Enable','on'); -set(handles.cb_VRE,'Enable','on'); - -% --- Executes during object creation, after setting all properties. -function et_port_CreateFcn(hObject, eventdata, handles) -% hObject handle to et_port (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - - -% --- Executes on button press in pb_socketDisconnect. -function pb_socketDisconnect_Callback(hObject, eventdata, handles) -% hObject handle to pb_socketDisconnect (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -set(handles.pb_socketDisconnect,'Enable','off'); -set(handles.cb_VRE,'Enable','off'); -set(handles.pb_Camera,'Enable','off'); -set(handles.cb_VRE,'Value',0) -obj = handles.vre_Com; -fclose(obj); -set(handles.t_msg,'String','Server disconnected.'); -handles.vre_Com = obj; - set(handles.pb_socketConnect,'Enable','on'); - - -function et_port_Callback(hObject, eventdata, handles) -% hObject handle to et_port (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of et_port as text -% str2double(get(hObject,'String')) returns contents of et_port as a double - - -% --- Executes on button press in cb_VRE. -function cb_VRE_Callback(hObject, eventdata, handles) -% hObject handle to cb_VRE (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_VRE - - -% --- Executes on button press in pb_startTAC. -function pb_startTAC_Callback(hObject, eventdata, handles) -% hObject handle to pb_startTAC (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -global TAC - -if TAC.running - TAC.running = 0; - set(hObject,'String','Start'); - t = toc; - set(handles.t_timeTAC,'String',sprintf('Time:%0.3f s',t)); - time = TAC.timer; - stop(time); -else - TAC.running = 1; - set(hObject,'String','Stop'); - tic; - set(handles.t_timeTAC,'String',sprintf('Time:%0.3f s',toc)); - time = timer('Period',0.05,'ExecutionMode','fixedRate'); - time.TimerFcn = {@callback, handles}; - start(time); - TAC.timer = time; - TAC.ackTimes = 0; -end - -function callback(object, event, handles) -global TAC - -if isfield(TAC,'ackTimes') - if TAC.ackTimes > 0 - stop(object); - TAC.running = 0; - TAC.ackTimes = 0; - end - set(handles.t_timeTAC,'String',sprintf('Time:%0.3f s',toc)); - set(handles.pb_startTAC,'String','Start'); -end - - -% --- Executes on button press in cb_showTAC. -function cb_showTAC_Callback(hObject, eventdata, handles) -% hObject handle to cb_showTAC (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -if get(hObject,'Value') %Showing hand! - set(handles.pb_startTAC,'Enable','on'); - set(handles.cb_moveTAC,'Enable','on'); -else - set(handles.pb_startTAC,'Enable','off'); - set(handles.cb_moveTAC,'Enable','off'); - set(handles.cb_moveTAC,'Value',0); -end -if isfield(handles,'vre_Com') - obj = handles.vre_Com; - fwrite(obj,sprintf('%c%c%c%c','c',char(2),char(0),char(0))); - fread(obj,1); -end - - -% Hint: get(hObject,'Value') returns toggle state of cb_showTAC - - -% --- Executes on button press in cb_moveTAC. -function cb_moveTAC_Callback(hObject, eventdata, handles) -% hObject handle to cb_moveTAC (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of cb_moveTAC - - -% --- Executes on button press in pb_Camera. -function pb_Camera_Callback(hObject, eventdata, handles) -% hObject handle to pb_Camera (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -if ( get(handles.pb_Camera,'String') == 'Camera 2') - cam = 1; - set(handles.pb_Camera,'String','Camera 1'); -else - cam = 0; - set(handles.pb_Camera,'String','Camera 2'); -end - -if isfield(handles,'vre_Com') - obj = handles.vre_Com; - fwrite(obj,sprintf('%c%c%c%c','c',char(4),char(cam),char(0))); - fread(obj,1); -end diff --git a/PatRec/GUI_TestPatRec_Mov2Mov.fig b/PatRec/GUI_TestPatRec_Mov2Mov.fig index e759841..1a561a3 100644 Binary files a/PatRec/GUI_TestPatRec_Mov2Mov.fig and b/PatRec/GUI_TestPatRec_Mov2Mov.fig differ diff --git a/PatRec/GUI_TestPatRec_Mov2Mov.m b/PatRec/GUI_TestPatRec_Mov2Mov.m index c022b60..b89e665 100644 --- a/PatRec/GUI_TestPatRec_Mov2Mov.m +++ b/PatRec/GUI_TestPatRec_Mov2Mov.m @@ -4,11 +4,11 @@ % the full license governing this code and copyrights. % % BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and -% Chalmers University of Technology. All authors’ contributions must be kept +% Chalmers University of Technology. All authors contributions must be kept % acknowledged below in the section "Updates % Contributors". % % Would you like to contribute to science and sum efforts to improve -% amputees’ quality of life? Join this project! or, send your comments to: +% amputees quality of life? Join this project! or, send your comments to: % maxo@chalmers.se. % % The entire copyright notice must be kept in this or any source file @@ -51,9 +51,6 @@ % implemented, the SPC control does not need % anymore the MoveMotorWifi or any dedicated % SPC functions -% 2015-07-21 / Francesco Clemente / Folder select routines for the Control -% Framework. Connection to the robotic -% devices has been improved with WiFi fields % % 20xx-xx-xx / Author / Comment on update @@ -81,7 +78,7 @@ % Edit the above text to modify the response to help GUI_TestPatRec_Mov2Mov -% Last Modified by GUIDE v2.5 21-Jul-2015 13:39:26 +% Last Modified by GUIDE v2.5 19-May-2016 13:42:13 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; @@ -116,7 +113,6 @@ function GUI_TestPatRec_Mov2Mov_OpeningFcn(hObject, eventdata, handles, varargin % Choose default command line output for GUI_TestPatRec_Mov2Mov handles.output = hObject; global TAC -global ctrl_dir TAC.running = 0; TAC.ackTimes = 0; @@ -308,14 +304,14 @@ function pb_RealtimePatRec_Callback(hObject, eventdata, handles) % hObject handle to pb_RealtimePatRec (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) + set(hObject, 'Enable', 'off'); -%set(hObject,'Enable','off'); - % validation of patRec loaded - if ~isfield(handles,'patRec') - set(handles.t_msg,'String','No patRec to test'); - set(hObject,'Enable','on'); - return - end +% validation of patRec loaded +if ~isfield(handles,'patRec') + set(handles.t_msg,'String','No patRec to test'); + set(hObject,'Enable','on'); + return +end % if isfield(handles,'pm_controlAlg') % allControlAlg = get(handles.pm_controlAlg,'String'); @@ -325,17 +321,25 @@ function pb_RealtimePatRec_Callback(hObject, eventdata, handles) % end % handles.patRec.controlAlg = controlAlg; - % Run realtime patrec - set(handles.t_msg,'String','Real time PatRec started...'); - drawnow; - +% Run realtime patrec +set(handles.t_msg,'String','Real time PatRec started...'); +drawnow; + +% TEST ALCD +if isfield(handles,'cb_ALCD') + if get(handles.cb_ALCD,'Value') == 1 + handles = ControlTestALCD(handles.patRec, handles); + else + handles = RealtimePatRec(handles.patRec, handles); + end +else handles = RealtimePatRec(handles.patRec, handles); - set(handles.t_msg,'String','Real time PatRec finished'); +end +set(handles.t_msg,'String','Real time PatRec finished'); - % Save the handles back - guidata(hObject,handles); +% Save the handles back +guidata(hObject,handles); - set(hObject,'Enable','on'); @@ -1628,7 +1632,9 @@ function pb_connect_Callback(hObject, eventdata, handles) set(handles.pb_testConnection,'Enable','on'); set(handles.pb_disconnect,'Enable','on'); -set(handles.pb_sensors,'Enable','on'); +if isobject(handles.sensors) + set(handles.pb_sensors,'Enable','on'); +end function et_connect_Callback(hObject, eventdata, handles) @@ -1980,6 +1986,9 @@ function pb_socketDisconnect_Callback(hObject, eventdata, handles) % hObject handle to pb_socketDisconnect (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) +if isfield(handles,'vre_leg') +handles = rmfield(handles,'vre_leg'); +end handles = DisconnectVRE(handles); guidata(hObject,handles); @@ -2305,6 +2314,14 @@ function pb_sensors_Callback(hObject, eventdata, handles) GUI_Sensors(hObject, eventdata, handles); +% --- Executes on button press in cb_ALCD. +function cb_ALCD_Callback(hObject, eventdata, handles) +% hObject handle to cb_ALCD (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hint: get(hObject,'Value') returns toggle state of cb_ALCD + function et_COM_Callback(hObject, eventdata, handles) % hObject handle to et_COM (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB @@ -2454,8 +2471,8 @@ function rb_wifi_Callback(hObject, eventdata, handles) % Hint: get(hObject,'Value') returns toggle state of rb_wifi set(handles.rb_serial,'Value',0); set(handles.pm_serialportipaddress,'Style','edit'); -set(handles.pm_serialportipaddress,'String','IP'); -set(handles.et_baudrateport,'String','Port'); +set(handles.pm_serialportipaddress,'String','192.168.100.10'); % IP +set(handles.et_baudrateport,'String','65100'); % Port % --- Executes on button press in pb_selectctrlfolder. @@ -2464,25 +2481,60 @@ function pb_selectctrlfolder_Callback(hObject, eventdata, handles) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) -global ctrl_dir - -% check if another folder was added to the path before and, if yes, remove -% it from the path -if ctrl_dir - rmpath(ctrl_dir); -end - -% add the folder selected by the user to the Matlab path ctrl_dir = uigetdir; if ctrl_dir - addpath(ctrl_dir); + [~,handles.prostheticDeviceName,~] = fileparts(ctrl_dir); + handles.motors = InitMotors(ctrl_dir); + handles.mov = InitMovements(ctrl_dir); + listOfFile = dir(ctrl_dir); + for i=1:size(listOfFile,1) + if strcmp(listOfFile(i).name,'sensors.def') + handles.sensors = InitSensors(ctrl_dir); + set(handles.pb_sensors,'Enable','on'); + end + end + % Update list of possible movements accordingly to the new loaded + % definition files. It compares the recorded list of movement with the + % movement available for the particular robotic device selected. Only the + % matching movements will be available in the list. + recordedMovs = handles.patRec.mov; + k = 1; + for i = 2:length(handles.mov) % Avoid Rest from the list, so start from 2 + if(~isempty(intersect(recordedMovs,handles.mov(i).name))) + availableMovs(k,1) = handles.mov(i); + k = k+1; + end + end + for i = 1:10 + set(eval(strcat('handles.pm_m',num2str(i))),'Value',1); + set(eval(strcat('handles.et_speed',num2str(i))),'String',num2str(1)); + end + for i = 1:length(availableMovs) + set(eval(strcat('handles.pm_m',num2str(i))),'Value',availableMovs(i).id+1); + speed = handles.motors(availableMovs(i).motor(1)).pct; + set(eval(strcat('handles.et_speed',num2str(i))),'String',num2str(speed)); + end +else + handles.motors = InitMotors(); + handles.mov = InitMovements(); + handles.prostheticDeviceName = 'VRE'; + % Update list of possible movements accordingly to the standard VRE + % definition file. + for i = 1:10 + set(eval(strcat('handles.pm_m',num2str(i))),'Value',i); + set(eval(strcat('handles.et_speed',num2str(i))),'String',num2str(1)); + end end -% Re-Initialize control variables -% newHandles.motors = InitMotors; -% mov = InitMovements; - -handles.mov = InitMovements(); -handles.motors = InitMotors(); % Update handles structure guidata(hObject, handles); + + +% --- Executes on button press in pb_VRleg. +function pb_VRleg_Callback(hObject, eventdata, handles) +% hObject handle to pb_VRleg (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles.vre_leg = 1; +handles = ConnectVRE(handles,'Virtual Reality.exe'); +guidata(hObject,handles); diff --git a/PatRec/LDA/DiscriminantAnalysis.m b/PatRec/LDA/DiscriminantAnalysis.m index 1d938e6..08c6415 100644 --- a/PatRec/LDA/DiscriminantAnalysis.m +++ b/PatRec/LDA/DiscriminantAnalysis.m @@ -25,6 +25,7 @@ % 2011-10-02 / Max Ortiz / Creation of the function DiscriminantAccuracy % 2012-05-20 / Max Ortiz / Move the Get_SetsLabels funtion inside this % routne and deleted old commented code +% 2015-06-26 / Olga Mikhaylova / Error handling of "classify" % 20xx-xx-xx / Author / Comment on update %function [coeff accVset] = DiscriminantAnalysis(trSet, trLables, vSet, vLables, mov, dType) @@ -40,7 +41,14 @@ end %Apply discriminat to vset -[class,err,POSTERIOR,logp,coeff] = classify(vSets,trSets,trLables,dType); +try + [class,err,POSTERIOR,logp,coeff] = classify(vSets,trSets,trLables,dType); +catch + errordlg('Too many features selected. Please try with a smaller set.','Matrix mismatch'); + accVset = []; + coeff = []; + return; +end nM = size(mov,1); good = zeros(size(vSets,1),1); diff --git a/PatRec/Load_patRec.m b/PatRec/Load_patRec.m index c63c63a..4e006a8 100644 --- a/PatRec/Load_patRec.m +++ b/PatRec/Load_patRec.m @@ -58,14 +58,13 @@ function Load_patRec(patRec, newGUI, loadMovements) if exist('loadMovements','var') if(loadMovements) - % Fill List of Movements + % Fill List of Movements % Setup variables - newHandles.motors = InitMotors; - mov = InitMovements; + newHandles.motors = InitMotors(); + mov = InitMovements(); newHandles.mov = mov; movements = []; patRecMovements = []; - % Save Valid movements, that can be used with VRE/ARE and % motors i = 1; @@ -77,9 +76,7 @@ function Load_patRec(patRec, newGUI, loadMovements) % Read movements trained in patRec structure i = 1; while length( patRec.movOutIdx{i} ) == 1 && i < size( patRec.movOutIdx,2 ) - patMov = patRec.mov{i}; - patMov = strrep(patMov,'Extend', 'Ext'); - patMov = strrep(patMov,'Pointer', 'Point'); + patMov = patRec.mov{i}; patRecMovements = [patRecMovements; {patMov}]; i = i+1; end diff --git a/PatRec/MotionTest.m b/PatRec/MotionTest.m index 1944ed9..d880baa 100644 --- a/PatRec/MotionTest.m +++ b/PatRec/MotionTest.m @@ -37,6 +37,8 @@ % to be compatible with the functions % placed into COMM/AFE folder. For more % details read RecordingSession.m log. +% 2016-05-03 / Julian Maier / Artifact inseration added to tempdata if +% required % 20xx-xx-xx / Author / Comment on update @@ -143,8 +145,8 @@ % Get sampling time sT = motionTest.timeOut; -tW = sT/100; % Time window size -tWs = tW*sF; % Time window samples +tW = patRec.tW; % Time window size +tWs = tW*sF; % Time window samples %% Motion Test @@ -421,7 +423,17 @@ function MotionTest_OneShot(src,event) if size(tempData,1) >= (patRec.sF*patRec.tW) % Save the TW data, maybe useful for further analysis - tData = tempData(end-patRec.sF*patRec.tW+1:end,:); %Copy the temporal data to the test data + %tData = tempData(end-patRec.sF*patRec.tW+1:end,:); %Copy the temporal data to the test data + + % Add artifact if required + if isfield(patRec,'addArtifact') + timeLength=str2double(handles.et_timeOut.String); + tempDataArt = AddArtifactRealtime(tempData,timeLength); + tData = tempDataArt(end-patRec.sF*patRec.tW+1:end,:); + else % Copy the temporal data to the test data + tData = tempData(end-patRec.sF*patRec.tW+1:end,:); + end + dataTW(:,:,nTW) = tData; % Save data for future analisys % Start of processing time diff --git a/PatRec/NetLab/NetLab_GLMTest.m b/PatRec/NetLab/NetLab_GLMTest.m new file mode 100644 index 0000000..53f4e8a --- /dev/null +++ b/PatRec/NetLab/NetLab_GLMTest.m @@ -0,0 +1,30 @@ +function [outMov outVector] = NetLab_GLMTest(patRecTrained, tSet) +%UNTITLED2 Summary of this function goes here +% Detailed explanation goes here + + + outVector = glmfwd(patRecTrained.GLM, tSet); + + if isfield(patRecTrained,'thOut') + % Output according to a given threshold + outMov = find(outVector>patRecTrained.thOut'); + else + % The output movement is given by any prediction over 50% + outMov = find(round(outVector)); + + % The output movement is given by the higest prediction + %[maxV, outMov] = max(outVector); + end + + + + + + + + + + + +end + diff --git a/PatRec/NetLab/NetLab_GLM_InitAndTrain.m b/PatRec/NetLab/NetLab_GLM_InitAndTrain.m new file mode 100644 index 0000000..f04bb09 --- /dev/null +++ b/PatRec/NetLab/NetLab_GLM_InitAndTrain.m @@ -0,0 +1,61 @@ +% ---------------------------- Copyright Notice --------------------------- +% This file is part of BioPatRec © which is open and free software under +% the GNU Lesser General Public License (LGPL). See the file "LICENSE" for +% the full license governing this code and copyrights. +% +% BioPatRec was initially developed by Max J. Ortiz C. at Integrum AB and +% Chalmers University of Technology. All authors’ contributions must be kept +% acknowledged below in the section "Updates % Contributors". +% +% Would you like to contribute to science and sum efforts to improve +% amputees’ quality of life? Join this project! or, send your comments to: +% maxo@chalmers.se. +% +% The entire copyright notice must be kept in this or any source file +% linked to BioPatRec. This will ensure communication with all authors and +% acknowledge contributions here and in the project web page (optional). +% +% -------------------------- Function Description ------------------------- +% +% Initialization and training of the GLM based in the open source: NetLab +% +% ------------------------- Updates & Contributors ------------------------ +% [Contributors are welcome to add their email] +% 2011-10-29 / Cosima Prahm / Creation +% 20xx-xx-xx / Authors / Comments + + + +function [GLM, acc] = NetLab_GLM_InitAndTrain(trSet, trOut, vSet, vOut, tType) + +%% Initialize GLM +nOn = size(trOut,2); % Number of output neurons +nIn = size(trSet,2); % Number of input neurons +maxItr = 200; % Maximum number iterations + +% Selection of output function +if strcmp(tType, 'softmax') + ofun = 'softmax'; +elseif strcmp(tType, 'linear') + ofun = 'linear'; +elseif strcmp(tType, 'logistic') + ofun = 'logistic'; +else + ofun = 'softmax'; + disp([tType ' is not available, ' ofun ' is used']) +end + +% Initilization of GLM +GLM = glm(nIn, nOn, ofun); % all possible output functions available + + +%% Train GLM +options = foptions(); % Standard options +options(14) = maxItr; % Maximum Iterations + +GLM = netopt(GLM, options, [trSet; vSet], [trOut; vOut], 'scg'); + +acc = 0; + + +end \ No newline at end of file diff --git a/PatRec/NetLab/NetLab_MLPTest.m b/PatRec/NetLab/NetLab_MLPTest.m new file mode 100644 index 0000000..75c548a --- /dev/null +++ b/PatRec/NetLab/NetLab_MLPTest.m @@ -0,0 +1,32 @@ +function [outMov outVector] = NetLab_MLPTest(patRecTrained, tSet) +%UNTITLED2 Summary of this function goes here +% Detailed explanation goes here + + outVector = mlpfwd(patRecTrained.MLP(1), tSet); + + if isfield(patRecTrained,'thOut') + % Output according to a given threshold + outMov = find(outVector>patRecTrained.thOut'); + else + % The output movement is given by any prediction over 50% + outMov = find(round(outVector)); % returns all indices for accepted movements + + if size(patRecTrained.MLP,2) == 2 + outVector(outMov) = mlpfwd(patRecTrained.MLP(2), tSet); + + + end + + end + + + + + + + + + + +end + diff --git a/PatRec/NetLab/NetLab_MLP_InitAndTrain.m b/PatRec/NetLab/NetLab_MLP_InitAndTrain.m new file mode 100644 index 0000000..3811f24 --- /dev/null +++ b/PatRec/NetLab/NetLab_MLP_InitAndTrain.m @@ -0,0 +1,44 @@ +function [MLP, acc] = NetLab_MLP_InitAndTrain(trSet, trOut, vSet, vOut, tType) +%UNTITLED Summary of this function goes here +% Detailed explanation goes here + + + +%% Initialize Multi Layer Perceptron +nOn = size(trOut,2); % Number of output neurons +nIn = size(trSet,2); % Number of input neurons +nHn = ((nIn)+nOn); % Number of hiden neurons --> more hidden units->more iterations necessary +maxItr = 200; % Maximum number iterations + + +% Selection of output function for proportional control +if strcmp(tType, 'proportional') + ofunc = 'softmax'; + prop = 1; %proportional control +elseif strcmp(tType, 'proportional logistic') + ofunc = 'logistic'; + prop = 1; %proportional control +else + ofunc = tType; + prop = 0; +end + +% Initilization of MLP +MLP(1) = mlp(nIn, nHn, nOn, ofunc); %Softmax is best, if only one output can be activated +%MLP = mlp(nIn, nHn, nOn, 'logistic'); + +%% Train Multi Layer Perceptron +options = foptions(); % Standard options +options(14) = maxItr; % Maximum Iterations +% training with both trSet and vSet (internal training validation) +MLP(1) = netopt(MLP(1), options, [trSet; vSet], [trOut; vOut], 'scg'); + +if prop %additional net for proportional output, not executed if no proportional output selected + MLP(2) = mlp(nIn, 4, 1, 'linear'); + MLP(2) = netopt( MLP(2), options, [trSet; vSet], (1-[trOut(:,end); vOut(:,end)]), 'scg' ); +end + +acc = 0; + + +end \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/Contents.m b/PatRec/NetLab/netlab3_3/Contents.m new file mode 100644 index 0000000..aaf32e1 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/Contents.m @@ -0,0 +1,176 @@ +% Netlab Toolbox +% Version 3.3.1 18-Jun-2004 +% +% conffig - Display a confusion matrix. +% confmat - Compute a confusion matrix. +% conjgrad - Conjugate gradients optimization. +% consist - Check that arguments are consistent. +% convertoldnet- Convert pre-2.3 release MLP and MDN nets to new format +% datread - Read data from an ascii file. +% datwrite - Write data to ascii file. +% dem2ddat - Generates two dimensional data for demos. +% demard - Automatic relevance determination using the MLP. +% demev1 - Demonstrate Bayesian regression for the MLP. +% demev2 - Demonstrate Bayesian classification for the MLP. +% demev3 - Demonstrate Bayesian regression for the RBF. +% demgauss - Demonstrate sampling from Gaussian distributions. +% demglm1 - Demonstrate simple classification using a generalized linear model. +% demglm2 - Demonstrate simple classification using a generalized linear model. +% demgmm1 - Demonstrate density modelling with a Gaussian mixture model. +% demgmm3 - Demonstrate density modelling with a Gaussian mixture model. +% demgmm4 - Demonstrate density modelling with a Gaussian mixture model. +% demgmm5 - Demonstrate density modelling with a PPCA mixture model. +% demgp - Demonstrate simple regression using a Gaussian Process. +% demgpard - Demonstrate ARD using a Gaussian Process. +% demgpot - Computes the gradient of the negative log likelihood for a mixture model. +% demgtm1 - Demonstrate EM for GTM. +% demgtm2 - Demonstrate GTM for visualisation. +% demhint - Demonstration of Hinton diagram for 2-layer feed-forward network. +% demhmc1 - Demonstrate Hybrid Monte Carlo sampling on mixture of two Gaussians. +% demhmc2 - Demonstrate Bayesian regression with Hybrid Monte Carlo sampling. +% demhmc3 - Demonstrate Bayesian regression with Hybrid Monte Carlo sampling. +% demkmean - Demonstrate simple clustering model trained with K-means. +% demknn1 - Demonstrate nearest neighbour classifier. +% demmdn1 - Demonstrate fitting a multi-valued function using a Mixture Density Network. +% demmet1 - Demonstrate Markov Chain Monte Carlo sampling on a Gaussian. +% demmlp1 - Demonstrate simple regression using a multi-layer perceptron +% demmlp2 - Demonstrate simple classification using a multi-layer perceptron +% demnlab - A front-end Graphical User Interface to the demos +% demns1 - Demonstrate Neuroscale for visualisation. +% demolgd1 - Demonstrate simple MLP optimisation with on-line gradient descent +% demopt1 - Demonstrate different optimisers on Rosenbrock's function. +% dempot - Computes the negative log likelihood for a mixture model. +% demprgp - Demonstrate sampling from a Gaussian Process prior. +% demprior - Demonstrate sampling from a multi-parameter Gaussian prior. +% demrbf1 - Demonstrate simple regression using a radial basis function network. +% demsom1 - Demonstrate SOM for visualisation. +% demtrain - Demonstrate training of MLP network. +% dist2 - Calculates squared distance between two sets of points. +% eigdec - Sorted eigendecomposition +% errbayes - Evaluate Bayesian error function for network. +% evidence - Re-estimate hyperparameters using evidence approximation. +% fevbayes - Evaluate Bayesian regularisation for network forward propagation. +% gauss - Evaluate a Gaussian distribution. +% gbayes - Evaluate gradient of Bayesian error function for network. +% glm - Create a generalized linear model. +% glmderiv - Evaluate derivatives of GLM outputs with respect to weights. +% glmerr - Evaluate error function for generalized linear model. +% glmevfwd - Forward propagation with evidence for GLM +% glmfwd - Forward propagation through generalized linear model. +% glmgrad - Evaluate gradient of error function for generalized linear model. +% glmhess - Evaluate the Hessian matrix for a generalised linear model. +% glminit - Initialise the weights in a generalized linear model. +% glmpak - Combines weights and biases into one weights vector. +% glmtrain - Specialised training of generalized linear model +% glmunpak - Separates weights vector into weight and bias matrices. +% gmm - Creates a Gaussian mixture model with specified architecture. +% gmmactiv - Computes the activations of a Gaussian mixture model. +% gmmem - EM algorithm for Gaussian mixture model. +% gmminit - Initialises Gaussian mixture model from data +% gmmpak - Combines all the parameters in a Gaussian mixture model into one vector. +% gmmpost - Computes the class posterior probabilities of a Gaussian mixture model. +% gmmprob - Computes the data probability for a Gaussian mixture model. +% gmmsamp - Sample from a Gaussian mixture distribution. +% gmmunpak - Separates a vector of Gaussian mixture model parameters into its components. +% gp - Create a Gaussian Process. +% gpcovar - Calculate the covariance for a Gaussian Process. +% gpcovarf - Calculate the covariance function for a Gaussian Process. +% gpcovarp - Calculate the prior covariance for a Gaussian Process. +% gperr - Evaluate error function for Gaussian Process. +% gpfwd - Forward propagation through Gaussian Process. +% gpgrad - Evaluate error gradient for Gaussian Process. +% gpinit - Initialise Gaussian Process model. +% gppak - Combines GP hyperparameters into one vector. +% gpunpak - Separates hyperparameter vector into components. +% gradchek - Checks a user-defined gradient function using finite differences. +% graddesc - Gradient descent optimization. +% gsamp - Sample from a Gaussian distribution. +% gtm - Create a Generative Topographic Map. +% gtmem - EM algorithm for Generative Topographic Mapping. +% gtmfwd - Forward propagation through GTM. +% gtminit - Initialise the weights and latent sample in a GTM. +% gtmlmean - Mean responsibility for data in a GTM. +% gtmlmode - Mode responsibility for data in a GTM. +% gtmmag - Magnification factors for a GTM +% gtmpost - Latent space responsibility for data in a GTM. +% gtmprob - Probability for data under a GTM. +% hbayes - Evaluate Hessian of Bayesian error function for network. +% hesschek - Use central differences to confirm correct evaluation of Hessian matrix. +% hintmat - Evaluates the coordinates of the patches for a Hinton diagram. +% hinton - Plot Hinton diagram for a weight matrix. +% histp - Histogram estimate of 1-dimensional probability distribution. +% hmc - Hybrid Monte Carlo sampling. +% kmeans - Trains a k means cluster model. +% knn - Creates a K-nearest-neighbour classifier. +% knnfwd - Forward propagation through a K-nearest-neighbour classifier. +% linef - Calculate function value along a line. +% linemin - One dimensional minimization. +% maxitmess- Create a standard error message when training reaches max. iterations. +% mdn - Creates a Mixture Density Network with specified architecture. +% mdn2gmm - Converts an MDN mixture data structure to array of GMMs. +% mdndist2 - Calculates squared distance between centres of Gaussian kernels and data +% mdnerr - Evaluate error function for Mixture Density Network. +% mdnfwd - Forward propagation through Mixture Density Network. +% mdngrad - Evaluate gradient of error function for Mixture Density Network. +% mdninit - Initialise the weights in a Mixture Density Network. +% mdnpak - Combines weights and biases into one weights vector. +% mdnpost - Computes the posterior probability for each MDN mixture component. +% mdnprob - Computes the data probability likelihood for an MDN mixture structure. +% mdnunpak - Separates weights vector into weight and bias matrices. +% metrop - Markov Chain Monte Carlo sampling with Metropolis algorithm. +% minbrack - Bracket a minimum of a function of one variable. +% mlp - Create a 2-layer feedforward network. +% mlpbkp - Backpropagate gradient of error function for 2-layer network. +% mlpderiv - Evaluate derivatives of network outputs with respect to weights. +% mlperr - Evaluate error function for 2-layer network. +% mlpevfwd - Forward propagation with evidence for MLP +% mlpfwd - Forward propagation through 2-layer network. +% mlpgrad - Evaluate gradient of error function for 2-layer network. +% mlphdotv - Evaluate the product of the data Hessian with a vector. +% mlphess - Evaluate the Hessian matrix for a multi-layer perceptron network. +% mlphint - Plot Hinton diagram for 2-layer feed-forward network. +% mlpinit - Initialise the weights in a 2-layer feedforward network. +% mlppak - Combines weights and biases into one weights vector. +% mlpprior - Create Gaussian prior for mlp. +% mlptrain - Utility to train an MLP network for demtrain +% mlpunpak - Separates weights vector into weight and bias matrices. +% netderiv - Evaluate derivatives of network outputs by weights generically. +% neterr - Evaluate network error function for generic optimizers +% netevfwd - Generic forward propagation with evidence for network +% netgrad - Evaluate network error gradient for generic optimizers +% nethess - Evaluate network Hessian +% netinit - Initialise the weights in a network. +% netopt - Optimize the weights in a network model. +% netpak - Combines weights and biases into one weights vector. +% netunpak - Separates weights vector into weight and bias matrices. +% olgd - On-line gradient descent optimization. +% pca - Principal Components Analysis +% plotmat - Display a matrix. +% ppca - Probabilistic Principal Components Analysis +% quasinew - Quasi-Newton optimization. +% rbf - Creates an RBF network with specified architecture +% rbfbkp - Backpropagate gradient of error function for RBF network. +% rbfderiv - Evaluate derivatives of RBF network outputs with respect to weights. +% rbferr - Evaluate error function for RBF network. +% rbfevfwd - Forward propagation with evidence for RBF +% rbffwd - Forward propagation through RBF network with linear outputs. +% rbfgrad - Evaluate gradient of error function for RBF network. +% rbfhess - Evaluate the Hessian matrix for RBF network. +% rbfjacob - Evaluate derivatives of RBF network outputs with respect to inputs. +% rbfpak - Combines all the parameters in an RBF network into one weights vector. +% rbfprior - Create Gaussian prior and output layer mask for RBF. +% rbfsetbf - Set basis functions of RBF from data. +% rbfsetfw - Set basis function widths of RBF. +% rbftrain - Two stage training of RBF network. +% rbfunpak - Separates a vector of RBF weights into its components. +% rosegrad - Calculate gradient of Rosenbrock's function. +% rosen - Calculate Rosenbrock's function. +% scg - Scaled conjugate gradient optimization. +% som - Creates a Self-Organising Map. +% somfwd - Forward propagation through a Self-Organising Map. +% sompak - Combines node weights into one weights matrix. +% somtrain - Kohonen training algorithm for SOM. +% somunpak - Replaces node weights in SOM. +% +% Copyright (c) Ian T Nabney (1996-2001) +% diff --git a/PatRec/NetLab/netlab3_3/LICENSE b/PatRec/NetLab/netlab3_3/LICENSE new file mode 100644 index 0000000..0dd4a36 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/LICENSE @@ -0,0 +1,42 @@ + Copyright (c) 1996-2001, Ian T. Nabney + All rights reserved. + + Redistribution and use in source and binary + forms, with or without modification, are + permitted provided that the following + conditions are met: + + * Redistributions of source code must + retain the above copyright notice, this + list of conditions and the following + disclaimer. + * Redistributions in binary form must + reproduce the above copyright notice, + this list of conditions and the + following disclaimer in the + documentation and/or other materials + provided with the distribution. + * Neither the name of the Aston University, Birmingham, U.K. + nor the names of its contributors may be + used to endorse or promote products + derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT + HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. diff --git a/PatRec/NetLab/netlab3_3/conffig.m b/PatRec/NetLab/netlab3_3/conffig.m new file mode 100644 index 0000000..23d774e --- /dev/null +++ b/PatRec/NetLab/netlab3_3/conffig.m @@ -0,0 +1,29 @@ +function fh=conffig(y, t) +%CONFFIG Display a confusion matrix. +% +% Description +% CONFFIG(Y, T) displays the confusion matrix and classification +% performance for the predictions mat{y} compared with the targets T. +% The data is assumed to be in a 1-of-N encoding, unless there is just +% one column, when it is assumed to be a 2 class problem with a 0-1 +% encoding. Each row of Y and T corresponds to a single example. +% +% In the confusion matrix, the rows represent the true classes and the +% columns the predicted classes. +% +% FH = CONFFIG(Y, T) also returns the figure handle FH which can be +% used, for instance, to delete the figure when it is no longer needed. +% +% See also +% CONFMAT, DEMTRAIN +% + +% Copyright (c) Ian T Nabney (1996-2001) + +[C, rate] = confmat(y, t); + +fh = figure('Name', 'Confusion matrix', ... + 'NumberTitle', 'off'); + +plotmat(C, 'k', 'k', 14); +title(['Classification rate: ' num2str(rate(1)) '%'], 'FontSize', 14); diff --git a/PatRec/NetLab/netlab3_3/confmat.m b/PatRec/NetLab/netlab3_3/confmat.m new file mode 100644 index 0000000..e03315b --- /dev/null +++ b/PatRec/NetLab/netlab3_3/confmat.m @@ -0,0 +1,56 @@ +function [C,rate]=confmat(Y,T) +%CONFMAT Compute a confusion matrix. +% +% Description +% [C, RATE] = CONFMAT(Y, T) computes the confusion matrix C and +% classification performance RATE for the predictions mat{y} compared +% with the targets T. The data is assumed to be in a 1-of-N encoding, +% unless there is just one column, when it is assumed to be a 2 class +% problem with a 0-1 encoding. Each row of Y and T corresponds to a +% single example. +% +% In the confusion matrix, the rows represent the true classes and the +% columns the predicted classes. The vector RATE has two entries: the +% percentage of correct classifications and the total number of correct +% classifications. +% +% See also +% CONFFIG, DEMTRAIN +% + +% Copyright (c) Ian T Nabney (1996-2001) + +[n c]=size(Y); +[n2 c2]=size(T); + +if n~=n2 | c~=c2 + error('Outputs and targets are different sizes') +end + +if c > 1 + % Find the winning class assuming 1-of-N encoding + [maximum Yclass] = max(Y', [], 1); + + TL=[1:c]*T'; +else + % Assume two classes with 0-1 encoding + c = 2; + class2 = find(T > 0.5); + TL = ones(n, 1); + TL(class2) = 2; + class2 = find(Y > 0.5); + Yclass = ones(n, 1); + Yclass(class2) = 2; +end + +% Compute +correct = (Yclass==TL); +total=sum(sum(correct)); +rate=[total*100/n total]; + +C=zeros(c,c); +for i=1:c + for j=1:c + C(i,j) = sum((Yclass==j).*(TL==i)); + end +end diff --git a/PatRec/NetLab/netlab3_3/conjgrad.m b/PatRec/NetLab/netlab3_3/conjgrad.m new file mode 100644 index 0000000..d459af2 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/conjgrad.m @@ -0,0 +1,168 @@ +function [x, options, flog, pointlog] = conjgrad(f, x, options, gradf, ... + varargin) +%CONJGRAD Conjugate gradients optimization. +% +% Description +% [X, OPTIONS, FLOG, POINTLOG] = CONJGRAD(F, X, OPTIONS, GRADF) uses a +% conjugate gradients algorithm to find the minimum of the function +% F(X) whose gradient is given by GRADF(X). Here X is a row vector and +% F returns a scalar value. The point at which F has a local minimum +% is returned as X. The function value at that point is returned in +% OPTIONS(8). A log of the function values after each cycle is +% (optionally) returned in FLOG, and a log of the points visited is +% (optionally) returned in POINTLOG. +% +% CONJGRAD(F, X, OPTIONS, GRADF, P1, P2, ...) allows additional +% arguments to be passed to F() and GRADF(). +% +% The optional parameters have the following interpretations. +% +% OPTIONS(1) is set to 1 to display error values; also logs error +% values in the return argument ERRLOG, and the points visited in the +% return argument POINTSLOG. If OPTIONS(1) is set to 0, then only +% warning messages are displayed. If OPTIONS(1) is -1, then nothing is +% displayed. +% +% OPTIONS(2) is a measure of the absolute precision required for the +% value of X at the solution. If the absolute difference between the +% values of X between two successive steps is less than OPTIONS(2), +% then this condition is satisfied. +% +% OPTIONS(3) is a measure of the precision required of the objective +% function at the solution. If the absolute difference between the +% objective function values between two successive steps is less than +% OPTIONS(3), then this condition is satisfied. Both this and the +% previous condition must be satisfied for termination. +% +% OPTIONS(9) is set to 1 to check the user defined gradient function. +% +% OPTIONS(10) returns the total number of function evaluations +% (including those in any line searches). +% +% OPTIONS(11) returns the total number of gradient evaluations. +% +% OPTIONS(14) is the maximum number of iterations; default 100. +% +% OPTIONS(15) is the precision in parameter space of the line search; +% default 1E-4. +% +% See also +% GRADDESC, LINEMIN, MINBRACK, QUASINEW, SCG +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Set up the options. +if length(options) < 18 + error('Options vector too short') +end + +if(options(14)) + niters = options(14); +else + niters = 100; +end + +% Set up options for line search +line_options = foptions; +% Need a precise line search for success +if options(15) > 0 + line_options(2) = options(15); +else + line_options(2) = 1e-4; +end + +display = options(1); + +% Next two lines allow conjgrad to work with expression strings +f = fcnchk(f, length(varargin)); +gradf = fcnchk(gradf, length(varargin)); + +% Check gradients +if (options(9)) + feval('gradchek', x, f, gradf, varargin{:}); +end + +options(10) = 0; +options(11) = 0; +nparams = length(x); +fnew = feval(f, x, varargin{:}); +options(10) = options(10) + 1; +gradnew = feval(gradf, x, varargin{:}); +options(11) = options(11) + 1; +d = -gradnew; % Initial search direction +br_min = 0; +br_max = 1.0; % Initial value for maximum distance to search along +tol = sqrt(eps); + +j = 1; +if nargout >= 3 + flog(j, :) = fnew; + if nargout == 4 + pointlog(j, :) = x; + end +end + +while (j <= niters) + + xold = x; + fold = fnew; + gradold = gradnew; + + gg = gradold*gradold'; + if (gg == 0.0) + % If the gradient is zero then we are done. + options(8) = fnew; + return; + end + + % This shouldn't occur, but rest of code depends on d being downhill + if (gradnew*d' > 0) + d = -d; + if options(1) >= 0 + warning('search direction uphill in conjgrad'); + end + end + + line_sd = d./norm(d); + [lmin, line_options] = feval('linemin', f, xold, line_sd, fold, ... + line_options, varargin{:}); + options(10) = options(10) + line_options(10); + options(11) = options(11) + line_options(11); + % Set x and fnew to be the actual search point we have found + x = xold + lmin * line_sd; + fnew = line_options(8); + + % Check for termination + if (max(abs(x - xold)) < options(2) & max(abs(fnew - fold)) < options(3)) + options(8) = fnew; + return; + end + + gradnew = feval(gradf, x, varargin{:}); + options(11) = options(11) + 1; + + % Use Polak-Ribiere formula to update search direction + gamma = ((gradnew - gradold)*(gradnew)')/gg; + d = (d .* gamma) - gradnew; + + if (display > 0) + fprintf(1, 'Cycle %4d Function %11.6f\n', j, line_options(8)); + end + + j = j + 1; + if nargout >= 3 + flog(j, :) = fnew; + if nargout == 4 + pointlog(j, :) = x; + end + end +end + +% If we get here, then we haven't terminated in the given number of +% iterations. + +options(8) = fold; +if (options(1) >= 0) + disp(maxitmess); +end diff --git a/PatRec/NetLab/netlab3_3/consist.m b/PatRec/NetLab/netlab3_3/consist.m new file mode 100644 index 0000000..9305b26 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/consist.m @@ -0,0 +1,87 @@ +function errstring = consist(model, type, inputs, outputs) +%CONSIST Check that arguments are consistent. +% +% Description +% +% ERRSTRING = CONSIST(NET, TYPE, INPUTS) takes a network data structure +% NET together with a string TYPE containing the correct network type, +% a matrix INPUTS of input vectors and checks that the data structure +% is consistent with the other arguments. An empty string is returned +% if there is no error, otherwise the string contains the relevant +% error message. If the TYPE string is empty, then any type of network +% is allowed. +% +% ERRSTRING = CONSIST(NET, TYPE) takes a network data structure NET +% together with a string TYPE containing the correct network type, and +% checks that the two types match. +% +% ERRSTRING = CONSIST(NET, TYPE, INPUTS, OUTPUTS) also checks that the +% network has the correct number of outputs, and that the number of +% patterns in the INPUTS and OUTPUTS is the same. The fields in NET +% that are used are +% type +% nin +% nout +% +% See also +% MLPFWD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Assume that all is OK as default +errstring = ''; + +% If type string is not empty +if ~isempty(type) + % First check that model has type field + if ~isfield(model, 'type') + errstring = 'Data structure does not contain type field'; + return + end + % Check that model has the correct type + s = model.type; + if ~strcmp(s, type) + errstring = ['Model type ''', s, ''' does not match expected type ''',... + type, '''']; + return + end +end + +% If inputs are present, check that they have correct dimension +if nargin > 2 + if ~isfield(model, 'nin') + errstring = 'Data structure does not contain nin field'; + return + end + + data_nin = size(inputs, 2); + if model.nin ~= data_nin + errstring = ['Dimension of inputs ', num2str(data_nin), ... + ' does not match number of model inputs ', num2str(model.nin)]; + return + end +end + +% If outputs are present, check that they have correct dimension +if nargin > 3 + if ~isfield(model, 'nout') + errstring = 'Data structure does not conatin nout field'; + return + end + data_nout = size(outputs, 2); + if model.nout ~= data_nout + errstring = ['Dimension of outputs ', num2str(data_nout), ... + ' does not match number of model outputs ', num2str(model.nout)]; + return + end + +% Also check that number of data points in inputs and outputs is the same + num_in = size(inputs, 1); + num_out = size(outputs, 1); + if num_in ~= num_out + errstring = ['Number of input patterns ', num2str(num_in), ... + ' does not match number of output patterns ', num2str(num_out)]; + return + end +end diff --git a/PatRec/NetLab/netlab3_3/convertoldnet.m b/PatRec/NetLab/netlab3_3/convertoldnet.m new file mode 100644 index 0000000..bf281c8 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/convertoldnet.m @@ -0,0 +1,26 @@ +function net = convertoldnet(net) +%CONVERTOLDNET Convert pre-2.3 release MLP and MDN nets to new format +% +% Description +% NET = CONVERTOLDNET(NET) takes a network NET and, if appropriate, +% converts it from pre-2.3 to the current format. The difference is +% simply that in MLPs and the MLP sub-net of MDNs the field ACTFN has +% been renamed OUTFN to make it consistent with GLM and RBF networks. +% If the network is not old-format or an MLP or MDN it is left +% unchanged. +% +% See also +% MLP, MDN +% + +% Copyright (c) Ian T Nabney (1996-2001) + +switch net.type + case 'mlp' + if (isfield(net, 'actfn')) + net.outfn = net.actfn; + net = rmfield(net, 'actfn'); + end + case 'mdn' + net.mlp = convertoldnet(net.mlp); +end diff --git a/PatRec/NetLab/netlab3_3/datread.m b/PatRec/NetLab/netlab3_3/datread.m new file mode 100644 index 0000000..f729ef5 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/datread.m @@ -0,0 +1,99 @@ +function [x, t, nin, nout, ndata] = datread(filename) +%DATREAD Read data from an ascii file. +% +% Description +% +% [X, T, NIN, NOUT, NDATA] = DATREAD(FILENAME) reads from the file +% FILENAME and returns a matrix X of input vectors, a matrix T of +% target vectors, and integers NIN, NOUT and NDATA specifying the +% number of inputs, the number of outputs and the number of data points +% respectively. +% +% The format of the data file is as follows: the first row contains the +% string NIN followed by the number of inputs, the second row contains +% the string NOUT followed by the number of outputs, and the third row +% contains the string NDATA followed by the number of data vectors. +% Subsequent lines each contain one input vector followed by one output +% vector, with individual values separated by spaces. +% +% See also +% nin 2 nout 1 ndata 4 0.000000e+00 0.000000e+00 +% 1.000000e+00 0.000000e+00 1.000000e+00 0.000000e+00 +% 1.000000e+00 0.000000e+00 0.000000e+00 1.000000e+00 +% 1.000000e+00 1.000000e+00 See Also +% DATWRITE +% + +% Copyright (c) Ian T Nabney (1996-2001) + +fid = fopen(filename, 'rt'); +if fid == -1 + error('Failed to open file.') +end + +% Read number of inputs +s1 = fscanf(fid, '%s', 1); +if ~strcmp(s1, 'nin') + fclose(fid); + error('String ''nin'' not found') +end +nin = fscanf(fid, '%d\n', 1); +if ~isnumeric(nin) + fclose(fid); + error('No number for nin') +end +if nin < 0 | round(nin) ~= nin + fclose(fid); + error('nin must be a non-negative integer') +end + +% Read number of outputs +s2 = fscanf(fid, '%s', 1); +if ~strcmp(s2, 'nout') + fclose(fid); + error('String ''nout'' not found') +end +nout = fscanf(fid, '%d\n', 1); +if ~isnumeric(nout) + fclose(fid); + error('No number for nout') +end +if nout < 0 | round(nout) ~= nout + fclose(fid); + error('nout must be a non-negative integer') +end + +% Read number of data values +s3 = fscanf(fid, '%s', 1); +if ~strcmp(s3, 'ndata') + fclose(fid); + error('String ''ndata'' not found') +end +ndata = fscanf(fid, '%d\n', 1); +if ~isnumeric(ndata) + fclose(fid); + error('No number for ndata') +end +if ndata < 0 | round(ndata) ~= ndata + fclose(fid); + error('ndata must be a non-negative integer') +end + +% The following line reads all of the remaining data to the end of file. +temp = fscanf(fid, '%f', inf); + +% Check that size of temp is correct +if size(temp, 1) * size(temp,2) ~= (nin+nout) * ndata + fclose(fid); + error('Incorrect number of elements in file') +end + +temp = reshape(temp, nin + nout, ndata)'; +x = temp(:, 1:nin); +t = temp(:, nin + 1 : nin + nout); + +flag = fclose(fid); +if flag == -1 + error('Failed to close file.') +end + diff --git a/PatRec/NetLab/netlab3_3/datwrite.m b/PatRec/NetLab/netlab3_3/datwrite.m new file mode 100644 index 0000000..75df14d --- /dev/null +++ b/PatRec/NetLab/netlab3_3/datwrite.m @@ -0,0 +1,44 @@ +function datwrite(filename, x, t) +%DATWRITE Write data to ascii file. +% +% Description +% +% DATWRITE(FILENAME, X, T) takes a matrix X of input vectors and a +% matrix T of target vectors and writes them to an ascii file named +% FILENAME. The file format is as follows: the first row contains the +% string NIN followed by the number of inputs, the second row contains +% the string NOUT followed by the number of outputs, and the third row +% contains the string NDATA followed by the number of data vectors. +% Subsequent lines each contain one input vector followed by one output +% vector, with individual values separated by spaces. +% +% See also +% DATREAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +nin = size(x, 2); +nout = size(t, 2); +ndata = size(x, 1); + +fid = fopen(filename, 'wt'); +if fid == -1 + error('Failed to open file.') +end + +if size(t, 1) ~= ndata + error('x and t must have same number of rows.'); +end + +fprintf(fid, ' nin %d\n nout %d\n ndata %d\n', nin , nout, ndata); +for i = 1 : ndata + fprintf(fid, '%13e ', x(i,:), t(i,:)); + fprintf(fid, '\n'); +end + +flag = fclose(fid); +if flag == -1 + error('Failed to close file.') +end + diff --git a/PatRec/NetLab/netlab3_3/dem2ddat.m b/PatRec/NetLab/netlab3_3/dem2ddat.m new file mode 100644 index 0000000..abdb7cc --- /dev/null +++ b/PatRec/NetLab/netlab3_3/dem2ddat.m @@ -0,0 +1,48 @@ +function [data, c, prior, sd] = dem2ddat(ndata) +%DEM2DDAT Generates two dimensional data for demos. +% +% Description +% The data is drawn from three spherical Gaussian distributions with +% priors 0.3, 0.5 and 0.2; centres (2, 3.5), (0, 0) and (0,2); and +% standard deviations 0.2, 0.5 and 1.0. DATA = DEM2DDAT(NDATA) +% generates NDATA points. +% +% [DATA, C] = DEM2DDAT(NDATA) also returns a matrix containing the +% centres of the Gaussian distributions. +% +% See also +% DEMGMM1, DEMKMEAN, DEMKNN1 +% + +% Copyright (c) Ian T Nabney (1996-2001) + +input_dim = 2; + +% Fix seed for reproducible results +randn('state', 42); + +% Generate mixture of three Gaussians in two dimensional space +data = randn(ndata, input_dim); + +% Priors for the three clusters +prior(1) = 0.3; +prior(2) = 0.5; +prior(3) = 0.2; + +% Cluster centres +c = [2.0, 3.5; 0.0, 0.0; 0.0, 2.0]; + +% Cluster standard deviations +sd = [0.2 0.5 1.0]; + +% Put first cluster at (2, 3.5) +data(1:prior(1)*ndata, 1) = data(1:prior(1)*ndata, 1) * 0.2 + c(1,1); +data(1:prior(1)*ndata, 2) = data(1:prior(1)*ndata, 2) * 0.2 + c(1,2); + +% Leave second cluster at (0,0) +data((prior(1)*ndata + 1):(prior(2)+prior(1))*ndata, :) = ... + data((prior(1)*ndata + 1):(prior(2)+prior(1))*ndata, :) * 0.5; + +% Put third cluster at (0,2) +data((prior(1)+prior(2))*ndata +1:ndata, 2) = ... + data((prior(1)+prior(2))*ndata+1:ndata, 2) + c(3, 2); diff --git a/PatRec/NetLab/netlab3_3/demard.m b/PatRec/NetLab/netlab3_3/demard.m new file mode 100644 index 0000000..8347830 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demard.m @@ -0,0 +1,157 @@ +%DEMARD Automatic relevance determination using the MLP. +% +% Description +% This script demonstrates the technique of automatic relevance +% determination (ARD) using a synthetic problem having three input +% variables: X1 is sampled uniformly from the range (0,1) and has a low +% level of added Gaussian noise, X2 is a copy of X1 with a higher level +% of added noise, and X3 is sampled randomly from a Gaussian +% distribution. The single target variable is determined by +% SIN(2*PI*X1) with additive Gaussian noise. Thus X1 is very relevant +% for determining the target value, X2 is of some relevance, while X3 +% is irrelevant. The prior over weights is given by the ARD Gaussian +% prior with a separate hyper-parameter for the group of weights +% associated with each input. A multi-layer perceptron is trained on +% this data, with re-estimation of the hyper-parameters using EVIDENCE. +% The final values for the hyper-parameters reflect the relative +% importance of the three inputs. +% +% See also +% DEMMLP1, DEMEV1, MLP, EVIDENCE +% + +% Copyright (c) Ian T Nabney (1996-2001) + +clc; +disp('This demonstration illustrates the technique of automatic relevance') +disp('determination (ARD) using a multi-layer perceptron.') +disp(' '); +disp('First, we set up a synthetic data set involving three input variables:') +disp('x1 is sampled uniformly from the range (0,1) and has a low level of') +disp('added Gaussian noise, x2 is a copy of x1 with a higher level of added') +disp('noise, and x3 is sampled randomly from a Gaussian distribution. The') +disp('single target variable is given by t = sin(2*pi*x1) with additive') +disp('Gaussian noise. Thus x1 is very relevant for determining the target') +disp('value, x2 is of some relevance, while x3 should in principle be') +disp('irrelevant.') +disp(' '); +disp('Press any key to see a plot of t against x1.') +pause; + +% Generate the data set. +randn('state', 0); +rand('state', 0); +ndata = 100; +noise = 0.05; +x1 = rand(ndata, 1) + 0.002*randn(ndata, 1); +x2 = x1 + 0.02*randn(ndata, 1); +x3 = 0.5 + 0.2*randn(ndata, 1); +x = [x1, x2, x3]; +t = sin(2*pi*x1) + noise*randn(ndata, 1); + +% Plot the data and the original function. +h = figure; +plotvals = linspace(0, 1, 200)'; +plot(x1, t, 'ob') +hold on +axis([0 1 -1.5 1.5]) +[fx, fy] = fplot('sin(2*pi*x)', [0 1]); +plot(fx, fy, '-g', 'LineWidth', 2); +legend('data', 'function'); + +disp(' '); +disp('Press any key to continue') +pause; clc; + +disp('The prior over weights is given by the ARD Gaussian prior with a') +disp('separate hyper-parameter for the group of weights associated with each') +disp('input. This prior is set up using the utility MLPPRIOR. The network is') +disp('trained by error minimization using scaled conjugate gradient function') +disp('SCG. There are two cycles of training, and at the end of each cycle') +disp('the hyper-parameters are re-estimated using EVIDENCE.') +disp(' '); +disp('Press any key to create and train the network.') +disp(' '); +pause; + +% Set up network parameters. +nin = 3; % Number of inputs. +nhidden = 2; % Number of hidden units. +nout = 1; % Number of outputs. +aw1 = 0.01*ones(1, nin); % First-layer ARD hyperparameters. +ab1 = 0.01; % Hyperparameter for hidden unit biases. +aw2 = 0.01; % Hyperparameter for second-layer weights. +ab2 = 0.01; % Hyperparameter for output unit biases. +beta = 50.0; % Coefficient of data error. + +% Create and initialize network. +prior = mlpprior(nin, nhidden, nout, aw1, ab1, aw2, ab2); +net = mlp(nin, nhidden, nout, 'linear', prior, beta); + +% Set up vector of options for the optimiser. +nouter = 2; % Number of outer loops +ninner = 10; % Number of inner loops +options = zeros(1,18); % Default options vector. +options(1) = 1; % This provides display of error values. +options(2) = 1.0e-7; % This ensures that convergence must occur +options(3) = 1.0e-7; +options(14) = 300; % Number of training cycles in inner loop. + +% Train using scaled conjugate gradients, re-estimating alpha and beta. +for k = 1:nouter + net = netopt(net, options, x, t, 'scg'); + [net, gamma] = evidence(net, x, t, ninner); + fprintf(1, '\n\nRe-estimation cycle %d:\n', k); + disp('The first three alphas are the hyperparameters for the corresponding'); + disp('input to hidden unit weights. The remainder are the hyperparameters'); + disp('for the hidden unit biases, second layer weights and output unit') + disp('biases, respectively.') + fprintf(1, ' alpha = %8.5f\n', net.alpha); + fprintf(1, ' beta = %8.5f\n', net.beta); + fprintf(1, ' gamma = %8.5f\n\n', gamma); + disp(' ') + disp('Press any key to continue.') + pause +end + +% Plot the function corresponding to the trained network. +figure(h); hold on; +[y, z] = mlpfwd(net, plotvals*ones(1,3)); +plot(plotvals, y, '-r', 'LineWidth', 2) +legend('data', 'function', 'network'); + +disp('Press any key to continue.'); +pause; clc; + +disp('We can now read off the hyperparameter values corresponding to the') +disp('three inputs x1, x2 and x3:') +disp(' '); +fprintf(1, ' alpha1: %8.5f\n', net.alpha(1)); +fprintf(1, ' alpha2: %8.5f\n', net.alpha(2)); +fprintf(1, ' alpha3: %8.5f\n', net.alpha(3)); +disp(' '); +disp('Since each alpha corresponds to an inverse variance, we see that the') +disp('posterior variance for weights associated with input x1 is large, that') +disp('of x2 has an intermediate value and the variance of weights associated') +disp('with x3 is small.') +disp(' ') +disp('Press any key to continue.') +disp(' ') +pause +disp('This is confirmed by looking at the corresponding weight values:') +disp(' '); +fprintf(1, ' %8.5f %8.5f\n', net.w1'); +disp(' '); +disp('where the three rows correspond to weights asssociated with x1, x2 and') +disp('x3 respectively. We see that the network is giving greatest emphasis') +disp('to x1 and least emphasis to x3, with intermediate emphasis on') +disp('x2. Since the target t is statistically independent of x3 we might') +disp('expect the weights associated with this input would go to') +disp('zero. However, for any finite data set there may be some chance') +disp('correlation between x3 and t, and so the corresponding alpha remains') +disp('finite.') + +disp(' '); +disp('Press any key to end.') +pause; clc; close(h); clear all + diff --git a/PatRec/NetLab/netlab3_3/demev1.m b/PatRec/NetLab/netlab3_3/demev1.m new file mode 100644 index 0000000..b8fd746 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demev1.m @@ -0,0 +1,146 @@ +%DEMEV1 Demonstrate Bayesian regression for the MLP. +% +% Description +% The problem consists an input variable X which sampled from a +% Gaussian distribution, and a target variable T generated by computing +% SIN(2*PI*X) and adding Gaussian noise. A 2-layer network with linear +% outputs is trained by minimizing a sum-of-squares error function with +% isotropic Gaussian regularizer, using the scaled conjugate gradient +% optimizer. The hyperparameters ALPHA and BETA are re-estimated using +% the function EVIDENCE. A graph is plotted of the original function, +% the training data, the trained network function, and the error bars. +% +% See also +% EVIDENCE, MLP, SCG, DEMARD, DEMMLP1 +% + +% Copyright (c) Ian T Nabney (1996-2001) + +clc; +disp('This demonstration illustrates the application of Bayesian') +disp('re-estimation to determine the hyperparameters in a simple regression') +disp('problem. It is based on a local quadratic approximation to a mode of') +disp('the posterior distribution and the evidence maximization framework of') +disp('MacKay.') +disp(' ') +disp('First, we generate a synthetic data set consisting of a single input') +disp('variable x sampled from a Gaussian distribution, and a target variable') +disp('t obtained by evaluating sin(2*pi*x) and adding Gaussian noise.') +disp(' ') +disp('Press any key to see a plot of the data together with the sine function.') +pause; + +% Generate the matrix of inputs x and targets t. + +ndata = 16; % Number of data points. +noise = 0.1; % Standard deviation of noise distribution. +randn('state', 0); +x = 0.25 + 0.07*randn(ndata, 1); +t = sin(2*pi*x) + noise*randn(size(x)); + +% Plot the data and the original sine function. +h = figure; +nplot = 200; +plotvals = linspace(0, 1, nplot)'; +plot(x, t, 'ok') +xlabel('Input') +ylabel('Target') +hold on +axis([0 1 -1.5 1.5]) +fplot('sin(2*pi*x)', [0 1], '-g') +legend('data', 'function'); + +disp(' ') +disp('Press any key to continue') +pause; clc; + +disp('Next we create a two-layer MLP network having 3 hidden units and one') +disp('linear output. The model assumes Gaussian target noise governed by an') +disp('inverse variance hyperparmeter beta, and uses a simple Gaussian prior') +disp('distribution governed by an inverse variance hyperparameter alpha.') +disp(' '); +disp('The network weights and the hyperparameters are initialised and then') +disp('the weights are optimized with the scaled conjugate gradient') +disp('algorithm using the SCG function, with the hyperparameters kept') +disp('fixed. After a maximum of 500 iterations, the hyperparameters are') +disp('re-estimated using the EVIDENCE function. The process of optimizing') +disp('the weights with fixed hyperparameters and then re-estimating the') +disp('hyperparameters is repeated for a total of 3 cycles.') +disp(' ') +disp('Press any key to train the network and determine the hyperparameters.') +pause; + +% Set up network parameters. +nin = 1; % Number of inputs. +nhidden = 3; % Number of hidden units. +nout = 1; % Number of outputs. +alpha = 0.01; % Initial prior hyperparameter. +beta_init = 50.0; % Initial noise hyperparameter. + +% Create and initialize network weight vector. +net = mlp(nin, nhidden, nout, 'linear', alpha, beta_init); + +% Set up vector of options for the optimiser. +nouter = 3; % Number of outer loops. +ninner = 1; % Number of innter loops. +options = zeros(1,18); % Default options vector. +options(1) = 1; % This provides display of error values. +options(2) = 1.0e-7; % Absolute precision for weights. +options(3) = 1.0e-7; % Precision for objective function. +options(14) = 500; % Number of training cycles in inner loop. + +% Train using scaled conjugate gradients, re-estimating alpha and beta. +for k = 1:nouter + net = netopt(net, options, x, t, 'scg'); + [net, gamma] = evidence(net, x, t, ninner); + fprintf(1, '\nRe-estimation cycle %d:\n', k); + fprintf(1, ' alpha = %8.5f\n', net.alpha); + fprintf(1, ' beta = %8.5f\n', net.beta); + fprintf(1, ' gamma = %8.5f\n\n', gamma); + disp(' ') + disp('Press any key to continue.') + pause; +end + +fprintf(1, 'true beta: %f\n', 1/(noise*noise)); + +disp(' ') +disp('Network training and hyperparameter re-estimation are now complete.') +disp('Compare the final value for the hyperparameter beta with the true') +disp('value.') +disp(' ') +disp('Notice that the final error value is close to the number of data') +disp(['points (', num2str(ndata),') divided by two.']) +disp(' ') +disp('Press any key to continue.') +pause; clc; +disp('We can now plot the function represented by the trained network. This') +disp('corresponds to the mean of the predictive distribution. We can also') +disp('plot ''error bars'' representing one standard deviation of the') +disp('predictive distribution around the mean.') +disp(' ') +disp('Press any key to add the network function and error bars to the plot.') +pause; + +% Evaluate error bars. +[y, sig2] = netevfwd(mlppak(net), net, x, t, plotvals); +sig = sqrt(sig2); + +% Plot the data, the original function, and the trained network function. +[y, z] = mlpfwd(net, plotvals); +figure(h); hold on; +plot(plotvals, y, '-r') +xlabel('Input') +ylabel('Target') +plot(plotvals, y + sig, '-b'); +plot(plotvals, y - sig, '-b'); +legend('data', 'function', 'network', 'error bars'); + +disp(' ') +disp('Notice how the confidence interval spanned by the ''error bars'' is') +disp('smaller in the region of input space where the data density is high,') +disp('and becomes larger in regions away from the data.') +disp(' ') +disp('Press any key to end.') +pause; clc; close(h); +%clear all diff --git a/PatRec/NetLab/netlab3_3/demev2.m b/PatRec/NetLab/netlab3_3/demev2.m new file mode 100644 index 0000000..b479d88 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demev2.m @@ -0,0 +1,248 @@ +%DEMEV2 Demonstrate Bayesian classification for the MLP. +% +% Description +% A synthetic two class two-dimensional dataset X is sampled from a +% mixture of four Gaussians. Each class is associated with two of the +% Gaussians so that the optimal decision boundary is non-linear. A 2- +% layer network with logistic outputs is trained by minimizing the +% cross-entropy error function with isotroipc Gaussian regularizer (one +% hyperparameter for each of the four standard weight groups), using +% the scaled conjugate gradient optimizer. The hyperparameter vectors +% ALPHA and BETA are re-estimated using the function EVIDENCE. A graph +% is plotted of the optimal, regularised, and unregularised decision +% boundaries. A further plot of the moderated versus unmoderated +% contours is generated. +% +% See also +% EVIDENCE, MLP, SCG, DEMARD, DEMMLP2 +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +clc; + +disp('This program demonstrates the use of the evidence procedure on') +disp('a two-class problem. It also shows the improved generalisation') +disp('performance that can be achieved with moderated outputs; that is') +disp('predictions where an approximate integration over the true') +disp('posterior distribution is carried out.') +disp(' ') +disp('First we generate a synthetic dataset with two-dimensional input') +disp('sampled from a mixture of four Gaussians. Each class is') +disp('associated with two of the Gaussians so that the optimal decision') +disp('boundary is non-linear.') +disp(' ') +disp('Press any key to see a plot of the data.') +pause; + +% Generate the matrix of inputs x and targets t. + +rand('state', 423); +randn('state', 423); + +ClassSymbol1 = 'r.'; +ClassSymbol2 = 'y.'; +PointSize = 12; +titleSize = 10; + +fh1 = figure; +set(fh1, 'Name', 'True Data Distribution'); +whitebg(fh1, 'k'); + +% +% Generate the data +% +n=200; + +% Set up mixture model: 2d data with four centres +% Class 1 is first two centres, class 2 from the other two +mix = gmm(2, 4, 'full'); +mix.priors = [0.25 0.25 0.25 0.25]; +mix.centres = [0 -0.1; 1.5 0; 1 1; 1 -1]; +mix.covars(:,:,1) = [0.625 -0.2165; -0.2165 0.875]; +mix.covars(:,:,2) = [0.25 0; 0 0.25]; +mix.covars(:,:,3) = [0.2241 -0.1368; -0.1368 0.9759]; +mix.covars(:,:,4) = [0.2375 0.1516; 0.1516 0.4125]; + +[data, label] = gmmsamp(mix, n); + +% +% Calculate some useful axis limits +% +x0 = min(data(:,1)); +x1 = max(data(:,1)); +y0 = min(data(:,2)); +y1 = max(data(:,2)); +dx = x1-x0; +dy = y1-y0; +expand = 5/100; % Add on 5 percent each way +x0 = x0 - dx*expand; +x1 = x1 + dx*expand; +y0 = y0 - dy*expand; +y1 = y1 + dy*expand; +resolution = 100; +step = dx/resolution; +xrange = [x0:step:x1]; +yrange = [y0:step:y1]; +% +% Generate the grid +% +[X Y]=meshgrid([x0:step:x1],[y0:step:y1]); +% +% Calculate the class conditional densities, the unconditional densities and +% the posterior probabilities +% +px_j = gmmactiv(mix, [X(:) Y(:)]); +px = reshape(px_j*(mix.priors)',size(X)); +post = gmmpost(mix, [X(:) Y(:)]); +p1_x = reshape(post(:, 1) + post(:, 2), size(X)); +p2_x = reshape(post(:, 3) + post(:, 4), size(X)); + +plot(data((label<=2),1),data(label<=2,2),ClassSymbol1, 'MarkerSize', ... +PointSize) +hold on +axis([x0 x1 y0 y1]) +plot(data((label>2),1),data(label>2,2),ClassSymbol2, 'MarkerSize', ... + PointSize) + +% Convert targets to 0-1 encoding +target=[label<=2]; +disp(' ') +disp('Press any key to continue') +pause; clc; + +disp('Next we create a two-layer MLP network with 6 hidden units and') +disp('one logistic output. We use a separate inverse variance') +disp('hyperparameter for each group of weights (inputs, input bias,') +disp('outputs, output bias) and the weights are optimised with the') +disp('scaled conjugate gradient algorithm. After each 100 iterations') +disp('the hyperparameters are re-estimated twice. There are eight') +disp('cycles of the whole algorithm.') +disp(' ') +disp('Press any key to train the network and determine the hyperparameters.') +pause; + +% Set up network parameters. +nin = 2; % Number of inputs. +nhidden = 6; % Number of hidden units. +nout = 1; % Number of outputs. +alpha = 0.01; % Initial prior hyperparameter. +aw1 = 0.01; +ab1 = 0.01; +aw2 = 0.01; +ab2 = 0.01; + +% Create and initialize network weight vector. +prior = mlpprior(nin, nhidden, nout, aw1, ab1, aw2, ab2); +net = mlp(nin, nhidden, nout, 'logistic', prior); + +% Set up vector of options for the optimiser. +nouter = 8; % Number of outer loops. +ninner = 2; % Number of innter loops. +options = foptions; % Default options vector. +options(1) = 1; % This provides display of error values. +options(2) = 1.0e-5; % Absolute precision for weights. +options(3) = 1.0e-5; % Precision for objective function. +options(14) = 100; % Number of training cycles in inner loop. + +% Train using scaled conjugate gradients, re-estimating alpha and beta. +for k = 1:nouter + net = netopt(net, options, data, target, 'scg'); + [net, gamma] = evidence(net, data, target, ninner); + fprintf(1, '\nRe-estimation cycle %d:\n', k); + disp([' alpha = ', num2str(net.alpha')]); + fprintf(1, ' gamma = %8.5f\n\n', gamma); + disp(' ') + disp('Press any key to continue.') + pause; +end + +disp(' ') +disp('Network training and hyperparameter re-estimation are now complete.') +disp('Notice that the final error value is close to the number of data') +disp(['points (', num2str(n), ') divided by two.']) +disp('Also, the hyperparameter values differ, which suggests that a single') +disp('hyperparameter would not be so effective.') +disp(' ') +disp('First we train an MLP without Bayesian regularisation on the') +disp('same dataset using 400 iterations of scaled conjugate gradient') +disp(' ') +disp('Press any key to train the network by maximum likelihood.') +pause; +% Train standard network +net2 = mlp(nin, nhidden, nout, 'logistic'); +options(14) = 400; +net2 = netopt(net2, options, data, target, 'scg'); +y2g = mlpfwd(net2, [X(:), Y(:)]); +y2g = reshape(y2g(:, 1), size(X)); + +disp(' ') +disp('We can now plot the function represented by the trained networks.') +disp('We show the decision boundaries (output = 0.5) and the optimal') +disp('decision boundary given by applying Bayes'' theorem to the true') +disp('data model.') +disp(' ') +disp('Press any key to add the boundaries to the plot.') +pause; + +% Evaluate predictions. +[yg, ymodg] = mlpevfwd(net, data, target, [X(:) Y(:)]); +yg = reshape(yg(:,1),size(X)); +ymodg = reshape(ymodg(:,1),size(X)); + +% Bayesian decision boundary +[cB, hB] = contour(xrange,yrange,p1_x,[0.5 0.5],'b-'); +[cNb, hNb] = contour(xrange,yrange,yg,[0.5 0.5],'r-'); +[cN, hN] = contour(xrange,yrange,y2g,[0.5 0.5],'g-'); +set(hB, 'LineWidth', 2); +set(hNb, 'LineWidth', 2); +set(hN, 'LineWidth', 2); +Chandles = [hB(1) hNb(1) hN(1)]; +legend(Chandles, 'Bayes', ... + 'Reg. Network', 'Network', 3); + +disp(' ') +disp('Note how the regularised network predictions are closer to the') +disp('optimal decision boundary, while the unregularised network is') +disp('overtrained.') + +disp(' ') +disp('We will now compare moderated and unmoderated outputs for the'); +disp('regularised network by showing the contour plot of the posterior') +disp('probability estimates.') +disp(' ') +disp('The first plot shows the regularised (moderated) predictions') +disp('and the second shows the standard predictions from the same network.') +disp('These agree at the level 0.5.') +disp('Press any key to continue') +pause +levels = 0:0.1:1; +fh4 = figure; +set(fh4, 'Name', 'Moderated outputs'); +hold on +plot(data((label<=2),1),data(label<=2,2),'r.', 'MarkerSize', PointSize) +plot(data((label>2),1),data(label>2,2),'y.', 'MarkerSize', PointSize) + +[cNby, hNby] = contour(xrange, yrange, ymodg, levels, 'k-'); +set(hNby, 'LineWidth', 1); + +fh5 = figure; +set(fh5, 'Name', 'Unmoderated outputs'); +hold on +plot(data((label<=2),1),data(label<=2,2),'r.', 'MarkerSize', PointSize) +plot(data((label>2),1),data(label>2,2),'y.', 'MarkerSize', PointSize) + +[cNbm, hNbm] = contour(xrange, yrange, yg, levels, 'k-'); +set(hNbm, 'LineWidth', 1); + +disp(' ') +disp('Note how the moderated contours are more widely spaced. This shows') +disp('that there is a larger region where the outputs are close to 0.5') +disp('and a smaller region where the outputs are close to 0 or 1.') +disp(' ') +disp('Press any key to exit') +pause +close(fh1); +close(fh4); +close(fh5); \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/demev3.m b/PatRec/NetLab/netlab3_3/demev3.m new file mode 100644 index 0000000..d288e03 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demev3.m @@ -0,0 +1,154 @@ +%DEMEV3 Demonstrate Bayesian regression for the RBF. +% +% Description +% The problem consists an input variable X which sampled from a +% Gaussian distribution, and a target variable T generated by computing +% SIN(2*PI*X) and adding Gaussian noise. An RBF network with linear +% outputs is trained by minimizing a sum-of-squares error function with +% isotropic Gaussian regularizer, using the scaled conjugate gradient +% optimizer. The hyperparameters ALPHA and BETA are re-estimated using +% the function EVIDENCE. A graph is plotted of the original function, +% the training data, the trained network function, and the error bars. +% +% See also +% DEMEV1, EVIDENCE, RBF, SCG, NETEVFWD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +clc; +disp('This demonstration illustrates the application of Bayesian') +disp('re-estimation to determine the hyperparameters in a simple regression') +disp('problem using an RBF netowk. It is based on a the fact that the') +disp('posterior distribution for the output weights of an RBF is Gaussian') +disp('and uses the evidence maximization framework of MacKay.') +disp(' ') +disp('First, we generate a synthetic data set consisting of a single input') +disp('variable x sampled from a Gaussian distribution, and a target variable') +disp('t obtained by evaluating sin(2*pi*x) and adding Gaussian noise.') +disp(' ') +disp('Press any key to see a plot of the data together with the sine function.') +pause; + +% Generate the matrix of inputs x and targets t. + +ndata = 16; % Number of data points. +noise = 0.1; % Standard deviation of noise distribution. +randn('state', 0); +rand('state', 0); +x = 0.25 + 0.07*randn(ndata, 1); +t = sin(2*pi*x) + noise*randn(size(x)); + +% Plot the data and the original sine function. +h = figure; +nplot = 200; +plotvals = linspace(0, 1, nplot)'; +plot(x, t, 'ok') +xlabel('Input') +ylabel('Target') +hold on +axis([0 1 -1.5 1.5]) +fplot('sin(2*pi*x)', [0 1], '-g') +legend('data', 'function'); + +disp(' ') +disp('Press any key to continue') +pause; clc; + +disp('Next we create a two-layer MLP network having 3 hidden units and one') +disp('linear output. The model assumes Gaussian target noise governed by an') +disp('inverse variance hyperparmeter beta, and uses a simple Gaussian prior') +disp('distribution governed by an inverse variance hyperparameter alpha.') +disp(' '); +disp('The network weights and the hyperparameters are initialised and then') +disp('the output layer weights are optimized with the scaled conjugate gradient') +disp('algorithm using the SCG function, with the hyperparameters kept') +disp('fixed. After a maximum of 50 iterations, the hyperparameters are') +disp('re-estimated using the EVIDENCE function. The process of optimizing') +disp('the weights with fixed hyperparameters and then re-estimating the') +disp('hyperparameters is repeated for a total of 3 cycles.') +disp(' ') +disp('Press any key to train the network and determine the hyperparameters.') +pause; + +% Set up network parameters. +nin = 1; % Number of inputs. +nhidden = 3; % Number of hidden units. +nout = 1; % Number of outputs. +alpha = 0.01; % Initial prior hyperparameter. +beta_init = 50.0; % Initial noise hyperparameter. + +% Create and initialize network weight vector. +net = rbf(nin, nhidden, nout, 'tps', 'linear', alpha, beta_init); +[net.mask, prior] = rbfprior('tps', nin, nhidden, nout, alpha, alpha); +net = netinit(net, prior); + +options = foptions; +options(14) = 5; % At most 5 EM iterations for basis functions +options(1) = -1; % Turn off all messages +net = rbfsetbf(net, options, x); % Initialise the basis functions + +% Now train the network +nouter = 5; +ninner = 2; +options = foptions; +options(1) = 1; +options(2) = 1.0e-5; % Absolute precision for weights. +options(3) = 1.0e-5; % Precision for objective function. +options(14) = 50; % Number of training cycles in inner loop. + +% Train using scaled conjugate gradients, re-estimating alpha and beta. +for k = 1:nouter + net = netopt(net, options, x, t, 'scg'); + [net, gamma] = evidence(net, x, t, ninner); + fprintf(1, '\nRe-estimation cycle %d:\n', k); + fprintf(1, ' alpha = %8.5f\n', net.alpha); + fprintf(1, ' beta = %8.5f\n', net.beta); + fprintf(1, ' gamma = %8.5f\n\n', gamma); + disp(' ') + disp('Press any key to continue.') + pause; +end + +fprintf(1, 'true beta: %f\n', 1/(noise*noise)); + +disp(' ') +disp('Network training and hyperparameter re-estimation are now complete.') +disp('Compare the final value for the hyperparameter beta with the true') +disp('value.') +disp(' ') +disp('Notice that the final error value is close to the number of data') +disp(['points (', num2str(ndata),') divided by two.']) +disp(' ') +disp('Press any key to continue.') +pause; clc; +disp('We can now plot the function represented by the trained network. This') +disp('corresponds to the mean of the predictive distribution. We can also') +disp('plot ''error bars'' representing one standard deviation of the') +disp('predictive distribution around the mean.') +disp(' ') +disp('Press any key to add the network function and error bars to the plot.') +pause; + +% Evaluate error bars. +[y, sig2] = netevfwd(netpak(net), net, x, t, plotvals); +sig = sqrt(sig2); + +% Plot the data, the original function, and the trained network function. +[y, z] = rbffwd(net, plotvals); +figure(h); hold on; +plot(plotvals, y, '-r') +xlabel('Input') +ylabel('Target') +plot(plotvals, y + sig, '-b'); +plot(plotvals, y - sig, '-b'); +legend('data', 'function', 'network', 'error bars'); + +disp(' ') +disp('Notice how the confidence interval spanned by the ''error bars'' is') +disp('smaller in the region of input space where the data density is high,') +disp('and becomes larger in regions away from the data.') +disp(' ') +disp('Press any key to end.') +pause; clc; close(h); + diff --git a/PatRec/NetLab/netlab3_3/demgauss.m b/PatRec/NetLab/netlab3_3/demgauss.m new file mode 100644 index 0000000..c9751ae --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demgauss.m @@ -0,0 +1,80 @@ +%DEMGAUSS Demonstrate sampling from Gaussian distributions. +% +% Description +% +% DEMGAUSS provides a simple illustration of the generation of data +% from Gaussian distributions. It first samples from a one-dimensional +% distribution using RANDN, and then plots a normalized histogram +% estimate of the distribution using HISTP together with the true +% density calculated using GAUSS. +% +% DEMGAUSS then demonstrates sampling from a Gaussian distribution in +% two dimensions. It creates a mean vector and a covariance matrix, and +% then plots contours of constant density using the function GAUSS. A +% sample of points drawn from this distribution, obtained using the +% function GSAMP, is then superimposed on the contours. +% +% See also +% GAUSS, GSAMP, HISTP +% + +% Copyright (c) Ian T Nabney (1996-2001) + +clc +mean = 2; var = 5; nsamp = 3000; +xmin = -10; xmax = 10; nbins = 30; +disp('Demonstration of sampling from a uni-variate Gaussian with mean') +dstring = [num2str(mean), ' and variance ', num2str(var), '. ', ... + num2str(nsamp), ' samples are taken.']; +disp(dstring); +x = mean + sqrt(var)*randn(nsamp, 1); +fh1 = figure; +histp(x, xmin, xmax, nbins); +hold on; +axis([xmin xmax 0 0.2]); +plotvals = linspace(xmin, xmax, 200)'; +probs = gauss(mean, var, plotvals); +plot(plotvals, probs, '-r'); +xlabel('X') +ylabel('Density') + +disp(' ') +disp('Press any key to continue') +pause; +mu = [3 2]; +lam1 = 0.5; +lam2 = 5.0; +Sigma = lam1*[1,1]'*[1,1] + lam2*[1,-1]'*[1,-1]; +disp(' ') +disp('Demonstration of sampling from a bi-variate Gaussian. The mean is') +dstring = ['[', num2str(mu(1)), ', ', num2str(mu(2)), ... + '] and the covariance matrix is']; +disp(dstring) +disp(Sigma); +ngrid = 40; +cmin = -5; cmax = 10; +cvals = linspace(cmin, cmax, ngrid); +[X1, X2] = meshgrid(cvals, cvals); +XX = [X1(:), X2(:)]; +probs = gauss(mu, Sigma, XX); +probs = reshape(probs, ngrid, ngrid); + +fh2 = figure; +contour(X1, X2, probs, 'b'); +hold on + +nsamp = 300; +dstring = [num2str(nsamp), ' samples are generated.']; +disp('The plot shows the sampled data points with a contour plot of their density.') +samples = gsamp(mu, Sigma, nsamp); +plot(samples(:,1), samples(:,2), 'or'); +xlabel('X1') +ylabel('X2') +grid off; + +disp(' ') +disp('Press any key to end') +pause; +close(fh1); +close(fh2); +clear all; \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/demglm1.m b/PatRec/NetLab/netlab3_3/demglm1.m new file mode 100644 index 0000000..d6c54ba --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demglm1.m @@ -0,0 +1,95 @@ +%DEMGLM1 Demonstrate simple classification using a generalized linear model. +% +% Description +% The problem consists of a two dimensional input matrix DATA and a +% vector of classifications T. The data is generated from two +% Gaussian clusters, and a generalized linear model with logistic +% output is trained using iterative reweighted least squares. A plot of +% the data together with the 0.1, 0.5 and 0.9 contour lines of the +% conditional probability is generated. +% +% See also +% DEMGLM2, GLM, GLMTRAIN +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +% Generate data from two classes in 2d +input_dim = 2; + +% Fix seeds for reproducible results +randn('state', 42); +rand('state', 42); + +ndata = 100; +% Generate mixture of two Gaussians in two dimensional space +mix = gmm(2, 2, 'spherical'); +mix.priors = [0.4 0.6]; % Cluster priors +mix.centres = [2.0, 2.0; 0.0, 0.0]; % Cluster centres +mix.covars = [0.5, 1.0]; + +[data, label] = gmmsamp(mix, ndata); +targets = label - ones(ndata, 1); + +% Plot the result + +clc +disp('This demonstration illustrates the use of a generalized linear model') +disp('to classify data from two classes in a two-dimensional space. We') +disp('begin by generating and plotting the data.') +disp(' ') +disp('Press any key to continue.') +pause + +fh1 = figure; +plot(data(label==1,1), data(label==1,2), 'bo'); +hold on +axis([-4 5 -4 5]) +set(gca, 'box', 'on') +plot(data(label==2,1), data(label==2,2), 'rx') +title('Data') + +clc +disp('Now we fit a model consisting of a logistic sigmoid function of') +disp('a linear combination of the input variables.') +disp(' ') +disp('The model is trained using the IRLS algorithm for 5 iterations') +disp(' ') +disp('Press any key to continue.') +pause + +net = glm(input_dim, 1, 'logistic'); +options = foptions; +options(1) = 1; +options(14) = 5; +net = glmtrain(net, options, data, targets); + +disp(' ') +disp('We now plot some density contours given by this model.') +disp('The contour labelled 0.5 is the decision boundary.') +disp(' ') +disp('Press any key to continue.') +pause +x = -4.0:0.2:5.0; +y = -4.0:0.2:5.0; +[X, Y] = meshgrid(x,y); +X = X(:); +Y = Y(:); +grid = [X Y]; +Z = glmfwd(net, grid); +Z = reshape(Z, length(x), length(y)); +v = [0.1 0.5 0.9]; +[c, h] = contour(x, y, Z, v); +title('Generalized Linear Model') +set(h, 'linewidth', 3) +clabel(c, h); + +clc +disp('Note that the contours of constant density are straight lines.') +disp(' ') +disp('Press any key to end.') +pause +close(fh1); +clear all; + diff --git a/PatRec/NetLab/netlab3_3/demglm2.m b/PatRec/NetLab/netlab3_3/demglm2.m new file mode 100644 index 0000000..ea3d6bd --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demglm2.m @@ -0,0 +1,103 @@ +%DEMGLM2 Demonstrate simple classification using a generalized linear model. +% +% Description +% The problem consists of a two dimensional input matrix DATA and a +% vector of classifications T. The data is generated from three +% Gaussian clusters, and a generalized linear model with softmax output +% is trained using iterative reweighted least squares. A plot of the +% data together with regions shaded by the classification given by the +% network is generated. +% +% See also +% DEMGLM1, GLM, GLMTRAIN +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +% Generate data from three classes in 2d +input_dim = 2; + +% Fix seeds for reproducible results +randn('state', 42); +rand('state', 42); + +ndata = 100; +% Generate mixture of three Gaussians in two dimensional space +mix = gmm(2, 3, 'spherical'); +mix.priors = [0.4 0.3 0.3]; % Cluster priors +mix.centres = [2, 2; 0.0, 0.0; 1, -1]; % Cluster centres +mix.covars = [0.5 1.0 0.6]; + +[data, label] = gmmsamp(mix, ndata); +id = eye(3); +targets = id(label,:); + +% Plot the result + +clc +disp('This demonstration illustrates the use of a generalized linear model') +disp('to classify data from three classes in a two-dimensional space. We') +disp('begin by generating and plotting the data.') +disp(' ') +disp('Press any key to continue.') +pause + +fh1 = figure; +plot(data(label==1,1), data(label==1,2), 'bo'); +hold on +axis([-4 5 -4 5]); +set(gca, 'Box', 'on') +plot(data(label==2,1), data(label==2,2), 'rx') +plot(data(label==3, 1), data(label==3, 2), 'go') +title('Data') + +clc +disp('Now we fit a model consisting of a softmax function of') +disp('a linear combination of the input variables.') +disp(' ') +disp('The model is trained using the IRLS algorithm for up to 10 iterations') +disp(' ') +disp('Press any key to continue.') +pause + +net = glm(input_dim, size(targets, 2), 'softmax'); +options = foptions; +options(1) = 1; +options(14) = 10; +net = glmtrain(net, options, data, targets); + +disp(' ') +disp('We now plot the decision regions given by this model.') +disp(' ') +disp('Press any key to continue.') +pause + +x = -4.0:0.2:5.0; +y = -4.0:0.2:5.0; +[X, Y] = meshgrid(x,y); +X = X(:); +Y = Y(:); +grid = [X Y]; +Z = glmfwd(net, grid); +[foo , class] = max(Z'); +class = class'; +colors = ['b.'; 'r.'; 'g.']; +for i = 1:3 + thisX = X(class == i); + thisY = Y(class == i); + h = plot(thisX, thisY, colors(i,:)); + set(h, 'MarkerSize', 8); +end +title('Plot of Decision regions') + +hold off + +clc +disp('Note that the boundaries of decision regions are straight lines.') +disp(' ') +disp('Press any key to end.') +pause +close(fh1); +clear all; + diff --git a/PatRec/NetLab/netlab3_3/demgmm1.m b/PatRec/NetLab/netlab3_3/demgmm1.m new file mode 100644 index 0000000..e2d1ef4 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demgmm1.m @@ -0,0 +1,173 @@ +%DEMGMM1 Demonstrate EM for Gaussian mixtures. +% +% Description +% This script demonstrates the use of the EM algorithm to fit a mixture +% of Gaussians to a set of data using maximum likelihood. A colour +% coding scheme is used to illustrate the evaluation of the posterior +% probabilities in the E-step of the EM algorithm. +% +% See also +% DEMGMM2, DEMGMM3, DEMGMM4, GMM, GMMEM, GMMPOST +% + +% Copyright (c) Ian T Nabney (1996-2001) + +clc; +disp('This demonstration illustrates the use of the EM (expectation-') +disp('maximization) algorithm for fitting of a mixture of Gaussians to a') +disp('data set by maximum likelihood.') +disp(' ') +disp('The data set consists of 40 data points in a 2-dimensional') +disp('space, generated by sampling from a mixture of 2 Gaussian') +disp('distributions.') +disp(' ') +disp('Press any key to see a plot of the data.') +pause; + +% Generate the data +randn('state', 0); rand('state', 0); +gmix = gmm(2, 2, 'spherical'); +ndat1 = 20; ndat2 = 20; ndata = ndat1+ndat2; +gmix.centres = [0.3 0.3; 0.7 0.7]; +gmix.covars = [0.01 0.01]; +x = gmmsamp(gmix, ndata); + +h = figure; +hd = plot(x(:, 1), x(:, 2), '.g', 'markersize', 30); +hold on; axis([0 1 0 1]); axis square; set(gca, 'box', 'on'); +ht = text(0.5, 1.05, 'Data', 'horizontalalignment', 'center'); +disp(' '); +disp('Press any key to continue.') +pause; clc; + +disp('We next create and initialize a mixture model consisting of a mixture') +disp('of 2 Gaussians having ''spherical'' covariance matrices, using the') +disp('function GMM. The Gaussian components can be displayed on the same') +disp('plot as the data by drawing a contour of constant probability density') +disp('for each component having radius equal to the corresponding standard') +disp('deviation. Component 1 is coloured red and component 2 is coloured') +disp('blue.') +disp(' ') +disp('Note that a particulary poor choice of initial parameters has been') +disp('made in order to illustrate more effectively the operation of the') +disp('EM algorithm.') +disp(' ') +disp('Press any key to see the initial configuration of the mixture model.') +pause; + +% Set up mixture model +ncentres = 2; input_dim = 2; +mix = gmm(input_dim, ncentres, 'spherical'); + +% Initialise the mixture model +mix.centres = [0.2 0.8; 0.8, 0.2]; +mix.covars = [0.01 0.01]; + +% Plot the initial model +ncirc = 30; theta = linspace(0, 2*pi, ncirc); +xs = cos(theta); ys = sin(theta); +xvals = mix.centres(:, 1)*ones(1,ncirc) + sqrt(mix.covars')*xs; +yvals = mix.centres(:, 2)*ones(1,ncirc) + sqrt(mix.covars')*ys; +hc(1)=line(xvals(1,:), yvals(1,:), 'color', 'r'); +hc(2)=line(xvals(2,:), yvals(2,:), 'color', 'b'); +set(ht, 'string', 'Initial Configuration'); +figure(h); +disp(' ') +disp('Press any key to continue'); +pause; clc; + +disp('Now we adapt the parameters of the mixture model iteratively using the') +disp('EM algorithm. Each cycle of the EM algorithm consists of an E-step') +disp('followed by an M-step. We start with the E-step, which involves the') +disp('evaluation of the posterior probabilities (responsibilities) which the') +disp('two components have for each of the data points.') +disp(' ') +disp('Since we have labelled the two components using the colours red and') +disp('blue, a convenient way to indicate the value of a posterior') +disp('probability for a given data point is to colour the point using a') +disp('scale ranging from pure red (corresponding to a posterior probability') +disp('of 1.0 for the red component and 0.0 for the blue component) through') +disp('to pure blue.') +disp(' ') +disp('Press any key to see the result of applying the first E-step.') +pause; + +% Initial E-step. +set(ht, 'string', 'E-step'); +post = gmmpost(mix, x); +dcols = [post(:,1), zeros(ndata, 1), post(:,2)]; +delete(hd); +for i = 1 : ndata + hd(i) = plot(x(i, 1), x(i, 2), 'color', dcols(i,:), ... + 'marker', '.', 'markersize', 30); +end +figure(h); + +disp(' '); +disp('Press any key to continue') +pause; clc; + +disp('Next we perform the corresponding M-step. This involves replacing the') +disp('centres of the component Gaussians by the corresponding weighted means') +disp('of the data. Thus the centre of the red component is replaced by the') +disp('mean of the data set, in which each data point is weighted according to') +disp('the amount of red ink (corresponding to the responsibility of') +disp('component 1 for explaining that data point). The variances and mixing') +disp('proportions of the two components are similarly re-estimated.') +disp(' ') +disp('Press any key to see the result of applying the first M-step.') +pause; + +% M-step. +set(ht, 'string', 'M-step'); +options = foptions; +options(14) = 1; % A single iteration +options(1) = -1; % Switch off all messages, including warning +mix = gmmem(mix, x, options); +delete(hc); +xvals = mix.centres(:, 1)*ones(1,ncirc) + sqrt(mix.covars')*xs; +yvals = mix.centres(:, 2)*ones(1,ncirc) + sqrt(mix.covars')*ys; +hc(1)=line(xvals(1,:), yvals(1,:), 'color', 'r'); +hc(2)=line(xvals(2,:), yvals(2,:), 'color', 'b'); +figure(h); +disp(' ') +disp('Press any key to continue') +pause; clc; + +disp('We can continue making alternate E and M steps until the changes in') +disp('the log likelihood at each cycle become sufficiently small.') +disp(' ') +disp('Press any key to see an animation of a further 9 EM cycles.') +pause; +figure(h); + +% Loop over EM iterations. +numiters = 9; +for n = 1 : numiters + + set(ht, 'string', 'E-step'); + post = gmmpost(mix, x); + dcols = [post(:,1), zeros(ndata, 1), post(:,2)]; + delete(hd); + for i = 1 : ndata + hd(i) = plot(x(i, 1), x(i, 2), 'color', dcols(i,:), ... + 'marker', '.', 'markersize', 30); + end + pause(1) + + set(ht, 'string', 'M-step'); + [mix, options] = gmmem(mix, x, options); + fprintf(1, 'Cycle %4d Error %11.6f\n', n, options(8)); + delete(hc); + xvals = mix.centres(:, 1)*ones(1,ncirc) + sqrt(mix.covars')*xs; + yvals = mix.centres(:, 2)*ones(1,ncirc) + sqrt(mix.covars')*ys; + hc(1)=line(xvals(1,:), yvals(1,:), 'color', 'r'); + hc(2)=line(xvals(2,:), yvals(2,:), 'color', 'b'); + pause(1) + +end + +disp(' '); +disp('Press any key to end.') +pause; clc; close(h); clear all + diff --git a/PatRec/NetLab/netlab3_3/demgmm2.m b/PatRec/NetLab/netlab3_3/demgmm2.m new file mode 100644 index 0000000..ae0e04f --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demgmm2.m @@ -0,0 +1,152 @@ +%DEMGMM1 Demonstrate density modelling with a Gaussian mixture model. +% +% Description +% The problem consists of modelling data generated by a mixture of +% three Gaussians in 2 dimensions. The priors are 0.3, 0.5 and 0.2; +% the centres are (2, 3.5), (0, 0) and (0,2); the variances are 0.2, +% 0.5 and 1.0. The first figure contains a scatter plot of the data. +% +% A Gaussian mixture model with three components is trained using EM. +% The parameter vector is printed before training and after training. +% The user should press any key to continue at these points. The +% parameter vector consists of priors (the column), centres (given as +% (x, y) pairs as the next two columns), and variances (the last +% column). +% +% The second figure is a 3 dimensional view of the density function, +% while the third shows the 1-standard deviation circles for the three +% components of the mixture model. +% +% See also +% GMM, GMMINIT, GMMEM, GMMPROB, GMMUNPAK +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Generate the data +% Fix seeds for reproducible results +randn('state', 42); +rand('state', 42); + +ndata = 500; +[data, datac, datap, datasd] = dem2ddat(ndata); + +clc +disp('This demonstration illustrates the use of a Gaussian mixture model') +disp('to approximate the unconditional probability density of data in') +disp('a two-dimensional space. We begin by generating the data from') +disp('a mixture of three Gaussians and plotting it.') +disp(' ') +disp('Press any key to continue') +pause + +fh1 = figure; +plot(data(:, 1), data(:, 2), 'o') +set(gca, 'Box', 'on') +% Set up mixture model +ncentres = 3; +input_dim = 2; +mix = gmm(input_dim, ncentres, 'spherical'); + +options = foptions; +options(14) = 5; % Just use 5 iterations of k-means in initialisation +% Initialise the model parameters from the data +mix = gmminit(mix, data, options); + +clc +disp('The data is drawn from a mixture with parameters') +disp(' Priors Centres Variances') +disp([datap' datac (datasd.^2)']) +disp(' ') +disp('The mixture model has three components and spherical covariance') +disp('matrices. The model parameters after initialisation using the') +disp('k-means algorithm are as follows') +% Print out model +disp(' Priors Centres Variances') +disp([mix.priors' mix.centres mix.covars']) +disp('Press any key to continue') +pause + +% Set up vector of options for EM trainer +options = zeros(1, 18); +options(1) = 1; % Prints out error values. +options(14) = 10; % Max. Number of iterations. + +disp('We now train the model using the EM algorithm for 10 iterations') +disp(' ') +disp('Press any key to continue') +pause +[mix, options, errlog] = gmmem(mix, data, options); + +% Print out model +disp(' ') +disp('The trained model has parameters ') +disp(' Priors Centres Variances') +disp([mix.priors' mix.centres mix.covars']) +disp('Note the close correspondence between these parameters and those') +disp('of the distribution used to generate the data, which are repeated here.') +disp(' Priors Centres Variances') +disp([datap' datac (datasd.^2)']) +disp(' ') +disp('Press any key to continue') +pause + +clc +disp('We now plot the density given by the mixture model as a surface plot') +disp(' ') +disp('Press any key to continue') +pause +% Plot the result +x = -4.0:0.2:5.0; +y = -4.0:0.2:5.0; +[X, Y] = meshgrid(x,y); +X = X(:); +Y = Y(:); +grid = [X Y]; +Z = gmmprob(mix, grid); +Z = reshape(Z, length(x), length(y)); +c = mesh(x, y, Z); +hold on +title('Surface plot of probability density') +hold off + +clc +disp('The final plot shows the centres and widths, given by one standard') +disp('deviation, of the three components of the mixture model.') +disp(' ') +disp('Press any key to continue.') +pause +% Try to calculate a sensible position for the second figure, below the first +fig1_pos = get(fh1, 'Position'); +fig2_pos = fig1_pos; +fig2_pos(2) = fig2_pos(2) - fig1_pos(4); +fh2 = figure; +set(fh2, 'Position', fig2_pos) + +hp1 = plot(data(:, 1), data(:, 2), 'bo'); +axis('equal'); +hold on +hp2 = plot(mix.centres(:, 1), mix.centres(:,2), 'g+'); +set(hp2, 'MarkerSize', 10); +set(hp2, 'LineWidth', 3); + +title('Plot of data and mixture centres') +angles = 0:pi/30:2*pi; +for i = 1 : mix.ncentres + x_circle = mix.centres(i,1)*ones(1, length(angles)) + ... + sqrt(mix.covars(i))*cos(angles); + y_circle = mix.centres(i,2)*ones(1, length(angles)) + ... + sqrt(mix.covars(i))*sin(angles); + plot(x_circle, y_circle, 'r') +end +hold off +disp('Note how the data cluster positions and widths are captured by') +disp('the mixture model.') +disp(' ') +disp('Press any key to end.') +pause + +close(fh1); +close(fh2); +clear all; + diff --git a/PatRec/NetLab/netlab3_3/demgmm3.m b/PatRec/NetLab/netlab3_3/demgmm3.m new file mode 100644 index 0000000..4e4210d --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demgmm3.m @@ -0,0 +1,192 @@ +%DEMGMM3 Demonstrate density modelling with a Gaussian mixture model. +% +% Description +% The problem consists of modelling data generated by a mixture of +% three Gaussians in 2 dimensions with a mixture model using diagonal +% covariance matrices. The priors are 0.3, 0.5 and 0.2; the centres +% are (2, 3.5), (0, 0) and (0,2); the covariances are all axis aligned +% (0.16, 0.64), (0.25, 1) and the identity matrix. The first figure +% contains a scatter plot of the data. +% +% A Gaussian mixture model with three components is trained using EM. +% The parameter vector is printed before training and after training. +% The user should press any key to continue at these points. The +% parameter vector consists of priors (the column), and centres (given +% as (x, y) pairs as the next two columns). The diagonal entries of +% the covariance matrices are printed separately. +% +% The second figure is a 3 dimensional view of the density function, +% while the third shows the axes of the 1-standard deviation circles +% for the three components of the mixture model. +% +% See also +% GMM, GMMINIT, GMMEM, GMMPROB, GMMUNPAK +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Generate the data +ndata = 500; + +% Fix the seeds for reproducible results +randn('state', 42); +rand('state', 42); +data = randn(ndata, 2); +prior = [0.3 0.5 0.2]; +% Mixture model swaps clusters 1 and 3 +datap = [0.2 0.5 0.3]; +datac = [0 2; 0 0; 2 3.5]; +datacov = [1 1;1 0.25; 0.4*0.4 0.8*0.8]; +data1 = data(1:prior(1)*ndata,:); +data2 = data(prior(1)*ndata+1:(prior(2)+prior(1))*ndata, :); +data3 = data((prior(1)+prior(2))*ndata +1:ndata, :); + +% First cluster has axis aligned variance and centre (2, 3.5) +data1(:, 1) = data1(:, 1)*0.4 + 2.0; +data1(:, 2) = data1(:, 2)*0.8 + 3.5; + +% Second cluster has axis aligned variance and centre (0, 0) +data2(:,2) = data2(:, 2)*0.5; + +% Third cluster is at (0,2) with identity matrix for covariance +data3 = data3 + repmat([0 2], prior(3)*ndata, 1); + +% Put the dataset together again +data = [data1; data2; data3]; + +clc +disp('This demonstration illustrates the use of a Gaussian mixture model') +disp('with diagonal covariance matrices to approximate the unconditional') +disp('probability density of data in a two-dimensional space.') +disp('We begin by generating the data from a mixture of three Gaussians') +disp('with axis aligned covariance structure and plotting it.') +disp(' ') +disp('The first cluster has centre (0, 2).') +disp('The second cluster has centre (0, 0).') +disp('The third cluster has centre (2, 3.5).') +disp(' ') +disp('Press any key to continue') +pause + +fh1 = figure; +plot(data(:, 1), data(:, 2), 'o') +set(gca, 'Box', 'on') + +% Set up mixture model +ncentres = 3; +input_dim = 2; +mix = gmm(input_dim, ncentres, 'diag'); + +options = foptions; +options(14) = 5; % Just use 5 iterations of k-means in initialisation +% Initialise the model parameters from the data +mix = gmminit(mix, data, options); + +% Print out model +disp('The mixture model has three components and diagonal covariance') +disp('matrices. The model parameters after initialisation using the') +disp('k-means algorithm are as follows') +disp(' Priors Centres') +disp([mix.priors' mix.centres]) +disp('Covariance diagonals are') +disp(mix.covars) +disp('Press any key to continue.') +pause + +% Set up vector of options for EM trainer +options = zeros(1, 18); +options(1) = 1; % Prints out error values. +options(14) = 20; % Number of iterations. + +disp('We now train the model using the EM algorithm for 20 iterations.') +disp(' ') +disp('Press any key to continue.') +pause + +[mix, options, errlog] = gmmem(mix, data, options); + +% Print out model +disp(' ') +disp('The trained model has priors and centres:') +disp(' Priors Centres') +disp([mix.priors' mix.centres]) +disp('The data generator has priors and centres') +disp(' Priors Centres') +disp([datap' datac]) +disp('Model covariance diagonals are') +disp(mix.covars) +disp('Data generator covariance diagonals are') +disp(datacov) +disp('Note the close correspondence between these parameters and those') +disp('of the distribution used to generate the data.') +disp(' ') +disp('Press any key to continue.') +pause + +clc +disp('We now plot the density given by the mixture model as a surface plot.') +disp(' ') +disp('Press any key to continue.') +pause + +% Plot the result +x = -4.0:0.2:5.0; +y = -4.0:0.2:5.0; +[X, Y] = meshgrid(x,y); +X = X(:); +Y = Y(:); +grid = [X Y]; +Z = gmmprob(mix, grid); +Z = reshape(Z, length(x), length(y)); +c = mesh(x, y, Z); +hold on +title('Surface plot of probability density') +hold off +drawnow + +clc +disp('The final plot shows the centres and widths, given by one standard') +disp('deviation, of the three components of the mixture model. The axes') +disp('of the ellipses of constant density are shown.') +disp(' ') +disp('Press any key to continue.') +pause + +% Try to calculate a sensible position for the second figure, below the first +fig1_pos = get(fh1, 'Position'); +fig2_pos = fig1_pos; +fig2_pos(2) = fig2_pos(2) - fig1_pos(4); +fh2 = figure('Position', fig2_pos); + +h = plot(data(:, 1), data(:, 2), 'bo'); +hold on +axis('equal'); +title('Plot of data and covariances') +for i = 1:ncentres + v = [1 0]; + for j = 1:2 + start=mix.centres(i,:)-sqrt(mix.covars(i,:).*v); + endpt=mix.centres(i,:)+sqrt(mix.covars(i,:).*v); + linex = [start(1) endpt(1)]; + liney = [start(2) endpt(2)]; + line(linex, liney, 'Color', 'k', 'LineWidth', 3) + v = [0 1]; + end + % Plot ellipses of one standard deviation + theta = 0:0.02:2*pi; + x = sqrt(mix.covars(i,1))*cos(theta) + mix.centres(i,1); + y = sqrt(mix.covars(i,2))*sin(theta) + mix.centres(i,2); + plot(x, y, 'r-'); +end +hold off + +disp('Note how the data cluster positions and widths are captured by') +disp('the mixture model.') +disp(' ') +disp('Press any key to end.') +pause + +close(fh1); +close(fh2); +clear all; + diff --git a/PatRec/NetLab/netlab3_3/demgmm4.m b/PatRec/NetLab/netlab3_3/demgmm4.m new file mode 100644 index 0000000..1242678 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demgmm4.m @@ -0,0 +1,210 @@ +%DEMGMM4 Demonstrate density modelling with a Gaussian mixture model. +% +% Description +% The problem consists of modelling data generated by a mixture of +% three Gaussians in 2 dimensions with a mixture model using full +% covariance matrices. The priors are 0.3, 0.5 and 0.2; the centres +% are (2, 3.5), (0, 0) and (0,2); the variances are (0.16, 0.64) axis +% aligned, (0.25, 1) rotated by 30 degrees and the identity matrix. The +% first figure contains a scatter plot of the data. +% +% A Gaussian mixture model with three components is trained using EM. +% The parameter vector is printed before training and after training. +% The user should press any key to continue at these points. The +% parameter vector consists of priors (the column), and centres (given +% as (x, y) pairs as the next two columns). The covariance matrices +% are printed separately. +% +% The second figure is a 3 dimensional view of the density function, +% while the third shows the axes of the 1-standard deviation ellipses +% for the three components of the mixture model. +% +% See also +% GMM, GMMINIT, GMMEM, GMMPROB, GMMUNPAK +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +% Generate the data + +ndata = 500; + +% Fix the seeds for reproducible results +randn('state', 42); +rand('state', 42); +data = randn(ndata, 2); +prior = [0.3 0.5 0.2]; +% Mixture model swaps clusters 1 and 3 +datap = [0.2 0.5 0.3]; +datac = [0 2; 0 0; 2 3.5]; +datacov = repmat(eye(2), [1 1 3]); +data1 = data(1:prior(1)*ndata,:); +data2 = data(prior(1)*ndata+1:(prior(2)+prior(1))*ndata, :); +data3 = data((prior(1)+prior(2))*ndata +1:ndata, :); + +% First cluster has axis aligned variance and centre (2, 3.5) +data1(:, 1) = data1(:, 1)*0.4 + 2.0; +data1(:, 2) = data1(:, 2)*0.8 + 3.5; +datacov(:, :, 3) = [0.4*0.4 0; 0 0.8*0.8]; + +% Second cluster has variance axes rotated by 30 degrees and centre (0, 0) +rotn = [cos(pi/6) -sin(pi/6); sin(pi/6) cos(pi/6)]; +data2(:,1) = data2(:, 1)*0.5; +data2 = data2*rotn; +datacov(:, :, 2) = rotn' * [0.25 0; 0 1] * rotn; + +% Third cluster is at (0,2) +data3 = data3 + repmat([0 2], prior(3)*ndata, 1); + +% Put the dataset together again +data = [data1; data2; data3]; + +clc +disp('This demonstration illustrates the use of a Gaussian mixture model') +disp('with full covariance matrices to approximate the unconditional ') +disp('probability density of data in a two-dimensional space.') +disp('We begin by generating the data from a mixture of three Gaussians and') +disp('plotting it.') +disp(' ') +disp('The first cluster has axis aligned variance and centre (0, 2).') +disp('The second cluster has variance axes rotated by 30 degrees') +disp('and centre (0, 0). The third cluster has unit variance and centre') +disp('(2, 3.5).') +disp(' ') +disp('Press any key to continue.') +pause + +fh1 = figure; +plot(data(:, 1), data(:, 2), 'o') +set(gca, 'Box', 'on') + +% Set up mixture model +ncentres = 3; +input_dim = 2; +mix = gmm(input_dim, ncentres, 'full'); + +% Initialise the model parameters from the data +options = foptions; +options(14) = 5; % Just use 5 iterations of k-means in initialisation +mix = gmminit(mix, data, options); + +% Print out model +clc +disp('The mixture model has three components and full covariance') +disp('matrices. The model parameters after initialisation using the') +disp('k-means algorithm are as follows') +disp(' Priors Centres') +disp([mix.priors' mix.centres]) +disp('Covariance matrices are') +disp(mix.covars) +disp('Press any key to continue.') +pause + +% Set up vector of options for EM trainer +options = zeros(1, 18); +options(1) = 1; % Prints out error values. +options(14) = 50; % Number of iterations. + +disp('We now train the model using the EM algorithm for 50 iterations.') +disp(' ') +disp('Press any key to continue.') +pause +[mix, options, errlog] = gmmem(mix, data, options); + +% Print out model +disp(' ') +disp('The trained model has priors and centres:') +disp(' Priors Centres') +disp([mix.priors' mix.centres]) +disp('The data generator has priors and centres') +disp(' Priors Centres') +disp([datap' datac]) +disp('Model covariance matrices are') +disp(mix.covars(:, :, 1)) +disp(mix.covars(:, :, 2)) +disp(mix.covars(:, :, 3)) +disp('Data generator covariance matrices are') +disp(datacov(:, :, 1)) +disp(datacov(:, :, 2)) +disp(datacov(:, :, 3)) +disp('Note the close correspondence between these parameters and those') +disp('of the distribution used to generate the data. The match for') +disp('covariance matrices is not that close, but would be improved with') +disp('more iterations of the training algorithm.') +disp(' ') +disp('Press any key to continue.') +pause + +clc +disp('We now plot the density given by the mixture model as a surface plot.') +disp(' ') +disp('Press any key to continue.') +pause + +% Plot the result +x = -4.0:0.2:5.0; +y = -4.0:0.2:5.0; +[X, Y] = meshgrid(x,y); +X = X(:); +Y = Y(:); +grid = [X Y]; +Z = gmmprob(mix, grid); +Z = reshape(Z, length(x), length(y)); +c = mesh(x, y, Z); +hold on +title('Surface plot of probability density') +hold off +drawnow + +clc +disp('The final plot shows the centres and widths, given by one standard') +disp('deviation, of the three components of the mixture model. The axes') +disp('of the ellipses of constant density are shown.') +disp(' ') +disp('Press any key to continue.') +pause + +% Try to calculate a sensible position for the second figure, below the first +fig1_pos = get(fh1, 'Position'); +fig2_pos = fig1_pos; +fig2_pos(2) = fig2_pos(2) - fig1_pos(4) - 30; +fh2 = figure('Position', fig2_pos); + +h3 = plot(data(:, 1), data(:, 2), 'bo'); +axis equal; +hold on +title('Plot of data and covariances') +for i = 1:ncentres + [v,d] = eig(mix.covars(:,:,i)); + for j = 1:2 + % Ensure that eigenvector has unit length + v(:,j) = v(:,j)/norm(v(:,j)); + start=mix.centres(i,:)-sqrt(d(j,j))*(v(:,j)'); + endpt=mix.centres(i,:)+sqrt(d(j,j))*(v(:,j)'); + linex = [start(1) endpt(1)]; + liney = [start(2) endpt(2)]; + line(linex, liney, 'Color', 'k', 'LineWidth', 3) + end + % Plot ellipses of one standard deviation + theta = 0:0.02:2*pi; + x = sqrt(d(1,1))*cos(theta); + y = sqrt(d(2,2))*sin(theta); + % Rotate ellipse axes + ellipse = (v*([x; y]))'; + % Adjust centre + ellipse = ellipse + ones(length(theta), 1)*mix.centres(i,:); + plot(ellipse(:,1), ellipse(:,2), 'r-'); +end +hold off + +disp('Note how the data cluster positions and widths are captured by') +disp('the mixture model.') +disp(' ') +disp('Press any key to end.') +pause + +close(fh1); +close(fh2); +clear all; + diff --git a/PatRec/NetLab/netlab3_3/demgmm5.m b/PatRec/NetLab/netlab3_3/demgmm5.m new file mode 100644 index 0000000..a9fd3ee --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demgmm5.m @@ -0,0 +1,147 @@ +%DEMGMM5 Demonstrate density modelling with a PPCA mixture model. +% +% Description +% The problem consists of modelling data generated by a mixture of +% three Gaussians in 2 dimensions with a mixture model using full +% covariance matrices. The priors are 0.3, 0.5 and 0.2; the centres +% are (2, 3.5), (0, 0) and (0,2); the variances are (0.16, 0.64) axis +% aligned, (0.25, 1) rotated by 30 degrees and the identity matrix. The +% first figure contains a scatter plot of the data. +% +% A mixture model with three one-dimensional PPCA components is trained +% using EM. The parameter vector is printed before training and after +% training. The parameter vector consists of priors (the column), and +% centres (given as (x, y) pairs as the next two columns). +% +% The second figure is a 3 dimensional view of the density function, +% while the third shows the axes of the 1-standard deviation ellipses +% for the three components of the mixture model together with the one +% standard deviation along the principal component of each mixture +% model component. +% +% See also +% GMM, GMMINIT, GMMEM, GMMPROB, PPCA +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +ndata = 500; +data = randn(ndata, 2); +prior = [0.3 0.5 0.2]; +% Mixture model swaps clusters 1 and 3 +datap = [0.2 0.5 0.3]; +datac = [0 2; 0 0; 2 3.5]; +datacov = repmat(eye(2), [1 1 3]); +data1 = data(1:prior(1)*ndata,:); +data2 = data(prior(1)*ndata+1:(prior(2)+prior(1))*ndata, :); +data3 = data((prior(1)+prior(2))*ndata +1:ndata, :); + +% First cluster has axis aligned variance and centre (2, 3.5) +data1(:, 1) = data1(:, 1)*0.1 + 2.0; +data1(:, 2) = data1(:, 2)*0.8 + 3.5; +datacov(:, :, 3) = [0.1*0.1 0; 0 0.8*0.8]; + +% Second cluster has variance axes rotated by 30 degrees and centre (0, 0) +rotn = [cos(pi/6) -sin(pi/6); sin(pi/6) cos(pi/6)]; +data2(:,1) = data2(:, 1)*0.2; +data2 = data2*rotn; +datacov(:, :, 2) = rotn' * [0.04 0; 0 1] * rotn; + +% Third cluster is at (0,2) +data3(:, 2) = data3(:, 2)*0.1; +data3 = data3 + repmat([0 2], prior(3)*ndata, 1); + +% Put the dataset together again +data = [data1; data2; data3]; + +ndata = 100; % Number of data points. +noise = 0.2; % Standard deviation of noise distribution. +x = [0:1/(2*(ndata - 1)):0.5]'; +randn('state', 1); +rand('state', 1); +t = sin(2*pi*x) + noise*randn(ndata, 1); + +% Fit three one-dimensional PPCA models +ncentres = 3; +ppca_dim = 1; + +clc +disp('This demonstration illustrates the use of a Gaussian mixture model') +disp('with a probabilistic PCA covariance structure to approximate the') +disp('unconditional probability density of data in a two-dimensional space.') +disp('We begin by generating the data from a mixture of three Gaussians and') +disp('plotting it.') +disp(' ') +disp('The first cluster has axis aligned variance and centre (0, 2).') +disp('The variance parallel to the x-axis is significantly greater') +disp('than that parallel to the y-axis.') +disp('The second cluster has variance axes rotated by 30 degrees') +disp('and centre (0, 0). The third cluster has significant variance') +disp('parallel to the y-axis and centre (2, 3.5).') +disp(' ') +disp('Press any key to continue.') +pause + +fh1 = figure; +plot(data(:, 1), data(:, 2), 'o') +set(gca, 'Box', 'on') +axis equal +hold on + +mix = gmm(2, ncentres, 'ppca', ppca_dim); +options = foptions; +options(14) = 10; +options(1) = -1; % Switch off all warnings + +% Just use 10 iterations of k-means in initialisation +% Initialise the model parameters from the data +mix = gmminit(mix, data, options); +disp('The mixture model has three components with 1-dimensional') +disp('PPCA subspaces. The model parameters after initialisation using') +disp('the k-means algorithm are as follows') +disp(' Priors Centres') +disp([mix.priors' mix.centres]) +disp(' ') +disp('Press any key to continue') +pause + +options(1) = 1; % Prints out error values. +options(14) = 30; % Number of iterations. + +disp('We now train the model using the EM algorithm for up to 30 iterations.') +disp(' ') +disp('Press any key to continue.') +pause + +[mix, options, errlog] = gmmem(mix, data, options); +disp('The trained model has priors and centres:') +disp(' Priors Centres') +disp([mix.priors' mix.centres]) + +% Now plot the result +for i = 1:ncentres + % Plot the PC vectors + v = mix.U(:,:,i); + start=mix.centres(i,:)-sqrt(mix.lambda(i))*(v'); + endpt=mix.centres(i,:)+sqrt(mix.lambda(i))*(v'); + linex = [start(1) endpt(1)]; + liney = [start(2) endpt(2)]; + line(linex, liney, 'Color', 'k', 'LineWidth', 3) + % Plot ellipses of one standard deviation + theta = 0:0.02:2*pi; + x = sqrt(mix.lambda(i))*cos(theta); + y = sqrt(mix.covars(i))*sin(theta); + % Rotate ellipse axes + rot_matrix = [v(1) -v(2); v(2) v(1)]; + ellipse = (rot_matrix*([x; y]))'; + % Adjust centre + ellipse = ellipse + ones(length(theta), 1)*mix.centres(i,:); + plot(ellipse(:,1), ellipse(:,2), 'r-') +end + +disp(' ') +disp('Press any key to exit') +pause +close (fh1); +clear all; \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/demgp.m b/PatRec/NetLab/netlab3_3/demgp.m new file mode 100644 index 0000000..65c587a --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demgp.m @@ -0,0 +1,160 @@ +%DEMGP Demonstrate simple regression using a Gaussian Process. +% +% Description +% The problem consists of one input variable X and one target variable +% T. The values in X are chosen in two separated clusters and the +% target data is generated by computing SIN(2*PI*X) and adding Gaussian +% noise. Two Gaussian Processes, each with different covariance +% functions are trained by optimising the hyperparameters using the +% scaled conjugate gradient algorithm. The final predictions are +% plotted together with 2 standard deviation error bars. +% +% See also +% GP, GPERR, GPFWD, GPGRAD, GPINIT, SCG +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +% Find out if flops is available (i.e. pre-version 6 Matlab) +v = version; +if (str2num(strtok(v, '.')) >= 6) + flops_works = logical(0); +else + flops_works = logical(1); +end + +randn('state', 42); +x = [0.1 0.15 0.2 0.25 0.65 0.7 0.75 0.8 0.85 0.9]'; +ndata = length(x); +t = sin(2*pi*x) + 0.05*randn(ndata, 1); + +xtest = linspace(0, 1, 50)'; + +clc +disp('This demonstration illustrates the use of a Gaussian Process') +disp('model for regression problems. The data is generated from a noisy') +disp('sine function.') +disp(' ') +disp('Press any key to continue.') +pause + +flops(0); +% Initialise the parameters. +net = gp(1, 'sqexp'); +prior.pr_mean = 0; +prior.pr_var = 1; +net = gpinit(net, x, t, prior); + +clc +disp('The first GP uses the squared exponential covariance function.') +disp('The hyperparameters are initialised by sampling from a Gaussian with a') +disp(['mean of ', num2str(prior.pr_mean), ' and variance ', ... + num2str(prior.pr_var), '.']) +disp('After initializing the network, we train it using the scaled conjugate') +disp('gradients algorithm for 20 cycles.') +disp(' ') +disp('Press any key to continue') +pause + +% Now train to find the hyperparameters. +options = foptions; +options(1) = 1; % Display training error values +options(14) = 20; +flops(0) +[net, options] = netopt(net, options, x, t, 'scg'); +if flops_works + sflops = flops; +end + +disp('The second GP uses the rational quadratic covariance function.') +disp('The hyperparameters are initialised by sampling from a Gaussian with a') +disp(['mean of ', num2str(prior.pr_mean), ' and variance ', num2str(prior.pr_var)]) +disp('After initializing the network, we train it using the scaled conjugate') +disp('gradients algorithm for 20 cycles.') +disp(' ') +disp('Press any key to continue') +pause +flops(0) +net2 = gp(1, 'ratquad'); +net2 = gpinit(net2, x, t, prior); +flops(0) +[net2, options] = netopt(net2, options, x, t, 'scg'); +if flops_works + rflops = flops; +end + +disp(' ') +disp('Press any key to continue') +disp(' ') +pause +clc + +fprintf(1, 'For squared exponential covariance function,'); +if flops_works + fprintf(1, 'flops = %d', sflops); +end +fprintf(1, '\nfinal hyperparameters:\n') +format_string = strcat(' bias:\t\t\t%10.6f\n noise:\t\t%10.6f\n', ... + ' inverse lengthscale:\t%10.6f\n vertical scale:\t%10.6f\n'); +fprintf(1, format_string, ... + exp(net.bias), exp(net.noise), exp(net.inweights(1)), exp(net.fpar(1))); +fprintf(1, '\n\nFor rational quadratic covariance function,'); +if flops_works + fprintf(1, 'flops = %d', rflops); +end +fprintf(1, '\nfinal hyperparameters:\n') +format_string = [format_string ' cov decay order:\t%10.6f\n']; +fprintf(1, format_string, ... + exp(net2.bias), exp(net2.noise), exp(net2.inweights(1)), ... + exp(net2.fpar(1)), exp(net2.fpar(2))); +disp(' ') +disp('Press any key to continue') +pause + +disp(' ') +disp('Now we plot the data, underlying function, model outputs and two') +disp('standard deviation error bars on a single graph to compare the results.') +disp(' ') +disp('Press any key to continue.') +pause +cn = gpcovar(net, x); +cninv = inv(cn); +[ytest, sigsq] = gpfwd(net, xtest, cninv); +sig = sqrt(sigsq); + +fh1 = figure; +hold on +plot(x, t, 'ok'); +xlabel('Input') +ylabel('Target') +fplot('sin(2*pi*x)', [0 1], '--m'); +plot(xtest, ytest, '-k'); +plot(xtest, ytest+(2*sig), '-b', xtest, ytest-(2*sig), '-b'); +axis([0 1 -1.5 1.5]); +title('Squared exponential covariance function') +legend('data', 'function', 'GP', 'error bars'); +hold off + +cninv2 = inv(gpcovar(net2, x)); +[ytest2, sigsq2] = gpfwd(net2, xtest, cninv2); +sig2 = sqrt(sigsq2); +fh2 = figure; +hold on +plot(x, t, 'ok'); +xlabel('Input') +ylabel('Target') +fplot('sin(2*pi*x)', [0 1], '--m'); +plot(xtest, ytest2, '-k'); +plot(xtest, ytest2+(2*sig2), '-b', xtest, ytest2-(2*sig2), '-b'); +axis([0 1 -1.5 1.5]); +title('Rational quadratic covariance function') +legend('data', 'function', 'GP', 'error bars'); +hold off + +disp(' ') +disp('Press any key to end.') +pause +close(fh1); +close(fh2); +clear all; \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/demgpard.m b/PatRec/NetLab/netlab3_3/demgpard.m new file mode 100644 index 0000000..82e8d2a --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demgpard.m @@ -0,0 +1,126 @@ +%DEMGPARD Demonstrate ARD using a Gaussian Process. +% +% Description +% The data consists of three input variables X1, X2 and X3, and one +% target variable T. The target data is generated by computing +% SIN(2*PI*X1) and adding Gaussian noise, x2 is a copy of x1 with a +% higher level of added noise, and x3 is sampled randomly from a +% Gaussian distribution. A Gaussian Process, is trained by optimising +% the hyperparameters using the scaled conjugate gradient algorithm. +% The final values of the hyperparameters show that the model +% successfully identifies the importance of each input. +% +% See also +% DEMGP, GP, GPERR, GPFWD, GPGRAD, GPINIT, SCG +% + +% Copyright (c) Ian T Nabney (1996-2001) + +clc; +randn('state', 1729); +rand('state', 1729); +disp('This demonstration illustrates the technique of automatic relevance') +disp('determination (ARD) using a Gaussian Process.') +disp(' '); +disp('First, we set up a synthetic data set involving three input variables:') +disp('x1 is sampled uniformly from the range (0,1) and has a low level of') +disp('added Gaussian noise, x2 is a copy of x1 with a higher level of added') +disp('noise, and x3 is sampled randomly from a Gaussian distribution. The') +disp('single target variable is given by t = sin(2*pi*x1) with additive') +disp('Gaussian noise. Thus x1 is very relevant for determining the target') +disp('value, x2 is of some relevance, while x3 should in principle be') +disp('irrelevant.') +disp(' '); +disp('Press any key to see a plot of t against x1.') +pause; + +ndata = 100; +x1 = rand(ndata, 1); +x2 = x1 + 0.05*randn(ndata, 1); +x3 = 0.5 + 0.5*randn(ndata, 1); +x = [x1, x2, x3]; +t = sin(2*pi*x1) + 0.1*randn(ndata, 1); + +% Plot the data and the original function. +h = figure; +plotvals = linspace(0, 1, 200)'; +plot(x1, t, 'ob') +hold on +xlabel('Input x1') +ylabel('Target') +axis([0 1 -1.5 1.5]) +[fx, fy] = fplot('sin(2*pi*x)', [0 1]); +plot(fx, fy, '-g', 'LineWidth', 2); +legend('data', 'function'); + +disp(' '); +disp('Press any key to continue') +pause; clc; + +disp('The Gaussian Process has a separate hyperparameter for each input.') +disp('The hyperparameters are trained by error minimisation using the scaled.') +disp('conjugate gradient optimiser.') +disp(' '); +disp('Press any key to create and train the model.') +disp(' '); +pause; + +net = gp(3, 'sqexp'); +% Initialise the parameters. +prior.pr_mean = 0; +prior.pr_var = 0.1; +net = gpinit(net, x, t, prior); + +% Now train to find the hyperparameters. +options = foptions; +options(1) = 1; +options(14) = 30; + +[net, options] = netopt(net, options, x, t, 'scg'); + +rel = exp(net.inweights); + +fprintf(1, ... + '\nFinal hyperparameters:\n\n bias:\t\t%10.6f\n noise:\t%10.6f\n', ... + exp(net.bias), exp(net.noise)); +fprintf(1, ' Vertical scale: %8.6f\n', exp(net.fpar(1))); +fprintf(1, ' Input 1:\t%10.6f\n Input 2:\t%10.6f\n', ... + rel(1), rel(2)); +fprintf(1, ' Input 3:\t%10.6f\n\n', rel(3)); +disp(' '); +disp('We see that the inverse lengthscale associated with') +disp('input x1 is large, that of x2 has an intermediate value and the variance') +disp('of weights associated with x3 is small.') +disp(' '); +disp('This implies that the Gaussian Process is giving greatest emphasis') +disp('to x1 and least emphasis to x3, with intermediate emphasis on') +disp('x2 in the covariance function.') +disp(' ') +disp('Since the target t is statistically independent of x3 we might') +disp('expect the weights associated with this input would go to') +disp('zero. However, for any finite data set there may be some chance') +disp('correlation between x3 and t, and so the corresponding hyperparameter remains') +disp('finite.') +disp('Press any key to continue.') +pause + +disp('Finally, we plot the output of the Gaussian Process along the line') +disp('x1 = x2 = x3, together with the true underlying function.') +xt = linspace(0, 1, 50); +xtest = [xt', xt', xt']; + +cn = gpcovar(net, x); +cninv = inv(cn); +[ytest, sigsq] = gpfwd(net, xtest, cninv); +sig = sqrt(sigsq); + +figure(h); hold on; +plot(xt, ytest, '-k'); +plot(xt, ytest+(2*sig), '-b', xt, ytest-(2*sig), '-b'); +axis([0 1 -1.5 1.5]); +fplot('sin(2*pi*x)', [0 1], '--m'); + +disp(' '); +disp('Press any key to end.') +pause; clc; close(h); clear all + diff --git a/PatRec/NetLab/netlab3_3/demgpot.m b/PatRec/NetLab/netlab3_3/demgpot.m new file mode 100644 index 0000000..c859fd0 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demgpot.m @@ -0,0 +1,29 @@ +function g = demgpot(x, mix) +%DEMGPOT Computes the gradient of the negative log likelihood for a mixture model. +% +% Description +% This function computes the gradient of the negative log of the +% unconditional data density P(X) with respect to the coefficients of +% the data vector X for a Gaussian mixture model. The data structure +% MIX defines the mixture model, while the matrix X contains the data +% vector as a row vector. Note the unusual order of the arguments: this +% is so that the function can be used in DEMHMC1 directly for sampling +% from the distribution P(X). +% +% See also +% DEMHMC1, DEMMET1, DEMPOT +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Computes the potential gradient + +temp = (ones(mix.ncentres,1)*x)-mix.centres; +temp = temp.*(gmmactiv(mix,x)'*ones(1, mix.nin)); +% Assume spherical covariance structure +if ~strcmp(mix.covar_type, 'spherical') + error('Spherical covariance only.') +end +temp = temp./(mix.covars'*ones(1, mix.nin)); +temp = temp.*(mix.priors'*ones(1, mix.nin)); +g = sum(temp, 1)/gmmprob(mix, x); \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/demgtm1.m b/PatRec/NetLab/netlab3_3/demgtm1.m new file mode 100644 index 0000000..a127617 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demgtm1.m @@ -0,0 +1,147 @@ +%DEMGTM1 Demonstrate EM for GTM. +% +% Description +% This script demonstrates the use of the EM algorithm to fit a one- +% dimensional GTM to a two-dimensional set of data using maximum +% likelihood. The location and spread of the Gaussian kernels in the +% data space is shown during training. +% +% See also +% DEMGTM2, GTM, GTMEM, GTMPOST +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Demonstrates the GTM with a 2D target space and a 1D latent space. +% +% This script generates a simple data set in 2 dimensions, +% with an intrinsic dimensionality of 1, and trains a GTM +% with a 1-dimensional latent variable to model this data +% set, visually illustrating the training process +% +% Synopsis: gtm_demo + +% Generate and plot a 2D data set + +data_min = 0.15; +data_max = 3.05; +T = [data_min:0.05:data_max]'; +T = [T (T + 1.25*sin(2*T))]; +fh1 = figure; +plot(T(:,1), T(:,2), 'ro'); +axis([data_min-0.05 data_max+0.05 data_min-0.05 data_max+0.05]); +clc; +disp('This demonstration shows in detail how the EM algorithm works') +disp('for training a GTM with a one dimensional latent space.') +disp(' ') +fprintf([... +'The figure shows data generated by feeding a 1D uniform distribution\n', ... +'(on the X-axis) through a non-linear function (y = x + 1.25*sin(2*x))\n', ... +'\nPress any key to continue ...\n\n']); +pause; + +% Generate a unit circle figure, to be used for plotting +src = [0:(2*pi)/(20-1):2*pi]'; +unitC = [sin(src) cos(src)]; + +% Generate and plot (along with the data) an initial GTM model + +clc; +num_latent_points = 20; +num_rbf_centres = 5; + +net = gtm(1, num_latent_points, 2, num_rbf_centres, 'gaussian'); + +options = zeros(1, 18); +options(7) = 1; +net = gtminit(net, options, T, 'regular', num_latent_points, ... + num_rbf_centres); + +mix = gtmfwd(net); +% Replot the figure +hold off; +plot(mix.centres(:,1), mix.centres(:,2), 'g'); +hold on; +for i=1:num_latent_points + c = 2*unitC*sqrt(mix.covars(1)) + [ones(20,1)*mix.centres(i,1) ... + ones(num_latent_points,1)*mix.centres(i,2)]; + fill(c(:,1), c(:,2), [0.8 1 0.8]); +end +plot(T(:,1), T(:,2), 'ro'); +plot(mix.centres(:,1), mix.centres(:,2), 'g+'); +plot(mix.centres(:,1), mix.centres(:,2), 'g'); +axis([data_min-0.05 data_max+0.05 data_min-0.05 data_max+0.05]); +drawnow; +title('Initial configuration'); +disp(' ') +fprintf([... +'The figure shows the starting point for the GTM, before the training.\n', ... +'A discrete latent variable distribution of %d points in 1 dimension \n', ... +'is mapped to the 1st principal component of the target data by an RBF.\n', ... +'with %d basis functions. Each of the %d points defines the centre of\n', ... +'a Gaussian in a Gaussian mixture, marked by the green ''+''-signs. The\n', ... +'mixture components all have equal variance, illustrated by the filled\n', ... +'circle around each ''+''-sign, the radii corresponding to 2 standard\n', ... +'deviations. The ''+''-signs are connected with a line according to their\n', ... +'corresponding ordering in latent space.\n\n', ... +'Press any key to begin training ...\n\n'], num_latent_points, ... +num_rbf_centres, num_latent_points); +pause; + +figure(fh1); +%%%% Train the GTM and plot it (along with the data) as training proceeds %%%% +options = foptions; +options(1) = -1; % Turn off all warning messages +options(14) = 1; +for j = 1:15 + [net, options] = gtmem(net, T, options); + hold off; + mix = gtmfwd(net); + plot(mix.centres(:,1), mix.centres(:,2), 'g'); + hold on; + for i=1:20 + c = 2*unitC*sqrt(mix.covars(1)) + [ones(20,1)*mix.centres(i,1) ... + ones(20,1)*mix.centres(i,2)]; + fill(c(:,1), c(:,2), [0.8 1.0 0.8]); + end + plot(T(:,1), T(:,2), 'ro'); + plot(mix.centres(:,1), mix.centres(:,2), 'g+'); + plot(mix.centres(:,1), mix.centres(:,2), 'g'); + axis([0 3.5 0 3.5]); + title(['After ', int2str(j),' iterations of training.']); + drawnow; + if (j == 4) + fprintf([... +'The GTM initially adapts relatively quickly - already after \n', ... +'4 iterations of training, a rough fit is attained.\n\n', ... +'Press any key to continue training ...\n\n']); +pause; +figure(fh1); + elseif (j == 8) + fprintf([... +'After another 4 iterations of training: from now on further \n', ... +'training only makes small changes to the mapping, which combined with \n', ... +'decrements of the Gaussian mixture variance, optimize the fit in \n', ... +'terms of likelihood.\n\n', ... +'Press any key to continue training ...\n\n']); +pause; +figure(fh1); + else + pause(1); + end +end + +clc; +fprintf([... +'After 15 iterations of training the GTM can be regarded as converged. \n', ... +'Is has been adapted to fit the target data distribution as well \n', ... +'as possible, given prior smoothness constraints on the mapping. It \n', ... +'captures the fact that the probabilty density is higher at the two \n', ... +'bends of the curve, and lower towards its end points.\n\n']); +disp(' '); +disp('Press any key to exit.'); +pause; + +close(fh1); +clear all; + diff --git a/PatRec/NetLab/netlab3_3/demgtm2.m b/PatRec/NetLab/netlab3_3/demgtm2.m new file mode 100644 index 0000000..2cfa907 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demgtm2.m @@ -0,0 +1,194 @@ +%DEMGTM2 Demonstrate GTM for visualisation. +% +% Description +% This script demonstrates the use of a GTM with a two-dimensional +% latent space to visualise data in a higher dimensional space. This is +% done through the use of the mean responsibility and magnification +% factors. +% +% See also +% DEMGTM1, GTM, GTMEM, GTMPOST +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +% Fix seeds for reproducible results +rand('state', 420); +randn('state', 420); + +ndata = 300 +clc; +disp('This demonstration shows how a Generative Topographic Mapping') +disp('can be used to model and visualise high dimensional data. The') +disp('data is generated from a mixture of two spherical Gaussians in') +dstring = ['four dimensional space. ', num2str(ndata), ... + ' data points are generated.']; +disp(dstring); +disp(' '); +disp('Press any key to continue.') +pause +% Create data +data_dim = 4; +latent_dim = 2; +mix = gmm(data_dim, 2, 'spherical'); +mix.centres = [1 1 1 1; 0 0 0 0]; +mix.priors = [0.5 0.5]; +mix.covars = [0.1 0.1]; + +[data, labels] = gmmsamp(mix, ndata); + +latent_shape = [15 15]; % Number of latent points in each dimension +nlatent = prod(latent_shape); % Number of latent points +num_rbf_centres = 16; + +clc; +dstring = ['Next we generate and initialise the GTM. There are ',... + num2str(nlatent), ' latent points']; +disp(dstring); +dstring = ['arranged in a square of ', num2str(latent_shape(1)), ... + ' points on a side. There are ', num2str(num_rbf_centres), ... + ' centres in the']; +disp(dstring); +disp('RBF model, which has Gaussian activation functions.') +disp(' ') +disp('Once the model is created, the latent data sample') +disp('and RBF centres are placed uniformly in the square [-1 1 -1 1].') +disp('The output weights of the RBF are computed to map the latent'); +disp('space to the two dimensional PCA subspace of the data.'); +disp(' ') +disp('Press any key to continue.'); +pause; + +% Create and initialise GTM model +net = gtm(latent_dim, nlatent, data_dim, num_rbf_centres, ... + 'gaussian', 0.1); + +options = foptions; +options(1) = -1; +options(7) = 1; % Set width factor of RBF +net = gtminit(net, options, data, 'regular', latent_shape, [4 4]); + +options = foptions; +options(14) = 30; +options(1) = 1; + +clc; +dstring = ['We now train the model with ', num2str(options(14)), ... + ' iterations of']; +disp(dstring) +disp('the EM algorithm for the GTM.') +disp(' ') +disp('Press any key to continue.') +pause; + +[net, options] = gtmem(net, data, options); + +disp(' ') +disp('Press any key to continue.') +pause; + +clc; +disp('We now visualise the data by plotting, for each data point,'); +disp('the posterior mean and mode (in latent space). These give'); +disp('a summary of the entire posterior distribution in latent space.') +disp('The corresponding values are joined by a line to aid the') +disp('interpretation.') +disp(' ') +disp('Press any key to continue.'); +pause; +% Plot posterior means +means = gtmlmean(net, data); +modes = gtmlmode(net, data); +PointSize = 12; +ClassSymbol1 = 'r.'; +ClassSymbol2 = 'b.'; +fh1 = figure; +hold on; +title('Visualisation in latent space') +plot(means((labels==1),1), means(labels==1,2), ... + ClassSymbol1, 'MarkerSize', PointSize) +plot(means((labels>1),1),means(labels>1,2),... + ClassSymbol2, 'MarkerSize', PointSize) + +ClassSymbol1 = 'ro'; +ClassSymbol2 = 'bo'; +plot(modes(labels==1,1), modes(labels==1,2), ... + ClassSymbol1) +plot(modes(labels>1,1),modes(labels>1,2),... + ClassSymbol2) + +% Join up means and modes +for n = 1:ndata + plot([means(n,1); modes(n,1)], [means(n,2); modes(n,2)], 'g-') +end +% Place legend outside data plot +legend('Mean (class 1)', 'Mean (class 2)', 'Mode (class 1)',... + 'Mode (class 2)', -1); + +% Display posterior for a data point +% Choose an interesting one with a large distance between mean and +% mode +[distance, point] = max(sum((means-modes).^2, 2)); +resp = gtmpost(net, data(point, :)); + +disp(' ') +disp('For more detailed information, the full posterior distribution') +disp('(or responsibility) can be plotted in latent space for a') +disp('single data point. This point has been chosen as the one') +disp('with the largest distance between mean and mode.') +disp(' ') +disp('Press any key to continue.'); +pause; + +R = reshape(resp, fliplr(latent_shape)); +XL = reshape(net.X(:,1), fliplr(latent_shape)); +YL = reshape(net.X(:,2), fliplr(latent_shape)); + +fh2 = figure; +imagesc(net.X(:, 1), net.X(:,2), R); +hold on; +tstr = ['Responsibility for point ', num2str(point)]; +title(tstr); +set(gca,'YDir','normal') +colormap(hot); +colorbar +disp(' '); +disp('Press any key to continue.') +pause + +clc +disp('Finally, we visualise the data with the posterior means in') +disp('latent space as before, but superimpose the magnification') +disp('factors to highlight the separation between clusters.') +disp(' ') +disp('Note the large magnitude factors down the centre of the') +disp('graph, showing that the manifold is stretched more in') +disp('this region than within each of the two clusters.') +ClassSymbol1 = 'g.'; +ClassSymbol2 = 'b.'; + +fh3 = figure; +mags = gtmmag(net, net.X); +% Reshape into grid form +Mags = reshape(mags, fliplr(latent_shape)); +imagesc(net.X(:, 1), net.X(:,2), Mags); +hold on +title('Dataset visualisation with magnification factors') +set(gca,'YDir','normal') +colormap(hot); +colorbar +hold on; % Else the magnification plot disappears +plot(means(labels==1,1), means(labels==1,2), ... + ClassSymbol1, 'MarkerSize', PointSize) +plot(means(labels>1,1), means(labels>1,2), ... + ClassSymbol2, 'MarkerSize', PointSize) + +disp(' ') +disp('Press any key to exit.') +pause + +close(fh1); +close(fh2); +close(fh3); +clear all; \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/demhint.m b/PatRec/NetLab/netlab3_3/demhint.m new file mode 100644 index 0000000..bd2e502 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demhint.m @@ -0,0 +1,49 @@ +function demhint(nin, nhidden, nout) +%DEMHINT Demonstration of Hinton diagram for 2-layer feed-forward network. +% +% Description +% +% DEMHINT plots a Hinton diagram for a 2-layer feedforward network with +% 5 inputs, 4 hidden units and 3 outputs. The weight vector is chosen +% from a Gaussian distribution as described under MLP. +% +% DEMHINT(NIN, NHIDDEN, NOUT) allows the user to specify the number of +% inputs, hidden units and outputs. +% +% See also +% HINTON, HINTMAT, MLP, MLPPAK, MLPUNPAK +% + +% Copyright (c) Ian T Nabney (1996-2001) + +if nargin < 1 nin = 5; end +if nargin < 2 nhidden = 7; end +if nargin < 3 nout = 3; end + +% Fix the seed for reproducible results +randn('state', 42); +clc +disp('This demonstration illustrates the plotting of Hinton diagrams') +disp('for Multi-Layer Perceptron networks.') +disp(' ') +disp('Press any key to continue.') +pause +net = mlp(nin, nhidden, nout, 'linear'); + +[h1, h2] = mlphint(net); +clc +disp('The MLP has been created with') +disp([' ' int2str(nin) ' inputs']) +disp([' ' int2str(nhidden) ' hidden units']) +disp([' ' int2str(nout) ' outputs']) +disp(' ') +disp('One figure is produced for each layer of weights.') +disp('For each layer the fan-in weights are arranged in rows for each unit.') +disp('The bias weight is separated from the rest by a red vertical line.') +disp('The area of each box is proportional to the weight value: positive') +disp('values are white, and negative are black.') +disp(' ') +disp('Press any key to exit.'); +pause; +delete(h1); +delete(h2); diff --git a/PatRec/NetLab/netlab3_3/demhmc1.m b/PatRec/NetLab/netlab3_3/demhmc1.m new file mode 100644 index 0000000..69102f9 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demhmc1.m @@ -0,0 +1,145 @@ +%DEMHMC1 Demonstrate Hybrid Monte Carlo sampling on mixture of two Gaussians. +% +% Description +% The problem consists of generating data from a mixture of two +% Gaussians in two dimensions using a hybrid Monte Carlo algorithm with +% persistence. A mixture model is then fitted to the sample to compare +% it with the true underlying generator. +% +% See also +% DEMHMC3, HMC, DEMPOT, DEMGPOT +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +dim = 2; % Data dimension +ncentres = 2; % Number of centres in mixture model + +seed = 42; % Seed for random weight initialization. +randn('state', seed); +rand('state', seed); + +clc +disp('This demonstration illustrates the use of the hybrid Monte Carlo') +disp('algorithm to sample from a mixture of two Gaussians.') +disp('The means of the two components are [0 0] and [2 2].') +disp(' ') +disp('First we set up the parameters of the mixture model we are sampling') +disp('from.') +disp(' ') +disp('Press any key to continue.') +pause + +% Set up mixture model to sample from +mix = gmm(dim, ncentres, 'spherical'); +mix.centres(1, :) = [0 0]; +mix.centres(2, :) = [2 2]; +x = [0 1]; % Start vector + +% Set up vector of options for hybrid Monte Carlo. + +nsamples = 160; % Number of retained samples. + +options = foptions; % Default options vector. +options(1) = 1; % Switch on diagnostics. +options(5) = 1; % Use persistence +options(7) = 50; % Number of steps in trajectory. +options(14) = nsamples; % Number of Monte Carlo samples returned. +options(15) = 30; % Number of samples omitted at start of chain. +options(18) = 0.02; + +clc +disp(['Next we take ', num2str(nsamples),' samples from the distribution.'... + , 'The first ', num2str(options(15))]) +disp('samples at the start of the chain are omitted. As persistence') +disp('is used, the momentum has a small random component added at each step.') +disp([num2str(options(7)), ... + ' iterations are used at each step and the step size is ',... + num2str(options(18))]) +disp('Sampling starts at the point [0 1].') +disp('The new state is accepted if the threshold value is greater than') +disp('a random number between 0 and 1.') +disp(' ') +disp('Negative step numbers indicate samples discarded from the start of the') +disp('chain.') +disp(' ') +disp('Press any key to continue.') +pause + +[samples, energies] = hmc('dempot', x, options, 'demgpot', mix); + +disp(' ') +disp('Press any key to continue.') +pause +clc +disp('The plot shows the samples generated by the HMC function.') +disp('The different colours are used to show how the samples move from') +disp('one component to the other over time.') +disp(' ') +disp('Press any key to continue.') +pause +probs = exp(-energies); +fh1 = figure; +% Plot data in 4 groups +ngroups = 4; +g1end = floor(nsamples/ngroups); +g2end = floor(2*nsamples/ngroups); +g3end = floor(3*nsamples/ngroups); +p1 = plot(samples(1:g1end,1), samples(1:g1end,2), 'k.', 'MarkerSize', 12); +hold on +lstrings = char(['Samples 1-' int2str(g1end)], ... + ['Samples ' int2str(g1end+1) '-' int2str(g2end)], ... + ['Samples ' int2str(g2end+1) '-' int2str(g3end)], ... + ['Samples ' int2str(g3end+1) '-' int2str(nsamples)]); +p2 = plot(samples(g1end+1:g2end,1), samples(g1end+1:g2end,2), ... + 'r.', 'MarkerSize', 12); +p3 = plot(samples(g2end+1:g3end,1), samples(g2end+1:g3end,2), ... + 'g.', 'MarkerSize', 12); +p4 = plot(samples(g3end+1:nsamples,1), samples(g3end+1:nsamples,2), ... + 'b.', 'MarkerSize', 12); +legend([p1 p2 p3 p4], lstrings, 2); + +clc +disp('We now fit a Gaussian mixture model to the sampled data.') +disp('The model has spherical covariance structure and the correct') +disp('number of components.') +disp(' ') +disp('Press any key to continue.') +pause +% Fit a mixture model to the sample +newmix = gmm(dim, ncentres, 'spherical'); +options = foptions; +options(1) = -1; % Switch off all diagnostics +options(14) = 5; % Just use 5 iterations of k-means in initialisation +% Initialise the model parameters from the samples +newmix = gmminit(newmix, samples, options); + +% Set up vector of options for EM trainer +options = zeros(1, 18); +options(1) = 1; % Prints out error values. +options(14) = 15; % Max. Number of iterations. + +disp('We now train the model using the EM algorithm for 15 iterations') +disp(' ') +disp('Press any key to continue') +pause +[newmix, options, errlog] = gmmem(newmix, samples, options); + +% Print out model +disp(' ') +disp('The trained model has parameters ') +disp(' Priors Centres Variances') +disp([newmix.priors' newmix.centres newmix.covars']) +disp('Note the close correspondence between these parameters and those') +disp('of the distribution used to generate the data') +disp(' ') +disp(' Priors Centres Variances') +disp([mix.priors' mix.centres mix.covars']) +disp(' ') +disp('Press any key to exit') +pause + +close(fh1); +clear all; + diff --git a/PatRec/NetLab/netlab3_3/demhmc2.m b/PatRec/NetLab/netlab3_3/demhmc2.m new file mode 100644 index 0000000..d3df79d --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demhmc2.m @@ -0,0 +1,132 @@ +%DEMHMC2 Demonstrate Bayesian regression with Hybrid Monte Carlo sampling. +% +% Description +% The problem consists of one input variable X and one target variable +% T with data generated by sampling X at equal intervals and then +% generating target data by computing SIN(2*PI*X) and adding Gaussian +% noise. The model is a 2-layer network with linear outputs, and the +% hybrid Monte Carlo algorithm (without persistence) is used to sample +% from the posterior distribution of the weights. The graph shows the +% underlying function, 100 samples from the function given by the +% posterior distribution of the weights, and the average prediction +% (weighted by the posterior probabilities). +% +% See also +% DEMHMC3, HMC, MLP, MLPERR, MLPGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +% Generate the matrix of inputs x and targets t. +ndata = 20; % Number of data points. +noise = 0.1; % Standard deviation of noise distribution. +nin = 1; % Number of inputs. +nout = 1; % Number of outputs. + +seed = 42; % Seed for random weight initialization. +randn('state', seed); +rand('state', seed); + +x = 0.25 + 0.1*randn(ndata, nin); +t = sin(2*pi*x) + noise*randn(size(x)); + +clc +disp('This demonstration illustrates the use of the hybrid Monte Carlo') +disp('algorithm to sample from the posterior weight distribution of a') +disp('multi-layer perceptron.') +disp(' ') +disp('A regression problem is used, with the one-dimensional data drawn') +disp('from a noisy sine function. The x values are sampled from a normal') +disp('distribution with mean 0.25 and variance 0.01.') +disp(' ') +disp('First we initialise the network.') +disp(' ') +disp('Press any key to continue.') +pause + +% Set up network parameters. +nhidden = 5; % Number of hidden units. +alpha = 0.001; % Coefficient of weight-decay prior. +beta = 100.0; % Coefficient of data error. + +% Create and initialize network model. +% Initialise weights reasonably close to 0 +net = mlp(nin, nhidden, nout, 'linear', alpha, beta); +net = mlpinit(net, 10); + +clc +disp('Next we take 100 samples from the posterior distribution. The first') +disp('200 samples at the start of the chain are omitted. As persistence') +disp('is not used, the momentum is randomised at each step. 100 iterations') +disp('are used at each step. The new state is accepted if the threshold') +disp('value is greater than a random number between 0 and 1.') +disp(' ') +disp('Negative step numbers indicate samples discarded from the start of the') +disp('chain.') +disp(' ') +disp('Press any key to continue.') +pause +% Set up vector of options for hybrid Monte Carlo. +nsamples = 100; % Number of retained samples. + +options = foptions; % Default options vector. +options(1) = 1; % Switch on diagnostics. +options(7) = 100; % Number of steps in trajectory. +options(14) = nsamples; % Number of Monte Carlo samples returned. +options(15) = 200; % Number of samples omitted at start of chain. +options(18) = 0.002; % Step size. + +w = mlppak(net); +% Initialise HMC +hmc('state', 42); +[samples, energies] = hmc('neterr', w, options, 'netgrad', net, x, t); + +clc +disp('The plot shows the underlying noise free function, the 100 samples') +disp('produced from the MLP, and their average as a Monte Carlo estimate') +disp('of the true posterior average.') +disp(' ') +disp('Press any key to continue.') +pause +nplot = 300; +plotvals = [0 : 1/(nplot - 1) : 1]'; +pred = zeros(size(plotvals)); +fh = figure; +for k = 1:nsamples + w2 = samples(k,:); + net2 = mlpunpak(net, w2); + y = mlpfwd(net2, plotvals); + % Average sample predictions as Monte Carlo estimate of true integral + pred = pred + y; + h4 = plot(plotvals, y, '-r', 'LineWidth', 1); + if k == 1 + hold on + end +end +pred = pred./nsamples; + +% Plot data +h1 = plot(x, t, 'ob', 'LineWidth', 2, 'MarkerFaceColor', 'blue'); +axis([0 1 -3 3]) + +% Plot function +[fx, fy] = fplot('sin(2*pi*x)', [0 1], '--g'); +h2 = plot(fx, fy, '--g', 'LineWidth', 2); +set(gca, 'box', 'on'); + +% Plot averaged prediction +h3 = plot(plotvals, pred, '-c', 'LineWidth', 2); +hold off + +lstrings = char('Data', 'Function', 'Prediction', 'Samples'); +legend([h1 h2 h3 h4], lstrings, 3); + +disp('Note how the predictions become much further from the true function') +disp('away from the region of high data density.') +disp(' ') +disp('Press any key to exit.') +pause +close(fh); +clear all; + diff --git a/PatRec/NetLab/netlab3_3/demhmc3.m b/PatRec/NetLab/netlab3_3/demhmc3.m new file mode 100644 index 0000000..f2956ae --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demhmc3.m @@ -0,0 +1,135 @@ +%DEMHMC3 Demonstrate Bayesian regression with Hybrid Monte Carlo sampling. +% +% Description +% The problem consists of one input variable X and one target variable +% T with data generated by sampling X at equal intervals and then +% generating target data by computing SIN(2*PI*X) and adding Gaussian +% noise. The model is a 2-layer network with linear outputs, and the +% hybrid Monte Carlo algorithm (with persistence) is used to sample +% from the posterior distribution of the weights. The graph shows the +% underlying function, 300 samples from the function given by the +% posterior distribution of the weights, and the average prediction +% (weighted by the posterior probabilities). +% +% See also +% DEMHMC2, HMC, MLP, MLPERR, MLPGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +% Generate the matrix of inputs x and targets t. +ndata = 20; % Number of data points. +noise = 0.1; % Standard deviation of noise distribution. +nin = 1; % Number of inputs. +nout = 1; % Number of outputs. + +seed = 42; % Seed for random number generators. +randn('state', seed); +rand('state', seed); + +x = 0.25 + 0.1*randn(ndata, nin); +t = sin(2*pi*x) + noise*randn(size(x)); + +clc +disp('This demonstration illustrates the use of the hybrid Monte Carlo') +disp('algorithm to sample from the posterior weight distribution of a') +disp('multi-layer perceptron.') +disp(' ') +disp('A regression problem is used, with the one-dimensional data drawn') +disp('from a noisy sine function. The x values are sampled from a normal') +disp('distribution with mean 0.25 and variance 0.01.') +disp(' ') +disp('First we initialise the network.') +disp(' ') +disp('Press any key to continue.') +pause + +% Set up network parameters. +nhidden = 5; % Number of hidden units. +alpha = 0.001; % Coefficient of weight-decay prior. +beta = 100.0; % Coefficient of data error. + +% Create and initialize network model. + +% Initialise weights reasonably close to 0 +net = mlp(nin, nhidden, nout, 'linear', alpha, beta); +net = mlpinit(net, 10); + +clc +disp('Next we take 100 samples from the posterior distribution. The first') +disp('300 samples at the start of the chain are omitted. As persistence') +disp('is used, the momentum has a small random component added at each step.') +disp('10 iterations are used at each step (compared with 100 in demhmc2).') +disp('The step size is 0.005 (compared with 0.002).') +disp('The new state is accepted if the threshold') +disp('value is greater than a random number between 0 and 1.') +disp(' ') +disp('Negative step numbers indicate samples discarded from the start of the') +disp('chain.') +disp(' ') +disp('Press any key to continue.') +pause + +% Set up vector of options for hybrid Monte Carlo. +nsamples = 100; % Number of retained samples. + +options = foptions; % Default options vector. +options(1) = 1; % Switch on diagnostics. +options(5) = 1; % Use persistence +options(7) = 10; % Number of steps in trajectory. +options(14) = nsamples; % Number of Monte Carlo samples returned. +options(15) = 300; % Number of samples omitted at start of chain. +options(17) = 0.95; % Alpha value in persistence +options(18) = 0.005; % Step size. + +w = mlppak(net); +% Initialise HMC +hmc('state', 42); +[samples, energies] = hmc('neterr', w, options, 'netgrad', net, x, t); + +clc +disp('The plot shows the underlying noise free function, the 100 samples') +disp('produced from the MLP, and their average as a Monte Carlo estimate') +disp('of the true posterior average.') +disp(' ') +disp('Press any key to continue.') +pause + +nplot = 300; +plotvals = [0 : 1/(nplot - 1) : 1]'; +pred = zeros(size(plotvals)); +fh1 = figure; +hold on +for k = 1:nsamples + w2 = samples(k,:); + net2 = mlpunpak(net, w2); + y = mlpfwd(net2, plotvals); + % Sum predictions + pred = pred + y; + h4 = plot(plotvals, y, '-r', 'LineWidth', 1); +end +pred = pred./nsamples; +% Plot data +h1 = plot(x, t, 'ob', 'LineWidth', 2, 'MarkerFaceColor', 'blue'); +axis([0 1 -3 3]) + +% Plot function +[fx, fy] = fplot('sin(2*pi*x)', [0 1], '--g'); +h2 = plot(fx, fy, '--g', 'LineWidth', 2); +set(gca, 'box', 'on'); + +% Plot averaged prediction +h3 = plot(plotvals, pred, '-c', 'LineWidth', 2); + +lstrings = char('Data', 'Function', 'Prediction', 'Samples'); +legend([h1 h2 h3 h4], lstrings, 3); +hold off + +disp('Note how the predictions become much further from the true function') +disp('away from the region of high data density.') +disp(' ') +disp('Press any key to exit.') +pause +close(fh1); +clear all; \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/demkmn1.m b/PatRec/NetLab/netlab3_3/demkmn1.m new file mode 100644 index 0000000..d9a7c6e --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demkmn1.m @@ -0,0 +1,111 @@ +%DEMKMEAN Demonstrate simple clustering model trained with K-means. +% +% Description +% The problem consists of data in a two-dimensional space. The data is +% drawn from three spherical Gaussian distributions with priors 0.3, +% 0.5 and 0.2; centres (2, 3.5), (0, 0) and (0,2); and standard +% deviations 0.2, 0.5 and 1.0. The first figure contains a scatter plot +% of the data. The data is the same as in DEMGMM1. +% +% A cluster model with three components is trained using the batch K- +% means algorithm. The matrix of centres is printed after training. The +% second figure shows the data labelled with a colour derived from the +% corresponding cluster +% +% See also +% DEM2DDAT, DEMGMM1, KNN1, KMEANS +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Generate the data, fixing seeds for reproducible results +ndata = 250; +randn('state', 42); +rand('state', 42); +data = dem2ddat(ndata); + +% Randomise data order +data = data(randperm(ndata),:); + +clc +disp('This demonstration illustrates the use of a cluster model to') +disp('find centres that reflect the distribution of data points.') +disp('We begin by generating the data from a mixture of three Gaussians') +disp('in two-dimensional space and plotting it.') +disp(' ') +disp('Press any key to continue.') +pause + +fh1 = figure; +plot(data(:, 1), data(:, 2), 'o') +set(gca, 'Box', 'on') +title('Data') + +% Set up cluster model +ncentres = 3; +centres = zeros(ncentres, 2); + +% Set up vector of options for kmeans trainer +options = foptions; +options(1) = 1; % Prints out error values. +options(5) = 1; +options(14) = 10; % Number of iterations. + +clc +disp('The model is chosen to have three centres, which are initialised') +disp('at randomly selected data points. We now train the model using') +disp('the batch K-means algorithm with a maximum of 10 iterations and') +disp('stopping tolerance of 1e-4.') +disp(' ') +disp('Press any key to continue.') +pause + +% Train the centres from the data +[centres, options, post] = kmeans(centres, data, options); + +% Print out model +disp(' ') +disp('Note that training has terminated before 10 iterations as there') +disp('has been no change in the centres or error function.') +disp(' ') +disp('The trained model has centres:') +disp(centres); +disp('Press any key to continue.') +pause + +clc +disp('We now plot each data point coloured according to its classification') +disp('given by the nearest cluster centre. The cluster centres are denoted') +disp('by black crosses.') + +% Plot the result +fh2 = figure; + +hold on +colours = ['b.'; 'r.'; 'g.']; + +[tempi, tempj] = find(post); +hold on +for i = 1:3 + % Select data points closest to ith centre + thisX = data(tempi(tempj == i), 1); + thisY = data(tempi(tempj == i), 2); + hp(i) = plot(thisX, thisY, colours(i,:)); + set(hp(i), 'MarkerSize', 12); +end +set(gca, 'Box', 'on') +legend('Class 1', 'Class 2', 'Class 3', 2) +hold on +plot(centres(:, 1), centres(:,2), 'k+', 'LineWidth', 2, ... + 'MarkerSize', 8) +title('Centres and data labels') +hold off + +disp(' ') +disp('Press any key to end.') +pause + +close(fh1); +close(fh2); +clear all; + diff --git a/PatRec/NetLab/netlab3_3/demknn1.m b/PatRec/NetLab/netlab3_3/demknn1.m new file mode 100644 index 0000000..e49acdf --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demknn1.m @@ -0,0 +1,103 @@ +%DEMKNN1 Demonstrate nearest neighbour classifier. +% +% Description +% The problem consists of data in a two-dimensional space. The data is +% drawn from three spherical Gaussian distributions with priors 0.3, +% 0.5 and 0.2; centres (2, 3.5), (0, 0) and (0,2); and standard +% deviations 0.2, 0.5 and 1.0. The first figure contains a scatter plot +% of the data. The data is the same as in DEMGMM1. +% +% The second figure shows the data labelled with the corresponding +% class given by the classifier. +% +% See also +% DEM2DDAT, DEMGMM1, KNN +% + +% Copyright (c) Ian T Nabney (1996-2001) + +clc +disp('This program demonstrates the use of the K nearest neighbour algorithm.') +disp(' ') +disp('Press any key to continue.') +pause +% Generate the test data +ndata = 250; +randn('state', 42); +rand('state', 42); + +[data, c] = dem2ddat(ndata); + +% Randomise data order +data = data(randperm(ndata),:); + +clc +disp('We generate the data in two-dimensional space from a mixture of') +disp('three spherical Gaussians. The centres are shown as black crosses') +disp('in the plot.') +disp(' ') +disp('Press any key to continue.') +pause +fh1 = figure; +plot(data(:, 1), data(:, 2), 'o') +set(gca, 'Box', 'on') +hold on +title('Data') +hp1 = plot(c(:, 1), c(:,2), 'k+') +% Increase size of crosses +set(hp1, 'MarkerSize', 8); +set(hp1, 'LineWidth', 2); +hold off + +clc +disp('We next use the centres as training examplars for the K nearest') +disp('neighbour algorithm.') +disp(' ') +disp('Press any key to continue.') +pause + +% Use centres as training data +train_labels = [1, 0, 0; 0, 1, 0; 0, 0, 1]; + +% Label the test data up to kmax neighbours +kmax = 1; +net = knn(2, 3, kmax, c, train_labels); +[y, l] = knnfwd(net, data); + +clc +disp('We now plot each data point coloured according to its classification.') +disp(' ') +disp('Press any key to continue.') +pause +% Plot the result +fh2 = figure; +colors = ['b.'; 'r.'; 'g.']; +for i = 1:3 + thisX = data(l == i,1); + thisY = data(l == i,2); + hp(i) = plot(thisX, thisY, colors(i,:)); + set(hp(i), 'MarkerSize', 12); + if i == 1 + hold on + end +end +set(gca, 'Box', 'on'); +legend('Class 1', 'Class 2', 'Class 3', 2) +hold on +labels = ['1', '2', '3']; +hp2 = plot(c(:, 1), c(:,2), 'k+'); +% Increase size of crosses +set(hp2, 'MarkerSize', 8); +set(hp2, 'LineWidth', 2); + +test_labels = labels(l(:,1)); + +title('Training data and data labels') +hold off + +disp('The demonstration is now complete: press any key to exit.') +pause +close(fh1); +close(fh2); +clear all; + diff --git a/PatRec/NetLab/netlab3_3/demmdn1.m b/PatRec/NetLab/netlab3_3/demmdn1.m new file mode 100644 index 0000000..43c2d98 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demmdn1.m @@ -0,0 +1,211 @@ +%DEMMDN1 Demonstrate fitting a multi-valued function using a Mixture Density Network. +% +% Description +% The problem consists of one input variable X and one target variable +% T with data generated by sampling T at equal intervals and then +% generating target data by computing T + 0.3*SIN(2*PI*T) and adding +% Gaussian noise. A Mixture Density Network with 3 centres in the +% mixture model is trained by minimizing a negative log likelihood +% error function using the scaled conjugate gradient optimizer. +% +% The conditional means, mixing coefficients and variances are plotted +% as a function of X, and a contour plot of the full conditional +% density is also generated. +% +% See also +% MDN, MDNERR, MDNGRAD, SCG +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +% Generate the matrix of inputs x and targets t. +seedn = 42; +seed = 42; +randn('state', seedn); +rand('state', seed); +ndata = 300; % Number of data points. +noise = 0.2; % Range of noise distribution. +t = [0:1/(ndata - 1):1]'; +x = t + 0.3*sin(2*pi*t) + noise*rand(ndata, 1) - noise/2; +axis_limits = [-0.2 1.2 -0.2 1.2]; + +clc +disp('This demonstration illustrates the use of a Mixture Density Network') +disp('to model multi-valued functions. The data is generated from the') +disp('mapping x = t + 0.3 sin(2 pi t) + e, where e is a noise term.') +disp('We begin by plotting the data.') +disp(' ') +disp('Press any key to continue') +pause +% Plot the data +fh1 = figure; +p1 = plot(x, t, 'ob'); +axis(axis_limits); +hold on +disp('Note that for x in the range 0.35 to 0.65, there are three possible') +disp('branches of the function.') +disp(' ') +disp('Press any key to continue') +pause + +% Set up network parameters. +nin = 1; % Number of inputs. +nhidden = 5; % Number of hidden units. +ncentres = 3; % Number of mixture components. +dim_target = 1; % Dimension of target space +mdntype = '0'; % Currently unused: reserved for future use +alpha = 100; % Inverse variance for weight initialisation + % Make variance small for good starting point + +% Create and initialize network weight vector. +net = mdn(nin, nhidden, ncentres, dim_target, mdntype); +init_options = zeros(1, 18); +init_options(1) = -1; % Suppress all messages +init_options(14) = 10; % 10 iterations of K means in gmminit +net = mdninit(net, alpha, t, init_options); + +% Set up vector of options for the optimiser. +options = foptions; +options(1) = 1; % This provides display of error values. +options(14) = 200; % Number of training cycles. + +clc +disp('We initialise the neural network model, which is an MLP with a') +disp('Gaussian mixture model with three components and spherical variance') +disp('as the error function. This enables us to model the complete') +disp('conditional density function.') +disp(' ') +disp('Next we train the model for 200 epochs using a scaled conjugate gradient') +disp('optimizer. The error function is the negative log likelihood of the') +disp('training data.') +disp(' ') +disp('Press any key to continue.') +pause + +% Train using scaled conjugate gradients. +[net, options] = netopt(net, options, x, t, 'scg'); + +disp(' ') +disp('Press any key to continue.') +pause + +clc +disp('We can also train a conventional MLP with sum of squares error function.') +disp('This will approximate the conditional mean, which is not always a') +disp('good representation of the data. Note that the error function is the') +disp('sum of squares error on the training data, which accounts for the') +disp('different values from training the MDN.') +disp(' ') +disp('We train the network with the quasi-Newton optimizer for 80 epochs.') +disp(' ') +disp('Press any key to continue.') +pause +mlp_nhidden = 8; +net2 = mlp(nin, mlp_nhidden, dim_target, 'linear'); +options(14) = 80; +[net2, options] = netopt(net2, options, x, t, 'quasinew'); +disp(' ') +disp('Press any key to continue.') +pause + +clc +disp('Now we plot the underlying function, the MDN prediction,') +disp('represented by the mode of the conditional distribution, and the') +disp('prediction of the conventional MLP.') +disp(' ') +disp('Press any key to continue.') +pause + +% Plot the original function, and the trained network function. +plotvals = [0:0.01:1]'; +mixes = mdn2gmm(mdnfwd(net, plotvals)); +axis(axis_limits); +yplot = t+0.3*sin(2*pi*t); +p2 = plot(yplot, t, '--y'); + +% Use the mode to represent the function +y = zeros(1, length(plotvals)); +priors = zeros(length(plotvals), ncentres); +c = zeros(length(plotvals), 3); +widths = zeros(length(plotvals), ncentres); +for i = 1:length(plotvals) + [m, j] = max(mixes(i).priors); + y(i) = mixes(i).centres(j,:); + c(i,:) = mixes(i).centres'; +end +p3 = plot(plotvals, y, '*r'); +p4 = plot(plotvals, mlpfwd(net2, plotvals), 'g'); +set(p4, 'LineWidth', 2); +legend([p1 p2 p3 p4], 'data', 'function', 'MDN mode', 'MLP mean', 4); +hold off + +clc +disp('We can also plot how the mixture model parameters depend on x.') +disp('First we plot the mixture centres, then the priors and finally') +disp('the variances.') +disp(' ') +disp('Press any key to continue.') +pause +fh2 = figure; +subplot(3, 1, 1) +plot(plotvals, c) +hold on +title('Mixture centres') +legend('centre 1', 'centre 2', 'centre 3') +hold off + +priors = reshape([mixes.priors], mixes(1).ncentres, size(mixes, 2))'; +%%fh3 = figure; +subplot(3, 1, 2) +plot(plotvals, priors) +hold on +title('Mixture priors') +legend('centre 1', 'centre 2', 'centre 3') +hold off + +variances = reshape([mixes.covars], mixes(1).ncentres, size(mixes, 2))'; +%%fh4 = figure; +subplot(3, 1, 3) +plot(plotvals, variances) +hold on +title('Mixture variances') +legend('centre 1', 'centre 2', 'centre 3') +hold off + +disp('The last figure is a contour plot of the conditional probability') +disp('density generated by the Mixture Density Network. Note how it') +disp('is well matched to the regions of high data density.') +disp(' ') +disp('Press any key to continue.') +pause +% Contour plot for MDN. +i = 0:0.01:1.0; +j = 0:0.01:1.0; + +[I, J] = meshgrid(i,j); +I = I(:); +J = J(:); +li = length(i); +lj = length(j); +Z = zeros(li, lj); +for k = 1:li; + Z(:,k) = gmmprob(mixes(k), j'); +end +fh5 = figure; +% Set up levels by hand to make a good figure +v = [2 2.5 3 3.5 5:3:18]; +contour(i, j, Z, v) +hold on +title('Contour plot of conditional density') +hold off + +disp(' ') +disp('Press any key to exit.') +pause +close(fh1); +close(fh2); +%%close(fh3); +%%close(fh4); +close(fh5); +%%clear all; diff --git a/PatRec/NetLab/netlab3_3/demmet1.m b/PatRec/NetLab/netlab3_3/demmet1.m new file mode 100644 index 0000000..58a4289 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demmet1.m @@ -0,0 +1,103 @@ +function demmet1(plot_wait) +%DEMMET1 Demonstrate Markov Chain Monte Carlo sampling on a Gaussian. +% +% Description +% The problem consists of generating data from a Gaussian in two +% dimensions using a Markov Chain Monte Carlo algorithm. The points are +% plotted one after another to show the path taken by the chain. +% +% DEMMET1(PLOTWAIT) allows the user to set the time (in a whole number +% of seconds) between the plotting of points. This is passed to PAUSE +% +% See also +% DEMHMC1, METROP, GMM, DEMPOT +% + +% Copyright (c) Ian T Nabney (1996-2001) + +if nargin == 0 | plot_wait < 0 + plot_wait = 0; % No wait if not specified or incorrect +end +dim = 2; % Data dimension +ncentres = 1; % Number of centres in mixture model + +seed = 42; % Seed for random weight initialization. +randn('state', seed); +rand('state', seed); + +clc +disp('This demonstration illustrates the use of the Markov chain Monte Carlo') +disp('algorithm to sample from a Gaussian distribution.') +disp('The mean is at [0 0].') +disp(' ') +disp('First we set up the parameters of the mixture model we are sampling') +disp('from.') +disp(' ') +disp('Press any key to continue.') +pause + +% Set up mixture model to sample from +mix = gmm(dim, ncentres, 'spherical'); +mix.centres(1, :) = [0 0]; +x = [0 4]; % Start vector + +% Set up vector of options for hybrid Monte Carlo. + +nsamples = 150; % Number of retained samples. + +options = foptions; % Default options vector. +options(1) = 0; % Switch off diagnostics. +options(14) = nsamples; % Number of Monte Carlo samples returned. +options(18) = 0.1; + +clc +disp('Next we take 150 samples from the distribution.') +disp('Sampling starts at the point [0 4].') +disp('The new state is accepted if the threshold value is greater than') +disp('a random number between 0 and 1.') +disp(' ') +disp('Press any key to continue.') +pause + +[samples, energies] = metrop('dempot', x, options, '', mix); + +clc +disp('The plot shows the samples generated by the MCMC function in order') +disp('as an animation to show the path taken by the Markov chain.') +disp('The different colours are used to show that the first few samples') +disp('should be discarded as they lie too far from the mean.') +disp(' ') +disp('Press any key to continue.') +pause +probs = exp(-energies); +fh1 = figure; +g1end = floor(nsamples/4); + +for n = 1:nsamples + + if n < g1end + Marker = 'k.'; + p1 = plot(samples(n,1), samples(n,2), Marker, ... + 'EraseMode', 'none', 'MarkerSize', 12); + if n == 1 + axis([-3 5 -2 5]) + end + else + Marker = 'r.'; + p2 = plot(samples(n,1), samples(n,2), Marker, ... + 'EraseMode', 'none', 'MarkerSize', 12); + end + hold on + drawnow; % Force drawing immediately + pause(plot_wait); +end +lstrings = char(['Samples 1-' int2str(g1end)], ... + ['Samples ' int2str(g1end+1) '-' int2str(nsamples)]); +legend([p1 p2], lstrings, 1); + +disp(' ') +disp('Press any key to exit.') +pause +close(fh1); +clear all; + diff --git a/PatRec/NetLab/netlab3_3/demmlp1.m b/PatRec/NetLab/netlab3_3/demmlp1.m new file mode 100644 index 0000000..4f102b7 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demmlp1.m @@ -0,0 +1,88 @@ +%DEMMLP1 Demonstrate simple regression using a multi-layer perceptron +% +% Description +% The problem consists of one input variable X and one target variable +% T with data generated by sampling X at equal intervals and then +% generating target data by computing SIN(2*PI*X) and adding Gaussian +% noise. A 2-layer network with linear outputs is trained by minimizing +% a sum-of-squares error function using the scaled conjugate gradient +% optimizer. +% +% See also +% MLP, MLPERR, MLPGRAD, SCG +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +% Generate the matrix of inputs x and targets t. + +ndata = 20; % Number of data points. +noise = 0.2; % Standard deviation of noise distribution. +x = [0:1/(ndata - 1):1]'; +randn('state', 1); +t = sin(2*pi*x) + noise*randn(ndata, 1); + +clc +disp('This demonstration illustrates the use of a Multi-Layer Perceptron') +disp('network for regression problems. The data is generated from a noisy') +disp('sine function.') +disp(' ') +disp('Press any key to continue.') +pause + +% Set up network parameters. +nin = 1; % Number of inputs. +nhidden = 3; % Number of hidden units. +nout = 1; % Number of outputs. +alpha = 0.01; % Coefficient of weight-decay prior. + +% Create and initialize network weight vector. + +net = mlp(nin, nhidden, nout, 'linear', alpha); + +% Set up vector of options for the optimiser. + +options = zeros(1,18); +options(1) = 1; % This provides display of error values. +options(14) = 100; % Number of training cycles. + +clc +disp(['The network has ', num2str(nhidden), ' hidden units and a weight decay']) +disp(['coefficient of ', num2str(alpha), '.']) +disp(' ') +disp('After initializing the network, we train it use the scaled conjugate') +disp('gradients algorithm for 100 cycles.') +disp(' ') +disp('Press any key to continue') +pause + +% Train using scaled conjugate gradients. +[net, options] = netopt(net, options, x, t, 'scg'); + +disp(' ') +disp('Now we plot the data, underlying function, and network outputs') +disp('on a single graph to compare the results.') +disp(' ') +disp('Press any key to continue.') +pause + +% Plot the data, the original function, and the trained network function. +plotvals = [0:0.01:1]'; +y = mlpfwd(net, plotvals); +fh1 = figure; +plot(x, t, 'ob') +hold on +xlabel('Input') +ylabel('Target') +axis([0 1 -1.5 1.5]) +[fx, fy] = fplot('sin(2*pi*x)', [0 1]); +plot(fx, fy, '-r', 'LineWidth', 2) +plot(plotvals, y, '-k', 'LineWidth', 2) +legend('data', 'function', 'network'); + +disp(' ') +disp('Press any key to end.') +pause +close(fh1); +clear all; diff --git a/PatRec/NetLab/netlab3_3/demmlp2.m b/PatRec/NetLab/netlab3_3/demmlp2.m new file mode 100644 index 0000000..20a86cf --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demmlp2.m @@ -0,0 +1,337 @@ +%DEMMLP2 Demonstrate simple classification using a multi-layer perceptron +% +% Description +% The problem consists of input data in two dimensions drawn from a +% mixture of three Gaussians: two of which are assigned to a single +% class. An MLP with logistic outputs trained with a quasi-Newton +% optimisation algorithm is compared with the optimal Bayesian decision +% rule. +% +% See also +% MLP, MLPFWD, NETERR, QUASINEW +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +% Set up some figure parameters +AxisShift = 0.05; +ClassSymbol1 = 'r.'; +ClassSymbol2 = 'y.'; +PointSize = 12; +titleSize = 10; + +% Fix the seeds +rand('state', 423); +randn('state', 423); + +clc +disp('This demonstration shows how an MLP with logistic outputs and') +disp('and cross entropy error function can be trained to model the') +disp('posterior class probabilities in a classification problem.') +disp('The results are compared with the optimal Bayes rule classifier,') +disp('which can be computed exactly as we know the form of the generating') +disp('distribution.') +disp(' ') +disp('Press any key to continue.') +pause + +fh1 = figure; +set(fh1, 'Name', 'True Data Distribution'); +whitebg(fh1, 'k'); + +% +% Generate the data +% +n=200; + +% Set up mixture model: 2d data with three centres +% Class 1 is first centre, class 2 from the other two +mix = gmm(2, 3, 'full'); +mix.priors = [0.5 0.25 0.25]; +mix.centres = [0 -0.1; 1 1; 1 -1]; +mix.covars(:,:,1) = [0.625 -0.2165; -0.2165 0.875]; +mix.covars(:,:,2) = [0.2241 -0.1368; -0.1368 0.9759]; +mix.covars(:,:,3) = [0.2375 0.1516; 0.1516 0.4125]; + +[data, label] = gmmsamp(mix, n); + +% +% Calculate some useful axis limits +% +x0 = min(data(:,1)); +x1 = max(data(:,1)); +y0 = min(data(:,2)); +y1 = max(data(:,2)); +dx = x1-x0; +dy = y1-y0; +expand = 5/100; % Add on 5 percent each way +x0 = x0 - dx*expand; +x1 = x1 + dx*expand; +y0 = y0 - dy*expand; +y1 = y1 + dy*expand; +resolution = 100; +step = dx/resolution; +xrange = [x0:step:x1]; +yrange = [y0:step:y1]; +% +% Generate the grid +% +[X Y]=meshgrid([x0:step:x1],[y0:step:y1]); +% +% Calculate the class conditional densities, the unconditional densities and +% the posterior probabilities +% +px_j = gmmactiv(mix, [X(:) Y(:)]); +px = reshape(px_j*(mix.priors)',size(X)); +post = gmmpost(mix, [X(:) Y(:)]); +p1_x = reshape(post(:, 1), size(X)); +p2_x = reshape(post(:, 2) + post(:, 3), size(X)); + +% +% Generate some pretty pictures !! +% +colormap(hot) +colorbar +subplot(1,2,1) +hold on +plot(data((label==1),1),data(label==1,2),ClassSymbol1, 'MarkerSize', PointSize) +plot(data((label>1),1),data(label>1,2),ClassSymbol2, 'MarkerSize', PointSize) +contour(xrange,yrange,p1_x,[0.5 0.5],'w-'); +axis([x0 x1 y0 y1]) +set(gca,'Box','On') +title('The Sampled Data'); +rect=get(gca,'Position'); +rect(1)=rect(1)-AxisShift; +rect(3)=rect(3)+AxisShift; +set(gca,'Position',rect) +hold off + +subplot(1,2,2) +imagesc(X(:),Y(:),px); +hold on +[cB, hB] = contour(xrange,yrange,p1_x,[0.5 0.5],'w:'); +set(hB,'LineWidth', 2); +axis([x0 x1 y0 y1]) +set(gca,'YDir','normal') +title('Probability Density p(x)') +hold off + +drawnow; +clc; +disp('The first figure shows the data sampled from a mixture of three') +disp('Gaussians, the first of which (whose centre is near the origin) is') +disp('labelled red and the other two are labelled yellow. The second plot') +disp('shows the unconditional density of the data with the optimal Bayesian') +disp('decision boundary superimposed.') +disp(' ') +disp('Press any key to continue.') +pause +fh2 = figure; +set(fh2, 'Name', 'Class-conditional Densities and Posterior Probabilities'); +whitebg(fh2, 'w'); + +subplot(2,2,1) +p1=reshape(px_j(:,1),size(X)); +imagesc(X(:),Y(:),p1); +colormap hot +colorbar +axis(axis) +set(gca,'YDir','normal') +hold on +plot(mix.centres(:,1),mix.centres(:,2),'b+','MarkerSize',8,'LineWidth',2) +title('Density p(x|red)') +hold off + +subplot(2,2,2) +p2=reshape((px_j(:,2)+px_j(:,3)),size(X)); +imagesc(X(:),Y(:),p2); +colorbar +set(gca,'YDir','normal') +hold on +plot(mix.centres(:,1),mix.centres(:,2),'b+','MarkerSize',8,'LineWidth',2) +title('Density p(x|yellow)') +hold off + +subplot(2,2,3) +imagesc(X(:),Y(:),p1_x); +set(gca,'YDir','normal') +colorbar +title('Posterior Probability p(red|x)') +hold on +plot(mix.centres(:,1),mix.centres(:,2),'b+','MarkerSize',8,'LineWidth',2) +hold off + +subplot(2,2,4) +imagesc(X(:),Y(:),p2_x); +set(gca,'YDir','normal') +colorbar +title('Posterior Probability p(yellow|x)') +hold on +plot(mix.centres(:,1),mix.centres(:,2),'b+','MarkerSize',8,'LineWidth',2) +hold off + +% Now set up and train the MLP +nhidden=6; +nout=1; +alpha = 0.2; % Weight decay +ncycles = 60; % Number of training cycles. +% Set up MLP network +net = mlp(2, nhidden, nout, 'logistic', alpha); +options = zeros(1,18); +options(1) = 1; % Print out error values +options(14) = ncycles; + +mlpstring = ['We now set up an MLP with ', num2str(nhidden), ... + ' hidden units, logistic output and cross']; +trainstring = ['entropy error function, and train it for ', ... + num2str(ncycles), ' cycles using the']; +wdstring = ['quasi-Newton optimisation algorithm with weight decay of ', ... + num2str(alpha), '.']; + +% Force out the figure before training the MLP +drawnow; +disp(' ') +disp('The second figure shows the class conditional densities and posterior') +disp('probabilities for each class. The blue crosses mark the centres of') +disp('the three Gaussians.') +disp(' ') +disp(mlpstring) +disp(trainstring) +disp(wdstring) +disp(' ') +disp('Press any key to continue.') +pause + +% Convert targets to 0-1 encoding +target=[label==1]; + +% Train using quasi-Newton. +[net] = netopt(net, options, data, target, 'quasinew'); +y = mlpfwd(net, data); +yg = mlpfwd(net, [X(:) Y(:)]); +yg = reshape(yg(:,1),size(X)); + +fh3 = figure; +set(fh3, 'Name', 'Network Output'); +whitebg(fh3, 'k') +subplot(1, 2, 1) +hold on +plot(data((label==1),1),data(label==1,2),'r.', 'MarkerSize', PointSize) +plot(data((label>1),1),data(label>1,2),'y.', 'MarkerSize', PointSize) +% Bayesian decision boundary +[cB, hB] = contour(xrange,yrange,p1_x,[0.5 0.5],'b-'); +[cN, hN] = contour(xrange,yrange,yg,[0.5 0.5],'r-'); +set(hB, 'LineWidth', 2); +set(hN, 'LineWidth', 2); +Chandles = [hB(1) hN(1)]; +legend(Chandles, 'Bayes', ... + 'Network', 3); + +axis([x0 x1 y0 y1]) +set(gca,'Box','on','XTick',[],'YTick',[]) + +title('Training Data','FontSize',titleSize); +hold off + +subplot(1, 2, 2) +imagesc(X(:),Y(:),yg); +colormap hot +colorbar +axis(axis) +set(gca,'YDir','normal','XTick',[],'YTick',[]) +title('Network Output','FontSize',titleSize) + +clc +disp('This figure shows the training data with the decision boundary') +disp('produced by the trained network and the network''s prediction of') +disp('the posterior probability of the red class.') +disp(' ') +disp('Press any key to continue.') +pause + +% +% Now generate and classify a test data set +% +[testdata testlabel] = gmmsamp(mix, n); +testlab=[testlabel==1 testlabel>1]; + +% This is the Bayesian classification +tpx_j = gmmpost(mix, testdata); +Bpost = [tpx_j(:,1), tpx_j(:,2)+tpx_j(:,3)]; +[Bcon Brate]=confmat(Bpost, [testlabel==1 testlabel>1]); + +% Compute network classification +yt = mlpfwd(net, testdata); +% Convert single output to posteriors for both classes +testpost = [yt 1-yt]; +[C trate]=confmat(testpost,[testlabel==1 testlabel>1]); + +fh4 = figure; +set(fh4, 'Name', 'Decision Boundaries'); +whitebg(fh4, 'k'); +hold on +plot(testdata((testlabel==1),1),testdata((testlabel==1),2),... + ClassSymbol1, 'MarkerSize', PointSize) +plot(testdata((testlabel>1),1),testdata((testlabel>1),2),... + ClassSymbol2, 'MarkerSize', PointSize) +% Bayesian decision boundary +[cB, hB] = contour(xrange,yrange,p1_x,[0.5 0.5],'b-'); +set(hB, 'LineWidth', 2); +% Network decision boundary +[cN, hN] = contour(xrange,yrange,yg,[0.5 0.5],'r-'); +set(hN, 'LineWidth', 2); +Chandles = [hB(1) hN(1)]; +legend(Chandles, 'Bayes decision boundary', ... + 'Network decision boundary', -1); +axis([x0 x1 y0 y1]) +title('Test Data') +set(gca,'Box','On','Xtick',[],'YTick',[]) + +clc +disp('This figure shows the test data with the decision boundary') +disp('produced by the trained network and the optimal Bayes rule.') +disp(' ') +disp('Press any key to continue.') +pause + +fh5 = figure; +set(fh5, 'Name', 'Test Set Performance'); +whitebg(fh5, 'w'); +% Bayes rule performance +subplot(1,2,1) +plotmat(Bcon,'b','k',12) +set(gca,'XTick',[0.5 1.5]) +set(gca,'YTick',[0.5 1.5]) +grid('off') +set(gca,'XTickLabel',['Red ' ; 'Yellow']) +set(gca,'YTickLabel',['Yellow' ; 'Red ']) +ylabel('True') +xlabel('Predicted') +title(['Bayes Confusion Matrix (' num2str(Brate(1)) '%)']) + +% Network performance +subplot(1,2, 2) +plotmat(C,'b','k',12) +set(gca,'XTick',[0.5 1.5]) +set(gca,'YTick',[0.5 1.5]) +grid('off') +set(gca,'XTickLabel',['Red ' ; 'Yellow']) +set(gca,'YTickLabel',['Yellow' ; 'Red ']) +ylabel('True') +xlabel('Predicted') +title(['Network Confusion Matrix (' num2str(trate(1)) '%)']) + +disp('The final figure shows the confusion matrices for the') +disp('two rules on the test set.') +disp(' ') +disp('Press any key to exit.') +pause +whitebg(fh1, 'w'); +whitebg(fh2, 'w'); +whitebg(fh3, 'w'); +whitebg(fh4, 'w'); +whitebg(fh5, 'w'); +close(fh1); close(fh2); close(fh3); +close(fh4); close(fh5); +clear all; \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/demnlab.m b/PatRec/NetLab/netlab3_3/demnlab.m new file mode 100644 index 0000000..11fa3e8 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demnlab.m @@ -0,0 +1,380 @@ +function demnlab(action); +%DEMNLAB A front-end Graphical User Interface to the demos +% +% Description +% This function will start a user interface allowing the user to select +% different demonstration functions to view. The demos are divided into +% 4 groups, with the demo being executed by selecting the desired +% option from a pop-up menu. +% +% See also +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% If run without parameters, initialise gui. +if nargin<1, + action='initialise'; +end; + +if strcmp(action,'initialise'), + + % Create figure + fig = figure( ... + 'Name', 'Netlab Demos', ... + 'NumberTitle', 'off', ... + 'Color', [0.7529 0.7529 0.7529], ... + 'Visible', 'on'); + + % Create GROUPS + % Bottom of demo buttons + group1_bot = 0.20; + group1_top = 0.75; + uicontrol(fig, ... + 'Style', 'frame', ... + 'Units', 'normalized', ... + 'Position', [0.03 group1_bot 0.94 group1_top - group1_bot], ... + 'BackgroundColor', [0.5 0.5 0.5]); + + % Bottom of help and close buttons + group2_bot = 0.04; + uicontrol(fig, ... + 'Style', 'frame', ... + 'Units', 'normalized', ... + 'Position', [0.03 group2_bot 0.94 0.12], ... + 'BackgroundColor', [0.5 0.5 0.5]); + + % Draw title + hLogoAxis = axes( ... + 'Units', 'normalized', ... + 'Position', [0.05 0.82 0.90 0.14], ... + 'Box', 'off', ... + 'XColor', [0 0 0], ... + 'YColor', [0 0 0], ... + 'Visible', 'on'); + + load netlogo; % load image and colour map + colormap(netcmap(1:3,:)); % change colour map: don't need many entries + image(nlogo); % draw logo + axis('image'); % ensures pixels on axis are square + axis off; % turn axes off + + % Create static text + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.5 0.5 0.5], ... + 'Position', [0.05 group1_top-0.1 0.90 0.08], ... + 'String', 'Select demo to run:'); + + % First row text offset + tRow1Offset = 0.14; + % Offset between text and button + TBoffset = 0.07; + % First row button offset + bRow1Offset = tRow1Offset+TBoffset; + % ONE text + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.5 0.5 0.5], ... + 'Position', [0.08 group1_top-tRow1Offset 0.36 0.05], ... + 'String', 'Regression'); + + popup1str(1) = {'Select Option'}; + popup1str(2) = {'Multi-Layer Perceptron'}; + popup1str(3) = {'Radial Basis Function'}; + popup1str(4) = {'Mixture Density Network'}; + % ONE popup + hPop1 = uicontrol(fig, ... + 'Style','popup', ... + 'Units','normalized', ... + 'String', popup1str, ... + 'Position', [0.08 group1_top-bRow1Offset 0.36 0.08], ... + 'BackgroundColor', [0.7 0.7 0.7], ... + 'Callback', 'demnlab popup1'); + + % TWO text + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.5 0.5 0.5], ... + 'Position', [0.56 group1_top-tRow1Offset 0.36 0.05], ... + 'String', 'Classification'); + + popup2str(1) = popup1str(1); + popup2str(2) = {'Generalised Linear Model (2 class)'}; + popup2str(3) = {'Generalised Linear Model (3 class)'}; + popup2str(4) = {'Multi-Layer Perceptron'}; + popup2str(5) = {'K nearest neighbour'}; + % TWO popup + hPop2 = uicontrol(fig, ... + 'Style','popup', ... + 'Units','normalized', ... + 'String', popup2str, ... + 'Position', [0.56 group1_top-bRow1Offset 0.36 0.08], ... + 'BackgroundColor', [0.7 0.7 0.7], ... + 'Callback', 'demnlab popup2'); + + tRow2Offset = 0.30; + bRow2Offset = tRow2Offset+TBoffset; + % THREE text + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.5 0.5 0.5], ... + 'Position', [0.08 group1_top - tRow2Offset 0.36 0.05], ... + 'String', 'Density Modelling and Clustering'); + + popup3str(1) = popup1str(1); + popup3str(2) = {'Gaussian Mixture (EM training)'}; + popup3str(3) = {'Gaussian Mixture (spherical)'}; + popup3str(4) = {'Gaussian Mixture (diagonal)'}; + popup3str(5) = {'Gaussian Mixture (full)'}; + popup3str(6) = {'Neuroscale'}; + popup3str(7) = {'GTM (EM training)'}; + popup3str(8) = {'GTM (visualisation)'}; + popup3str(9) = {'K-means clustering'}; + popup3str(10) = {'Self-Organising Map'}; + % TWO popup + % THREE popup + hPop3 = uicontrol(fig, ... + 'Style','popup', ... + 'Units','normalized', ... + 'String', popup3str, ... + 'Position', [0.08 group1_top - bRow2Offset 0.36 0.08], ... + 'BackgroundColor', [0.7 0.7 0.7], ... + 'Callback', 'demnlab popup3'); + + % FOUR text + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.5 0.5 0.5], ... + 'Position', [0.56 group1_top - tRow2Offset 0.36 0.05], ... + 'String', 'Bayesian Methods'); + + popup4str(1) = popup1str(1); + popup4str(2) = {'Sampling the MLP Prior'}; + popup4str(3) = {'Evidence Approximation for MLP'}; + popup4str(4) = {'Evidence Approximation for RBF'}; + popup4str(5) = {'Evidence Approximation in Classification'}; + popup4str(6) = {'ARD for MLP'}; + popup4str(7) = {'Sampling the GP Prior'}; + popup4str(8) = {'GPs for Regression'}; + popup4str(9) = {'ARD for GP'}; + % FOUR popup + hPop4 = uicontrol(fig, ... + 'Style','popup', ... + 'Units','normalized', ... + 'String', popup4str, ... + 'Position', [0.56 group1_top - bRow2Offset 0.36 0.08], ... + 'BackgroundColor', [0.7 0.7 0.7], ... + 'Callback', 'demnlab popup4'); + + + tRow3Offset = 0.45; + bRow3Offset = tRow3Offset+TBoffset; + % FIVE text + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.5 0.5 0.5], ... + 'Position', [0.08 group1_top - tRow3Offset 0.36 0.05], ... + 'String', 'Optimisation and Visualisation'); + + popup5str(1) = popup1str(1); + popup5str(2) = {'Algorithm Comparison'}; + popup5str(3) = {'On-line Gradient Descent'}; + popup5str(4) = {'Hinton Diagrams'}; + % FIVE popup + hPop5 = uicontrol(fig, ... + 'Style','popup', ... + 'Units','normalized', ... + 'String',popup5str, ... + 'Position', [0.08 group1_top - bRow3Offset 0.36 0.08], ... + 'BackgroundColor', [0.7 0.7 0.7], ... + 'Callback', 'demnlab popup5'); + + % SIX text + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.5 0.5 0.5], ... + 'Position', [0.56 group1_top - tRow3Offset 0.36 0.05], ... + 'String', 'Sampling'); + + popup6str(1) = popup1str(1); + popup6str(2) = {'Sampling a Gaussian'}; + popup6str(3) = {'MCMC sampling (Metropolis)'}; + popup6str(4) = {'Hybrid MC (Gaussian mixture)'}; + popup6str(5) = {'Hybrid MC for MLP I'}; + popup6str(6) = {'Hybrid MC for MLP II'}; + % SIX popup + hPop6 = uicontrol(fig, ... + 'Style','popup', ... + 'Units','normalized', ... + 'String', popup6str, ... + 'Position', [0.56 group1_top - bRow3Offset 0.36 0.08], ... + 'BackgroundColor', [0.7 0.7 0.7], ... + 'Callback', 'demnlab popup6'); + + + % Create HELP button + uicontrol(fig, ... + 'Units', 'normalized', ... + 'Position' , [0.05 group2_bot+0.02 0.40 0.08], ... + 'String', 'Help', ... + 'Callback', 'demnlab help'); + + % Create CLOSE button + uicontrol(fig, ... + 'Units', 'normalized', ... + 'Position' , [0.55 group2_bot+0.02 0.40 0.08], ... + 'String', 'Close', ... + 'Callback', 'close(gcf)'); + + hndlList=[fig hPop1 hPop2 hPop3 hPop4 hPop5 hPop6]; + set(fig, 'UserData', hndlList); + set(fig, 'HandleVisibility', 'callback'); + +elseif strcmp(action, 'popup1'), + + hndlList=get(gcf,'UserData'); + hPop = hndlList(2); + + selected = get(hPop, 'Val'); + set(hPop, 'Val', [1]); + + switch selected + case 2 + demmlp1; + case 3 + demrbf1; + case 4 + demmdn1; + end; + +elseif strcmp(action,'popup2'), + + hndlList=get(gcf,'UserData'); + hPop = hndlList(3); + + selected = get(hPop, 'Val'); + set(hPop, 'Val', [1]); + + switch selected + case 2 + demglm1; + case 3 + demglm2; + case 4 + demmlp2; + case 5 + demknn1; + end + +elseif strcmp(action,'popup3'), + + hndlList=get(gcf,'UserData'); + hPop = hndlList(4); + + selected = get(hPop, 'Val'); + set(hPop, 'Val', [1]); + + switch selected + case 2 + demgmm1; + case 3 + demgmm2; + case 4 + demgmm3; + case 5 + demgmm4; + case 6 + demns1; + case 7 + demgtm1; + case 8 + demgtm2; + case 9 + demkmn1; + case 10 + demsom1; + end + +elseif strcmp(action,'popup4'), + + hndlList=get(gcf,'UserData'); + hPop = hndlList(5); + + selected = get(hPop, 'Val'); + set(hPop, 'Val', [1]); + + switch selected + case 2 + demprior; + case 3 + demev1; + case 4 + demev3; + case 5 + demev2; + case 6 + demard; + case 7 + demprgp; + case 8 + demgp; + case 9 + demgpard; + end + +elseif strcmp(action,'popup5'), + + hndlList=get(gcf,'UserData'); + hPop = hndlList(6); + + selected = get(hPop, 'Val'); + set(hPop, 'Val', [1]); + + switch selected + case 2 + demopt1; + case 3 + demolgd1; + case 4 + demhint; + end + + +elseif strcmp(action,'popup6'), + + hndlList=get(gcf,'UserData'); + hPop = hndlList(7); + + selected = get(hPop, 'Val'); + set(hPop, 'Val', [1]); + + switch selected + case 2 + demgauss; + case 3 + demmet1; + case 4 + demhmc1; + case 5 + demhmc2; + case 6 + demhmc3; + end + +elseif strcmp(action, 'help'), + + helpStr = {'To run a demo, press the appropriate button.'; ... + 'Instructions and information will appear in the Matlab';... + 'command window.'}; + + hHelpDlg = helpdlg(helpStr, 'Netlab Demo Help'); + +end; \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/demns1.m b/PatRec/NetLab/netlab3_3/demns1.m new file mode 100644 index 0000000..029e1b4 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demns1.m @@ -0,0 +1,114 @@ +%DEMNS1 Demonstrate Neuroscale for visualisation. +% +% Description +% This script demonstrates the use of the Neuroscale algorithm for +% topographic projection and visualisation. A data sample is generated +% from a mixture of two Gaussians in 4d space, and an RBF is trained +% with the stress error function to project the data into 2d. The +% training data and a test sample are both plotted in this projection. +% +% See also +% RBF, RBFTRAIN, RBFPRIOR +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Generate the data +% Fix seeds for reproducible results +rand('state', 420); +randn('state', 420); + +input_dim = 4; +output_dim = 2; +mix = gmm(input_dim, 2, 'spherical'); +mix.centres = [1 1 1 1; 0 0 0 0]; +mix.priors = [0.5 0.5]; +mix.covars = [0.1 0.1]; + +ndata = 60; +[data, labels] = gmmsamp(mix, ndata); + +clc +disp('This demonstration illustrates the use of the Neuroscale model') +disp('to perform a topographic projection of data. We begin by generating') +disp('60 data points from a mixture of two Gaussians in 4 dimensional space.') +disp(' ') +disp('Press any key to continue') +pause + +ncentres = 10; +net = rbf(input_dim, ncentres, output_dim, 'tps', 'neuroscale'); +dstring = ['the Sammon mapping. The model has ', num2str(ncentres), ... + ' centres, two outputs, and uses']; +clc +disp('The Neuroscale model is an RBF with a Stress error measure as used in') +disp(dstring) +disp('thin plate spline basis functions.') +disp(' ') +disp('It is trained using the shadow targets algorithm for at most 60 iterations.') +disp(' ') +disp('Press any key to continue') +pause + +% First row controls shadow targets, second row controls rbfsetbf +options(1, :) = foptions; +options(2, :) = foptions; +options(1, 1) = 1; +options(1, 2) = 1e-2; +options(1, 3) = 1e-2; +options(1, 6) = 1; % Switch on PCA initialisation +options(1, 14) = 60; +options(2, 1) = -1; % Switch off all warnings +options(2, 5) = 1; +options(2, 14) = 10; +net2 = rbftrain(net, options, data); + +disp(' ') +disp('After training the model, we project the training data by a normal') +disp('forward propagation through the RBF network. Because there are two') +disp('outputs, the results can be plotted and visualised.') +disp(' ') +disp('Press any key to continue') +pause + +% Plot the result +y = rbffwd(net2, data); +ClassSymbol1 = 'r.'; +ClassSymbol2 = 'b.'; +PointSize = 12; +fh1 = figure; +hold on; +plot(y((labels==1),1),y(labels==1,2),ClassSymbol1, 'MarkerSize', PointSize) +plot(y((labels>1),1),y(labels>1,2),ClassSymbol2, 'MarkerSize', PointSize) + +disp(' ') +disp('In this plot, the red dots denote the first class and the blue') +disp('dots the second class.') +disp(' ') +disp('Press any key to continue.') +disp(' ') +pause + +disp('We now generate a further 100 data points from the original distribution') +disp('and plot their projection using star symbols. Note that a Sammon') +disp('mapping cannot be used to generalise to new data in this fashion.') + +[test_data, test_labels] = gmmsamp(mix, 100); +ytest = rbffwd(net2, test_data); +ClassSymbol1 = 'ro'; +ClassSymbol2 = 'bo'; +% Circles are rather large symbols +PointSize = 6; +hold on +plot(ytest((test_labels==1),1),ytest(test_labels==1,2), ... + ClassSymbol1, 'MarkerSize', PointSize) +plot(ytest((test_labels>1),1),ytest(test_labels>1,2),... + ClassSymbol2, 'MarkerSize', PointSize) +hold on +legend('Class 1', 'Class 2', 'Test Class 1', 'Test Class 2') +disp('Press any key to exit.') +pause + +close(fh1); +clear all; + diff --git a/PatRec/NetLab/netlab3_3/demolgd1.m b/PatRec/NetLab/netlab3_3/demolgd1.m new file mode 100644 index 0000000..fb18f76 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demolgd1.m @@ -0,0 +1,115 @@ +%DEMOLGD1 Demonstrate simple MLP optimisation with on-line gradient descent +% +% Description +% The problem consists of one input variable X and one target variable +% T with data generated by sampling X at equal intervals and then +% generating target data by computing SIN(2*PI*X) and adding Gaussian +% noise. A 2-layer network with linear outputs is trained by minimizing +% a sum-of-squares error function using on-line gradient descent. +% +% See also +% DEMMLP1, OLGD +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +% Generate the matrix of inputs x and targets t. + +ndata = 20; % Number of data points. +noise = 0.2; % Standard deviation of noise distribution. +x = [0:1/(ndata - 1):1]'; +randn('state', 42); +rand('state', 42); +t = sin(2*pi*x) + noise*randn(ndata, 1); + +clc +disp('This demonstration illustrates the use of the on-line gradient') +disp('descent algorithm to train a Multi-Layer Perceptron network for') +disp('regression problems. It is intended to illustrate the drawbacks') +disp('of this algorithm compared to more powerful non-linear optimisation') +disp('algorithms, such as conjugate gradients.') +disp(' ') +disp('First we generate the data from a noisy sine function and construct') +disp('the network.') +disp(' ') +disp('Press any key to continue.') +pause +% Set up network parameters. +nin = 1; % Number of inputs. +nhidden = 3; % Number of hidden units. +nout = 1; % Number of outputs. +alpha = 0.01; % Coefficient of weight-decay prior. + +% Create and initialize network weight vector. +net = mlp(nin, nhidden, nout, 'linear'); +% Initialise weights reasonably close to 0 +net = mlpinit(net, 10); + +% Set up vector of options for the optimiser. +options = foptions; +options(1) = 1; % This provides display of error values. +options(14) = 20; % Number of training cycles. +options(18) = 0.1; % Learning rate +%options(17) = 0.4; % Momentum +options(17) = 0.4; % Momentum +options(5) = 1; % Do randomise pattern order +clc +disp('Then we set the options for the training algorithm.') +disp(['In the first phase of training, which lasts for ',... + num2str(options(14)), ' cycles,']) +disp(['the learning rate is ', num2str(options(18)), ... + ' and the momentum is ', num2str(options(17)), '.']) +disp('The error values are displayed at the end of each pass through the') +disp('entire pattern set.') +disp(' ') +disp('Press any key to continue.') +pause + +% Train using online gradient descent +[net, options] = olgd(net, options, x, t); + +% Now allow learning rate to decay and remove momentum +options(2) = 0; +options(3) = 0; +options(17) = 0.4; % Turn off momentum +options(5) = 1; % Randomise pattern order +options(6) = 1; % Set learning rate decay on +options(14) = 200; +options(18) = 0.1; % Initial learning rate + +disp(['In the second phase of training, which lasts for up to ',... + num2str(options(14)), ' cycles,']) +disp(['the learning rate starts at ', num2str(options(18)), ... + ', decaying at 1/t and the momentum is ', num2str(options(17)), '.']) +disp(' ') +disp('Press any key to continue.') +pause +[net, options] = olgd(net, options, x, t); + +clc +disp('Now we plot the data, underlying function, and network outputs') +disp('on a single graph to compare the results.') +disp(' ') +disp('Press any key to continue.') +pause + +% Plot the data, the original function, and the trained network function. +plotvals = [0:0.01:1]'; +y = mlpfwd(net, plotvals); +fh1 = figure; +plot(x, t, 'ob') +hold on +axis([0 1 -1.5 1.5]) +fplot('sin(2*pi*x)', [0 1], '--g') +plot(plotvals, y, '-r') +legend('data', 'function', 'network'); +hold off + +disp('Note the very poor fit to the data: this should be compared with') +disp('the results obtained in demmlp1.') +disp(' ') +disp('Press any key to exit.') +pause +close(fh1); +clear all; \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/demopt1.m b/PatRec/NetLab/netlab3_3/demopt1.m new file mode 100644 index 0000000..31b4a42 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demopt1.m @@ -0,0 +1,170 @@ +function demopt1(xinit) +%DEMOPT1 Demonstrate different optimisers on Rosenbrock's function. +% +% Description +% The four general optimisers (quasi-Newton, conjugate gradients, +% scaled conjugate gradients, and gradient descent) are applied to the +% minimisation of Rosenbrock's well known `banana' function. Each +% optimiser is run for at most 100 cycles, and a stopping criterion of +% 1.0e-4 is used for both position and function value. At the end, the +% trajectory of each algorithm is shown on a contour plot of the +% function. +% +% DEMOPT1(XINIT) allows the user to specify a row vector with two +% columns as the starting point. The default is the point [-1 1]. Note +% that the contour plot has an x range of [-1.5, 1.5] and a y range of +% [-0.5, 2.1], so it is best to choose a starting point in the same +% region. +% +% See also +% CONJGRAD, GRADDESC, QUASINEW, SCG, ROSEN, ROSEGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Initialise start point for search +if nargin < 1 | size(xinit) ~= [1 2] + xinit = [-1 1]; % Traditional start point +end + +% Find out if flops is available (i.e. pre-version 6 Matlab) +v = version; +if (str2num(strtok(v, '.')) >= 6) + flops_works = logical(0); +else + flops_works = logical(1); +end + +% Set up options +options = foptions; % Standard options +options(1) = -1; % Turn off printing completely +options(3) = 1e-8; % Tolerance in value of function +options(14) = 100; % Max. 100 iterations of algorithm + +clc +disp('This demonstration compares the performance of four generic') +disp('optimisation routines when finding the minimum of Rosenbrock''s') +disp('function y = 100*(x2-x1^2)^2 + (1-x1)^2.') +disp(' ') +disp('The global minimum of this function is at [1 1].') +disp(['Each algorithm starts at the point [' num2str(xinit(1))... + ' ' num2str(xinit(2)) '].']) +disp(' ') +disp('Press any key to continue.') +pause + +% Generate a contour plot of the function +a = -1.5:.02:1.5; +b = -0.5:.02:2.1; +[A, B] = meshgrid(a, b); +Z = rosen([A(:), B(:)]); +Z = reshape(Z, length(b), length(a)); +l = -1:6; +v = 2.^l; +fh1 = figure; +contour(a, b, Z, v) +title('Contour plot of Rosenbrock''s function') +hold on + +clc +disp('We now use quasi-Newton, conjugate gradient, scaled conjugate') +disp('gradient, and gradient descent with line search algorithms') +disp('to find a local minimum of this function. Each algorithm is stopped') +disp('when 100 cycles have elapsed, or if the change in function value') +disp('is less than 1.0e-8 or the change in the input vector is less than') +disp('1.0e-4 in magnitude.') +disp(' ') +disp('Press any key to continue.') +pause + +clc +x = xinit; +flops(0) +[x, options, errlog, pointlog] = quasinew('rosen', x, options, 'rosegrad'); +fprintf(1, 'For quasi-Newton method:\n') +fprintf(1, 'Final point is (%f, %f), value is %f\n', x(1), x(2), options(8)) +fprintf(1, 'Number of function evaluations is %d\n', options(10)) +fprintf(1, 'Number of gradient evaluations is %d\n', options(11)) +if flops_works + opt_flops = flops; + fprintf(1, 'Number of floating point operations is %d\n', opt_flops) +end +fprintf(1, 'Number of cycles is %d\n', size(pointlog, 1) - 1); +disp(' ') + +x = xinit; +flops(0) +[x, options, errlog2, pointlog2] = conjgrad('rosen', x, options, 'rosegrad'); +fprintf(1, 'For conjugate gradient method:\n') +fprintf(1, 'Final point is (%f, %f), value is %f\n', x(1), x(2), options(8)) +fprintf(1, 'Number of function evaluations is %d\n', options(10)) +fprintf(1, 'Number of gradient evaluations is %d\n', options(11)) +if flops_works + opt_flops = flops; + fprintf(1, 'Number of floating point operations is %d\n', ... + opt_flops) +end +fprintf(1, 'Number of cycles is %d\n', size(pointlog2, 1) - 1); +disp(' ') + +x = xinit; +flops(0) +[x, options, errlog3, pointlog3] = scg('rosen', x, options, 'rosegrad'); +fprintf(1, 'For scaled conjugate gradient method:\n') +fprintf(1, 'Final point is (%f, %f), value is %f\n', x(1), x(2), options(8)) +fprintf(1, 'Number of function evaluations is %d\n', options(10)) +fprintf(1, 'Number of gradient evaluations is %d\n', options(11)) +if flops_works + opt_flops = flops; + fprintf(1, 'Number of floating point operations is %d\n', opt_flops) +end +fprintf(1, 'Number of cycles is %d\n', size(pointlog3, 1) - 1); +disp(' ') + +x = xinit; +options(7) = 1; % Line minimisation used +flops(0) +[x, options, errlog4, pointlog4] = graddesc('rosen', x, options, 'rosegrad'); +fprintf(1, 'For gradient descent method:\n') +fprintf(1, 'Final point is (%f, %f), value is %f\n', x(1), x(2), options(8)) +fprintf(1, 'Number of function evaluations is %d\n', options(10)) +fprintf(1, 'Number of gradient evaluations is %d\n', options(11)) +if flops_works + opt_flops = flops; + fprintf(1, 'Number of floating point operations is %d\n', opt_flops) +end +fprintf(1, 'Number of cycles is %d\n', size(pointlog4, 1) - 1); +disp(' ') +disp('Note that gradient descent does not reach a local minimum in') +disp('100 cycles.') +disp(' ') +disp('On this problem, where the function is cheap to evaluate, the') +disp('computational effort is dominated by the algorithm overhead.') +disp('However on more complex optimisation problems (such as those') +disp('involving neural networks), computational effort is dominated by') +disp('the number of function and gradient evaluations. Counting these,') +disp('we can rank the algorithms: quasi-Newton (the best), conjugate') +disp('gradient, scaled conjugate gradient, gradient descent (the worst)') +disp(' ') +disp('Press any key to continue.') +pause +clc +disp('We now plot the trajectory of search points for each algorithm') +disp('superimposed on the contour plot.') +disp(' ') +disp('Press any key to continue.') +pause +plot(pointlog4(:,1), pointlog4(:,2), 'bd', 'MarkerSize', 6) +plot(pointlog3(:,1), pointlog3(:,2), 'mx', 'MarkerSize', 6, 'LineWidth', 2) +plot(pointlog(:,1), pointlog(:,2), 'k.', 'MarkerSize', 18) +plot(pointlog2(:,1), pointlog2(:,2), 'g+', 'MarkerSize', 6, 'LineWidth', 2) +lh = legend( 'Gradient Descent', 'Scaled Conjugate Gradients', ... + 'Quasi Newton', 'Conjugate Gradients'); + +hold off + +clc +disp('Press any key to end.') +pause +close(fh1); +clear all; \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/dempot.m b/PatRec/NetLab/netlab3_3/dempot.m new file mode 100644 index 0000000..87301bc --- /dev/null +++ b/PatRec/NetLab/netlab3_3/dempot.m @@ -0,0 +1,17 @@ +function e = dempot(x, mix) +%DEMPOT Computes the negative log likelihood for a mixture model. +% +% Description +% This function computes the negative log of the unconditional data +% density P(X) for a Gaussian mixture model. The data structure MIX +% defines the mixture model, while the matrix X contains the data +% vectors. +% +% See also +% DEMGPOT, DEMHMC1, DEMMET1 +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Computes the potential (negative log likelihood) +e = -log(gmmprob(mix, x)); \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/demprgp.m b/PatRec/NetLab/netlab3_3/demprgp.m new file mode 100644 index 0000000..79ca573 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demprgp.m @@ -0,0 +1,542 @@ +function demprgp(action); +%DEMPRGP Demonstrate sampling from a Gaussian Process prior. +% +% Description +% This function plots the functions represented by a Gaussian Process +% model. The hyperparameter values can be adjusted on a linear scale +% using the sliders (though the exponential of the parameters is used +% in the covariance function), or by typing values into the text boxes +% and pressing the return key. Both types of covariance function are +% supported. An extra function specific parameter is needed for the +% rational quadratic function. +% +% See also +% GP +% + +% Copyright (c) Ian T Nabney (1996-2001) + +if nargin<1, + action='initialize'; +end; + +if strcmp(action,'initialize') + + % Bounds on hyperparameter values + biasminval = -3.0; biasmaxval = 3.0; + noiseminval = -20; noisemaxval = -2; + fparminval = 0.0; fparmaxval = 2.0; + inwminval = 0; inwmaxval = 8; + % Initial hyperparameter values + bias = (biasminval+biasmaxval)/2; + noise = (noiseminval+noisemaxval)/2; + inweights = (inwminval+inwmaxval)/2; + fpar = (fparminval+fparmaxval)/2; + fpar2 = (fparminval+fparmaxval)/2; + + gptype = 'sqexp'; + + % Create FIGURE + fig=figure( ... + 'Name','Sampling from a Gaussian Process prior', ... + 'Position', [50 50 480 380], ... + 'NumberTitle','off', ... + 'Color', [0.8 0.8 0.8], ... + 'Visible','on'); + + % List box for covariance function type + nettype_box = uicontrol(fig, ... + 'Style', 'listbox', ... + 'Units', 'normalized', ... + 'HorizontalAlignment', 'center', ... + 'Position', [0.52 0.77 0.40 0.12], ... + 'String', 'Squared Exponential|Rational Quadratic', ... + 'Max', 1, 'Min', 0, ... % Only allow one selection + 'Value', 1, ... % Initial value is squared exponential + 'BackgroundColor',[0.60 0.60 0.60],... + 'CallBack', 'demprgp GPtype'); + + % Title for list box + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'Position', [0.52 0.89 0.40 0.05], ... + 'String', 'Covariance Function Type', ... + 'BackgroundColor', get(fig, 'Color'), ... + 'HorizontalAlignment', 'center'); + + % Frames to enclose sliders + bottom_row = 0.04; + slider_frame_height = 0.15; + biasframe = uicontrol(fig, ... + 'Style', 'frame', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'String', 'bias', ... + 'HorizontalAlignment', 'left', ... + 'Position', [0.05 bottom_row 0.35 slider_frame_height]); + + bpos = get(biasframe, 'Position'); + noise_frame_bottom = bpos(2) + bpos(4) + 0.02; + noiseframe = uicontrol(fig, ... + 'Style', 'frame', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.05 noise_frame_bottom 0.35 slider_frame_height]); + + npos = get(noiseframe, 'Position'); + inw_frame_bottom = npos(2) + npos(4) + 0.02; + inwframe = uicontrol(fig, ... + 'Style', 'frame', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.05 inw_frame_bottom 0.35 slider_frame_height]); + + inwpos = get(inwframe, 'Position'); + fpar_frame_bottom = inwpos(2) + inwpos(4) + 0.02; + % This frame sometimes has multiple parameters + uicontrol(fig, ... + 'Style', 'frame', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.05 fpar_frame_bottom 0.35 2*slider_frame_height]); + + % Frame text + slider_text_height = 0.05; + slider_text_voffset = 0.08; + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'HorizontalAlignment', 'left', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.07 bottom_row+slider_text_voffset ... + 0.06 slider_text_height], ... + 'String', 'bias'); + + % Frame text + noiseframe = uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'HorizontalAlignment', 'left', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.07 noise_frame_bottom+slider_text_voffset ... + 0.08 slider_text_height], ... + 'String', 'noise'); + + % Frame text + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'HorizontalAlignment', 'left', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.07 inw_frame_bottom+slider_text_voffset ... + 0.14 slider_text_height], ... + 'String', 'inweights'); + + % Frame text + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'HorizontalAlignment', 'left', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.07 fpar_frame_bottom+slider_frame_height+ ... + slider_text_voffset 0.06 slider_text_height], ... + 'String', 'fpar'); + + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'HorizontalAlignment', 'left', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.07 fpar_frame_bottom+slider_text_voffset ... + 0.06 slider_text_height], ... + 'String', 'fpar2', ... + 'Tag', 'fpar2text', ... + 'Enable', 'off'); + + % Slider + slider_left = 0.07; + slider_width = 0.31; + slider_frame_voffset = 0.02; + biasslide = uicontrol(fig, ... + 'Style', 'slider', ... + 'Units', 'normalized', ... + 'Value', bias, ... + 'BackgroundColor', [0.8 0.8 0.8], ... + 'Position', [slider_left bottom_row+slider_frame_voffset ... + slider_width 0.05], ... + 'Min', biasminval, 'Max', biasmaxval, ... + 'Callback', 'demprgp update'); + + % Slider + noiseslide = uicontrol(fig, ... + 'Style', 'slider', ... + 'Units', 'normalized', ... + 'Value', noise, ... + 'BackgroundColor', [0.8 0.8 0.8], ... + 'Position', [slider_left noise_frame_bottom+slider_frame_voffset ... + slider_width 0.05], ... + 'Min', noiseminval, 'Max', noisemaxval, ... + 'Callback', 'demprgp update'); + + % Slider + inweightsslide = uicontrol(fig, ... + 'Style', 'slider', ... + 'Units', 'normalized', ... + 'Value', inweights, ... + 'BackgroundColor', [0.8 0.8 0.8], ... + 'Position', [slider_left inw_frame_bottom+slider_frame_voffset ... + slider_width 0.05], ... + 'Min', inwminval, 'Max', inwmaxval, ... + 'Callback', 'demprgp update'); + + % Slider + fparslide = uicontrol(fig, ... + 'Style', 'slider', ... + 'Units', 'normalized', ... + 'Value', fpar, ... + 'BackgroundColor', [0.8 0.8 0.8], ... + 'Position', [slider_left fpar_frame_bottom+slider_frame_height+ ... + slider_frame_voffset slider_width 0.05], ... + 'Min', fparminval, 'Max', fparmaxval, ... + 'Callback', 'demprgp update'); + + fpar2slide = uicontrol(fig, ... + 'Style', 'slider', ... + 'Units', 'normalized', ... + 'Value', fpar2, ... + 'BackgroundColor', [0.8 0.8 0.8], ... + 'Position', [slider_left fpar_frame_bottom+slider_frame_voffset ... + slider_width 0.05], ... + 'Min', fparminval, 'Max', fparmaxval, ... + 'Callback', 'demprgp update', ... + 'Tag', 'fpar2slider', ... + 'Enable', 'off'); + + % Text display of hyper-parameter values + + format = '%8f'; + + hp_left = 0.20; + hp_width = 0.17; + biasval = uicontrol(fig, ... + 'Style', 'edit', ... + 'Units', 'normalized', ... + 'Position', [hp_left bottom_row+slider_text_voffset ... + hp_width slider_text_height], ... + 'String', sprintf(format, bias), ... + 'Callback', 'demprgp newval'); + + noiseval = uicontrol(fig, ... + 'Style', 'edit', ... + 'Units', 'normalized', ... + 'Position', [hp_left noise_frame_bottom+slider_text_voffset ... + hp_width slider_text_height], ... + 'String', sprintf(format, noise), ... + 'Callback', 'demprgp newval'); + + inweightsval = uicontrol(fig, ... + 'Style', 'edit', ... + 'Units', 'normalized', ... + 'Position', [hp_left inw_frame_bottom+slider_text_voffset ... + hp_width slider_text_height], ... + 'String', sprintf(format, inweights), ... + 'Callback', 'demprgp newval'); + + fparval = uicontrol(fig, ... + 'Style', 'edit', ... + 'Units', 'normalized', ... + 'Position', [hp_left fpar_frame_bottom+slider_frame_height+ ... + slider_text_voffset hp_width slider_text_height], ... + 'String', sprintf(format, fpar), ... + 'Callback', 'demprgp newval'); + + fpar2val = uicontrol(fig, ... + 'Style', 'edit', ... + 'Units', 'normalized', ... + 'Position', [hp_left fpar_frame_bottom+slider_text_voffset ... + hp_width slider_text_height], ... + 'String', sprintf(format, fpar), ... + 'Callback', 'demprgp newval', ... + 'Enable', 'off', ... + 'Tag', 'fpar2val'); + + + % The graph box + haxes = axes('Position', [0.5 0.28 0.45 0.45], ... + 'Units', 'normalized', ... + 'Visible', 'on'); + + % The SAMPLE button + uicontrol(fig, ... + 'Style','push', ... + 'Units','normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position',[0.5 bottom_row 0.13 0.1], ... + 'String','Sample', ... + 'Callback','demprgp replot'); + + % The CLOSE button + uicontrol(fig, ... + 'Style','push', ... + 'Units','normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position',[0.82 bottom_row 0.13 0.1], ... + 'String','Close', ... + 'Callback','close(gcf)'); + + % The HELP button + uicontrol(fig, ... + 'Style','push', ... + 'Units','normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position',[0.66 bottom_row 0.13 0.1], ... + 'String','Help', ... + 'Callback','demprgp help'); + + % Save handles to objects + + hndlList=[fig biasslide noiseslide inweightsslide fparslide ... + biasval noiseval inweightsval ... + fparval haxes nettype_box]; + set(fig, 'UserData', hndlList); + + demprgp('replot') + + +elseif strcmp(action, 'update'), + + % Update when a slider is moved. + + hndlList = get(gcf, 'UserData'); + biasslide = hndlList(2); + noiseslide = hndlList(3); + inweightsslide = hndlList(4); + fparslide = hndlList(5); + biasval = hndlList(6); + noiseval = hndlList(7); + inweightsval = hndlList(8); + fparval = hndlList(9); + haxes = hndlList(10); + nettype_box = hndlList(11); + + + bias = get(biasslide, 'Value'); + noise = get(noiseslide, 'Value'); + inweights = get(inweightsslide, 'Value'); + fpar = get(fparslide, 'Value'); + fpar2 = get(findobj('Tag', 'fpar2slider'), 'Value'); + + format = '%8f'; + set(biasval, 'String', sprintf(format, bias)); + set(noiseval, 'String', sprintf(format, noise)); + set(inweightsval, 'String', sprintf(format, inweights)); + set(fparval, 'String', sprintf(format, fpar)); + set(findobj('Tag', 'fpar2val'), 'String', ... + sprintf(format, fpar2)); + + demprgp('replot'); + +elseif strcmp(action, 'newval'), + + % Update when text is changed. + + hndlList = get(gcf, 'UserData'); + biasslide = hndlList(2); + noiseslide = hndlList(3); + inweightsslide = hndlList(4); + fparslide = hndlList(5); + biasval = hndlList(6); + noiseval = hndlList(7); + inweightsval = hndlList(8); + fparval = hndlList(9); + haxes = hndlList(10); + + bias = sscanf(get(biasval, 'String'), '%f'); + noise = sscanf(get(noiseval, 'String'), '%f'); + inweights = sscanf(get(inweightsval, 'String'), '%f'); + fpar = sscanf(get(fparval, 'String'), '%f'); + fpar2 = sscanf(get(findobj('Tag', 'fpar2val'), 'String'), '%f'); + + set(biasslide, 'Value', bias); + set(noiseslide, 'Value', noise); + set(inweightsslide, 'Value', inweights); + set(fparslide, 'Value', fpar); + set(findobj('Tag', 'fpar2slider'), 'Value', fpar2); + + demprgp('replot'); + +elseif strcmp(action, 'GPtype') + hndlList = get(gcf, 'UserData'); + nettype_box = hndlList(11); + gptval = get(nettype_box, 'Value'); + if gptval == 1 + % Squared exponential, so turn off fpar2 + set(findobj('Tag', 'fpar2text'), 'Enable', 'off'); + set(findobj('Tag', 'fpar2slider'), 'Enable', 'off'); + set(findobj('Tag', 'fpar2val'), 'Enable', 'off'); + else + % Rational quadratic, so turn on fpar2 + set(findobj('Tag', 'fpar2text'), 'Enable', 'on'); + set(findobj('Tag', 'fpar2slider'), 'Enable', 'on'); + set(findobj('Tag', 'fpar2val'), 'Enable', 'on'); + end + demprgp('replot'); + +elseif strcmp(action, 'replot'), + + % Re-sample from the prior and plot graphs. + + oldFigNumber=watchon; + + hndlList = get(gcf, 'UserData'); + biasslide = hndlList(2); + noiseslide = hndlList(3); + inweightsslide = hndlList(4); + fparslide = hndlList(5); + haxes = hndlList(10); + nettype_box = hndlList(11); + gptval = get(nettype_box, 'Value'); + if gptval == 1 + gptype = 'sqexp'; + else + gptype = 'ratquad'; + end + + bias = get(biasslide, 'Value'); + noise = get(noiseslide, 'Value'); + inweights = get(inweightsslide, 'Value'); + fpar = get(fparslide, 'Value'); + + + axes(haxes); + cla + set(gca, ... + 'Box', 'on', ... + 'Color', [0 0 0], ... + 'XColor', [0 0 0], ... + 'YColor', [0 0 0], ... + 'FontSize', 14); + ymin = -10; + ymax = 10; + axis([-1 1 ymin ymax]); + set(gca,'DefaultLineLineWidth', 2); + + xvals = (-1:0.01:1)'; + nsample = 10; % Number of samples from prior. + hold on + plot([-1 0; 1 0], [0 ymin; 0 ymax], 'b--'); + net = gp(1, gptype); + net.bias = bias; + net.noise = noise; + net.inweights = inweights; + if strcmp(gptype, 'sqexp') + net.fpar = fpar; + else + fpar2 = get(findobj('Tag', 'fpar2slider'), 'Value'); + net.fpar = [fpar fpar2]; + end + cn = gpcovar(net, xvals); + cninv = inv(cn); + cnchol = chol(cn); + set(gca, 'DefaultLineLineWidth', 1); + for n = 1:nsample + y = (cnchol') * randn(size(xvals)); + plot(xvals, y, 'y'); + end + + watchoff(oldFigNumber); + +elseif strcmp(action, 'help'), + + % Provide help to user. + + oldFigNumber=watchon; + + helpfig = figure('Position', [100 100 480 400], ... + 'Name', 'Help', ... + 'NumberTitle', 'off', ... + 'Color', [0.8 0.8 0.8], ... + 'Visible','on'); + + % The HELP TITLE BAR frame + uicontrol(helpfig, ... + 'Style','frame', ... + 'Units','normalized', ... + 'HorizontalAlignment', 'center', ... + 'Position', [0.05 0.82 0.9 0.1], ... + 'BackgroundColor',[0.60 0.60 0.60]); + + % The HELP TITLE BAR text + uicontrol(helpfig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.26 0.85 0.6 0.05], ... + 'HorizontalAlignment', 'left', ... + 'String', 'Help: Sampling from a Gaussian Process Prior'); + + helpstr1 = strcat(... + 'This demonstration shows the effects of sampling from a Gaussian', ... + ' process prior. The parameters bias, noise, inweights and fpar', ... + ' control the corresponding terms in the covariance function of the',... + ' Gaussian process. Their values can be adjusted on a linear scale',... + ' using the sliders, or by typing values into the text boxes and',... + ' pressing the return key. After setting these values, press the',... + ' ''Sample'' button to see a new sample from the prior.'); + + helpstr2 = strcat(... + 'Observe how inweights controls horizontal length-scale of the',... + ' variation in the functions, noise controls the roughness of the',... + ' functions, and the bias controls the size of the', ... + ' vertical offset of the signal.'); + helpstr3 = strcat(... + 'There are two types of covariance function supported by', ... + ' Netlab which can be selected using the ''Covariance Function', ... + ' Type'' menu.'); + helpstr4 = strcat(... + 'The squared exponential has a single fpar which', ... + ' controls the vertical scale of the process.'); + helpstr5 = strcat(... + 'The rational quadratic has two fpar values. The first is', ... + ' is a scale parameter inside the rational function like the',... + ' first fpar for the squared exponential covariance, while the', ... + ' second gives the exponent of the rational function (i.e. the',... + ' rate of decay of the covariance function.'); + % Set up cell array with help strings + hstr(1) = {helpstr1}; + hstr(2) = {''}; + hstr(3) = {helpstr2}; + hstr(4) = {''}; + hstr(5) = {helpstr3}; + hstr(6) = {''}; + hstr(7) = {helpstr4}; + hstr(8) = {''}; + hstr(9) = {helpstr5}; + + % The HELP text + helpui = uicontrol(helpfig, ... + 'Style', 'Text', ... + 'Units', 'normalized', ... + 'ForegroundColor', [0 0 0], ... + 'HorizontalAlignment', 'left', ... + 'BackgroundColor', [1 1 1], ... + 'Min', 0, ... + 'Max', 2, ... + 'Position', [0.05 0.2 0.9 0.57]); + [hstrw, newpos] = textwrap(helpui, hstr); + set(helpui, 'String', hstrw, 'Position', [0.05, 0.2, 0.9 newpos(4)]); + + % The CLOSE button + uicontrol(helpfig, ... + 'Style','push', ... + 'Units','normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position',[0.4 0.05 0.2 0.1], ... + 'String','Close', ... + 'Callback','close(gcf)'); + + watchoff(oldFigNumber); + +end; + diff --git a/PatRec/NetLab/netlab3_3/demprior.m b/PatRec/NetLab/netlab3_3/demprior.m new file mode 100644 index 0000000..4ad975a --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demprior.m @@ -0,0 +1,406 @@ +function demprior(action); +%DEMPRIOR Demonstrate sampling from a multi-parameter Gaussian prior. +% +% Description +% This function plots the functions represented by a multi-layer +% perceptron network when the weights are set to values drawn from a +% Gaussian prior distribution. The parameters AW1, AB1 AW2 and AB2 +% control the inverse variances of the first-layer weights, the hidden +% unit biases, the second-layer weights and the output unit biases +% respectively. Their values can be adjusted on a logarithmic scale +% using the sliders, or by typing values into the text boxes and +% pressing the return key. +% +% See also +% MLP +% + +% Copyright (c) Ian T Nabney (1996-2001) + +if nargin<1, + action='initialize'; +end; + +if strcmp(action,'initialize') + + aw1 = 0.01; + ab1 = 0.1; + aw2 = 1.0; + ab2 = 1.0; + + % Create FIGURE + fig=figure( ... + 'Name','Sampling from a Gaussian prior', ... + 'Position', [50 50 480 380], ... + 'NumberTitle','off', ... + 'Color', [0.8 0.8 0.8], ... + 'Visible','on'); + + % The TITLE BAR frame + uicontrol(fig, ... + 'Style','frame', ... + 'Units','normalized', ... + 'HorizontalAlignment', 'center', ... + 'Position', [0.5 0.82 0.45 0.1], ... + 'BackgroundColor',[0.60 0.60 0.60]); + + % The TITLE BAR text + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.54 0.85 0.40 0.05], ... + 'HorizontalAlignment', 'left', ... + 'String', 'Sampling from a Gaussian prior'); + + % Frames to enclose sliders + uicontrol(fig, ... + 'Style', 'frame', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.05 0.08 0.35 0.18]); + + uicontrol(fig, ... + 'Style', 'frame', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.05 0.3 0.35 0.18]); + + uicontrol(fig, ... + 'Style', 'frame', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.05 0.52 0.35 0.18]); + + uicontrol(fig, ... + 'Style', 'frame', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.05 0.74 0.35 0.18]); + + % Frame text + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'HorizontalAlignment', 'left', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.07 0.17 0.06 0.07], ... + 'String', 'aw1'); + + % Frame text + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'HorizontalAlignment', 'left', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.07 0.39 0.06 0.07], ... + 'String', 'ab1'); + + % Frame text + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'HorizontalAlignment', 'left', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.07 0.61 0.06 0.07], ... + 'String', 'aw2'); + + % Frame text + uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'HorizontalAlignment', 'left', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.07 0.83 0.06 0.07], ... + 'String', 'ab2'); + + % Slider + minval = -5; maxval = 5; + aw1slide = uicontrol(fig, ... + 'Style', 'slider', ... + 'Units', 'normalized', ... + 'Value', log10(aw1), ... + 'BackgroundColor', [0.8 0.8 0.8], ... + 'Position', [0.07 0.1 0.31 0.05], ... + 'Min', minval, 'Max', maxval, ... + 'Callback', 'demprior update'); + + % Slider + ab1slide = uicontrol(fig, ... + 'Style', 'slider', ... + 'Units', 'normalized', ... + 'Value', log10(ab1), ... + 'BackgroundColor', [0.8 0.8 0.8], ... + 'Position', [0.07 0.32 0.31 0.05], ... + 'Min', minval, 'Max', maxval, ... + 'Callback', 'demprior update'); + + % Slider + aw2slide = uicontrol(fig, ... + 'Style', 'slider', ... + 'Units', 'normalized', ... + 'Value', log10(aw2), ... + 'BackgroundColor', [0.8 0.8 0.8], ... + 'Position', [0.07 0.54 0.31 0.05], ... + 'Min', minval, 'Max', maxval, ... + 'Callback', 'demprior update'); + + % Slider + ab2slide = uicontrol(fig, ... + 'Style', 'slider', ... + 'Units', 'normalized', ... + 'Value', log10(ab2), ... + 'BackgroundColor', [0.8 0.8 0.8], ... + 'Position', [0.07 0.76 0.31 0.05], ... + 'Min', minval, 'Max', maxval, ... + 'Callback', 'demprior update'); + + % The graph box + haxes = axes('Position', [0.5 0.28 0.45 0.45], ... + 'Units', 'normalized', ... + 'Visible', 'on'); + + % Text display of hyper-parameter values + + format = '%8f'; + + aw1val = uicontrol(fig, ... + 'Style', 'edit', ... + 'Units', 'normalized', ... + 'Position', [0.15 0.17 0.23 0.07], ... + 'String', sprintf(format, aw1), ... + 'Callback', 'demprior newval'); + + ab1val = uicontrol(fig, ... + 'Style', 'edit', ... + 'Units', 'normalized', ... + 'Position', [0.15 0.39 0.23 0.07], ... + 'String', sprintf(format, ab1), ... + 'Callback', 'demprior newval'); + + aw2val = uicontrol(fig, ... + 'Style', 'edit', ... + 'Units', 'normalized', ... + 'Position', [0.15 0.61 0.23 0.07], ... + 'String', sprintf(format, aw2), ... + 'Callback', 'demprior newval'); + + ab2val = uicontrol(fig, ... + 'Style', 'edit', ... + 'Units', 'normalized', ... + 'Position', [0.15 0.83 0.23 0.07], ... + 'String', sprintf(format, ab2), ... + 'Callback', 'demprior newval'); + + % The SAMPLE button + uicontrol(fig, ... + 'Style','push', ... + 'Units','normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position',[0.5 0.08 0.13 0.1], ... + 'String','Sample', ... + 'Callback','demprior replot'); + + % The CLOSE button + uicontrol(fig, ... + 'Style','push', ... + 'Units','normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position',[0.82 0.08 0.13 0.1], ... + 'String','Close', ... + 'Callback','close(gcf)'); + + % The HELP button + uicontrol(fig, ... + 'Style','push', ... + 'Units','normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position',[0.66 0.08 0.13 0.1], ... + 'String','Help', ... + 'Callback','demprior help'); + + % Save handles to objects + + hndlList=[fig aw1slide ab1slide aw2slide ab2slide aw1val ab1val aw2val ... + ab2val haxes]; + set(fig, 'UserData', hndlList); + + demprior('replot') + + +elseif strcmp(action, 'update'), + + % Update when a slider is moved. + + hndlList = get(gcf, 'UserData'); + aw1slide = hndlList(2); + ab1slide = hndlList(3); + aw2slide = hndlList(4); + ab2slide = hndlList(5); + aw1val = hndlList(6); + ab1val = hndlList(7); + aw2val = hndlList(8); + ab2val = hndlList(9); + haxes = hndlList(10); + + aw1 = 10^get(aw1slide, 'Value'); + ab1 = 10^get(ab1slide, 'Value'); + aw2 = 10^get(aw2slide, 'Value'); + ab2 = 10^get(ab2slide, 'Value'); + + format = '%8f'; + set(aw1val, 'String', sprintf(format, aw1)); + set(ab1val, 'String', sprintf(format, ab1)); + set(aw2val, 'String', sprintf(format, aw2)); + set(ab2val, 'String', sprintf(format, ab2)); + + demprior('replot'); + +elseif strcmp(action, 'newval'), + + % Update when text is changed. + + hndlList = get(gcf, 'UserData'); + aw1slide = hndlList(2); + ab1slide = hndlList(3); + aw2slide = hndlList(4); + ab2slide = hndlList(5); + aw1val = hndlList(6); + ab1val = hndlList(7); + aw2val = hndlList(8); + ab2val = hndlList(9); + haxes = hndlList(10); + + aw1 = sscanf(get(aw1val, 'String'), '%f'); + ab1 = sscanf(get(ab1val, 'String'), '%f'); + aw2 = sscanf(get(aw2val, 'String'), '%f'); + ab2 = sscanf(get(ab2val, 'String'), '%f'); + + set(aw1slide, 'Value', log10(aw1)); + set(ab1slide, 'Value', log10(ab1)); + set(aw2slide, 'Value', log10(aw2)); + set(ab2slide, 'Value', log10(ab2)); + + demprior('replot'); + +elseif strcmp(action, 'replot'), + + % Re-sample from the prior and plot graphs. + + oldFigNumber=watchon; + + hndlList = get(gcf, 'UserData'); + aw1slide = hndlList(2); + ab1slide = hndlList(3); + aw2slide = hndlList(4); + ab2slide = hndlList(5); + haxes = hndlList(10); + + aw1 = 10^get(aw1slide, 'Value'); + ab1 = 10^get(ab1slide, 'Value'); + aw2 = 10^get(aw2slide, 'Value'); + ab2 = 10^get(ab2slide, 'Value'); + + axes(haxes); + cla + set(gca, ... + 'Box', 'on', ... + 'Color', [0 0 0], ... + 'XColor', [0 0 0], ... + 'YColor', [0 0 0], ... + 'FontSize', 14); + axis([-1 1 -10 10]); + set(gca,'DefaultLineLineWidth', 2); + + nhidden = 12; + prior = mlpprior(1, nhidden, 1, aw1, ab1, aw2, ab2); + xvals = -1:0.005:1; + nsample = 10; % Number of samples from prior. + hold on + plot([-1 0; 1 0], [0 -10; 0 10], 'b--'); + net = mlp(1, nhidden, 1, 'linear', prior); + for i = 1:nsample + net = mlpinit(net, prior); + yvals = mlpfwd(net, xvals'); + plot(xvals', yvals, 'y'); + end + + watchoff(oldFigNumber); + +elseif strcmp(action, 'help'), + + % Provide help to user. + + oldFigNumber=watchon; + + helpfig = figure('Position', [100 100 480 400], ... + 'Name', 'Help', ... + 'NumberTitle', 'off', ... + 'Color', [0.8 0.8 0.8], ... + 'Visible','on'); + + % The HELP TITLE BAR frame + uicontrol(helpfig, ... + 'Style','frame', ... + 'Units','normalized', ... + 'HorizontalAlignment', 'center', ... + 'Position', [0.05 0.82 0.9 0.1], ... + 'BackgroundColor',[0.60 0.60 0.60]); + + % The HELP TITLE BAR text + uicontrol(helpfig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position', [0.26 0.85 0.6 0.05], ... + 'HorizontalAlignment', 'left', ... + 'String', 'Help: Sampling from a Gaussian Prior'); + + helpstr1 = strcat( ... + 'This demonstration shows the effects of sampling from a Gaussian', ... + ' prior over weights for a two-layer feed-forward network. The', ... + ' parameters aw1, ab1, aw2 and ab2 control the inverse variances of', ... + ' the first-layer weights, the hidden unit biases, the second-layer', ... + ' weights and the output unit biases respectively. Their values can', ... + ' be adjusted on a logarithmic scale using the sliders, or by', ... + ' typing values into the text boxes and pressing the return key.', ... + ' After setting these values, press the ''Sample'' button to see a', ... + ' new sample from the prior. '); + helpstr2 = strcat( ... + 'Observe how aw1 controls the horizontal length-scale of the', ... + ' variation in the functions, ab1 controls the input range over', ... + ' such variations occur, aw2 sets the vertical scale of the output', ... + ' and ab2 sets the vertical off-set of the output. The network has', ... + ' 12 hidden units. '); + hstr(1) = {helpstr1}; + hstr(2) = {''}; + hstr(3) = {helpstr2}; + + % The HELP text + helpui = uicontrol(helpfig, ... + 'Style', 'edit', ... + 'Units', 'normalized', ... + 'ForegroundColor', [0 0 0], ... + 'HorizontalAlignment', 'left', ... + 'BackgroundColor', [1 1 1], ... + 'Min', 0, ... + 'Max', 2, ... + 'Position', [0.05 0.2 0.9 0.8]); + + [hstrw , newpos] = textwrap(helpui, hstr, 70); + set(helpui, 'String', hstrw, 'Position', [0.05, 0.2, 0.9, newpos(4)]); + + + % The CLOSE button + uicontrol(helpfig, ... + 'Style','push', ... + 'Units','normalized', ... + 'BackgroundColor', [0.6 0.6 0.6], ... + 'Position',[0.4 0.05 0.2 0.1], ... + 'String','Close', ... + 'Callback','close(gcf)'); + + watchoff(oldFigNumber); + +end; + diff --git a/PatRec/NetLab/netlab3_3/demrbf1.m b/PatRec/NetLab/netlab3_3/demrbf1.m new file mode 100644 index 0000000..ffd6fd5 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demrbf1.m @@ -0,0 +1,138 @@ +%DEMRBF1 Demonstrate simple regression using a radial basis function network. +% +% Description +% The problem consists of one input variable X and one target variable +% T with data generated by sampling X at equal intervals and then +% generating target data by computing SIN(2*PI*X) and adding Gaussian +% noise. This data is the same as that used in demmlp1. +% +% Three different RBF networks (with different activation functions) +% are trained in two stages. First, a Gaussian mixture model is trained +% using the EM algorithm, and the centres of this model are used to set +% the centres of the RBF. Second, the output weights (and biases) are +% determined using the pseudo-inverse of the design matrix. +% +% See also +% DEMMLP1, RBF, RBFFWD, GMM, GMMEM +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +% Generate the matrix of inputs x and targets t. +randn('state', 42); +rand('state', 42); +ndata = 20; % Number of data points. +noise = 0.2; % Standard deviation of noise distribution. +x = (linspace(0, 1, ndata))'; +t = sin(2*pi*x) + noise*randn(ndata, 1); +mu = mean(x); +sigma = std(x); +tr_in = (x - mu)./(sigma); + +clc +disp('This demonstration illustrates the use of a Radial Basis Function') +disp('network for regression problems. The data is generated from a noisy') +disp('sine function.') +disp(' ') +disp('Press any key to continue.') +pause +% Set up network parameters. +nin = 1; % Number of inputs. +nhidden = 7; % Number of hidden units. +nout = 1; % Number of outputs. + +clc +disp('We assess the effect of three different activation functions.') +disp('First we create a network with Gaussian activations.') +disp(' ') +disp('Press any key to continue.') +pause +% Create and initialize network weight and parameter vectors. +net = rbf(nin, nhidden, nout, 'gaussian'); + +disp('A two-stage training algorithm is used: it uses a small number of') +disp('iterations of EM to position the centres, and then the pseudo-inverse') +disp('of the design matrix to find the second layer weights.') +disp(' ') +disp('Press any key to continue.') +pause +disp('Error values from EM training.') +% Use fast training method +options = foptions; +options(1) = 1; % Display EM training +options(14) = 10; % number of iterations of EM +net = rbftrain(net, options, tr_in, t); + +disp(' ') +disp('Press any key to continue.') +pause +clc +disp('The second RBF network has thin plate spline activations.') +disp('The same centres are used again, so we just need to calculate') +disp('the second layer weights.') +disp(' ') +disp('Press any key to continue.') +pause +% Create a second RBF with thin plate spline functions +net2 = rbf(nin, nhidden, nout, 'tps'); + +% Re-use previous centres rather than calling rbftrain again +net2.c = net.c; +[y, act2] = rbffwd(net2, tr_in); + +% Solve for new output weights and biases from RBF activations +temp = pinv([act2 ones(ndata, 1)]) * t; +net2.w2 = temp(1:nhidden, :); +net2.b2 = temp(nhidden+1, :); + +disp('The third RBF network has r^4 log r activations.') +disp(' ') +disp('Press any key to continue.') +pause +% Create a third RBF with r^4 log r functions +net3 = rbf(nin, nhidden, nout, 'r4logr'); + +% Overwrite weight vector with parameters from first RBF +net3.c = net.c; +[y, act3] = rbffwd(net3, tr_in); +temp = pinv([act3 ones(ndata, 1)]) * t; +net3.w2 = temp(1:nhidden, :); +net3.b2 = temp(nhidden+1, :); + +disp('Now we plot the data, underlying function, and network outputs') +disp('on a single graph to compare the results.') +disp(' ') +disp('Press any key to continue.') +pause +% Plot the data, the original function, and the trained network functions. +plotvals = [x(1):0.01:x(end)]'; +inputvals = (plotvals-mu)./sigma; +y = rbffwd(net, inputvals); +y2 = rbffwd(net2, inputvals); +y3 = rbffwd(net3, inputvals); +fh1 = figure; + +plot(x, t, 'ob') +hold on +xlabel('Input') +ylabel('Target') +axis([x(1) x(end) -1.5 1.5]) +[fx, fy] = fplot('sin(2*pi*x)', [x(1) x(end)]); +plot(fx, fy, '-r', 'LineWidth', 2) +plot(plotvals, y, '--g', 'LineWidth', 2) +plot(plotvals, y2, 'k--', 'LineWidth', 2) +plot(plotvals, y3, '-.c', 'LineWidth', 2) +legend('data', 'function', 'Gaussian RBF', 'Thin plate spline RBF', ... + 'r^4 log r RBF'); +hold off + +disp('RBF training errors are'); +disp(['Gaussian ', num2str(rbferr(net, tr_in, t)), ' TPS ', ... +num2str(rbferr(net2, tr_in, t)), ' R4logr ', num2str(rbferr(net3, tr_in, t))]); + +disp(' ') +disp('Press any key to end.') +pause +close(fh1); +clear all; diff --git a/PatRec/NetLab/netlab3_3/demsom1.m b/PatRec/NetLab/netlab3_3/demsom1.m new file mode 100644 index 0000000..2f1fe93 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demsom1.m @@ -0,0 +1,113 @@ +%DEMSOM1 Demonstrate SOM for visualisation. +% +% Description +% This script demonstrates the use of a SOM with a two-dimensional +% grid to map onto data in two-dimensional space. Both on-line and +% batch training algorithms are shown. +% +% See also +% SOM, SOMPAK, SOMTRAIN +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +randn('state', 42); +rand('state', 42); +nin = 2; +ndata = 300; +% Give data an offset so that network has something to learn. +x = rand(ndata, nin) + ones(ndata, 1)*[1.5 1.5]; + +clc; +disp('This demonstration of the SOM, or Kohonen network, shows how the') +disp('network units after training lie in regions of high data density.') +disp('First we show the data, which is generated uniformly from a square.') +disp('Red crosses denote the data and black dots are the initial locations') +disp('of the SOM units.') +disp(' ') +disp('Press any key to continue.') +pause +net = som(nin, [8, 7]); +c1 = sompak(net); +h1 = figure; +plot(x(:, 1), x(:, 2), 'r+'); +hold on +plot(c1(:,1), c1(:, 2), 'k.'); +drawnow; % Force figure to be drawn before training starts +options = foptions; + +% Ordering phase +options(1) = 1; +options(14) = 50; +%options(14) = 5; % Just for testing +options(18) = 0.9; % Initial learning rate +options(16) = 0.05; % Final learning rate +options(17) = 8; % Initial neighbourhood size +options(15) = 1; % Final neighbourhood size + +disp('The SOM network is trained in two phases using an on-line algorithm.') +disp('Initially the neighbourhood is set to 8 and is then reduced') +disp('linearly to 1 over the first 50 iterations.') +disp('Each iteration consists of a pass through the complete') +disp('dataset, while the weights are adjusted after each pattern.') +disp('The learning rate is reduced linearly from 0.9 to 0.05.') +disp('This ordering phase puts the units in a rough grid shape.') +disp('Blue circles denote the units at the end of this phase.') +disp(' ') +disp('Press any key to continue.') +pause +net2 = somtrain(net, options, x); +c2 = sompak(net2); +plot(c2(:, 1), c2(:, 2), 'bo'); +drawnow; + +% Convergence phase +options(1) = 1; +options(14) = 400; +options(18) = 0.05; +options(16) = 0.01; +options(17) = 0; +options(15) = 0; + +disp('The second, convergence, phase of learning just updates the winning node.') +disp('The learning rate is reduced from 0.05 to 0.01 over 400 iterations.') +disp('Note how the error value does not decrease monotonically; it is') +disp('difficult to decide when training is complete in a principled way.') +disp('The units are plotted as green stars.') +disp(' ') +disp('Press any key to continue.') +pause +net3 = somtrain(net2, options, x); +c3 = sompak(net3); +plot(c3(:, 1), c3(:, 2), 'g*'); +drawnow; + +% Now try batch training +options(1) = 1; +options(6) = 1; +options(14) = 50; +options(17) = 3; +options(15) = 0; +disp('An alternative approach to the on-line algorithm is a batch update') +disp('rule. Each unit is updated to be the average weights') +disp('in a neighbourhood (which reduces from 3 to 0) over 50 iterations.'); +disp('Note how the error is even more unstable at first, though eventually') +disp('it does converge.') +disp('The final units are shown as black triangles.') +disp(' ') +disp('Press any key to continue.') +pause +net4 = somtrain(net, options, x); +c4 = sompak(net4); +plot(c4(:, 1), c4(:, 2), 'k^') +legend('Data', 'Initial weights', 'Weights after ordering', ... + 'Weights after convergence', 'Batch weights', 2); +drawnow; + +disp(' ') +disp('Press any key to end.') +disp(' ') +pause + +close(h1); \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/demtrain.m b/PatRec/NetLab/netlab3_3/demtrain.m new file mode 100644 index 0000000..61ebc16 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/demtrain.m @@ -0,0 +1,362 @@ +function demtrain(action); +%DEMTRAIN Demonstrate training of MLP network. +% +% Description +% DEMTRAIN brings up a simple GUI to show the training of an MLP +% network on classification and regression problems. The user should +% load in a dataset (which should be in Netlab format: see DATREAD), +% select the output activation function, the number of cycles and +% hidden units and then train the network. The scaled conjugate +% gradient algorithm is used. A graph shows the evolution of the error: +% the value is shown MAX(CEIL(ITERATIONS / 50), 5) cycles. +% +% Once the network is trained, it is saved to the file MLPTRAIN.NET. +% The results can then be viewed as a confusion matrix (for +% classification problems) or a plot of output versus target (for +% regression problems). +% +% See also +% CONFMAT, DATREAD, MLP, NETOPT, SCG +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% If run without parameters, initialise gui. +if nargin<1, + action='initialise'; +end; + +% Global variable to reference GUI figure +global DEMTRAIN_FIG +% Global array to reference sub-figures for results plots +global DEMTRAIN_RES_FIGS +global NUM_DEMTRAIN_RES_FIGS + +if strcmp(action,'initialise'), + + file = ''; + path = '.'; + + % Create FIGURE + fig = figure( ... + 'Name', 'Netlab Demo', ... + 'NumberTitle', 'off', ... + 'Menubar', 'none', ... + 'Color', [0.7529 0.7529 0.7529], ... + 'Visible', 'on'); + % Initialise the globals + DEMTRAIN_FIG = fig; + DEMTRAIN_RES_FIGS = 0; + NUM_DEMTRAIN_RES_FIGS = 0; + + % Create GROUP for buttons + uicontrol(fig, ... + 'Style', 'frame', ... + 'Units', 'normalized', ... + 'Position', [0.03 0.08 0.94 0.22], ... + 'BackgroundColor', [0.5 0.5 0.5]); + + % Create MAIN axis + hMain = axes( ... + 'Units', 'normalized', ... + 'Position', [0.10 0.5 0.80 0.40], ... + 'XColor', [0 0 0], ... + 'YColor', [0 0 0], ... + 'Visible', 'on'); + + % Create static text for FILENAME and PATH + hFilename = uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.7529 0.7529 0.7529], ... + 'Position', [0.05 0.32 0.90 0.05], ... + 'HorizontalAlignment', 'center', ... + 'String', 'Please load data file.', ... + 'Visible', 'on'); + hPath = uicontrol(fig, ... + 'Style', 'text', ... + 'Units', 'normalized', ... + 'BackgroundColor', [0.7529 0.7529 0.7529], ... + 'Position', [0.05 0.37 0.90 0.05], ... + 'HorizontalAlignment', 'center', ... + 'String', '', ... + 'Visible', 'on'); + + % Create NO OF HIDDEN UNITS slider and text + hSliderText = uicontrol(fig, ... + 'Style', 'text', ... + 'BackgroundColor', [0.5 0.5 0.5], ... + 'Units', 'normalized', ... + 'Position', [0.27 0.12 0.17 0.04], ... + 'HorizontalAlignment', 'right', ... + 'String', 'Hidden Units: 5'); + hSlider = uicontrol(fig, ... + 'Style', 'slider', ... + 'Units', 'normalized', ... + 'Position', [0.45 0.12 0.26 0.04], ... + 'String', 'Slider', ... + 'Min', 1, 'Max', 25, ... + 'Value', 5, ... + 'Callback', 'demtrain slider_moved'); + + % Create ITERATIONS slider and text + hIterationsText = uicontrol(fig, ... + 'Style', 'text', ... + 'BackgroundColor', [0.5 0.5 0.5], ... + 'Units', 'normalized', ... + 'Position', [0.27 0.21 0.17 0.04], ... + 'HorizontalAlignment', 'right', ... + 'String', 'Iterations: 50'); + hIterations = uicontrol(fig, ... + 'Style', 'slider', ... + 'Units', 'normalized', ... + 'Position', [0.45 0.21 0.26 0.04], ... + 'String', 'Slider', ... + 'Min', 10, 'Max', 500, ... + 'Value', 50, ... + 'Callback', 'demtrain iterations_moved'); + + % Create ACTIVATION FUNCTION popup and text + uicontrol(fig, ... + 'Style', 'text', ... + 'BackgroundColor', [0.5 0.5 0.5], ... + 'Units', 'normalized', ... + 'Position', [0.05 0.20 0.20 0.04], ... + 'HorizontalAlignment', 'center', ... + 'String', 'Activation Function:'); + hPopup = uicontrol(fig, ... + 'Style', 'popup', ... + 'Units', 'normalized', ... + 'Position' , [0.05 0.10 0.20 0.08], ... + 'String', 'Linear|Logistic|Softmax', ... + 'Callback', ''); + + % Create MENU + hMenu1 = uimenu('Label', 'Load Data file...', 'Callback', ''); + uimenu(hMenu1, 'Label', 'Select training data file', ... + 'Callback', 'demtrain get_ip_file'); + hMenu2 = uimenu('Label', 'Show Results...', 'Callback', ''); + uimenu(hMenu2, 'Label', 'Show classification results', ... + 'Callback', 'demtrain classify'); + uimenu(hMenu2, 'Label', 'Show regression results', ... + 'Callback', 'demtrain predict'); + + % Create START button + hStart = uicontrol(fig, ... + 'Units', 'normalized', ... + 'Position' , [0.75 0.2 0.20 0.08], ... + 'String', 'Start Training', ... + 'Enable', 'off',... + 'Callback', 'demtrain start'); + + % Create CLOSE button + uicontrol(fig, ... + 'Units', 'normalized', ... + 'Position' , [0.75 0.1 0.20 0.08], ... + 'String', 'Close', ... + 'Callback', 'demtrain close'); + + % Save handles of important UI objects + hndlList = [hSlider hSliderText hFilename hPath hPopup ... + hIterations hIterationsText hStart]; + set(fig, 'UserData', hndlList); + % Hide window from command line + set(fig, 'HandleVisibility', 'callback'); + + +elseif strcmp(action, 'slider_moved'), + + % Slider has been moved. + + hndlList = get(gcf, 'UserData'); + hSlider = hndlList(1); + hSliderText = hndlList(2); + + val = get(hSlider, 'Value'); + if rem(val, 1) < 0.5, % Force up and down arrows to work! + val = ceil(val); + else + val = floor(val); + end; + set(hSlider, 'Value', val); + set(hSliderText, 'String', ['Hidden Units: ' int2str(val)]); + + +elseif strcmp(action, 'iterations_moved'), + + % Slider has been moved. + + hndlList = get(gcf, 'UserData'); + hSlider = hndlList(6); + hSliderText = hndlList(7); + + val = get(hSlider, 'Value'); + set(hSliderText, 'String', ['Iterations: ' int2str(val)]); + +elseif strcmp(action, 'get_ip_file'), + + % Get data file button pressed. + + hndlList = get(gcf, 'UserData'); + + [file, path] = uigetfile('*.dat', 'Get Data File', 50, 50); + + if strcmp(file, '') | file == 0, + set(hndlList(3), 'String', 'No data file loaded.'); + set(hndlList(4), 'String', ''); + else + set(hndlList(3), 'String', file); + set(hndlList(4), 'String', path); + end; + + % Enable training button + set(hndlList(8), 'Enable', 'on'); + + set(gcf, 'UserData', hndlList); + +elseif strcmp(action, 'start'), + + % Start training + + % Get handles of and values from UI objects + hndlList = get(gcf, 'UserData'); + hSlider = hndlList(1); % No of hidden units + hIterations = hndlList(6); + iterations = get(hIterations, 'Value'); + + hFilename = hndlList(3); % Data file name + filename = get(hFilename, 'String'); + + hPath = hndlList(4); % Data file path + path = get(hPath, 'String'); + + hPopup = hndlList(5); % Activation function + if get(hPopup, 'Value') == 1, + act_fn = 'linear'; + elseif get(hPopup, 'Value') == 2, + act_fn = 'logistic'; + else + act_fn = 'softmax'; + end; + nhidden = get(hSlider, 'Value'); + + % Check data file exists + if fopen([path '/' filename]) == -1, + errordlg('Training data file has not been selected.', 'Error'); + else + % Load data file + [x,t,nin,nout,ndata] = datread([path filename]); + + % Call MLPTRAIN function repeatedly, while drawing training graph. + figure(DEMTRAIN_FIG); + hold on; + + title('Training - please wait.'); + + % Create net and find initial error + net = mlp(size(x, 2), nhidden, size(t, 2), act_fn); + % Initialise network with inverse variance of 10 + net = mlpinit(net, 10); + error = mlperr(net, x, t); + % Work out reporting step: should be sufficiently big to let training + % algorithm have a chance + step = max(ceil(iterations / 50), 5); + + % Refresh and rescale axis. + cla; + max = error; + min = max/10; + set(gca, 'YScale', 'log'); + ylabel('log Error'); + xlabel('No. iterations'); + axis([0 iterations min max+1]); + iold = 0; + errold = error; + % Plot circle to show error of last iteration + % Setting erase mode to none prevents screen flashing during + % training + plot(0, error, 'ro', 'EraseMode', 'none'); + hold on + drawnow; % Force redraw + for i = step-1:step:iterations, + [net, error] = mlptrain(net, x, t, step); + % Plot line from last point to new point. + line([iold i], [errold error], 'Color', 'r', 'EraseMode', 'none'); + iold = i; + errold = error; + + % If new point off scale, redraw axes. + if error > max, + max = error; + axis([0 iterations min max+1]); + end; + if error < min + min = error/10; + axis([0 iterations min max+1]); + end + % Plot circle to show error of last iteration + plot(i, error, 'ro', 'EraseMode', 'none'); + drawnow; % Force redraw + end; + save mlptrain.net net + zoom on; + + title(['Training complete. Final error=', num2str(error)]); + + end; + +elseif strcmp(action, 'close'), + + % Close all the figures we have created + close(DEMTRAIN_FIG); + for n = 1:NUM_DEMTRAIN_RES_FIGS + if ishandle(DEMTRAIN_RES_FIGS(n)) + close(DEMTRAIN_RES_FIGS(n)); + end + end + +elseif strcmp(action, 'classify'), + + if fopen('mlptrain.net') == -1, + errordlg('You have not yet trained the network.', 'Error'); + else + + hndlList = get(gcf, 'UserData'); + filename = get(hndlList(3), 'String'); + path = get(hndlList(4), 'String'); + [x,t,nin,nout,ndata] = datread([path filename]); + load mlptrain.net net -mat + y = mlpfwd(net, x); + + % Save results figure so that it can be closed later + NUM_DEMTRAIN_RES_FIGS = NUM_DEMTRAIN_RES_FIGS + 1; + DEMTRAIN_RES_FIGS(NUM_DEMTRAIN_RES_FIGS)=conffig(y,t); + + end; + +elseif strcmp(action, 'predict'), + + if fopen('mlptrain.net') == -1, + errordlg('You have not yet trained the network.', 'Error'); + else + + hndlList = get(gcf, 'UserData'); + filename = get(hndlList(3), 'String'); + path = get(hndlList(4), 'String'); + [x,t,nin,nout,ndata] = datread([path filename]); + load mlptrain.net net -mat + y = mlpfwd(net, x); + + for i = 1:size(y,2), + % Save results figure so that it can be closed later + NUM_DEMTRAIN_RES_FIGS = NUM_DEMTRAIN_RES_FIGS + 1; + DEMTRAIN_RES_FIGS(NUM_DEMTRAIN_RES_FIGS) = figure; + hold on; + title(['Output no ' num2str(i)]); + plot([0 1], [0 1], 'r:'); + plot(y(:,i),t(:,i), 'o'); + hold off; + end; + end; + +end; \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/dist2.m b/PatRec/NetLab/netlab3_3/dist2.m new file mode 100644 index 0000000..b5f1c64 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/dist2.m @@ -0,0 +1,31 @@ +function n2 = dist2(x, c) +%DIST2 Calculates squared distance between two sets of points. +% +% Description +% D = DIST2(X, C) takes two matrices of vectors and calculates the +% squared Euclidean distance between them. Both matrices must be of +% the same column dimension. If X has M rows and N columns, and C has +% L rows and N columns, then the result has M rows and L columns. The +% I, Jth entry is the squared distance from the Ith row of X to the +% Jth row of C. +% +% See also +% GMMACTIV, KMEANS, RBFFWD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +[ndata, dimx] = size(x); +[ncentres, dimc] = size(c); +if dimx ~= dimc + error('Data dimension does not match dimension of centres') +end + +n2 = (ones(ncentres, 1) * sum((x.^2)', 1))' + ... + ones(ndata, 1) * sum((c.^2)',1) - ... + 2.*(x*(c')); + +% Rounding errors occasionally cause negative entries in n2 +if any(any(n2<0)) + n2(n2<0) = 0; +end \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/eigdec.m b/PatRec/NetLab/netlab3_3/eigdec.m new file mode 100644 index 0000000..f5901d4 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/eigdec.m @@ -0,0 +1,55 @@ +function [evals, evec] = eigdec(x, N) +%EIGDEC Sorted eigendecomposition +% +% Description +% EVALS = EIGDEC(X, N computes the largest N eigenvalues of the +% matrix X in descending order. [EVALS, EVEC] = EIGDEC(X, N) also +% computes the corresponding eigenvectors. +% +% See also +% PCA, PPCA +% + +% Copyright (c) Ian T Nabney (1996-2001) + +if nargout == 1 + evals_only = logical(1); +else + evals_only = logical(0); +end + +if N ~= round(N) | N < 1 | N > size(x, 2) + error('Number of PCs must be integer, >0, < dim'); +end + +% Find the eigenvalues of the data covariance matrix +if evals_only + % Use eig function as always more efficient than eigs here + temp_evals = eig(x); +else + % Use eig function unless fraction of eigenvalues required is tiny + if (N/size(x, 2)) > 0.04 + [temp_evec, temp_evals] = eig(x); + else + options.disp = 0; + [temp_evec, temp_evals] = eigs(x, N, 'LM', options); + end + temp_evals = diag(temp_evals); +end + +% Eigenvalues nearly always returned in descending order, but just +% to make sure..... +[evals perm] = sort(-temp_evals); +evals = -evals(1:N); +if ~evals_only + if evals == temp_evals(1:N) + % Originals were in order + evec = temp_evec(:, 1:N); + return + else + % Need to reorder the eigenvectors + for i=1:N + evec(:,i) = temp_evec(:,perm(i)); + end + end +end \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/errbayes.m b/PatRec/NetLab/netlab3_3/errbayes.m new file mode 100644 index 0000000..7c2a330 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/errbayes.m @@ -0,0 +1,49 @@ +function [e, edata, eprior] = errbayes(net, edata) +%ERRBAYES Evaluate Bayesian error function for network. +% +% Description +% E = ERRBAYES(NET, EDATA) takes a network data structure NET together +% the data contribution to the error for a set of inputs and targets. +% It returns the regularised error using any zero mean Gaussian priors +% on the weights defined in NET. +% +% [E, EDATA, EPRIOR] = ERRBAYES(NET, X, T) additionally returns the +% data and prior components of the error. +% +% See also +% GLMERR, MLPERR, RBFERR +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Evaluate the data contribution to the error. +if isfield(net, 'beta') + e1 = net.beta*edata; +else + e1 = edata; +end + +% Evaluate the prior contribution to the error. +if isfield(net, 'alpha') + w = netpak(net); + if size(net.alpha) == [1 1] + eprior = 0.5*(w*w'); + e2 = eprior*net.alpha; + else + if (isfield(net, 'mask')) + nindx_cols = size(net.index, 2); + nmask_rows = size(find(net.mask), 1); + index = reshape(net.index(logical(repmat(net.mask, ... + 1, nindx_cols))), nmask_rows, nindx_cols); + else + index = net.index; + end + eprior = 0.5*(w.^2)*index; + e2 = eprior*net.alpha; + end +else + eprior = 0; + e2 = 0; +end + +e = e1 + e2; diff --git a/PatRec/NetLab/netlab3_3/evidence.m b/PatRec/NetLab/netlab3_3/evidence.m new file mode 100644 index 0000000..ab023cb --- /dev/null +++ b/PatRec/NetLab/netlab3_3/evidence.m @@ -0,0 +1,114 @@ +function [net, gamma, logev] = evidence(net, x, t, num) +%EVIDENCE Re-estimate hyperparameters using evidence approximation. +% +% Description +% [NET] = EVIDENCE(NET, X, T) re-estimates the hyperparameters ALPHA +% and BETA by applying Bayesian re-estimation formulae for NUM +% iterations. The hyperparameter ALPHA can be a simple scalar +% associated with an isotropic prior on the weights, or can be a vector +% in which each component is associated with a group of weights as +% defined by the INDEX matrix in the NET data structure. These more +% complex priors can be set up for an MLP using MLPPRIOR. Initial +% values for the iterative re-estimation are taken from the network +% data structure NET passed as an input argument, while the return +% argument NET contains the re-estimated values. +% +% [NET, GAMMA, LOGEV] = EVIDENCE(NET, X, T, NUM) allows the re- +% estimation formula to be applied for NUM cycles in which the re- +% estimated values for the hyperparameters from each cycle are used to +% re-evaluate the Hessian matrix for the next cycle. The return value +% GAMMA is the number of well-determined parameters and LOGEV is the +% log of the evidence. +% +% See also +% MLPPRIOR, NETGRAD, NETHESS, DEMEV1, DEMARD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +errstring = consist(net, '', x, t); +if ~isempty(errstring) + error(errstring); +end + +ndata = size(x, 1); +if nargin == 3 + num = 1; +end + +% Extract weights from network +w = netpak(net); + +% Evaluate data-dependent contribution to the Hessian matrix. +[h, dh] = nethess(w, net, x, t); +clear h; % To save memory when Hessian is large +if (~isfield(net, 'beta')) + local_beta = 1; +end + +[evec, evl] = eig(dh); +% Now set the negative eigenvalues to zero. +evl = evl.*(evl > 0); +% safe_evl is used to avoid taking log of zero +safe_evl = evl + eps.*(evl <= 0); + +[e, edata, eprior] = neterr(w, net, x, t); + +if size(net.alpha) == [1 1] + % Form vector of eigenvalues + evl = diag(evl); + safe_evl = diag(safe_evl); +else + ngroups = size(net.alpha, 1); + gams = zeros(1, ngroups); + logas = zeros(1, ngroups); + % Reconstruct data hessian with negative eigenvalues set to zero. + dh = evec*evl*evec'; +end + +% Do the re-estimation. +for k = 1 : num + % Re-estimate alpha. + if size(net.alpha) == [1 1] + % Evaluate number of well-determined parameters. + L = evl; + if isfield(net, 'beta') + L = net.beta*L; + end + gamma = sum(L./(L + net.alpha)); + net.alpha = 0.5*gamma/eprior; + % Partially evaluate log evidence: only include unmasked weights + logev = 0.5*length(w)*log(net.alpha); + else + hinv = inv(hbayes(net, dh)); + for m = 1 : ngroups + group_nweights = sum(net.index(:, m)); + gams(m) = group_nweights - ... + net.alpha(m)*sum(diag(hinv).*net.index(:,m)); + net.alpha(m) = real(gams(m)/(2*eprior(m))); + % Weight alphas by number of weights in group + logas(m) = 0.5*group_nweights*log(net.alpha(m)); + end + gamma = sum(gams, 2); + logev = sum(logas); + end + % Re-estimate beta. + if isfield(net, 'beta') + net.beta = 0.5*(net.nout*ndata - gamma)/edata; + logev = logev + 0.5*ndata*log(net.beta) - 0.5*ndata*log(2*pi); + local_beta = net.beta; + end + + % Evaluate new log evidence + e = errbayes(net, edata); + if size(net.alpha) == [1 1] + logev = logev - e - 0.5*sum(log(local_beta*safe_evl+net.alpha)); + else + for m = 1:ngroups + logev = logev - e - ... + 0.5*sum(log(local_beta*(safe_evl*net.index(:, m))+... + net.alpha(m))); + end + end +end + diff --git a/PatRec/NetLab/netlab3_3/fevbayes.m b/PatRec/NetLab/netlab3_3/fevbayes.m new file mode 100644 index 0000000..d568159 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/fevbayes.m @@ -0,0 +1,59 @@ +function [extra, invhess] = fevbayes(net, y, a, x, t, x_test, invhess) +%FEVBAYES Evaluate Bayesian regularisation for network forward propagation. +% +% Description +% EXTRA = FEVBAYES(NET, Y, A, X, T, X_TEST) takes a network data +% structure NET together with a set of hidden unit activations A from +% test inputs X_TEST, training data inputs X and T and outputs a matrix +% of extra information EXTRA that consists of error bars (variance) for +% a regression problem or moderated outputs for a classification +% problem. The optional argument (and return value) INVHESS is the +% inverse of the network Hessian computed on the training data inputs +% and targets. Passing it in avoids recomputing it, which can be a +% significant saving for large training sets. +% +% This is called by network-specific functions such as MLPEVFWD which +% are needed since the return values (predictions and hidden unit +% activations) for different network types are in different orders (for +% good reasons). +% +% See also +% MLPEVFWD, RBFEVFWD, GLMEVFWD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +w = netpak(net); +g = netderiv(w, net, x_test); +if nargin < 7 + % Need to compute inverse hessian + hess = nethess(w, net, x, t); + invhess = inv(hess); +end + +ntest = size(x_test, 1); +var = zeros(ntest, 1); +for idx = 1:1:net.nout, + for n = 1:1:ntest, + grad = squeeze(g(n,:,idx)); + var(n,idx) = grad*invhess*grad'; + end +end + +switch net.outfn + case 'linear' + % extra is variance + extra = ones(size(var))./net.beta + var; + case 'logistic' + % extra is moderated output + kappa = 1./(sqrt(ones(size(var)) + (pi.*var)./8)); + extra = 1./(1 + exp(-kappa.*a)); + case 'softmax' + % Use extended Mackay formula; beware that this may not + % be very accurate + kappa = 1./(sqrt(ones(size(var)) + (pi.*var)./8)); + temp = exp(kappa.*a); + extra = temp./(sum(temp, 2)*ones(1, net.nout)); + otherwise + error(['Unknown activation function ', net.outfn]); +end diff --git a/PatRec/NetLab/netlab3_3/gauss.m b/PatRec/NetLab/netlab3_3/gauss.m new file mode 100644 index 0000000..33e2313 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gauss.m @@ -0,0 +1,33 @@ +function y = gauss(mu, covar, x) +%GAUSS Evaluate a Gaussian distribution. +% +% Description +% +% Y = GAUSS(MU, COVAR, X) evaluates a multi-variate Gaussian density +% in D-dimensions at a set of points given by the rows of the matrix X. +% The Gaussian density has mean vector MU and covariance matrix COVAR. +% +% See also +% GSAMP, DEMGAUSS +% + +% Copyright (c) Ian T Nabney (1996-2001) + +[n, d] = size(x); + +[j, k] = size(covar); + +% Check that the covariance matrix is the correct dimension +if ((j ~= d) | (k ~=d)) + error('Dimension of the covariance matrix and data should match'); +end + +invcov = inv(covar); +mu = reshape(mu, 1, d); % Ensure that mu is a row vector + +x = x - ones(n, 1)*mu; +fact = sum(((x*invcov).*x), 2); + +y = exp(-0.5*fact); + +y = y./sqrt((2*pi)^d*det(covar)); diff --git a/PatRec/NetLab/netlab3_3/gbayes.m b/PatRec/NetLab/netlab3_3/gbayes.m new file mode 100644 index 0000000..7b814e9 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gbayes.m @@ -0,0 +1,56 @@ +function [g, gdata, gprior] = gbayes(net, gdata) +%GBAYES Evaluate gradient of Bayesian error function for network. +% +% Description +% G = GBAYES(NET, GDATA) takes a network data structure NET together +% the data contribution to the error gradient for a set of inputs and +% targets. It returns the regularised error gradient using any zero +% mean Gaussian priors on the weights defined in NET. In addition, if +% a MASK is defined in NET, then the entries in G that correspond to +% weights with a 0 in the mask are removed. +% +% [G, GDATA, GPRIOR] = GBAYES(NET, GDATA) additionally returns the data +% and prior components of the error. +% +% See also +% ERRBAYES, GLMGRAD, MLPGRAD, RBFGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Evaluate the data contribution to the gradient. +if (isfield(net, 'mask')) + gdata = gdata(logical(net.mask)); +end +if isfield(net, 'beta') + g1 = gdata*net.beta; +else + g1 = gdata; +end + +% Evaluate the prior contribution to the gradient. +if isfield(net, 'alpha') + w = netpak(net); + if size(net.alpha) == [1 1] + gprior = w; + g2 = net.alpha*gprior; + else + if (isfield(net, 'mask')) + nindx_cols = size(net.index, 2); + nmask_rows = size(find(net.mask), 1); + index = reshape(net.index(logical(repmat(net.mask, ... + 1, nindx_cols))), nmask_rows, nindx_cols); + else + index = net.index; + end + + ngroups = size(net.alpha, 1); + gprior = index'.*(ones(ngroups, 1)*w); + g2 = net.alpha'*gprior; + end +else + gprior = 0; + g2 = 0; +end + +g = g1 + g2; diff --git a/PatRec/NetLab/netlab3_3/glm.m b/PatRec/NetLab/netlab3_3/glm.m new file mode 100644 index 0000000..7741171 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/glm.m @@ -0,0 +1,82 @@ +function net = glm(nin, nout, outfunc, prior, beta) +%GLM Create a generalized linear model. +% +% Description +% +% NET = GLM(NIN, NOUT, FUNC) takes the number of inputs and outputs for +% a generalized linear model, together with a string FUNC which +% specifies the output unit activation function, and returns a data +% structure NET. The weights are drawn from a zero mean, isotropic +% Gaussian, with variance scaled by the fan-in of the output units. +% This makes use of the Matlab function RANDN and so the seed for the +% random weight initialization can be set using RANDN('STATE', S) +% where S is the seed value. The optional argument ALPHA sets the +% inverse variance for the weight initialization. +% +% The fields in NET are +% type = 'glm' +% nin = number of inputs +% nout = number of outputs +% nwts = total number of weights and biases +% actfn = string describing the output unit activation function: +% 'linear' +% 'logistic' +% 'softmax' +% w1 = first-layer weight matrix +% b1 = first-layer bias vector +% +% NET = GLM(NIN, NOUT, FUNC, PRIOR), in which PRIOR is a scalar, allows +% the field NET.ALPHA in the data structure NET to be set, +% corresponding to a zero-mean isotropic Gaussian prior with inverse +% variance with value PRIOR. Alternatively, PRIOR can consist of a data +% structure with fields ALPHA and INDEX, allowing individual Gaussian +% priors to be set over groups of weights in the network. Here ALPHA is +% a column vector in which each element corresponds to a separate +% group of weights, which need not be mutually exclusive. The +% membership of the groups is defined by the matrix INDEX in which the +% columns correspond to the elements of ALPHA. Each column has one +% element for each weight in the matrix, in the order defined by the +% function GLMPAK, and each element is 1 or 0 according to whether the +% weight is a member of the corresponding group or not. +% +% NET = GLM(NIN, NOUT, FUNC, PRIOR, BETA) also sets the additional +% field NET.BETA in the data structure NET, where beta corresponds to +% the inverse noise variance. +% +% See also +% GLMPAK, GLMUNPAK, GLMFWD, GLMERR, GLMGRAD, GLMTRAIN +% + +% Copyright (c) Ian T Nabney (1996-2001) + +net.type = 'glm'; +net.nin = nin; +net.nout = nout; +net.nwts = (nin + 1)*nout; + +outtfns = {'linear', 'logistic', 'softmax'}; + +if sum(strcmp(outfunc, outtfns)) == 0 + error('Undefined activation function. Exiting.'); +else + net.outfn = outfunc; +end + +if nargin > 3 + if isstruct(prior) + net.alpha = prior.alpha; + net.index = prior.index; + elseif size(prior) == [1 1] + net.alpha = prior; + else + error('prior must be a scalar or structure'); + end +end + +net.w1 = randn(nin, nout)/sqrt(nin + 1); +net.b1 = randn(1, nout)/sqrt(nin + 1); + +if nargin == 5 + net.beta = beta; +end + diff --git a/PatRec/NetLab/netlab3_3/glmderiv.m b/PatRec/NetLab/netlab3_3/glmderiv.m new file mode 100644 index 0000000..bc8de67 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/glmderiv.m @@ -0,0 +1,40 @@ +function g = glmderiv(net, x) +%GLMDERIV Evaluate derivatives of GLM outputs with respect to weights. +% +% Description +% G = GLMDERIV(NET, X) takes a network data structure NET and a matrix +% of input vectors X and returns a three-index matrix mat{g} whose I, +% J, K element contains the derivative of network output K with respect +% to weight or bias parameter J for input pattern I. The ordering of +% the weight and bias parameters is defined by GLMUNPAK. +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check arguments for consistency +errstring = consist(net, 'glm', x); +if ~isempty(errstring) + error(errstring); +end + +ndata = size(x, 1); +if isfield(net, 'mask') + nwts = size(find(net.mask), 1); + mask_array = logical(net.mask)*ones(1, net.nout); +else + nwts = net.nwts; +end +g = zeros(ndata, nwts, net.nout); + +temp = zeros(net.nwts, net.nout); +for n = 1:ndata + % Weight matrix w1 + temp(1:(net.nin*net.nout), :) = kron(eye(net.nout), (x(n, :))'); + % Bias term b1 + temp(net.nin*net.nout+1:end, :) = eye(net.nout); + if isfield(net, 'mask') + g(n, :, :) = reshape(temp(find(mask_array)), nwts, net.nout); + else + g(n, :, :) = temp; + end +end diff --git a/PatRec/NetLab/netlab3_3/glmerr.m b/PatRec/NetLab/netlab3_3/glmerr.m new file mode 100644 index 0000000..bab849c --- /dev/null +++ b/PatRec/NetLab/netlab3_3/glmerr.m @@ -0,0 +1,49 @@ +function [e, edata, eprior, y, a] = glmerr(net, x, t) +%GLMERR Evaluate error function for generalized linear model. +% +% Description +% E = GLMERR(NET, X, T) takes a generalized linear model data +% structure NET together with a matrix X of input vectors and a matrix +% T of target vectors, and evaluates the error function E. The choice +% of error function corresponds to the output unit activation function. +% Each row of X corresponds to one input vector and each row of T +% corresponds to one target vector. +% +% [E, EDATA, EPRIOR, Y, A] = GLMERR(NET, X, T) also returns the data +% and prior components of the total error. +% +% [E, EDATA, EPRIOR, Y, A] = GLMERR(NET, X) also returns a matrix Y +% giving the outputs of the models and a matrix A giving the summed +% inputs to each output unit, where each row corresponds to one +% pattern. +% +% See also +% GLM, GLMPAK, GLMUNPAK, GLMFWD, GLMGRAD, GLMTRAIN +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check arguments for consistency +errstring = consist(net, 'glm', x, t); +if ~isempty(errstring); + error(errstring); +end + +[y, a] = glmfwd(net, x); + +switch net.outfn + + case 'linear' % Linear outputs + edata = 0.5*sum(sum((y - t).^2)); + + case 'logistic' % Logistic outputs + edata = - sum(sum(t.*log(y) + (1 - t).*log(1 - y))); + + case 'softmax' % Softmax outputs + edata = - sum(sum(t.*log(y))); + + otherwise + error(['Unknown activation function ', net.outfn]); +end + +[e, edata, eprior] = errbayes(net, edata); diff --git a/PatRec/NetLab/netlab3_3/glmevfwd.m b/PatRec/NetLab/netlab3_3/glmevfwd.m new file mode 100644 index 0000000..d445a36 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/glmevfwd.m @@ -0,0 +1,28 @@ +function [y, extra, invhess] = glmevfwd(net, x, t, x_test, invhess) +%GLMEVFWD Forward propagation with evidence for GLM +% +% Description +% Y = GLMEVFWD(NET, X, T, X_TEST) takes a network data structure NET +% together with the input X and target T training data and input test +% data X_TEST. It returns the normal forward propagation through the +% network Y together with a matrix EXTRA which consists of error bars +% (variance) for a regression problem or moderated outputs for a +% classification problem. +% +% The optional argument (and return value) INVHESS is the inverse of +% the network Hessian computed on the training data inputs and targets. +% Passing it in avoids recomputing it, which can be a significant +% saving for large training sets. +% +% See also +% FEVBAYES +% + +% Copyright (c) Ian T Nabney (1996-2001) + +[y, a] = glmfwd(net, x_test); +if nargin == 4 + [extra, invhess] = fevbayes(net, y, a, x, t, x_test); +else + [extra, invhess] = fevbayes(net, y, a, x, t, x_test, invhess); +end diff --git a/PatRec/NetLab/netlab3_3/glmfwd.m b/PatRec/NetLab/netlab3_3/glmfwd.m new file mode 100644 index 0000000..5a9519c --- /dev/null +++ b/PatRec/NetLab/netlab3_3/glmfwd.m @@ -0,0 +1,62 @@ +function [y, a] = glmfwd(net, x) +%GLMFWD Forward propagation through generalized linear model. +% +% Description +% Y = GLMFWD(NET, X) takes a generalized linear model data structure +% NET together with a matrix X of input vectors, and forward propagates +% the inputs through the network to generate a matrix Y of output +% vectors. Each row of X corresponds to one input vector and each row +% of Y corresponds to one output vector. +% +% [Y, A] = GLMFWD(NET, X) also returns a matrix A giving the summed +% inputs to each output unit, where each row corresponds to one +% pattern. +% +% See also +% GLM, GLMPAK, GLMUNPAK, GLMERR, GLMGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check arguments for consistency +errstring = consist(net, 'glm', x); +if ~isempty(errstring); + error(errstring); +end + +ndata = size(x, 1); + +a = x*net.w1 + ones(ndata, 1)*net.b1; + +switch net.outfn + + case 'linear' % Linear outputs + y = a; + + case 'logistic' % Logistic outputs + % Prevent overflow and underflow: use same bounds as glmerr + % Ensure that log(1-y) is computable: need exp(a) > eps + maxcut = -log(eps); + % Ensure that log(y) is computable + mincut = -log(1/realmin - 1); + a = min(a, maxcut); + a = max(a, mincut); + y = 1./(1 + exp(-a)); + + case 'softmax' % Softmax outputs + nout = size(a,2); + % Prevent overflow and underflow: use same bounds as glmerr + % Ensure that sum(exp(a), 2) does not overflow + maxcut = log(realmax) - log(nout); + % Ensure that exp(a) > 0 + mincut = log(realmin); + a = min(a, maxcut); + a = max(a, mincut); + temp = exp(a); + y = temp./(sum(temp, 2)*ones(1,nout)); + % Ensure that log(y) is computable + y(y errold + errold = err; + w = wold; + options(8) = err; + fprintf(1, 'Error has increased: terminating\n') + return; + end + if test & n > 1 + if (max(abs(w - wold)) < options(2) & abs(err-errold) < options(3)) + options(8) = err; + return; + else + errold = err; + wold = w; + end + end +end + +options(8) = err; +if (options(1) >= 0) + disp(maxitmess); +end diff --git a/PatRec/NetLab/netlab3_3/glmunpak.m b/PatRec/NetLab/netlab3_3/glmunpak.m new file mode 100644 index 0000000..478ef65 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/glmunpak.m @@ -0,0 +1,30 @@ +function net = glmunpak(net, w) +%GLMUNPAK Separates weights vector into weight and bias matrices. +% +% Description +% NET = GLMUNPAK(NET, W) takes a glm network data structure NET and a +% weight vector W, and returns a network data structure identical to +% the input network, except that the first-layer weight matrix W1 and +% the first-layer bias vector B1 have been set to the corresponding +% elements of W. +% +% See also +% GLM, GLMPAK, GLMFWD, GLMERR, GLMGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check arguments for consistency +errstring = consist(net, 'glm'); +if ~errstring + error(errstring); +end + +if net.nwts ~= length(w) + error('Invalid weight vector length') +end + +nin = net.nin; +nout = net.nout; +net.w1 = reshape(w(1:nin*nout), nin, nout); +net.b1 = reshape(w(nin*nout + 1: (nin + 1)*nout), 1, nout); diff --git a/PatRec/NetLab/netlab3_3/gmm.m b/PatRec/NetLab/netlab3_3/gmm.m new file mode 100644 index 0000000..248de8f --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gmm.m @@ -0,0 +1,113 @@ +function mix = gmm(dim, ncentres, covar_type, ppca_dim) +%GMM Creates a Gaussian mixture model with specified architecture. +% +% Description +% MIX = GMM(DIM, NCENTRES, COVARTYPE) takes the dimension of the space +% DIM, the number of centres in the mixture model and the type of the +% mixture model, and returns a data structure MIX. The mixture model +% type defines the covariance structure of each component Gaussian: +% 'spherical' = single variance parameter for each component: stored as a vector +% 'diag' = diagonal matrix for each component: stored as rows of a matrix +% 'full' = full matrix for each component: stored as 3d array +% 'ppca' = probabilistic PCA: stored as principal components (in a 3d array +% and associated variances and off-subspace noise +% MIX = GMM(DIM, NCENTRES, COVARTYPE, PPCA_DIM) also sets the +% dimension of the PPCA sub-spaces: the default value is one. +% +% The priors are initialised to equal values summing to one, and the +% covariances are all the identity matrix (or equivalent). The centres +% are initialised randomly from a zero mean unit variance Gaussian. +% This makes use of the MATLAB function RANDN and so the seed for the +% random weight initialisation can be set using RANDN('STATE', S) where +% S is the state value. +% +% The fields in MIX are +% +% type = 'gmm' +% nin = the dimension of the space +% ncentres = number of mixture components +% covartype = string for type of variance model +% priors = mixing coefficients +% centres = means of Gaussians: stored as rows of a matrix +% covars = covariances of Gaussians +% The additional fields for mixtures of PPCA are +% U = principal component subspaces +% lambda = in-space covariances: stored as rows of a matrix +% The off-subspace noise is stored in COVARS. +% +% See also +% GMMPAK, GMMUNPAK, GMMSAMP, GMMINIT, GMMEM, GMMACTIV, GMMPOST, +% GMMPROB +% + +% Copyright (c) Ian T Nabney (1996-2001) + +if ncentres < 1 + error('Number of centres must be greater than zero') +end + +mix.type = 'gmm'; +mix.nin = dim; +mix.ncentres = ncentres; + +vartypes = {'spherical', 'diag', 'full', 'ppca'}; + +if sum(strcmp(covar_type, vartypes)) == 0 + error('Undefined covariance type') +else + mix.covar_type = covar_type; +end + +% Make default dimension of PPCA subspaces one. +if strcmp(covar_type, 'ppca') + if nargin < 4 + ppca_dim = 1; + end + if ppca_dim > dim + error('Dimension of PPCA subspaces must be less than data.') + end + mix.ppca_dim = ppca_dim; +end + +% Initialise priors to be equal and summing to one +mix.priors = ones(1,mix.ncentres) ./ mix.ncentres; + +% Initialise centres +mix.centres = randn(mix.ncentres, mix.nin); + +% Initialise all the variances to unity +switch mix.covar_type + +case 'spherical' + mix.covars = ones(1, mix.ncentres); + mix.nwts = mix.ncentres + mix.ncentres*mix.nin + mix.ncentres; +case 'diag' + % Store diagonals of covariance matrices as rows in a matrix + mix.covars = ones(mix.ncentres, mix.nin); + mix.nwts = mix.ncentres + mix.ncentres*mix.nin + ... + mix.ncentres*mix.nin; +case 'full' + % Store covariance matrices in a row vector of matrices + mix.covars = repmat(eye(mix.nin), [1 1 mix.ncentres]); + mix.nwts = mix.ncentres + mix.ncentres*mix.nin + ... + mix.ncentres*mix.nin*mix.nin; +case 'ppca' + % This is the off-subspace noise: make it smaller than + % lambdas + mix.covars = 0.1*ones(1, mix.ncentres); + % Also set aside storage for principal components and + % associated variances + init_space = eye(mix.nin); + init_space = init_space(:, 1:mix.ppca_dim); + init_space(mix.ppca_dim+1:mix.nin, :) = ... + ones(mix.nin - mix.ppca_dim, mix.ppca_dim); + mix.U = repmat(init_space , [1 1 mix.ncentres]); + mix.lambda = ones(mix.ncentres, mix.ppca_dim); + % Take account of additional parameters + mix.nwts = mix.ncentres + mix.ncentres*mix.nin + ... + mix.ncentres + mix.ncentres*mix.ppca_dim + ... + mix.ncentres*mix.nin*mix.ppca_dim; +otherwise + error(['Unknown covariance type ', mix.covar_type]); +end + diff --git a/PatRec/NetLab/netlab3_3/gmmactiv.m b/PatRec/NetLab/netlab3_3/gmmactiv.m new file mode 100644 index 0000000..117e1cd --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gmmactiv.m @@ -0,0 +1,77 @@ +function a = gmmactiv(mix, x) +%GMMACTIV Computes the activations of a Gaussian mixture model. +% +% Description +% This function computes the activations A (i.e. the probability +% P(X|J) of the data conditioned on each component density) for a +% Gaussian mixture model. For the PPCA model, each activation is the +% conditional probability of X given that it is generated by the +% component subspace. The data structure MIX defines the mixture model, +% while the matrix X contains the data vectors. Each row of X +% represents a single vector. +% +% See also +% GMM, GMMPOST, GMMPROB +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check that inputs are consistent +errstring = consist(mix, 'gmm', x); +if ~isempty(errstring) + error(errstring); +end + +ndata = size(x, 1); +a = zeros(ndata, mix.ncentres); % Preallocate matrix + +switch mix.covar_type + +case 'spherical' + % Calculate squared norm matrix, of dimension (ndata, ncentres) + n2 = dist2(x, mix.centres); + + % Calculate width factors + wi2 = ones(ndata, 1) * (2 .* mix.covars); + normal = (pi .* wi2) .^ (mix.nin/2); + + % Now compute the activations + a = exp(-(n2./wi2))./ normal; + +case 'diag' + normal = (2*pi)^(mix.nin/2); + s = prod(sqrt(mix.covars), 2); + for j = 1:mix.ncentres + diffs = x - (ones(ndata, 1) * mix.centres(j, :)); + a(:, j) = exp(-0.5*sum((diffs.*diffs)./(ones(ndata, 1) * ... + mix.covars(j, :)), 2)) ./ (normal*s(j)); + end + +case 'full' + normal = (2*pi)^(mix.nin/2); + for j = 1:mix.ncentres + diffs = x - (ones(ndata, 1) * mix.centres(j, :)); + % Use Cholesky decomposition of covariance matrix to speed computation + c = chol(mix.covars(:, :, j)); + temp = diffs/c; + a(:, j) = exp(-0.5*sum(temp.*temp, 2))./(normal*prod(diag(c))); + end +case 'ppca' + log_normal = mix.nin*log(2*pi); + d2 = zeros(ndata, mix.ncentres); + logZ = zeros(1, mix.ncentres); + for i = 1:mix.ncentres + k = 1 - mix.covars(i)./mix.lambda(i, :); + logZ(i) = log_normal + mix.nin*log(mix.covars(i)) - ... + sum(log(1 - k)); + diffs = x - ones(ndata, 1)*mix.centres(i, :); + proj = diffs*mix.U(:, :, i); + d2(:,i) = (sum(diffs.*diffs, 2) - ... + sum((proj.*(ones(ndata, 1)*k)).*proj, 2)) / ... + mix.covars(i); + end + a = exp(-0.5*(d2 + ones(ndata, 1)*logZ)); +otherwise + error(['Unknown covariance type ', mix.covar_type]); +end + diff --git a/PatRec/NetLab/netlab3_3/gmmem.m b/PatRec/NetLab/netlab3_3/gmmem.m new file mode 100644 index 0000000..442f0b4 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gmmem.m @@ -0,0 +1,181 @@ +function [mix, options, errlog] = gmmem(mix, x, options) +%GMMEM EM algorithm for Gaussian mixture model. +% +% Description +% [MIX, OPTIONS, ERRLOG] = GMMEM(MIX, X, OPTIONS) uses the Expectation +% Maximization algorithm of Dempster et al. to estimate the parameters +% of a Gaussian mixture model defined by a data structure MIX. The +% matrix X represents the data whose expectation is maximized, with +% each row corresponding to a vector. The optional parameters have +% the following interpretations. +% +% OPTIONS(1) is set to 1 to display error values; also logs error +% values in the return argument ERRLOG. If OPTIONS(1) is set to 0, then +% only warning messages are displayed. If OPTIONS(1) is -1, then +% nothing is displayed. +% +% OPTIONS(3) is a measure of the absolute precision required of the +% error function at the solution. If the change in log likelihood +% between two steps of the EM algorithm is less than this value, then +% the function terminates. +% +% OPTIONS(5) is set to 1 if a covariance matrix is reset to its +% original value when any of its singular values are too small (less +% than MIN_COVAR which has the value eps). With the default value of +% 0 no action is taken. +% +% OPTIONS(14) is the maximum number of iterations; default 100. +% +% The optional return value OPTIONS contains the final error value +% (i.e. data log likelihood) in OPTIONS(8). +% +% See also +% GMM, GMMINIT +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check that inputs are consistent +errstring = consist(mix, 'gmm', x); +if ~isempty(errstring) + error(errstring); +end + +[ndata, xdim] = size(x); + +% Sort out the options +if (options(14)) + niters = options(14); +else + niters = 100; +end + +display = options(1); +store = 0; +if (nargout > 2) + store = 1; % Store the error values to return them + errlog = zeros(1, niters); +end +test = 0; +if options(3) > 0.0 + test = 1; % Test log likelihood for termination +end + +check_covars = 0; +if options(5) >= 1 + if display >= 0 + disp('check_covars is on'); + end + check_covars = 1; % Ensure that covariances don't collapse + MIN_COVAR = eps; % Minimum singular value of covariance matrix + init_covars = mix.covars; +end + +% Main loop of algorithm +for n = 1:niters + + % Calculate posteriors based on old parameters + [post, act] = gmmpost(mix, x); + + % Calculate error value if needed + if (display | store | test) + prob = act*(mix.priors)'; + % Error value is negative log likelihood of data + e = - sum(log(prob)); + if store + errlog(n) = e; + end + if display > 0 + fprintf(1, 'Cycle %4d Error %11.6f\n', n, e); + end + if test + if (n > 1 & abs(e - eold) < options(3)) + options(8) = e; + return; + else + eold = e; + end + end + end + + % Adjust the new estimates for the parameters + new_pr = sum(post, 1); + new_c = post' * x; + + % Now move new estimates to old parameter vectors + mix.priors = new_pr ./ ndata; + + mix.centres = new_c ./ (new_pr' * ones(1, mix.nin)); + + switch mix.covar_type + case 'spherical' + n2 = dist2(x, mix.centres); + for j = 1:mix.ncentres + v(j) = (post(:,j)'*n2(:,j)); + end + mix.covars = ((v./new_pr))./mix.nin; + if check_covars + % Ensure that no covariance is too small + for j = 1:mix.ncentres + if mix.covars(j) < MIN_COVAR + mix.covars(j) = init_covars(j); + end + end + end + case 'diag' + for j = 1:mix.ncentres + diffs = x - (ones(ndata, 1) * mix.centres(j,:)); + mix.covars(j,:) = sum((diffs.*diffs).*(post(:,j)*ones(1, ... + mix.nin)), 1)./new_pr(j); + end + if check_covars + % Ensure that no covariance is too small + for j = 1:mix.ncentres + if min(mix.covars(j,:)) < MIN_COVAR + mix.covars(j,:) = init_covars(j,:); + end + end + end + case 'full' + for j = 1:mix.ncentres + diffs = x - (ones(ndata, 1) * mix.centres(j,:)); + diffs = diffs.*(sqrt(post(:,j))*ones(1, mix.nin)); + mix.covars(:,:,j) = (diffs'*diffs)/new_pr(j); + end + if check_covars + % Ensure that no covariance is too small + for j = 1:mix.ncentres + if min(svd(mix.covars(:,:,j))) < MIN_COVAR + mix.covars(:,:,j) = init_covars(:,:,j); + end + end + end + case 'ppca' + for j = 1:mix.ncentres + diffs = x - (ones(ndata, 1) * mix.centres(j,:)); + diffs = diffs.*(sqrt(post(:,j))*ones(1, mix.nin)); + [tempcovars, tempU, templambda] = ... + ppca((diffs'*diffs)/new_pr(j), mix.ppca_dim); + if length(templambda) ~= mix.ppca_dim + error('Unable to extract enough components'); + else + mix.covars(j) = tempcovars; + mix.U(:, :, j) = tempU; + mix.lambda(j, :) = templambda; + end + end + if check_covars + if mix.covars(j) < MIN_COVAR + mix.covars(j) = init_covars(j); + end + end + otherwise + error(['Unknown covariance type ', mix.covar_type]); + end +end + +options(8) = -sum(log(gmmprob(mix, x))); +if (display >= 0) + disp(maxitmess); +end + \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/gmminit.m b/PatRec/NetLab/netlab3_3/gmminit.m new file mode 100644 index 0000000..299ca46 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gmminit.m @@ -0,0 +1,94 @@ +function mix = gmminit(mix, x, options) +%GMMINIT Initialises Gaussian mixture model from data +% +% Description +% MIX = GMMINIT(MIX, X, OPTIONS) uses a dataset X to initialise the +% parameters of a Gaussian mixture model defined by the data structure +% MIX. The k-means algorithm is used to determine the centres. The +% priors are computed from the proportion of examples belonging to each +% cluster. The covariance matrices are calculated as the sample +% covariance of the points associated with (i.e. closest to) the +% corresponding centres. For a mixture of PPCA model, the PPCA +% decomposition is calculated for the points closest to a given centre. +% This initialisation can be used as the starting point for training +% the model using the EM algorithm. +% +% See also +% GMM +% + +% Copyright (c) Ian T Nabney (1996-2001) + +[ndata, xdim] = size(x); + +% Check that inputs are consistent +errstring = consist(mix, 'gmm', x); +if ~isempty(errstring) + error(errstring); +end + +% Arbitrary width used if variance collapses to zero: make it 'large' so +% that centre is responsible for a reasonable number of points. +GMM_WIDTH = 1.0; + +% Use kmeans algorithm to set centres +options(5) = 1; +[mix.centres, options, post] = kmeans(mix.centres, x, options); + +% Set priors depending on number of points in each cluster +cluster_sizes = max(sum(post, 1), 1); % Make sure that no prior is zero +mix.priors = cluster_sizes/sum(cluster_sizes); % Normalise priors + +switch mix.covar_type +case 'spherical' + if mix.ncentres > 1 + % Determine widths as distance to nearest centre + % (or a constant if this is zero) + cdist = dist2(mix.centres, mix.centres); + cdist = cdist + diag(ones(mix.ncentres, 1)*realmax); + mix.covars = min(cdist); + mix.covars = mix.covars + GMM_WIDTH*(mix.covars < eps); + else + % Just use variance of all data points averaged over all + % dimensions + mix.covars = mean(diag(cov(x))); + end + case 'diag' + for j = 1:mix.ncentres + % Pick out data points belonging to this centre + c = x(find(post(:, j)),:); + diffs = c - (ones(size(c, 1), 1) * mix.centres(j, :)); + mix.covars(j, :) = sum((diffs.*diffs), 1)/size(c, 1); + % Replace small entries by GMM_WIDTH value + mix.covars(j, :) = mix.covars(j, :) + GMM_WIDTH.*(mix.covars(j, :) 1 + label = zeros(n, 1); +end +cum_prior = 0; % Cumulative sum of priors +total_samples = 0; % Cumulative sum of number of sampled points +for j = 1:mix.ncentres + num_samples = sum(priors >= cum_prior & ... + priors < cum_prior + mix.priors(j)); + % Form a full covariance matrix + switch mix.covar_type + case 'spherical' + covar = mix.covars(j) * eye(mix.nin); + case 'diag' + covar = diag(mix.covars(j, :)); + case 'full' + covar = mix.covars(:, :, j); + case 'ppca' + covar = mix.covars(j) * eye(mix.nin) + ... + mix.U(:, :, j)* ... + (diag(mix.lambda(j, :))-(mix.covars(j)*eye(mix.ppca_dim)))* ... + (mix.U(:, :, j)'); + otherwise + error(['Unknown covariance type ', mix.covar_type]); + end + data(total_samples+1:total_samples+num_samples, :) = ... + gsamp(mix.centres(j, :), covar, num_samples); + if nargout > 1 + label(total_samples+1:total_samples+num_samples) = j; + end + cum_prior = cum_prior + mix.priors(j); + total_samples = total_samples + num_samples; +end + diff --git a/PatRec/NetLab/netlab3_3/gmmunpak.m b/PatRec/NetLab/netlab3_3/gmmunpak.m new file mode 100644 index 0000000..9a50381 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gmmunpak.m @@ -0,0 +1,54 @@ +function mix = gmmunpak(mix, p) +%GMMUNPAK Separates a vector of Gaussian mixture model parameters into its components. +% +% Description +% MIX = GMMUNPAK(MIX, P) takes a GMM data structure MIX and a single +% row vector of parameters P and returns a mixture data structure +% identical to the input MIX, except that the mixing coefficients +% PRIORS, centres CENTRES and covariances COVARS (and, for PPCA, the +% lambdas and U (PCA sub-spaces)) are all set to the corresponding +% elements of P. +% +% See also +% GMM, GMMPAK +% + +% Copyright (c) Ian T Nabney (1996-2001) + +errstring = consist(mix, 'gmm'); +if ~errstring + error(errstring); +end +if mix.nwts ~= length(p) + error('Invalid weight vector length') +end + +mark1 = mix.ncentres; +mark2 = mark1 + mix.ncentres*mix.nin; + +mix.priors = reshape(p(1:mark1), 1, mix.ncentres); +mix.centres = reshape(p(mark1 + 1:mark2), mix.ncentres, mix.nin); +switch mix.covar_type + case 'spherical' + mark3 = mix.ncentres*(2 + mix.nin); + mix.covars = reshape(p(mark2 + 1:mark3), 1, mix.ncentres); + case 'diag' + mark3 = mix.ncentres*(1 + mix.nin + mix.nin); + mix.covars = reshape(p(mark2 + 1:mark3), mix.ncentres, mix.nin); + case 'full' + mark3 = mix.ncentres*(1 + mix.nin + mix.nin*mix.nin); + mix.covars = reshape(p(mark2 + 1:mark3), mix.nin, mix.nin, ... + mix.ncentres); + case 'ppca' + mark3 = mix.ncentres*(2 + mix.nin); + mix.covars = reshape(p(mark2 + 1:mark3), 1, mix.ncentres); + % Now also extract k and eigenspaces + mark4 = mark3 + mix.ncentres*mix.ppca_dim; + mix.lambda = reshape(p(mark3 + 1:mark4), mix.ncentres, ... + mix.ppca_dim); + mix.U = reshape(p(mark4 + 1:end), mix.nin, mix.ppca_dim, ... + mix.ncentres); + otherwise + error(['Unknown covariance type ', mix.covar_type]); +end + diff --git a/PatRec/NetLab/netlab3_3/gp.m b/PatRec/NetLab/netlab3_3/gp.m new file mode 100644 index 0000000..54643fa --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gp.m @@ -0,0 +1,93 @@ +function net = gp(nin, covar_fn, prior) +%GP Create a Gaussian Process. +% +% Description +% +% NET = GP(NIN, COVARFN) takes the number of inputs NIN for a Gaussian +% Process model with a single output, together with a string COVARFN +% which specifies the type of the covariance function, and returns a +% data structure NET. The parameters are set to zero. +% +% The fields in NET are +% type = 'gp' +% nin = number of inputs +% nout = number of outputs: always 1 +% nwts = total number of weights and covariance function parameters +% bias = logarithm of constant offset in covariance function +% noise = logarithm of output noise variance +% inweights = logarithm of inverse length scale for each input +% covarfn = string describing the covariance function: +% 'sqexp' +% 'ratquad' +% fpar = covariance function specific parameters (1 for squared exponential, +% 2 for rational quadratic) +% trin = training input data (initially empty) +% trtargets = training target data (initially empty) +% +% NET = GP(NIN, COVARFN, PRIOR) sets a Gaussian prior on the parameters +% of the model. PRIOR must contain the fields PR_MEAN and PR_VARIANCE. +% If PR_MEAN is a scalar, then the Gaussian is assumed to be isotropic +% and the additional fields NET.PR_MEAN and PR_VARIANCE are set. +% Otherwise, the Gaussian prior has a mean defined by a column vector +% of parameters PRIOR.PR_MEAN and covariance defined by a column vector +% of parameters PRIOR.PR_VARIANCE. Each element of PRMEAN corresponds +% to a separate group of parameters, which need not be mutually +% exclusive. The membership of the groups is defined by the matrix +% PRIOR.INDEX in which the columns correspond to the elements of +% PRMEAN. Each column has one element for each weight in the matrix, in +% the order defined by the function GPPAK, and each element is 1 or 0 +% according to whether the parameter is a member of the corresponding +% group or not. The additional field NET.INDEX is set in this case. +% +% See also +% GPPAK, GPUNPAK, GPFWD, GPERR, GPCOVAR, GPGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +net.type = 'gp'; +net.nin = nin; +net.nout = 1; % Only do single output GP + +% Store log parameters +net.bias = 0; +net.min_noise = sqrt(eps); % Prevent output noise collapsing completely +net.noise = 0; +net.inweights = zeros(1,nin); % Weights on inputs in covariance function + +covarfns = {'sqexp', 'ratquad'}; + +if sum(strcmp(covar_fn, covarfns)) == 0 + error('Undefined activation function. Exiting.'); +else + net.covar_fn = covar_fn; +end + +switch covar_fn + + case 'sqexp' % Squared exponential + net.fpar = zeros(1,1); % One function specific parameter + + case 'ratquad' % Rational quadratic + net.fpar = zeros(1, 2); % Two function specific parameters + + otherwise + error(['Unknown covariance function ', covar_fn]); +end + +net.nwts = 2 + nin + length(net.fpar); + +if nargin >= 3 + if size(prior.pr_mean) == [1 1] + net.pr_mean = prior.pr_mean; + net.pr_var = prior.pr_var; + else + net.pr_mean = prior.pr_mean; + net.pr_var = prior.pr_var; + net.index = prior.index; + end +end + +% Store training data as needed for gpfwd +net.tr_in = []; +net.tr_targets = []; \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/gpcovar.m b/PatRec/NetLab/netlab3_3/gpcovar.m new file mode 100644 index 0000000..f71fa4d --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gpcovar.m @@ -0,0 +1,38 @@ +function [cov, covf] = gpcovar(net, x) +%GPCOVAR Calculate the covariance for a Gaussian Process. +% +% Description +% +% COV = GPCOVAR(NET, X) takes a Gaussian Process data structure NET +% together with a matrix X of input vectors, and computes the +% covariance matrix COV. The inverse of this matrix is used when +% calculating the mean and variance of the predictions made by NET. +% +% [COV, COVF] = GPCOVAR(NET, X) also generates the covariance matrix +% due to the covariance function specified by NET.COVARFN as calculated +% by GPCOVARF. +% +% See also +% GP, GPPAK, GPUNPAK, GPCOVARP, GPCOVARF, GPFWD, GPERR, GPGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check arguments for consistency +errstring = consist(net, 'gp', x); +if ~isempty(errstring); + error(errstring); +end + +ndata = size(x, 1); + +% Compute prior covariance +if nargout >= 2 + [covp, covf] = gpcovarp(net, x, x); +else + covp = gpcovarp(net, x, x); +end + +% Add output noise variance +cov = covp + (net.min_noise + exp(net.noise))*eye(ndata); + diff --git a/PatRec/NetLab/netlab3_3/gpcovarf.m b/PatRec/NetLab/netlab3_3/gpcovarf.m new file mode 100644 index 0000000..ed66e60 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gpcovarf.m @@ -0,0 +1,44 @@ +function covf = gpcovarf(net, x1, x2) +%GPCOVARF Calculate the covariance function for a Gaussian Process. +% +% Description +% +% COVF = GPCOVARF(NET, X1, X2) takes a Gaussian Process data structure +% NET together with two matrices X1 and X2 of input vectors, and +% computes the matrix of the covariance function values COVF. +% +% See also +% GP, GPCOVAR, GPCOVARP, GPERR, GPGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +errstring = consist(net, 'gp', x1); +if ~isempty(errstring); + error(errstring); +end + +if size(x1, 2) ~= size(x2, 2) + error('Number of variables in x1 and x2 must be the same'); +end + +n1 = size(x1, 1); +n2 = size(x2, 1); +beta = diag(exp(net.inweights)); + +% Compute the weighted squared distances between x1 and x2 +z = (x1.*x1)*beta*ones(net.nin, n2) - 2*x1*beta*x2' ... + + ones(n1, net.nin)*beta*(x2.*x2)'; + +switch net.covar_fn + + case 'sqexp' % Squared exponential + covf = exp(net.fpar(1) - 0.5*z); + + case 'ratquad' % Rational quadratic + nu = exp(net.fpar(2)); + covf = exp(net.fpar(1))*((ones(size(z)) + z).^(-nu)); + + otherwise + error(['Unknown covariance function ', net.covar_fn]); +end \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/gpcovarp.m b/PatRec/NetLab/netlab3_3/gpcovarp.m new file mode 100644 index 0000000..203c405 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gpcovarp.m @@ -0,0 +1,30 @@ +function [covp, covf] = gpcovarp(net, x1, x2) +%GPCOVARP Calculate the prior covariance for a Gaussian Process. +% +% Description +% +% COVP = GPCOVARP(NET, X1, X2) takes a Gaussian Process data structure +% NET together with two matrices X1 and X2 of input vectors, and +% computes the matrix of the prior covariance. This is the function +% component of the covariance plus the exponential of the bias term. +% +% [COVP, COVF] = GPCOVARP(NET, X1, X2) also returns the function +% component of the covariance. +% +% See also +% GP, GPCOVAR, GPCOVARF, GPERR, GPGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +errstring = consist(net, 'gp', x1); +if ~isempty(errstring); + error(errstring); +end + +if size(x1, 2) ~= size(x2, 2) + error('Number of variables in x1 and x2 must be the same'); +end + +covf = gpcovarf(net, x1, x2); +covp = covf + exp(net.bias); \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/gperr.m b/PatRec/NetLab/netlab3_3/gperr.m new file mode 100644 index 0000000..402d63b --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gperr.m @@ -0,0 +1,51 @@ +function [e, edata, eprior] = gperr(net, x, t) +%GPERR Evaluate error function for Gaussian Process. +% +% Description +% E = GPERR(NET, X, T) takes a Gaussian Process data structure NET +% together with a matrix X of input vectors and a matrix T of target +% vectors, and evaluates the error function E. Each row of X +% corresponds to one input vector and each row of T corresponds to one +% target vector. +% +% [E, EDATA, EPRIOR] = GPERR(NET, X, T) additionally returns the data +% and hyperprior components of the error, assuming a Gaussian prior on +% the weights with mean and variance parameters PRMEAN and PRVARIANCE +% taken from the network data structure NET. +% +% See also +% GP, GPCOVAR, GPFWD, GPGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +errstring = consist(net, 'gp', x, t); +if ~isempty(errstring); + error(errstring); +end + +cn = gpcovar(net, x); + +edata = 0.5*(sum(log(eig(cn, 'nobalance'))) + t'*inv(cn)*t); + +% Evaluate the hyperprior contribution to the error. +% The hyperprior is Gaussian with mean pr_mean and variance +% pr_variance +if isfield(net, 'pr_mean') + w = gppak(net); + m = repmat(net.pr_mean, size(w)); + if size(net.pr_mean) == [1 1] + eprior = 0.5*((w-m)*(w-m)'); + e2 = eprior/net.pr_var; + else + wpr = repmat(w, size(net.pr_mean, 1), 1)'; + eprior = 0.5*(((wpr - m').^2).*net.index); + e2 = (sum(eprior, 1))*(1./net.pr_var); + end +else + e2 = 0; + eprior = 0; +end + +e = edata + e2; + diff --git a/PatRec/NetLab/netlab3_3/gpfwd.m b/PatRec/NetLab/netlab3_3/gpfwd.m new file mode 100644 index 0000000..b2d390e --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gpfwd.m @@ -0,0 +1,51 @@ +function [y, sigsq] = gpfwd(net, x, cninv) +%GPFWD Forward propagation through Gaussian Process. +% +% Description +% Y = GPFWD(NET, X) takes a Gaussian Process data structure NET +% together with a matrix X of input vectors, and forward propagates +% the inputs through the model to generate a matrix Y of output +% vectors. Each row of X corresponds to one input vector and each row +% of Y corresponds to one output vector. This assumes that the +% training data (both inputs and targets) has been stored in NET by a +% call to GPINIT; these are needed to compute the training data +% covariance matrix. +% +% [Y, SIGSQ] = GPFWD(NET, X) also generates a column vector SIGSQ of +% conditional variances (or squared error bars) where each value +% corresponds to a pattern. +% +% [Y, SIGSQ] = GPFWD(NET, X, CNINV) uses the pre-computed inverse +% covariance matrix CNINV in the forward propagation. This increases +% efficiency if several calls to GPFWD are made. +% +% See also +% GP, DEMGP, GPINIT +% + +% Copyright (c) Ian T Nabney (1996-2001) + +errstring = consist(net, 'gp', x); +if ~isempty(errstring); + error(errstring); +end + +if ~(isfield(net, 'tr_in') & isfield(net, 'tr_targets')) + error('Require training inputs and targets'); +end + +if nargin == 2 + % Inverse covariance matrix not supplied. + cninv = inv(gpcovar(net, net.tr_in)); +end +ktest = gpcovarp(net, x, net.tr_in); + +% Predict mean +y = ktest*cninv*net.tr_targets; + +if nargout >= 2 + % Predict error bar + ndata = size(x, 1); + sigsq = (ones(ndata, 1) * gpcovarp(net, x(1,:), x(1,:))) ... + - sum((ktest*cninv).*ktest, 2); +end diff --git a/PatRec/NetLab/netlab3_3/gpgrad.m b/PatRec/NetLab/netlab3_3/gpgrad.m new file mode 100644 index 0000000..de28e80 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gpgrad.m @@ -0,0 +1,100 @@ +function g = gpgrad(net, x, t) +%GPGRAD Evaluate error gradient for Gaussian Process. +% +% Description +% G = GPGRAD(NET, X, T) takes a Gaussian Process data structure NET +% together with a matrix X of input vectors and a matrix T of target +% vectors, and evaluates the error gradient G. Each row of X +% corresponds to one input vector and each row of T corresponds to one +% target vector. +% +% See also +% GP, GPCOVAR, GPFWD, GPERR +% + +% Copyright (c) Ian T Nabney (1996-2001) + +errstring = consist(net, 'gp', x, t); +if ~isempty(errstring); + error(errstring); +end + +% Evaluate derivatives with respect to each hyperparameter in turn. +ndata = size(x, 1); +[cov, covf] = gpcovar(net, x); +cninv = inv(cov); +trcninv = trace(cninv); +cninvt = cninv*t; + +% Function parameters +switch net.covar_fn + + case 'sqexp' % Squared exponential + gfpar = trace(cninv*covf) - cninvt'*covf*cninvt; + + case 'ratquad' % Rational quadratic + beta = diag(exp(net.inweights)); + gfpar(1) = trace(cninv*covf) - cninvt'*covf*cninvt; + D2 = (x.*x)*beta*ones(net.nin, ndata) - 2*x*beta*x' ... + + ones(ndata, net.nin)*beta*(x.*x)'; + E = ones(size(D2)); + L = - exp(net.fpar(2)) * covf .* log(E + D2); % d(cn)/d(nu) + gfpar(2) = trace(cninv*L) - cninvt'*L*cninvt; + + otherwise + error(['Unknown covariance function ', net.covar_fn]); +end + +% Bias derivative +ndata = size(x, 1); +fac = exp(net.bias)*ones(ndata); +gbias = trace(cninv*fac) - cninvt'*fac*cninvt; + +% Noise derivative +gnoise = exp(net.noise)*(trcninv - cninvt'*cninvt); + +% Input weight derivatives +if strcmp(net.covar_fn, 'ratquad') + F = (exp(net.fpar(2))*E)./(E + D2); +end + +nparams = length(net.inweights); +for l = 1 : nparams + vect = x(:, l); + matx = (vect.*vect)*ones(1, ndata) ... + - 2.0*vect*vect' ... + + ones(ndata, 1)*(vect.*vect)'; + switch net.covar_fn + case 'sqexp' % Squared exponential + dmat = -0.5*exp(net.inweights(l))*covf.*matx; + + case 'ratquad' % Rational quadratic + dmat = - exp(net.inweights(l))*covf.*matx.*F; + otherwise + error(['Unknown covariance function ', net.covar_fn]); + end + + gw1(l) = trace(cninv*dmat) - cninvt'*dmat*cninvt; +end + +g1 = [gbias, gnoise, gw1, gfpar]; +g1 = 0.5*g1; + +% Evaluate the prior contribution to the gradient. +if isfield(net, 'pr_mean') + w = gppak(net); + m = repmat(net.pr_mean, size(w)); + if size(net.pr_mean) == [1 1] + gprior = w - m; + g2 = gprior/net.pr_var; + else + ngroups = size(net.pr_mean, 1); + gprior = net.index'.*(ones(ngroups, 1)*w - m); + g2 = (1./net.pr_var)'*gprior; + end +else + gprior = 0; + g2 = 0; +end + +g = g1 + g2; diff --git a/PatRec/NetLab/netlab3_3/gpinit.m b/PatRec/NetLab/netlab3_3/gpinit.m new file mode 100644 index 0000000..c355c0d --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gpinit.m @@ -0,0 +1,43 @@ +function net = gpinit(net, tr_in, tr_targets, prior) +%GPINIT Initialise Gaussian Process model. +% +% Description +% NET = GPINIT(NET, TRIN, TRTARGETS) takes a Gaussian Process data +% structure NET together with a matrix TRIN of training input vectors +% and a matrix TRTARGETS of training target vectors, and stores them +% in NET. These datasets are required if the corresponding inverse +% covariance matrix is not supplied to GPFWD. This is important if the +% data structure is saved and then reloaded before calling GPFWD. Each +% row of TRIN corresponds to one input vector and each row of TRTARGETS +% corresponds to one target vector. +% +% NET = GPINIT(NET, TRIN, TRTARGETS, PRIOR) additionally initialises +% the parameters in NET from the PRIOR data structure which contains +% the mean and variance of the Gaussian distribution which is sampled +% from. +% +% See also +% GP, GPFWD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +errstring = consist(net, 'gp', tr_in, tr_targets); +if ~isempty(errstring); + error(errstring); +end + +if nargin >= 4 + % Initialise weights at random + if size(prior.pr_mean) == [1 1] + w = randn(1, net.nwts).*sqrt(prior.pr_var) + ... + repmat(prior.pr_mean, 1, net.nwts); + else + sig = sqrt(prior.index*prior.pr_var); + w = sig'.*randn(1, net.nwts) + (prior.index*prior.pr_mean)'; + end + net = gpunpak(net, w); +end + +net.tr_in = tr_in; +net.tr_targets = tr_targets; diff --git a/PatRec/NetLab/netlab3_3/gppak.m b/PatRec/NetLab/netlab3_3/gppak.m new file mode 100644 index 0000000..bb1c52a --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gppak.m @@ -0,0 +1,19 @@ +function hp = gppak(net) +%GPPAK Combines GP hyperparameters into one vector. +% +% Description +% HP = GPPAK(NET) takes a Gaussian Process data structure NET and +% combines the hyperparameters into a single row vector HP. +% +% See also +% GP, GPUNPAK, GPFWD, GPERR, GPGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check arguments for consistency +errstring = consist(net, 'gp'); +if ~isempty(errstring); + error(errstring); +end +hp = [net.bias, net.noise, net.inweights, net.fpar]; diff --git a/PatRec/NetLab/netlab3_3/gpunpak.m b/PatRec/NetLab/netlab3_3/gpunpak.m new file mode 100644 index 0000000..8e1058e --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gpunpak.m @@ -0,0 +1,36 @@ +function net = gpunpak(net, hp) +%GPUNPAK Separates hyperparameter vector into components. +% +% Description +% NET = GPUNPAK(NET, HP) takes an Gaussian Process data structure NET +% and a hyperparameter vector HP, and returns a Gaussian Process data +% structure identical to the input model, except that the covariance +% bias BIAS, output noise NOISE, the input weight vector INWEIGHTS and +% the vector of covariance function specific parameters FPAR have all +% been set to the corresponding elements of HP. +% +% See also +% GP, GPPAK, GPFWD, GPERR, GPGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check arguments for consistency +errstring = consist(net, 'gp'); +if ~isempty(errstring); + error(errstring); +end +if net.nwts ~= length(hp) + error('Invalid weight vector length'); +end + +net.bias = hp(1); +net.noise = hp(2); + +% Unpack input weights +mark1 = 2 + net.nin; +net.inweights = hp(3:mark1); + +% Unpack function specific parameters +net.fpar = hp(mark1 + 1:size(hp, 2)); + diff --git a/PatRec/NetLab/netlab3_3/gradchek.m b/PatRec/NetLab/netlab3_3/gradchek.m new file mode 100644 index 0000000..3f9298f --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gradchek.m @@ -0,0 +1,49 @@ +function [gradient, delta] = gradchek(w, func, grad, varargin) +%GRADCHEK Checks a user-defined gradient function using finite differences. +% +% Description +% This function is intended as a utility for other netlab functions +% (particularly optimisation functions) to use. It enables the user to +% check whether a gradient calculation has been correctly implmented +% for a given function. GRADCHEK(W, FUNC, GRAD) checks how accurate the +% gradient GRAD of a function FUNC is at a parameter vector X. A +% central difference formula with step size 1.0e-6 is used, and the +% results for both gradient function and finite difference +% approximation are printed. The optional return value GRADIENT is the +% gradient calculated using the function GRAD and the return value +% DELTA is the difference between the functional and finite difference +% methods of calculating the graident. +% +% GRADCHEK(X, FUNC, GRAD, P1, P2, ...) allows additional arguments to +% be passed to FUNC and GRAD. +% +% See also +% CONJGRAD, GRADDESC, HMC, OLGD, QUASINEW, SCG +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Reasonable value for step size +epsilon = 1.0e-6; + +func = fcnchk(func, length(varargin)); +grad = fcnchk(grad, length(varargin)); + +% Treat +nparams = length(w); +deltaf = zeros(1, nparams); +step = zeros(1, nparams); +for i = 1:nparams + % Move a small way in the ith coordinate of w + step(i) = 1.0; + fplus = feval('linef', epsilon, func, w, step, varargin{:}); + fminus = feval('linef', -epsilon, func, w, step, varargin{:}); + % Use central difference formula for approximation + deltaf(i) = 0.5*(fplus - fminus)/epsilon; + step(i) = 0.0; +end +gradient = feval(grad, w, varargin{:}); +fprintf(1, 'Checking gradient ...\n\n'); +delta = gradient - deltaf; +fprintf(1, ' analytic diffs delta\n\n'); +disp([gradient', deltaf', delta']) diff --git a/PatRec/NetLab/netlab3_3/graddesc.m b/PatRec/NetLab/netlab3_3/graddesc.m new file mode 100644 index 0000000..3cc6414 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/graddesc.m @@ -0,0 +1,180 @@ +function [x, options, flog, pointlog] = graddesc(f, x, options, gradf, ... + varargin) +%GRADDESC Gradient descent optimization. +% +% Description +% [X, OPTIONS, FLOG, POINTLOG] = GRADDESC(F, X, OPTIONS, GRADF) uses +% batch gradient descent to find a local minimum of the function F(X) +% whose gradient is given by GRADF(X). A log of the function values +% after each cycle is (optionally) returned in ERRLOG, and a log of the +% points visited is (optionally) returned in POINTLOG. +% +% Note that X is a row vector and F returns a scalar value. The point +% at which F has a local minimum is returned as X. The function value +% at that point is returned in OPTIONS(8). +% +% GRADDESC(F, X, OPTIONS, GRADF, P1, P2, ...) allows additional +% arguments to be passed to F() and GRADF(). +% +% The optional parameters have the following interpretations. +% +% OPTIONS(1) is set to 1 to display error values; also logs error +% values in the return argument ERRLOG, and the points visited in the +% return argument POINTSLOG. If OPTIONS(1) is set to 0, then only +% warning messages are displayed. If OPTIONS(1) is -1, then nothing is +% displayed. +% +% OPTIONS(2) is the absolute precision required for the value of X at +% the solution. If the absolute difference between the values of X +% between two successive steps is less than OPTIONS(2), then this +% condition is satisfied. +% +% OPTIONS(3) is a measure of the precision required of the objective +% function at the solution. If the absolute difference between the +% objective function values between two successive steps is less than +% OPTIONS(3), then this condition is satisfied. Both this and the +% previous condition must be satisfied for termination. +% +% OPTIONS(7) determines the line minimisation method used. If it is +% set to 1 then a line minimiser is used (in the direction of the +% negative gradient). If it is 0 (the default), then each parameter +% update is a fixed multiple (the learning rate) of the negative +% gradient added to a fixed multiple (the momentum) of the previous +% parameter update. +% +% OPTIONS(9) should be set to 1 to check the user defined gradient +% function GRADF with GRADCHEK. This is carried out at the initial +% parameter vector X. +% +% OPTIONS(10) returns the total number of function evaluations +% (including those in any line searches). +% +% OPTIONS(11) returns the total number of gradient evaluations. +% +% OPTIONS(14) is the maximum number of iterations; default 100. +% +% OPTIONS(15) is the precision in parameter space of the line search; +% default FOPTIONS(2). +% +% OPTIONS(17) is the momentum; default 0.5. It should be scaled by the +% inverse of the number of data points. +% +% OPTIONS(18) is the learning rate; default 0.01. It should be scaled +% by the inverse of the number of data points. +% +% See also +% CONJGRAD, LINEMIN, OLGD, MINBRACK, QUASINEW, SCG +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Set up the options. +if length(options) < 18 + error('Options vector too short') +end + +if (options(14)) + niters = options(14); +else + niters = 100; +end + +line_min_flag = 0; % Flag for line minimisation option +if (round(options(7)) == 1) + % Use line minimisation + line_min_flag = 1; + % Set options for line minimiser + line_options = foptions; + if options(15) > 0 + line_options(2) = options(15); + end +else + % Learning rate: must be positive + if (options(18) > 0) + eta = options(18); + else + eta = 0.01; + end + % Momentum term: allow zero momentum + if (options(17) >= 0) + mu = options(17); + else + mu = 0.5; + end +end + +% Check function string +f = fcnchk(f, length(varargin)); +gradf = fcnchk(gradf, length(varargin)); + +% Display information if options(1) > 0 +display = options(1) > 0; + +% Work out if we need to compute f at each iteration. +% Needed if using line search or if display results or if termination +% criterion requires it. +fcneval = (options(7) | display | options(3)); + +% Check gradients +if (options(9) > 0) + feval('gradchek', x, f, gradf, varargin{:}); +end + +dxold = zeros(1, size(x, 2)); +xold = x; +fold = 0; % Must be initialised so that termination test can be performed +if fcneval + fnew = feval(f, x, varargin{:}); + options(10) = options(10) + 1; + fold = fnew; +end + +% Main optimization loop. +for j = 1:niters + xold = x; + grad = feval(gradf, x, varargin{:}); + options(11) = options(11) + 1; % Increment gradient evaluation counter + if (line_min_flag ~= 1) + dx = mu*dxold - eta*grad; + x = x + dx; + dxold = dx; + if fcneval + fold = fnew; + fnew = feval(f, x, varargin{:}); + options(10) = options(10) + 1; + end + else + sd = - grad./norm(grad); % New search direction. + fold = fnew; + % Do a line search: normalise search direction to have length 1 + [lmin, line_options] = feval('linemin', f, x, sd, fold, ... + line_options, varargin{:}); + options(10) = options(10) + line_options(10); + x = xold + lmin*sd; + fnew = line_options(8); + end + if nargout >= 3 + flog(j) = fnew; + if nargout >= 4 + pointlog(j, :) = x; + end + end + if display + fprintf(1, 'Cycle %5d Function %11.8f\n', j, fnew); + end + if (max(abs(x - xold)) < options(2) & abs(fnew - fold) < options(3)) + % Termination criteria are met + options(8) = fnew; + return; + end +end + +if fcneval + options(8) = fnew; +else + options(8) = feval(f, x, varargin{:}); + options(10) = options(10) + 1; +end +if (options(1) >= 0) + disp(maxitmess); +end diff --git a/PatRec/NetLab/netlab3_3/gsamp.m b/PatRec/NetLab/netlab3_3/gsamp.m new file mode 100644 index 0000000..58b1ba1 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gsamp.m @@ -0,0 +1,32 @@ +function x = gsamp(mu, covar, nsamp) +%GSAMP Sample from a Gaussian distribution. +% +% Description +% +% X = GSAMP(MU, COVAR, NSAMP) generates a sample of size NSAMP from a +% D-dimensional Gaussian distribution. The Gaussian density has mean +% vector MU and covariance matrix COVAR, and the matrix X has NSAMP +% rows in which each row represents a D-dimensional sample vector. +% +% See also +% GAUSS, DEMGAUSS +% + +% Copyright (c) Ian T Nabney (1996-2001) + +d = size(covar, 1); + +mu = reshape(mu, 1, d); % Ensure that mu is a row vector + +[evec, eval] = eig(covar); + +deig=diag(eval); + +if (~isreal(deig)) | any(deig<0), + warning('Covariance Matrix is not OK, redefined to be positive definite'); + eval=abs(eval); +end + +coeffs = randn(nsamp, d)*sqrt(eval); + +x = ones(nsamp, 1)*mu + coeffs*evec'; diff --git a/PatRec/NetLab/netlab3_3/gtm.m b/PatRec/NetLab/netlab3_3/gtm.m new file mode 100644 index 0000000..9d1b3ab --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gtm.m @@ -0,0 +1,61 @@ +function net = gtm(dim_latent, nlatent, dim_data, ncentres, rbfunc, ... + prior) +%GTM Create a Generative Topographic Map. +% +% Description +% +% NET = GTM(DIMLATENT, NLATENT, DIMDATA, NCENTRES, RBFUNC), takes the +% dimension of the latent space DIMLATENT, the number of data points +% sampled in the latent space NLATENT, the dimension of the data space +% DIMDATA, the number of centres in the RBF model NCENTRES, the +% activation function for the RBF RBFUNC and returns a data structure +% NET. The parameters in the RBF and GMM sub-models are set by calls to +% the corresponding creation routines RBF and GMM. +% +% The fields in NET are +% type = 'gtm' +% nin = dimension of data space +% dimlatent = dimension of latent space +% rbfnet = RBF network data structure +% gmmnet = GMM data structure +% X = sample of latent points +% +% NET = GTM(DIMLATENT, NLATENT, DIMDATA, NCENTRES, RBFUNC, PRIOR), +% sets a Gaussian zero mean prior on the parameters of the RBF model. +% PRIOR must be a scalar and represents the inverse variance of the +% prior distribution. This gives rise to a weight decay term in the +% error function. +% +% See also +% GTMFWD, GTMPOST, RBF, GMM +% + +% Copyright (c) Ian T Nabney (1996-2001) + +net.type = 'gtm'; +% Input to functions is data +net.nin = dim_data; +net.dim_latent = dim_latent; + +% Default is no regularisation +if nargin == 5 + prior = 0.0; +end + +% Only allow scalar prior +if isstruct(prior) | size(prior) ~= [1 1] + error('Prior must be a scalar'); +end + +% Create RBF network +net.rbfnet = rbf(dim_latent, ncentres, dim_data, rbfunc, ... + 'linear', prior); + +% Mask all but output weights +net.rbfnet.mask = rbfprior(rbfunc, dim_latent, ncentres, dim_data); + +% Create field for GMM output model +net.gmmnet = gmm(dim_data, nlatent, 'spherical'); + +% Create empty latent data sample +net.X = []; \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/gtmem.m b/PatRec/NetLab/netlab3_3/gtmem.m new file mode 100644 index 0000000..47dd84a --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gtmem.m @@ -0,0 +1,135 @@ +function [net, options, errlog] = gtmem(net, t, options) +%GTMEM EM algorithm for Generative Topographic Mapping. +% +% Description +% [NET, OPTIONS, ERRLOG] = GTMEM(NET, T, OPTIONS) uses the Expectation +% Maximization algorithm to estimate the parameters of a GTM defined by +% a data structure NET. The matrix T represents the data whose +% expectation is maximized, with each row corresponding to a vector. +% It is assumed that the latent data NET.X has been set following a +% call to GTMINIT, for example. The optional parameters have the +% following interpretations. +% +% OPTIONS(1) is set to 1 to display error values; also logs error +% values in the return argument ERRLOG. If OPTIONS(1) is set to 0, then +% only warning messages are displayed. If OPTIONS(1) is -1, then +% nothing is displayed. +% +% OPTIONS(3) is a measure of the absolute precision required of the +% error function at the solution. If the change in log likelihood +% between two steps of the EM algorithm is less than this value, then +% the function terminates. +% +% OPTIONS(14) is the maximum number of iterations; default 100. +% +% The optional return value OPTIONS contains the final error value +% (i.e. data log likelihood) in OPTIONS(8). +% +% See also +% GTM, GTMINIT +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check that inputs are consistent +errstring = consist(net, 'gtm', t); +if ~isempty(errstring) + error(errstring); +end + +% Sort out the options +if (options(14)) + niters = options(14); +else + niters = 100; +end + +display = options(1); +store = 0; +if (nargout > 2) + store = 1; % Store the error values to return them + errlog = zeros(1, niters); +end +test = 0; +if options(3) > 0.0 + test = 1; % Test log likelihood for termination +end + +% Calculate various quantities that remain constant during training +[ndata, tdim] = size(t); +ND = ndata*tdim; +[net.gmmnet.centres, Phi] = rbffwd(net.rbfnet, net.X); +Phi = [Phi ones(size(net.X, 1), 1)]; +PhiT = Phi'; +[K, Mplus1] = size(Phi); + +A = zeros(Mplus1, Mplus1); +cholDcmp = zeros(Mplus1, Mplus1); +% Use a sparse representation for the weight regularizing matrix. +if (net.rbfnet.alpha > 0) + Alpha = net.rbfnet.alpha*speye(Mplus1); + Alpha(Mplus1, Mplus1) = 0; +end + +for n = 1:niters + % Calculate responsibilities + [R, act] = gtmpost(net, t); + % Calculate error value if needed + if (display | store | test) + prob = act*(net.gmmnet.priors)'; + % Error value is negative log likelihood of data + e = - sum(log(max(prob,eps))); + if store + errlog(n) = e; + end + if display > 0 + fprintf(1, 'Cycle %4d Error %11.6f\n', n, e); + end + if test + if (n > 1 & abs(e - eold) < options(3)) + options(8) = e; + return; + else + eold = e; + end + end + end + + % Calculate matrix be inverted (Phi'*G*Phi + alpha*I in the papers). + % Sparse representation of G normally executes faster and saves + % memory + if (net.rbfnet.alpha > 0) + A = full(PhiT*spdiags(sum(R)', 0, K, K)*Phi + ... + (Alpha.*net.gmmnet.covars(1))); + else + A = full(PhiT*spdiags(sum(R)', 0, K, K)*Phi); + end + % A is a symmetric matrix likely to be positive definite, so try + % fast Cholesky decomposition to calculate W, otherwise use SVD. + % (PhiT*(R*t)) is computed right-to-left, as R + % and t are normally (much) larger than PhiT. + [cholDcmp singular] = chol(A); + if (singular) + if (display) + fprintf(1, ... + 'gtmem: Warning -- M-Step matrix singular, using pinv.\n'); + end + W = pinv(A)*(PhiT*(R'*t)); + else + W = cholDcmp \ (cholDcmp' \ (PhiT*(R'*t))); + end + % Put new weights into network to calculate responsibilities + % net.rbfnet = netunpak(net.rbfnet, W); + net.rbfnet.w2 = W(1:net.rbfnet.nhidden, :); + net.rbfnet.b2 = W(net.rbfnet.nhidden+1, :); + % Calculate new distances + d = dist2(t, Phi*W); + + % Calculate new value for beta + net.gmmnet.covars = ones(1, net.gmmnet.ncentres)*(sum(sum(d.*R))/ND); +end + +options(8) = -sum(log(gtmprob(net, t))); +if (display >= 0) + disp(maxitmess); +end diff --git a/PatRec/NetLab/netlab3_3/gtmfwd.m b/PatRec/NetLab/netlab3_3/gtmfwd.m new file mode 100644 index 0000000..bb84d34 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gtmfwd.m @@ -0,0 +1,17 @@ +function mix = gtmfwd(net) +%GTMFWD Forward propagation through GTM. +% +% Description +% MIX = GTMFWD(NET) takes a GTM structure NET, and forward propagates +% the latent data sample NET.X through the GTM to generate the +% structure MIX which represents the Gaussian mixture model in data +% space. +% +% See also +% GTM +% + +% Copyright (c) Ian T Nabney (1996-2001) + +net.gmmnet.centres = rbffwd(net.rbfnet, net.X); +mix = net.gmmnet; diff --git a/PatRec/NetLab/netlab3_3/gtminit.m b/PatRec/NetLab/netlab3_3/gtminit.m new file mode 100644 index 0000000..ae646a0 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gtminit.m @@ -0,0 +1,153 @@ +function net = gtminit(net, options, data, samp_type, varargin) +%GTMINIT Initialise the weights and latent sample in a GTM. +% +% Description +% NET = GTMINIT(NET, OPTIONS, DATA, SAMPTYPE) takes a GTM NET and +% generates a sample of latent data points and sets the centres (and +% widths if appropriate) of NET.RBFNET. +% +% If the SAMPTYPE is 'REGULAR', then regular grids of latent data +% points and RBF centres are created. The dimension of the latent data +% space must be 1 or 2. For one-dimensional latent space, the +% LSAMPSIZE parameter gives the number of latent points and the +% RBFSAMPSIZE parameter gives the number of RBF centres. For a two- +% dimensional latent space, these parameters must be vectors of length +% 2 with the number of points in each of the x and y directions to +% create a rectangular grid. The widths of the RBF basis functions are +% set by a call to RBFSETFW passing OPTIONS(7) as the scaling +% parameter. +% +% If the SAMPTYPE is 'UNIFORM' or 'GAUSSIAN' then the latent data is +% found by sampling from a uniform or Gaussian distribution +% correspondingly. The RBF basis function parameters are set by a call +% to RBFSETBF with the DATA parameter as dataset and the OPTIONS +% vector. +% +% Finally, the output layer weights of the RBF are initialised by +% mapping the mean of the latent variable to the mean of the target +% variable, and the L-dimensional latent variale variance to the +% variance of the targets along the first L principal components. +% +% See also +% GTM, GTMEM, PCA, RBFSETBF, RBFSETFW +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check for consistency +errstring = consist(net, 'gtm', data); +if ~isempty(errstring) + error(errstring); +end + +% Check type of sample +stypes = {'regular', 'uniform', 'gaussian'}; +if (strcmp(samp_type, stypes)) == 0 + error('Undefined sample type.') +end + +if net.dim_latent > size(data, 2) + error('Latent space dimension must not be greater than data dimension') +end +nlatent = net.gmmnet.ncentres; +nhidden = net.rbfnet.nhidden; + +% Create latent data sample and set RBF centres + +switch samp_type +case 'regular' + if nargin ~= 6 + error('Regular type must specify latent and RBF shapes'); + end + l_samp_size = varargin{1}; + rbf_samp_size = varargin{2}; + if round(l_samp_size) ~= l_samp_size + error('Latent sample specification must contain integers') + end + % Check existence and size of rbf specification + if any(size(rbf_samp_size) ~= [1 net.dim_latent]) | ... + prod(rbf_samp_size) ~= nhidden + error('Incorrect specification of RBF centres') + end + % Check dimension and type of latent data specification + if any(size(l_samp_size) ~= [1 net.dim_latent]) | ... + prod(l_samp_size) ~= nlatent + error('Incorrect dimension of latent sample spec.') + end + if net.dim_latent == 1 + net.X = [-1:2/(l_samp_size-1):1]'; + net.rbfnet.c = [-1:2/(rbf_samp_size-1):1]'; + net.rbfnet = rbfsetfw(net.rbfnet, options(7)); + elseif net.dim_latent == 2 + net.X = gtm_rctg(l_samp_size); + net.rbfnet.c = gtm_rctg(rbf_samp_size); + net.rbfnet = rbfsetfw(net.rbfnet, options(7)); + else + error('For regular sample, input dimension must be 1 or 2.') + end + + +case {'uniform', 'gaussian'} + if strcmp(samp_type, 'uniform') + net.X = 2 * (rand(nlatent, net.dim_latent) - 0.5); + else + % Sample from N(0, 0.25) distribution to ensure most latent + % data is inside square + net.X = randn(nlatent, net.dim_latent)/2; + end + net.rbfnet = rbfsetbf(net.rbfnet, options, net.X); +otherwise + % Shouldn't get here + error('Invalid sample type'); + +end + +% Latent data sample and basis function parameters chosen. +% Now set output weights +[PCcoeff, PCvec] = pca(data); + +% Scale PCs by eigenvalues +A = PCvec(:, 1:net.dim_latent)*diag(sqrt(PCcoeff(1:net.dim_latent))); + +[temp, Phi] = rbffwd(net.rbfnet, net.X); +% Normalise X to ensure 1:1 mapping of variances and calculate weights +% as solution of Phi*W = normX*A' +normX = (net.X - ones(size(net.X))*diag(mean(net.X)))*diag(1./std(net.X)); +net.rbfnet.w2 = Phi \ (normX*A'); +% Bias is mean of target data +net.rbfnet.b2 = mean(data); + +% Must also set initial value of variance +% Find average distance between nearest centres +% Ensure that distance of centre to itself is excluded by setting diagonal +% entries to realmax +net.gmmnet.centres = rbffwd(net.rbfnet, net.X); +d = dist2(net.gmmnet.centres, net.gmmnet.centres) + ... + diag(ones(net.gmmnet.ncentres, 1)*realmax); +sigma = mean(min(d))/2; + +% Now set covariance to minimum of this and next largest eigenvalue +if net.dim_latent < size(data, 2) + sigma = min(sigma, PCcoeff(net.dim_latent+1)); +end +net.gmmnet.covars = sigma*ones(1, net.gmmnet.ncentres); + +% Sub-function to create the sample data in 2d +function sample = gtm_rctg(samp_size) + +xDim = samp_size(1); +yDim = samp_size(2); +% Produce a grid with the right number of rows and columns +[X, Y] = meshgrid([0:1:(xDim-1)], [(yDim-1):-1:0]); + +% Change grid representation +sample = [X(:), Y(:)]; + +% Shift grid to correct position and scale it +maxXY= max(sample); +sample(:,1) = 2*(sample(:,1) - maxXY(1)/2)./maxXY(1); +sample(:,2) = 2*(sample(:,2) - maxXY(2)/2)./maxXY(2); +return; + + + diff --git a/PatRec/NetLab/netlab3_3/gtmlmean.m b/PatRec/NetLab/netlab3_3/gtmlmean.m new file mode 100644 index 0000000..8aad810 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gtmlmean.m @@ -0,0 +1,22 @@ +function means = gtmlmean(net, data) +%GTMLMEAN Mean responsibility for data in a GTM. +% +% Description +% MEANS = GTMLMEAN(NET, DATA) takes a GTM structure NET, and computes +% the means of the responsibility distributions for each data point in +% DATA. +% +% See also +% GTM, GTMPOST, GTMLMODE +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check for consistency +errstring = consist(net, 'gtm', data); +if ~isempty(errstring) + error(errstring); +end + +R = gtmpost(net, data); +means = R*net.X; diff --git a/PatRec/NetLab/netlab3_3/gtmlmode.m b/PatRec/NetLab/netlab3_3/gtmlmode.m new file mode 100644 index 0000000..6fee04a --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gtmlmode.m @@ -0,0 +1,25 @@ +function modes = gtmlmode(net, data) +%GTMLMODE Mode responsibility for data in a GTM. +% +% Description +% MODES = GTMLMODE(NET, DATA) takes a GTM structure NET, and computes +% the modes of the responsibility distributions for each data point in +% DATA. These will always lie at one of the latent space sample points +% NET.X. +% +% See also +% GTM, GTMPOST, GTMLMEAN +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check for consistency +errstring = consist(net, 'gtm', data); +if ~isempty(errstring) + error(errstring); +end + +R = gtmpost(net, data); +% Mode is maximum responsibility +[max_resp, max_index] = max(R, [], 2); +modes = net.X(max_index, :); diff --git a/PatRec/NetLab/netlab3_3/gtmmag.m b/PatRec/NetLab/netlab3_3/gtmmag.m new file mode 100644 index 0000000..f001497 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gtmmag.m @@ -0,0 +1,27 @@ +function mags = gtmmag(net, latent_data) +%GTMMAG Magnification factors for a GTM +% +% Description +% MAGS = GTMMAG(NET, LATENTDATA) takes a GTM structure NET, and +% computes the magnification factors for each point the latent space +% contained in LATENTDATA. +% +% See also +% GTM, GTMPOST, GTMLMEAN +% + +% Copyright (c) Ian T Nabney (1996-2001) + +errstring = consist(net, 'gtm'); +if ~isempty(errstring) + error(errstring); +end + +Jacs = rbfjacob(net.rbfnet, latent_data); +nlatent = size(latent_data, 1); +mags = zeros(nlatent, 1); +temp = zeros(net.rbfnet.nin, net.rbfnet.nout); +for m = 1:nlatent + temp = squeeze(Jacs(m, :, :)); % Turn into a 2d matrix + mags(m) = sqrt(det(temp*temp')); +end diff --git a/PatRec/NetLab/netlab3_3/gtmpost.m b/PatRec/NetLab/netlab3_3/gtmpost.m new file mode 100644 index 0000000..d9182af --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gtmpost.m @@ -0,0 +1,26 @@ +function [post, a] = gtmpost(net, data) +%GTMPOST Latent space responsibility for data in a GTM. +% +% Description +% POST = GTMPOST(NET, DATA) takes a GTM structure NET, and computes +% the responsibility at each latent space sample point NET.X for each +% data point in DATA. +% +% [POST, A] = GTMPOST(NET, DATA) also returns the activations A of the +% GMM NET.GMMNET as computed by GMMPOST. +% +% See also +% GTM, GTMEM, GTMLMEAN, GMLMODE, GMMPROB +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check for consistency +errstring = consist(net, 'gtm', data); +if ~isempty(errstring) + error(errstring); +end + +net.gmmnet.centres = rbffwd(net.rbfnet, net.X); + +[post, a] = gmmpost(net.gmmnet, data); diff --git a/PatRec/NetLab/netlab3_3/gtmprob.m b/PatRec/NetLab/netlab3_3/gtmprob.m new file mode 100644 index 0000000..203216a --- /dev/null +++ b/PatRec/NetLab/netlab3_3/gtmprob.m @@ -0,0 +1,22 @@ +function prob = gtmprob(net, data) +%GTMPROB Probability for data under a GTM. +% +% Description +% PROB = GTMPROB(NET, DATA) takes a GTM structure NET, and computes +% the probability of each point in the dataset DATA. +% +% See also +% GTM, GTMEM, GTMLMEAN, GTMLMODE, GTMPOST +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check for consistency +errstring = consist(net, 'gtm', data); +if ~isempty(errstring) + error(errstring); +end + +net.gmmnet.centres = rbffwd(net.rbfnet, net.X); + +prob = gmmprob(net.gmmnet, data); diff --git a/PatRec/NetLab/netlab3_3/hbayes.m b/PatRec/NetLab/netlab3_3/hbayes.m new file mode 100644 index 0000000..6586478 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/hbayes.m @@ -0,0 +1,49 @@ +function [h, hdata] = hbayes(net, hdata) +%HBAYES Evaluate Hessian of Bayesian error function for network. +% +% Description +% H = HBAYES(NET, HDATA) takes a network data structure NET together +% the data contribution to the Hessian for a set of inputs and targets. +% It returns the regularised Hessian using any zero mean Gaussian +% priors on the weights defined in NET. In addition, if a MASK is +% defined in NET, then the entries in H that correspond to weights with +% a 0 in the mask are removed. +% +% [H, HDATA] = HBAYES(NET, HDATA) additionally returns the data +% component of the Hessian. +% +% See also +% GBAYES, GLMHESS, MLPHESS, RBFHESS +% + +% Copyright (c) Ian T Nabney (1996-2001) + +if (isfield(net, 'mask')) + % Extract relevant entries in Hessian + nmask_rows = size(find(net.mask), 1); + hdata = reshape(hdata(logical(net.mask*(net.mask'))), ... + nmask_rows, nmask_rows); + nwts = nmask_rows; +else + nwts = net.nwts; +end +if isfield(net, 'beta') + h = net.beta*hdata; +else + h = hdata; +end + +if isfield(net, 'alpha') + if size(net.alpha) == [1 1] + h = h + net.alpha*eye(nwts); + else + if isfield(net, 'mask') + nindx_cols = size(net.index, 2); + index = reshape(net.index(logical(repmat(net.mask, ... + 1, nindx_cols))), nmask_rows, nindx_cols); + else + index = net.index; + end + h = h + diag(index*net.alpha); + end +end diff --git a/PatRec/NetLab/netlab3_3/hesschek.m b/PatRec/NetLab/netlab3_3/hesschek.m new file mode 100644 index 0000000..ffd7253 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/hesschek.m @@ -0,0 +1,60 @@ +function h = hesschek(net, x, t) +%HESSCHEK Use central differences to confirm correct evaluation of Hessian matrix. +% +% Description +% +% HESSCHEK(NET, X, T) takes a network data structure NET, together with +% input and target data matrices X and T, and compares the evaluation +% of the Hessian matrix using the function NETHESS and using central +% differences with the function NETERR. +% +% The optional return value H is the Hessian computed using NETHESS. +% +% See also +% NETHESS, NETERR +% + +% Copyright (c) Ian T Nabney (1996-2001) + +w0 = netpak(net); +nwts = length(w0); +h = nethess(w0, net, x, t); + +w = w0; +hcent = zeros(nwts, nwts); +h1 = 0.0; h2 = 0.0; h3 = 0.0; h4 = 0.0; +epsilon = 1.0e-4; +fprintf(1, 'Checking Hessian ...\n\n'); +for k = 1:nwts; + for l = 1:nwts; + if(l == k) + w(k) = w0(k) + 2.0*epsilon; + h1 = neterr(w, net, x, t); + w(k) = w0(k) - 2.0*epsilon; + h2 = neterr(w, net, x, t); + w(k) = w0(k); + h3 = neterr(w, net, x, t); + hcent(k, k) = (h1 + h2 - 2.0*h3)/(4.0*epsilon^2); + else + w(k) = w0(k) + epsilon; + w(l) = w0(l) + epsilon; + h1 = neterr(w, net, x, t); + w(k) = w0(k) - epsilon; + w(l) = w0(l) - epsilon; + h2 = neterr(w, net, x, t); + w(k) = w0(k) + epsilon; + w(l) = w0(l) - epsilon; + h3 = neterr(w, net, x, t); + w(k) = w0(k) - epsilon; + w(l) = w0(l) + epsilon; + h4 = neterr(w, net, x, t); + hcent(k, l) = (h1 + h2 - h3 - h4)/(4.0*epsilon^2); + w(k) = w0(k); + w(l) = w0(l); + end + end +end + +fprintf(1, ' analytical numerical delta\n\n'); +temp = [h(:), hcent(:), (h(:) - hcent(:))]; +fprintf(1, '%12.6f %12.6f %12.6f\n', temp'); \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/hintmat.m b/PatRec/NetLab/netlab3_3/hintmat.m new file mode 100644 index 0000000..2461792 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/hintmat.m @@ -0,0 +1,41 @@ +function [xvals, yvals, color] = hintmat(w); +%HINTMAT Evaluates the coordinates of the patches for a Hinton diagram. +% +% Description +% [xvals, yvals, color] = hintmat(w) +% takes a matrix W and returns coordinates XVALS, YVALS for the +% patches comrising the Hinton diagram, together with a vector COLOR +% labelling the color (black or white) of the corresponding elements +% according to their sign. +% +% See also +% HINTON +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Set scale to be up to 0.9 of maximum absolute weight value, where scale +% defined so that area of box proportional to weight value. + +w = flipud(w); +[nrows, ncols] = size(w); + +scale = 0.45*sqrt(abs(w)/max(max(abs(w)))); +scale = scale(:); +color = 0.5*(sign(w(:)) + 3); + +delx = 1; +dely = 1; +[X, Y] = meshgrid(0.5*delx:delx:(ncols-0.5*delx), 0.5*dely:dely:(nrows-0.5*dely)); + +% Now convert from matrix format to column vector format, and then duplicate +% columns with appropriate offsets determined by normalized weight magnitudes. + +xtemp = X(:); +ytemp = Y(:); + +xvals = [xtemp-delx*scale, xtemp+delx*scale, ... + xtemp+delx*scale, xtemp-delx*scale]; +yvals = [ytemp-dely*scale, ytemp-dely*scale, ... + ytemp+dely*scale, ytemp+dely*scale]; + diff --git a/PatRec/NetLab/netlab3_3/hinton.m b/PatRec/NetLab/netlab3_3/hinton.m new file mode 100644 index 0000000..c2c4b2b --- /dev/null +++ b/PatRec/NetLab/netlab3_3/hinton.m @@ -0,0 +1,57 @@ +function h = hinton(w); +%HINTON Plot Hinton diagram for a weight matrix. +% +% Description +% +% HINTON(W) takes a matrix W and plots the Hinton diagram. +% +% H = HINTON(NET) also returns the figure handle H which can be used, +% for instance, to delete the figure when it is no longer needed. +% +% To print the figure correctly in black and white, you should call +% SET(H, 'INVERTHARDCOPY', 'OFF') before printing. +% +% See also +% DEMHINT, HINTMAT, MLPHINT +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Set scale to be up to 0.9 of maximum absolute weight value, where scale +% defined so that area of box proportional to weight value. + +% Use no more than 640x480 pixels +xmax = 640; ymax = 480; + +% Offset bottom left hand corner +x01 = 40; y01 = 40; +x02 = 80; y02 = 80; + +% Need to allow 5 pixels border for window frame: but 30 at top +border = 5; +top_border = 30; + +ymax = ymax - top_border; +xmax = xmax - border; + +% First layer + +[xvals, yvals, color] = hintmat(w); +% Try to preserve aspect ratio approximately +if (8*size(w, 1) < 6*size(w, 2)) + delx = xmax; dely = xmax*size(w, 1)/(size(w, 2)); +else + delx = ymax*size(w, 2)/size(w, 1); dely = ymax; +end + +h = figure('Color', [0.5 0.5 0.5], ... + 'Name', 'Hinton diagram', ... + 'NumberTitle', 'off', ... + 'Colormap', [0 0 0; 1 1 1], ... + 'Units', 'pixels', ... + 'Position', [x01 y01 delx dely]); +set(gca, 'Visible', 'off', 'Position', [0 0 1 1]); +hold on +patch(xvals', yvals', color', 'Edgecolor', 'none'); +axis equal; + diff --git a/PatRec/NetLab/netlab3_3/histp.m b/PatRec/NetLab/netlab3_3/histp.m new file mode 100644 index 0000000..7b7fb31 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/histp.m @@ -0,0 +1,29 @@ +function h = histp(x, xmin, xmax, nbins) +%HISTP Histogram estimate of 1-dimensional probability distribution. +% +% Description +% +% HISTP(X, XMIN, XMAX, NBINS) takes a column vector X of data values +% and generates a normalized histogram plot of the distribution. The +% histogram has NBINS bins lying in the range XMIN to XMAX. +% +% H = HISTP(...) returns a vector of patch handles. +% +% See also +% DEMGAUSS +% + +% Copyright (c) Ian T Nabney (1996-2001) + +ndata = length(x); + +bins = linspace(xmin, xmax, nbins); + +binwidth = (xmax - xmin)/nbins; + +num = hist(x, bins); + +num = num/(ndata*binwidth); + +h = bar(bins, num, 0.6); + diff --git a/PatRec/NetLab/netlab3_3/hmc.m b/PatRec/NetLab/netlab3_3/hmc.m new file mode 100644 index 0000000..e9cb06c --- /dev/null +++ b/PatRec/NetLab/netlab3_3/hmc.m @@ -0,0 +1,281 @@ +function [samples, energies, diagn] = hmc(f, x, options, gradf, varargin) +%HMC Hybrid Monte Carlo sampling. +% +% Description +% SAMPLES = HMC(F, X, OPTIONS, GRADF) uses a hybrid Monte Carlo +% algorithm to sample from the distribution P ~ EXP(-F), where F is the +% first argument to HMC. The Markov chain starts at the point X, and +% the function GRADF is the gradient of the `energy' function F. +% +% HMC(F, X, OPTIONS, GRADF, P1, P2, ...) allows additional arguments to +% be passed to F() and GRADF(). +% +% [SAMPLES, ENERGIES, DIAGN] = HMC(F, X, OPTIONS, GRADF) also returns a +% log of the energy values (i.e. negative log probabilities) for the +% samples in ENERGIES and DIAGN, a structure containing diagnostic +% information (position, momentum and acceptance threshold) for each +% step of the chain in DIAGN.POS, DIAGN.MOM and DIAGN.ACC respectively. +% All candidate states (including rejected ones) are stored in +% DIAGN.POS. +% +% [SAMPLES, ENERGIES, DIAGN] = HMC(F, X, OPTIONS, GRADF) also returns +% the ENERGIES (i.e. negative log probabilities) corresponding to the +% samples. The DIAGN structure contains three fields: +% +% POS the position vectors of the dynamic process. +% +% MOM the momentum vectors of the dynamic process. +% +% ACC the acceptance thresholds. +% +% S = HMC('STATE') returns a state structure that contains the state of +% the two random number generators RAND and RANDN and the momentum of +% the dynamic process. These are contained in fields randstate, +% randnstate and mom respectively. The momentum state is only used for +% a persistent momentum update. +% +% HMC('STATE', S) resets the state to S. If S is an integer, then it +% is passed to RAND and RANDN and the momentum variable is randomised. +% If S is a structure returned by HMC('STATE') then it resets the +% generator to exactly the same state. +% +% The optional parameters in the OPTIONS vector have the following +% interpretations. +% +% OPTIONS(1) is set to 1 to display the energy values and rejection +% threshold at each step of the Markov chain. If the value is 2, then +% the position vectors at each step are also displayed. +% +% OPTIONS(5) is set to 1 if momentum persistence is used; default 0, +% for complete replacement of momentum variables. +% +% OPTIONS(7) defines the trajectory length (i.e. the number of leap- +% frog steps at each iteration). Minimum value 1. +% +% OPTIONS(9) is set to 1 to check the user defined gradient function. +% +% OPTIONS(14) is the number of samples retained from the Markov chain; +% default 100. +% +% OPTIONS(15) is the number of samples omitted from the start of the +% chain; default 0. +% +% OPTIONS(17) defines the momentum used when a persistent update of +% (leap-frog) momentum is used. This is bounded to the interval [0, +% 1). +% +% OPTIONS(18) is the step size used in leap-frogs; default 1/trajectory +% length. +% +% See also +% METROP +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Global variable to store state of momentum variables: set by set_state +% Used to initialise variable if set +global HMC_MOM +if nargin <= 2 + if ~strcmp(f, 'state') + error('Unknown argument to hmc'); + end + switch nargin + case 1 + samples = get_state(f); + return; + case 2 + set_state(f, x); + return; + end +end + +display = options(1); +if options(5) == 1 + persistence = 1; + % Set alpha to lie in [0, 1) + alpha = max(0, options(17)); + alpha = min(1, alpha); + salpha = sqrt(1-alpha*alpha); +else + persistence = 0; +end +L = max(1, options(7)); % At least one step in leap-frogging +if options(14) > 0 + nsamples = options(14); +else + nsamples = 100; % Default +end +if options(15) >= 0 + nomit = options(15); +else + nomit = 0; +end +if options(18) > 0 + step_size = options(18); % Step size. +else + step_size = 1/L; % Default +end +x = x(:)'; % Force x to be a row vector +nparams = length(x); + +% Set up strings for evaluating potential function and its gradient. +f = fcnchk(f, length(varargin)); +gradf = fcnchk(gradf, length(varargin)); + +% Check the gradient evaluation. +if (options(9)) + % Check gradients + feval('gradchek', x, f, gradf, varargin{:}); +end + +samples = zeros(nsamples, nparams); % Matrix of returned samples. +if nargout >= 2 + en_save = 1; + energies = zeros(nsamples, 1); +else + en_save = 0; +end +if nargout >= 3 + diagnostics = 1; + diagn_pos = zeros(nsamples, nparams); + diagn_mom = zeros(nsamples, nparams); + diagn_acc = zeros(nsamples, 1); +else + diagnostics = 0; +end + +n = - nomit + 1; +Eold = feval(f, x, varargin{:}); % Evaluate starting energy. +nreject = 0; +if (~persistence | isempty(HMC_MOM)) + p = randn(1, nparams); % Initialise momenta at random +else + p = HMC_MOM; % Initialise momenta from stored state +end +lambda = 1; + +% Main loop. +while n <= nsamples + + xold = x; % Store starting position. + pold = p; % Store starting momenta + Hold = Eold + 0.5*(p*p'); % Recalculate Hamiltonian as momenta have changed + + if ~persistence + % Choose a direction at random + if (rand < 0.5) + lambda = -1; + else + lambda = 1; + end + end + % Perturb step length. + epsilon = lambda*step_size*(1.0 + 0.1*randn(1)); + + % First half-step of leapfrog. + p = p - 0.5*epsilon*feval(gradf, x, varargin{:}); + x = x + epsilon*p; + + % Full leapfrog steps. + for m = 1 : L - 1 + p = p - epsilon*feval(gradf, x, varargin{:}); + x = x + epsilon*p; + end + + % Final half-step of leapfrog. + p = p - 0.5*epsilon*feval(gradf, x, varargin{:}); + + % Now apply Metropolis algorithm. + Enew = feval(f, x, varargin{:}); % Evaluate new energy. + p = -p; % Negate momentum + Hnew = Enew + 0.5*p*p'; % Evaluate new Hamiltonian. + a = exp(Hold - Hnew); % Acceptance threshold. + if (diagnostics & n > 0) + diagn_pos(n,:) = x; + diagn_mom(n,:) = p; + diagn_acc(n,:) = a; + end + if (display > 1) + fprintf(1, 'New position is\n'); + disp(x); + end + + if a > rand(1) % Accept the new state. + Eold = Enew; % Update energy + if (display > 0) + fprintf(1, 'Finished step %4d Threshold: %g\n', n, a); + end + else % Reject the new state. + if n > 0 + nreject = nreject + 1; + end + x = xold; % Reset position + p = pold; % Reset momenta + if (display > 0) + fprintf(1, ' Sample rejected %4d. Threshold: %g\n', n, a); + end + end + if n > 0 + samples(n,:) = x; % Store sample. + if en_save + energies(n) = Eold; % Store energy. + end + end + + % Set momenta for next iteration + if persistence + p = -p; + % Adjust momenta by a small random amount. + p = alpha.*p + salpha.*randn(1, nparams); + else + p = randn(1, nparams); % Replace all momenta. + end + + n = n + 1; +end + +if (display > 0) + fprintf(1, '\nFraction of samples rejected: %g\n', ... + nreject/(nsamples)); +end +if diagnostics + diagn.pos = diagn_pos; + diagn.mom = diagn_mom; + diagn.acc = diagn_acc; +end +% Store final momentum value in global so that it can be retrieved later +HMC_MOM = p; +return + +% Return complete state of sampler (including momentum) +function state = get_state(f) + +global HMC_MOM +state.randstate = rand('state'); +state.randnstate = randn('state'); +state.mom = HMC_MOM; +return + +% Set complete state of sampler (including momentum) or just set randn +% and rand with integer argument. +function set_state(f, x) + +global HMC_MOM +if isnumeric(x) + rand('state', x); + randn('state', x); + HMC_MOM = []; +else + if ~isstruct(x) + error('Second argument to hmc must be number or state structure'); + end + if (~isfield(x, 'randstate') | ~isfield(x, 'randnstate') ... + | ~isfield(x, 'mom')) + error('Second argument to hmc must contain correct fields') + end + rand('state', x.randstate); + randn('state', x.randnstate); + HMC_MOM = x.mom; +end +return diff --git a/PatRec/NetLab/netlab3_3/kmeans.m b/PatRec/NetLab/netlab3_3/kmeans.m new file mode 100644 index 0000000..09935f7 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/kmeans.m @@ -0,0 +1,124 @@ +function [centres, options, post, errlog] = kmeans(centres, data, options) +%KMEANS Trains a k means cluster model. +% +% Description +% CENTRES = KMEANS(CENTRES, DATA, OPTIONS) uses the batch K-means +% algorithm to set the centres of a cluster model. The matrix DATA +% represents the data which is being clustered, with each row +% corresponding to a vector. The sum of squares error function is used. +% The point at which a local minimum is achieved is returned as +% CENTRES. The error value at that point is returned in OPTIONS(8). +% +% [CENTRES, OPTIONS, POST, ERRLOG] = KMEANS(CENTRES, DATA, OPTIONS) +% also returns the cluster number (in a one-of-N encoding) for each +% data point in POST and a log of the error values after each cycle in +% ERRLOG. The optional parameters have the following +% interpretations. +% +% OPTIONS(1) is set to 1 to display error values; also logs error +% values in the return argument ERRLOG. If OPTIONS(1) is set to 0, then +% only warning messages are displayed. If OPTIONS(1) is -1, then +% nothing is displayed. +% +% OPTIONS(2) is a measure of the absolute precision required for the +% value of CENTRES at the solution. If the absolute difference between +% the values of CENTRES between two successive steps is less than +% OPTIONS(2), then this condition is satisfied. +% +% OPTIONS(3) is a measure of the precision required of the error +% function at the solution. If the absolute difference between the +% error functions between two successive steps is less than OPTIONS(3), +% then this condition is satisfied. Both this and the previous +% condition must be satisfied for termination. +% +% OPTIONS(14) is the maximum number of iterations; default 100. +% +% See also +% GMMINIT, GMMEM +% + +% Copyright (c) Ian T Nabney (1996-2001) + +[ndata, data_dim] = size(data); +[ncentres, dim] = size(centres); + +if dim ~= data_dim + error('Data dimension does not match dimension of centres') +end + +if (ncentres > ndata) + error('More centres than data') +end + +% Sort out the options +if (options(14)) + niters = options(14); +else + niters = 100; +end + +store = 0; +if (nargout > 3) + store = 1; + errlog = zeros(1, niters); +end + +% Check if centres and posteriors need to be initialised from data +if (options(5) == 1) + % Do the initialisation + perm = randperm(ndata); + perm = perm(1:ncentres); + + % Assign first ncentres (permuted) data points as centres + centres = data(perm, :); +end +% Matrix to make unit vectors easy to construct +id = eye(ncentres); + +% Main loop of algorithm +for n = 1:niters + + % Save old centres to check for termination + old_centres = centres; + + % Calculate posteriors based on existing centres + d2 = dist2(data, centres); + % Assign each point to nearest centre + [minvals, index] = min(d2', [], 1); + post = id(index,:); + + num_points = sum(post, 1); + % Adjust the centres based on new posteriors + for j = 1:ncentres + if (num_points(j) > 0) + centres(j,:) = sum(data(find(post(:,j)),:), 1)/num_points(j); + end + end + + % Error value is total squared distance from cluster centres + e = sum(minvals); + if store + errlog(n) = e; + end + if options(1) > 0 + fprintf(1, 'Cycle %4d Error %11.6f\n', n, e); + end + + if n > 1 + % Test for termination + if max(max(abs(centres - old_centres))) < options(2) & ... + abs(old_e - e) < options(3) + options(8) = e; + return; + end + end + old_e = e; +end + +% If we get here, then we haven't terminated in the given number of +% iterations. +options(8) = e; +if (options(1) >= 0) + disp(maxitmess); +end + diff --git a/PatRec/NetLab/netlab3_3/knn.m b/PatRec/NetLab/netlab3_3/knn.m new file mode 100644 index 0000000..0f066e6 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/knn.m @@ -0,0 +1,34 @@ +function net = knn(nin, nout, k, tr_in, tr_targets) +%KNN Creates a K-nearest-neighbour classifier. +% +% Description +% NET = KNN(NIN, NOUT, K, TR_IN, TR_TARGETS) creates a KNN model NET +% with input dimension NIN, output dimension NOUT and K neighbours. +% The training data is also stored in the data structure and the +% targets are assumed to be using a 1-of-N coding. +% +% The fields in NET are +% type = 'knn' +% nin = number of inputs +% nout = number of outputs +% tr_in = training input data +% tr_targets = training target data +% +% See also +% KMEANS, KNNFWD +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +net.type = 'knn'; +net.nin = nin; +net.nout = nout; +net.k = k; +errstring = consist(net, 'knn', tr_in, tr_targets); +if ~isempty(errstring) + error(errstring); +end +net.tr_in = tr_in; +net.tr_targets = tr_targets; + diff --git a/PatRec/NetLab/netlab3_3/knnfwd.m b/PatRec/NetLab/netlab3_3/knnfwd.m new file mode 100644 index 0000000..fed7be7 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/knnfwd.m @@ -0,0 +1,53 @@ +function [y, l] = knnfwd(net, x) +%KNNFWD Forward propagation through a K-nearest-neighbour classifier. +% +% Description +% [Y, L] = KNNFWD(NET, X) takes a matrix X of input vectors (one vector +% per row) and uses the K-nearest-neighbour rule on the training data +% contained in NET to produce a matrix Y of outputs and a matrix L of +% classification labels. The nearest neighbours are determined using +% Euclidean distance. The IJth entry of Y counts the number of +% occurrences that an example from class J is among the K closest +% training examples to example I from X. The matrix L contains the +% predicted class labels as an index 1..N, not as 1-of-N coding. +% +% See also +% KMEANS, KNN +% + +% Copyright (c) Ian T Nabney (1996-2001) + + +errstring = consist(net, 'knn', x); +if ~isempty(errstring) + error(errstring); +end + +ntest = size(x, 1); % Number of input vectors. +nclass = size(net.tr_targets, 2); % Number of classes. + +% Compute matrix of squared distances between input vectors from the training +% and test sets. The matrix distsq has dimensions (ntrain, ntest). + +distsq = dist2(net.tr_in, x); + +% Now sort the distances. This generates a matrix kind of the same +% dimensions as distsq, in which each column gives the indices of the +% elements in the corresponding column of distsq in ascending order. + +[vals, kind] = sort(distsq); +y = zeros(ntest, nclass); + +for k=1:net.k + % We now look at the predictions made by the Kth nearest neighbours alone, + % and represent this as a 1-of-N coded matrix, and then accumulate the + % predictions so far. + + y = y + net.tr_targets(kind(k,:),:); + +end + +if nargout == 2 + % Convert this set of outputs to labels, randomly breaking ties + [temp, l] = max((y + 0.1*rand(size(y))), [], 2); +end \ No newline at end of file diff --git a/PatRec/NetLab/netlab3_3/linef.m b/PatRec/NetLab/netlab3_3/linef.m new file mode 100644 index 0000000..4f0ddd3 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/linef.m @@ -0,0 +1,21 @@ +function y = linef(lambda, fn, x, d, varargin) +%LINEF Calculate function value along a line. +% +% Description +% LINEF(LAMBDA, FN, X, D) calculates the value of the function FN at +% the point X+LAMBDA*D. Here X is a row vector and LAMBDA is a scalar. +% +% LINEF(LAMBDA, FN, X, D, P1, P2, ...) allows additional arguments to +% be passed to FN(). This function is used for convenience in some of +% the optimisation routines. +% +% See also +% GRADCHEK, LINEMIN +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check function string +fn = fcnchk(fn, length(varargin)); + +y = feval(fn, x+lambda.*d, varargin{:}); diff --git a/PatRec/NetLab/netlab3_3/linemin.m b/PatRec/NetLab/netlab3_3/linemin.m new file mode 100644 index 0000000..8e390a4 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/linemin.m @@ -0,0 +1,152 @@ +function [x, options] = linemin(f, pt, dir, fpt, options, ... + varargin) +%LINEMIN One dimensional minimization. +% +% Description +% [X, OPTIONS] = LINEMIN(F, PT, DIR, FPT, OPTIONS) uses Brent's +% algorithm to find the minimum of the function F(X) along the line DIR +% through the point PT. The function value at the starting point is +% FPT. The point at which F has a local minimum is returned as X. The +% function value at that point is returned in OPTIONS(8). +% +% LINEMIN(F, PT, DIR, FPT, OPTIONS, P1, P2, ...) allows additional +% arguments to be passed to F(). +% +% The optional parameters have the following interpretations. +% +% OPTIONS(1) is set to 1 to display error values. +% +% OPTIONS(2) is a measure of the absolute precision required for the +% value of X at the solution. +% +% OPTIONS(3) is a measure of the precision required of the objective +% function at the solution. Both this and the previous condition must +% be satisfied for termination. +% +% OPTIONS(14) is the maximum number of iterations; default 100. +% +% See also +% CONJGRAD, MINBRACK, QUASINEW +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Set up the options. +if(options(14)) + niters = options(14); +else + niters = 100; +end +options(10) = 0; % Initialise count of function evaluations + +display = options(1); + +% Check function string +f = fcnchk(f, length(varargin)); + +% Value of golden section (1 + sqrt(5))/2.0 +phi = 1.6180339887499; +cphi = 1 - 1/phi; +TOL = sqrt(eps); % Maximal fractional precision +TINY = 1.0e-10; % Can't use fractional precision when minimum is at 0 + +% Bracket the minimum +[br_min, br_mid, br_max, num_evals] = feval('minbrack', 'linef', ... + 0.0, 1.0, fpt, f, pt, dir, varargin{:}); +options(10) = options(10) + num_evals; % Increment number of fn. evals + % No gradient evals in minbrack + +% Use Brent's algorithm to find minimum +% Initialise the points and function values +w = br_mid; % Where second from minimum is +v = br_mid; % Previous value of w +x = v; % Where current minimum is +e = 0.0; % Distance moved on step before last +fx = feval('linef', x, f, pt, dir, varargin{:}); +options(10) = options(10) + 1; +fv = fx; fw = fx; + +for n = 1:niters + xm = 0.5.*(br_min+br_max); % Middle of bracket + % Make sure that tolerance is big enough + tol1 = TOL * (max(abs(x))) + TINY; + % Decide termination on absolute precision required by options(2) + if (max(abs(x - xm)) <= options(2) & br_max-br_min < 4*options(2)) + options(8) = fx; + return; + end + % Check if step before last was big enough to try a parabolic step. + % Note that this will fail on first iteration, which must be a golden + % section step. + if (max(abs(e)) > tol1) + % Construct a trial parabolic fit through x, v and w + r = (fx - fv) .* (x - w); + q = (fx - fw) .* (x - v); + p = (x - v).*q - (x - w).*r; + q = 2.0 .* (q - r); + if (q > 0.0) p = -p; end + q = abs(q); + % Test if the parabolic fit is OK + if (abs(p) >= abs(0.5*q*e) | p <= q*(br_min-x) | p >= q*(br_max-x)) + % No it isn't, so take a golden section step + if (x >= xm) + e = br_min-x; + else + e = br_max-x; + end + d = cphi*e; + else + % Yes it is, so take the parabolic step + e = d; + d = p/q; + u = x+d; + if (u-br_min < 2*tol1 | br_max-u < 2*tol1) + d = sign(xm-x)*tol1; + end + end + else + % Step before last not big enough, so take a golden section step + if (x >= xm) + e = br_min - x; + else + e = br_max - x; + end + d = cphi*e; + end + % Make sure that step is big enough + if (abs(d) >= tol1) + u = x+d; + else + u = x + sign(d)*tol1; + end + % Evaluate function at u + fu = feval('linef', u, f, pt, dir, varargin{:}); + options(10) = options(10) + 1; + % Reorganise bracket + if (fu <= fx) + if (u >= x) + br_min = x; + else + br_max = x; + end + v = w; w = x; x = u; + fv = fw; fw = fx; fx = fu; + else + if (u < x) + br_min = u; + else + br_max = u; + end + if (fu <= fw | w == x) + v = w; w = u; + fv = fw; fw = fu; + elseif (fu <= fv | v == x | v == w) + v = u; + fv = fu; + end + end + if (display == 1) + fprintf(1, 'Cycle %4d Error %11.6f\n', n, fx); + end +end +options(8) = fx; diff --git a/PatRec/NetLab/netlab3_3/maxitmess.m b/PatRec/NetLab/netlab3_3/maxitmess.m new file mode 100644 index 0000000..338be6d --- /dev/null +++ b/PatRec/NetLab/netlab3_3/maxitmess.m @@ -0,0 +1,16 @@ +function s = maxitmess() +%MAXITMESS Create a standard error message when training reaches max. iterations. +% +% Description +% S = MAXITMESS returns a standard string that it used by training +% algorithms when the maximum number of iterations (as specified in +% OPTIONS(14) is reached. +% +% See also +% CONJGRAD, GLMTRAIN, GMMEM, GRADDESC, GTMEM, KMEANS, OLGD, QUASINEW, SCG +% + +% Copyright (c) Ian T Nabney (1996-2001) + +s = 'Maximum number of iterations has been exceeded'; + diff --git a/PatRec/NetLab/netlab3_3/mdn.m b/PatRec/NetLab/netlab3_3/mdn.m new file mode 100644 index 0000000..964baa1 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/mdn.m @@ -0,0 +1,77 @@ +function net = mdn(nin, nhidden, ncentres, dim_target, mix_type, ... + prior, beta) +%MDN Creates a Mixture Density Network with specified architecture. +% +% Description +% NET = MDN(NIN, NHIDDEN, NCENTRES, DIMTARGET) takes the number of +% inputs, hidden units for a 2-layer feed-forward network and the +% number of centres and target dimension for the mixture model whose +% parameters are set from the outputs of the neural network. The fifth +% argument MIXTYPE is used to define the type of mixture model. +% (Currently there is only one type supported: a mixture of Gaussians +% with a single covariance parameter for each component.) For this +% model, the mixture coefficients are computed from a group of softmax +% outputs, the centres are equal to a group of linear outputs, and the +% variances are obtained by applying the exponential function to a +% third group of outputs. +% +% The network is initialised by a call to MLP, and the arguments PRIOR, +% and BETA have the same role as for that function. Weight +% initialisation uses the Matlab function RANDN and so the seed for +% the random weight initialization can be set using RANDN('STATE', S) +% where S is the seed value. A specialised data structure (rather than +% GMM) is used for the mixture model outputs to improve the efficiency +% of error and gradient calculations in network training. The fields +% are described in MDNFWD where they are set up. +% +% The fields in NET are +% +% type = 'mdn' +% nin = number of input variables +% nout = dimension of target space (not number of network outputs) +% nwts = total number of weights and biases +% mdnmixes = data structure for mixture model output +% mlp = data structure for MLP network +% +% See also +% MDNFWD, MDNERR, MDN2GMM, MDNGRAD, MDNPAK, MDNUNPAK, MLP +% + +% Copyright (c) Ian T Nabney (1996-2001) +% David J Evans (1998) + +% Currently ignore type argument: reserved for future use +net.type = 'mdn'; + +% Set up the mixture model part of the structure +% For efficiency we use a specialised data structure in place of GMM +mdnmixes.type = 'mdnmixes'; +mdnmixes.ncentres = ncentres; +mdnmixes.dim_target = dim_target; + +% This calculation depends on spherical variances +mdnmixes.nparams = ncentres + ncentres*dim_target + ncentres; + +% Make the weights in the mdnmixes structure null +mdnmixes.mixcoeffs = []; +mdnmixes.centres = []; +mdnmixes.covars = []; + +% Number of output nodes = number of parameters in mixture model +nout = mdnmixes.nparams; + +% Set up the MLP part of the network +if (nargin == 5) + mlpnet = mlp(nin, nhidden, nout, 'linear'); +elseif (nargin == 6) + mlpnet = mlp(nin, nhidden, nout, 'linear', prior); +elseif (nargin == 7) + mlpnet = mlp(nin, nhidden, nout, 'linear', prior, beta); +end + +% Create descriptor +net.mdnmixes = mdnmixes; +net.mlp = mlpnet; +net.nin = nin; +net.nout = dim_target; +net.nwts = mlpnet.nwts; diff --git a/PatRec/NetLab/netlab3_3/mdn2gmm.m b/PatRec/NetLab/netlab3_3/mdn2gmm.m new file mode 100644 index 0000000..bad5ed9 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/mdn2gmm.m @@ -0,0 +1,41 @@ +function gmmmixes = mdn2gmm(mdnmixes) +%MDN2GMM Converts an MDN mixture data structure to array of GMMs. +% +% Description +% GMMMIXES = MDN2GMM(MDNMIXES) takes an MDN mixture data structure +% MDNMIXES containing three matrices (for priors, centres and +% variances) where each row represents the corresponding parameter +% values for a different mixture model and creates an array of GMMs. +% These can then be used with the standard Netlab Gaussian mixture +% model functions. +% +% See also +% GMM, MDN, MDNFWD +% + +% Copyright (c) Ian T Nabney (1996-2001) +% David J Evans (1998) + +% Check argument for consistency +errstring = consist(mdnmixes, 'mdnmixes'); +if ~isempty(errstring) + error(errstring); +end + +nmixes = size(mdnmixes.centres, 1); +% Construct ndata structures containing the mixture model information. +% First allocate the memory. +tempmix = gmm(mdnmixes.dim_target, mdnmixes.ncentres, 'spherical'); +f = fieldnames(tempmix); +gmmmixes = cell(size(f, 1), 1, nmixes); +gmmmixes = cell2struct(gmmmixes, f,1); + +% Then fill each structure in turn using gmmunpak. Assume that spherical +% covariance structure is used. +for i = 1:nmixes + centres = reshape(mdnmixes.centres(i, :), mdnmixes.dim_target, ... + mdnmixes.ncentres)'; + gmmmixes(i) = gmmunpak(tempmix, [mdnmixes.mixcoeffs(i,:), ... + centres(:)', mdnmixes.covars(i,:)]); +end + diff --git a/PatRec/NetLab/netlab3_3/mdndist2.m b/PatRec/NetLab/netlab3_3/mdndist2.m new file mode 100644 index 0000000..d7ed93d --- /dev/null +++ b/PatRec/NetLab/netlab3_3/mdndist2.m @@ -0,0 +1,51 @@ +function n2 = mdndist2(mixparams, t) +%MDNDIST2 Calculates squared distance between centres of Gaussian kernels and data +% +% Description +% N2 = MDNDIST2(MIXPARAMS, T) takes takes the centres of the Gaussian +% contained in MIXPARAMS and the target data matrix, T, and computes +% the squared Euclidean distance between them. If T has M rows and N +% columns, then the CENTRES field in the MIXPARAMS structure should +% have M rows and N*MIXPARAMS.NCENTRES columns: the centres in each row +% relate to the corresponding row in T. The result has M rows and +% MIXPARAMS.NCENTRES columns. The I, Jth entry is the squared distance +% from the Ith row of X to the Jth centre in the Ith row of +% MIXPARAMS.CENTRES. +% +% See also +% MDNFWD, MDNPROB +% + +% Copyright (c) Ian T Nabney (1996-2001) +% David J Evans (1998) + +% Check arguments for consistency +errstring = consist(mixparams, 'mdnmixes'); +if ~isempty(errstring) + error(errstring); +end + +ncentres = mixparams.ncentres; +dim_target = mixparams.dim_target; +ntarget = size(t, 1); +if ntarget ~= size(mixparams.centres, 1) + error('Number of targets does not match number of mixtures') +end +if size(t, 2) ~= mixparams.dim_target + error('Target dimension does not match mixture dimension') +end + +% Build t that suits parameters, that is repeat t for each centre +t = kron(ones(1, ncentres), t); + +% Do subtraction and square +diff2 = (t - mixparams.centres).^2; + +% Reshape and sum each component +diff2 = reshape(diff2', dim_target, (ntarget*ncentres))'; +n2 = sum(diff2, 2); + +% Calculate the sum of distance, and reshape +% so that we have a distance for each centre per target +n2 = reshape(n2, ncentres, ntarget)'; + diff --git a/PatRec/NetLab/netlab3_3/mdnerr.m b/PatRec/NetLab/netlab3_3/mdnerr.m new file mode 100644 index 0000000..a0b686e --- /dev/null +++ b/PatRec/NetLab/netlab3_3/mdnerr.m @@ -0,0 +1,33 @@ +function e = mdnerr(net, x, t) +%MDNERR Evaluate error function for Mixture Density Network. +% +% Description +% E = MDNERR(NET, X, T) takes a mixture density network data structure +% NET, a matrix X of input vectors and a matrix T of target vectors, +% and evaluates the error function E. The error function is the +% negative log likelihood of the target data under the conditional +% density given by the mixture model parameterised by the MLP. Each +% row of X corresponds to one input vector and each row of T +% corresponds to one target vector. +% +% See also +% MDN, MDNFWD, MDNGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) +% David J Evans (1998) + +% Check arguments for consistency +errstring = consist(net, 'mdn', x, t); +if ~isempty(errstring) + error(errstring); +end + +% Get the output mixture models +mixparams = mdnfwd(net, x); + +% Compute the probabilities of mixtures +probs = mdnprob(mixparams, t); +% Compute the error +e = sum( -log(max(eps, sum(probs, 2)))); + diff --git a/PatRec/NetLab/netlab3_3/mdnfwd.m b/PatRec/NetLab/netlab3_3/mdnfwd.m new file mode 100644 index 0000000..962fbe0 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/mdnfwd.m @@ -0,0 +1,93 @@ +function [mixparams, y, z, a] = mdnfwd(net, x) +%MDNFWD Forward propagation through Mixture Density Network. +% +% Description +% MIXPARAMS = MDNFWD(NET, X) takes a mixture density network data +% structure NET and a matrix X of input vectors, and forward propagates +% the inputs through the network to generate a structure MIXPARAMS +% which contains the parameters of several mixture models. Each row +% of X represents one input vector and the corresponding row of the +% matrices in MIXPARAMS represents the parameters of a mixture model +% for the conditional probability of target vectors given the input +% vector. This is not represented as an array of GMM structures to +% improve the efficiency of MDN training. +% +% The fields in MIXPARAMS are +% type = 'mdnmixes' +% ncentres = number of mixture components +% dimtarget = dimension of target space +% mixcoeffs = mixing coefficients +% centres = means of Gaussians: stored as one row per pattern +% covars = covariances of Gaussians +% nparams = number of parameters +% +% [MIXPARAMS, Y, Z] = MDNFWD(NET, X) also generates a matrix Y of the +% outputs of the MLP and a matrix Z of the hidden unit activations +% where each row corresponds to one pattern. +% +% [MIXPARAMS, Y, Z, A] = MLPFWD(NET, X) also returns a matrix A giving +% the summed inputs to each output unit, where each row corresponds to +% one pattern. +% +% See also +% MDN, MDN2GMM, MDNERR, MDNGRAD, MLPFWD +% + +% Copyright (c) Ian T Nabney (1996-2001) +% David J Evans (1998) + +% Check arguments for consistency +errstring = consist(net, 'mdn', x); +if ~isempty(errstring) + error(errstring); +end + +% Extract mlp and mixture model descriptors +mlpnet = net.mlp; +mixes = net.mdnmixes; + +ncentres = mixes.ncentres; % Number of components in mixture model +dim_target = mixes.dim_target; % Dimension of targets +nparams = mixes.nparams; % Number of parameters in mixture model + +% Propagate forwards through MLP +[y, z, a] = mlpfwd(mlpnet, x); + +% Compute the postion for each parameter in the whole +% matrix. Used to define the mixparams structure +mixcoeff = [1:1:ncentres]; +centres = [ncentres+1:1:(ncentres*(1+dim_target))]; +variances = [(ncentres*(1+dim_target)+1):1:nparams]; + +% Convert output values into mixture model parameters + +% Use softmax to calculate priors +% Prevent overflow and underflow: use same bounds as glmfwd +% Ensure that sum(exp(y), 2) does not overflow +maxcut = log(realmax) - log(ncentres); +% Ensure that exp(y) > 0 +mincut = log(realmin); +temp = min(y(:,1:ncentres), maxcut); +temp = max(temp, mincut); +temp = exp(temp); +mixpriors = temp./(sum(temp, 2)*ones(1,ncentres)); + +% Centres are just copies of network outputs +mixcentres = y(:,(ncentres+1):ncentres*(1+dim_target)); + +% Variances are exp of network outputs +mixwidths = exp(y(:,(ncentres*(1+dim_target)+1):nparams)); + +% Now build up all the mixture model weight vectors +ndata = size(x, 1); + +% Return parameters +mixparams.type = mixes.type; +mixparams.ncentres = mixes.ncentres; +mixparams.dim_target = mixes.dim_target; +mixparams.nparams = mixes.nparams; + +mixparams.mixcoeffs = mixpriors; +mixparams.centres = mixcentres; +mixparams.covars = mixwidths; + diff --git a/PatRec/NetLab/netlab3_3/mdngrad.m b/PatRec/NetLab/netlab3_3/mdngrad.m new file mode 100644 index 0000000..6a0b6ea --- /dev/null +++ b/PatRec/NetLab/netlab3_3/mdngrad.m @@ -0,0 +1,66 @@ +function g = mdngrad(net, x, t) +%MDNGRAD Evaluate gradient of error function for Mixture Density Network. +% +% Description +% G = MDNGRAD(NET, X, T) takes a mixture density network data +% structure NET, a matrix X of input vectors and a matrix T of target +% vectors, and evaluates the gradient G of the error function with +% respect to the network weights. The error function is negative log +% likelihood of the target data. Each row of X corresponds to one +% input vector and each row of T corresponds to one target vector. +% +% See also +% MDN, MDNFWD, MDNERR, MDNPROB, MLPBKP +% + +% Copyright (c) Ian T Nabney (1996-2001) +% David J Evans (1998) + +% Check arguments for consistency +errstring = consist(net, 'mdn', x, t); +if ~isempty(errstring) + error(errstring); +end + +[mixparams, y, z] = mdnfwd(net, x); + +% Compute gradients at MLP outputs: put the answer in deltas +ncentres = net.mdnmixes.ncentres; +dim_target = net.mdnmixes.dim_target; +nmixparams = net.mdnmixes.nparams; +ntarget = size(t, 1); +deltas = zeros(ntarget, net.mlp.nout); +e = ones(ncentres, 1); +f = ones(1, dim_target); + +post = mdnpost(mixparams, t); + +% Calculate prior derivatives +deltas(:,1:ncentres) = mixparams.mixcoeffs - post; + +% Calculate centre derivatives +long_t = kron(ones(1, ncentres), t); +centre_err = mixparams.centres - long_t; + +% Get the post to match each u_jk: +% this array will be (ntarget, (ncentres*dim_target)) +long_post = kron(ones(dim_target, 1), post); +long_post = reshape(long_post, ntarget, (ncentres*dim_target)); + +% Get the variance to match each u_jk: +var = mixparams.covars; +var = kron(ones(dim_target, 1), var); +var = reshape(var, ntarget, (ncentres*dim_target)); + +% Compute centre deltas +deltas(:, (ncentres+1):(ncentres*(1+dim_target))) = ... + (centre_err.*long_post)./var; + +% Compute variance deltas +dist2 = mdndist2(mixparams, t); +c = dim_target*ones(ntarget, ncentres); +deltas(:, (ncentres*(1+dim_target)+1):nmixparams) = ... + post.*((dist2./mixparams.covars)-c)./(-2); + +% Now back-propagate deltas through MLP +g = mlpbkp(net.mlp, x, z, deltas); diff --git a/PatRec/NetLab/netlab3_3/mdninit.m b/PatRec/NetLab/netlab3_3/mdninit.m new file mode 100644 index 0000000..20f23d0 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/mdninit.m @@ -0,0 +1,53 @@ +function net = mdninit(net, prior, t, options) +%MDNINIT Initialise the weights in a Mixture Density Network. +% +% Description +% +% NET = MDNINIT(NET, PRIOR) takes a Mixture Density Network NET and +% sets the weights and biases by sampling from a Gaussian distribution. +% It calls MLPINIT for the MLP component of NET. +% +% NET = MDNINIT(NET, PRIOR, T, OPTIONS) uses the target data T to +% initialise the biases for the output units after initialising the +% other weights as above. It calls GMMINIT, with T and OPTIONS as +% arguments, to obtain a model of the unconditional density of T. The +% biases are then set so that NET will output the values in the +% Gaussian mixture model. +% +% See also +% MDN, MLP, MLPINIT, GMMINIT +% + +% Copyright (c) Ian T Nabney (1996-2001) +% David J Evans (1998) + +% Initialise network weights from prior: this gives noise around values +% determined later +net.mlp = mlpinit(net.mlp, prior); + +if nargin > 2 + % Initialise priors, centres and variances from target data + temp_mix = gmm(net.mdnmixes.dim_target, net.mdnmixes.ncentres, 'spherical'); + temp_mix = gmminit(temp_mix, t, options); + + ncentres = net.mdnmixes.ncentres; + dim_target = net.mdnmixes.dim_target; + + % Now set parameters in MLP to yield the right values. + % This involves setting the biases correctly. + + % Priors + net.mlp.b2(1:ncentres) = temp_mix.priors; + + % Centres are arranged in mlp such that we have + % u11, u12, u13, ..., u1c, ... , uj1, uj2, uj3, ..., ujc, ..., um1, uM2, + % ..., uMc + % This is achieved by transposing temp_mix.centres before reshaping + end_centres = ncentres*(dim_target+1); + net.mlp.b2(ncentres+1:end_centres) = ... + reshape(temp_mix.centres', 1, ncentres*dim_target); + + % Variances + net.mlp.b2((end_centres+1):net.mlp.nout) = ... + log(temp_mix.covars); +end diff --git a/PatRec/NetLab/netlab3_3/mdnnet.mat b/PatRec/NetLab/netlab3_3/mdnnet.mat new file mode 100644 index 0000000..724f8d4 Binary files /dev/null and b/PatRec/NetLab/netlab3_3/mdnnet.mat differ diff --git a/PatRec/NetLab/netlab3_3/mdnpak.m b/PatRec/NetLab/netlab3_3/mdnpak.m new file mode 100644 index 0000000..47da11a --- /dev/null +++ b/PatRec/NetLab/netlab3_3/mdnpak.m @@ -0,0 +1,19 @@ +function w = mdnpak(net) +%MDNPAK Combines weights and biases into one weights vector. +% +% Description +% W = MDNPAK(NET) takes a mixture density network data structure NET +% and combines the network weights into a single row vector W. +% +% See also +% MDN, MDNUNPAK, MDNFWD, MDNERR, MDNGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) +% David J Evans (1998) + +errstring = consist(net, 'mdn'); +if ~errstring + error(errstring); +end +w = mlppak(net.mlp); diff --git a/PatRec/NetLab/netlab3_3/mdnpost.m b/PatRec/NetLab/netlab3_3/mdnpost.m new file mode 100644 index 0000000..2a27849 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/mdnpost.m @@ -0,0 +1,26 @@ +function [post, a] = mdnpost(mixparams, t) +%MDNPOST Computes the posterior probability for each MDN mixture component. +% +% Description +% POST = MDNPOST(MIXPARAMS, T) computes the posterior probability +% P(J|T) of each data vector in T under the Gaussian mixture model +% represented by the corresponding entries in MIXPARAMS. Each row of T +% represents a single vector. +% +% [POST, A] = MDNPOST(MIXPARAMS, T) also computes the activations A +% (i.e. the probability P(T|J) of the data conditioned on each +% component density) for a Gaussian mixture model. +% +% See also +% MDNGRAD, MDNPROB +% + +% Copyright (c) Ian T Nabney (1996-2001) +% David J Evans (1998) + +[prob a] = mdnprob(mixparams, t); + +s = sum(prob, 2); +% Set any zeros to one before dividing +s = s + (s==0); +post = prob./(s*ones(1, mixparams.ncentres)); diff --git a/PatRec/NetLab/netlab3_3/mdnprob.m b/PatRec/NetLab/netlab3_3/mdnprob.m new file mode 100644 index 0000000..3c828ea --- /dev/null +++ b/PatRec/NetLab/netlab3_3/mdnprob.m @@ -0,0 +1,52 @@ +function [prob,a] = mdnprob(mixparams, t) +%MDNPROB Computes the data probability likelihood for an MDN mixture structure. +% +% Description +% PROB = MDNPROB(MIXPARAMS, T) computes the probability P(T) of each +% data vector in T under the Gaussian mixture model represented by the +% corresponding entries in MIXPARAMS. Each row of T represents a single +% vector. +% +% [PROB, A] = MDNPROB(MIXPARAMS, T) also computes the activations A +% (i.e. the probability P(T|J) of the data conditioned on each +% component density) for a Gaussian mixture model. +% +% See also +% MDNERR, MDNPOST +% + +% Copyright (c) Ian T Nabney (1996-2001) +% David J Evans (1998) + +% Check arguments for consistency +errstring = consist(mixparams, 'mdnmixes'); +if ~isempty(errstring) + error(errstring); +end + +ntarget = size(t, 1); +if ntarget ~= size(mixparams.centres, 1) + error('Number of targets does not match number of mixtures') +end +if size(t, 2) ~= mixparams.dim_target + error('Target dimension does not match mixture dimension') +end + +dim_target = mixparams.dim_target; +ntarget = size(t, 1); + +% Calculate squared norm matrix, of dimension (ndata, ncentres) +% vector (ntarget * ncentres) +dist2 = mdndist2(mixparams, t); + +% Calculate variance factors +variance = 2.*mixparams.covars; + +% Compute the normalisation term +normal = ((2.*pi).*mixparams.covars).^(dim_target./2); + +% Now compute the activations +a = exp(-(dist2./variance))./normal; + +% Accumulate negative log likelihood of targets +prob = mixparams.mixcoeffs.*a; diff --git a/PatRec/NetLab/netlab3_3/mdnunpak.m b/PatRec/NetLab/netlab3_3/mdnunpak.m new file mode 100644 index 0000000..0b88cb7 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/mdnunpak.m @@ -0,0 +1,25 @@ +function net = mdnunpak(net, w) +%MDNUNPAK Separates weights vector into weight and bias matrices. +% +% Description +% NET = MDNUNPAK(NET, W) takes an mdn network data structure NET and a +% weight vector W, and returns a network data structure identical to +% the input network, except that the weights in the MLP sub-structure +% are set to the corresponding elements of W. +% +% See also +% MDN, MDNPAK, MDNFWD, MDNERR, MDNGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) +% David J Evans (1998) + +errstring = consist(net, 'mdn'); +if ~errstring + error(errstring); +end +if net.nwts ~= length(w) + error('Invalid weight vector length') +end + +net.mlp = mlpunpak(net.mlp, w); diff --git a/PatRec/NetLab/netlab3_3/metrop.m b/PatRec/NetLab/netlab3_3/metrop.m new file mode 100644 index 0000000..59fce18 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/metrop.m @@ -0,0 +1,182 @@ +function [samples, energies, diagn] = metrop(f, x, options, gradf, varargin) +%METROP Markov Chain Monte Carlo sampling with Metropolis algorithm. +% +% Description +% SAMPLES = METROP(F, X, OPTIONS) uses the Metropolis algorithm to +% sample from the distribution P ~ EXP(-F), where F is the first +% argument to METROP. The Markov chain starts at the point X and each +% candidate state is picked from a Gaussian proposal distribution and +% accepted or rejected according to the Metropolis criterion. +% +% SAMPLES = METROP(F, X, OPTIONS, [], P1, P2, ...) allows additional +% arguments to be passed to F(). The fourth argument is ignored, but +% is included for compatibility with HMC and the optimisers. +% +% [SAMPLES, ENERGIES, DIAGN] = METROP(F, X, OPTIONS) also returns a log +% of the energy values (i.e. negative log probabilities) for the +% samples in ENERGIES and DIAGN, a structure containing diagnostic +% information (position and acceptance threshold) for each step of the +% chain in DIAGN.POS and DIAGN.ACC respectively. All candidate states +% (including rejected ones) are stored in DIAGN.POS. +% +% S = METROP('STATE') returns a state structure that contains the state +% of the two random number generators RAND and RANDN. These are +% contained in fields randstate, randnstate. +% +% METROP('STATE', S) resets the state to S. If S is an integer, then +% it is passed to RAND and RANDN. If S is a structure returned by +% METROP('STATE') then it resets the generator to exactly the same +% state. +% +% The optional parameters in the OPTIONS vector have the following +% interpretations. +% +% OPTIONS(1) is set to 1 to display the energy values and rejection +% threshold at each step of the Markov chain. If the value is 2, then +% the position vectors at each step are also displayed. +% +% OPTIONS(14) is the number of samples retained from the Markov chain; +% default 100. +% +% OPTIONS(15) is the number of samples omitted from the start of the +% chain; default 0. +% +% OPTIONS(18) is the variance of the proposal distribution; default 1. +% +% See also +% HMC +% + +% Copyright (c) Ian T Nabney (1996-2001) + +if nargin <= 2 + if ~strcmp(f, 'state') + error('Unknown argument to metrop'); + end + switch nargin + case 1 + % Return state of sampler + samples = get_state(f); % Function defined in this module + return; + case 2 + % Set the state of the sampler + set_state(f, x); % Function defined in this module + return; + end +end + +display = options(1); +if options(14) > 0 + nsamples = options(14); +else + nsamples = 100; +end +if options(15) >= 0 + nomit = options(15); +else + nomit = 0; +end +if options(18) > 0.0 + std_dev = sqrt(options(18)); +else + std_dev = 1.0; % default +end +nparams = length(x); + +% Set up string for evaluating potential function. +f = fcnchk(f, length(varargin)); + +samples = zeros(nsamples, nparams); % Matrix of returned samples. +if nargout >= 2 + en_save = 1; + energies = zeros(nsamples, 1); +else + en_save = 0; +end +if nargout >= 3 + diagnostics = 1; + diagn_pos = zeros(nsamples, nparams); + diagn_acc = zeros(nsamples, 1); +else + diagnostics = 0; +end + +% Main loop. +n = - nomit + 1; +Eold = feval(f, x, varargin{:}); % Evaluate starting energy. +nreject = 0; % Initialise count of rejected states. +while n <= nsamples + + xold = x; + % Sample a new point from the proposal distribution + x = xold + randn(1, nparams)*std_dev; + + % Now apply Metropolis algorithm. + Enew = feval(f, x, varargin{:}); % Evaluate new energy. + a = exp(Eold - Enew); % Acceptance threshold. + if (diagnostics & n > 0) + diagn_pos(n,:) = x; + diagn_acc(n,:) = a; + end + if (display > 1) + fprintf(1, 'New position is\n'); + disp(x); + end + + if a > rand(1) % Accept the new state. + Eold = Enew; + if (display > 0) + fprintf(1, 'Finished step %4d Threshold: %g\n', n, a); + end + else % Reject the new state + if n > 0 + nreject = nreject + 1; + end + x = xold; % Reset position + if (display > 0) + fprintf(1, ' Sample rejected %4d. Threshold: %g\n', n, a); + end + end + if n > 0 + samples(n,:) = x; % Store sample. + if en_save + energies(n) = Eold; % Store energy. + end + end + n = n + 1; +end + +if (display > 0) + fprintf(1, '\nFraction of samples rejected: %g\n', ... + nreject/(nsamples)); +end + +if diagnostics + diagn.pos = diagn_pos; + diagn.acc = diagn_acc; +end + +% Return complete state of the sampler. +function state = get_state(f) + +state.randstate = rand('state'); +state.randnstate = randn('state'); +return + +% Set state of sampler, either from full state, or with an integer +function set_state(f, x) + +if isnumeric(x) + rand('state', x); + randn('state', x); +else + if ~isstruct(x) + error('Second argument to metrop must be number or state structure'); + end + if (~isfield(x, 'randstate') | ~isfield(x, 'randnstate')) + error('Second argument to metrop must contain correct fields') + end + rand('state', x.randstate); + randn('state', x.randnstate); +end +return diff --git a/PatRec/NetLab/netlab3_3/minbrack.m b/PatRec/NetLab/netlab3_3/minbrack.m new file mode 100644 index 0000000..31b93c4 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/minbrack.m @@ -0,0 +1,127 @@ +function [br_min, br_mid, br_max, num_evals] = minbrack(f, a, b, fa, ... + varargin) +%MINBRACK Bracket a minimum of a function of one variable. +% +% Description +% BRMIN, BRMID, BRMAX, NUMEVALS] = MINBRACK(F, A, B, FA) finds a +% bracket of three points around a local minimum of F. The function F +% must have a one dimensional domain. A < B is an initial guess at the +% minimum and maximum points of a bracket, but MINBRACK will search +% outside this interval if necessary. The bracket consists of three +% points (in increasing order) such that F(BRMID) < F(BRMIN) and +% F(BRMID) < F(BRMAX). FA is the value of the function at A: it is +% included to avoid unnecessary function evaluations in the +% optimization routines. The return value NUMEVALS is the number of +% function evaluations in MINBRACK. +% +% MINBRACK(F, A, B, FA, P1, P2, ...) allows additional arguments to be +% passed to F +% +% See also +% LINEMIN, LINEF +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check function string +f = fcnchk(f, length(varargin)); + +% Value of golden section (1 + sqrt(5))/2.0 +phi = 1.6180339887499; + +% Initialise count of number of function evaluations +num_evals = 0; + +% A small non-zero number to avoid dividing by zero in quadratic interpolation +TINY = 1.e-10; + +% Maximal proportional step to take: don't want to make this too big +% as then spend a lot of time finding the minimum inside the bracket +max_step = 10.0; + +fb = feval(f, b, varargin{:}); +num_evals = num_evals + 1; + +% Assume that we know going from a to b is downhill initially +% (usually because gradf(a) < 0). +if (fb > fa) + % Minimum must lie between a and b: do golden section until we find point + % low enough to be middle of bracket + c = b; + b = a + (c-a)/phi; + fb = feval(f, b, varargin{:}); + num_evals = num_evals + 1; + while (fb > fa) + c = b; + b = a + (c-a)/phi; + fb = feval(f, b, varargin{:}); + num_evals = num_evals + 1; + end +else + % There is a valid bracket upper bound greater than b + c = b + phi*(b-a); + fc = feval(f, c, varargin{:}); + num_evals = num_evals + 1; + bracket_found = 0; + + while (fb > fc) + % Do a quadratic interpolation (i.e. to minimum of quadratic) + r = (b-a).*(fb-fc); + q = (b-c).*(fb-fa); + u = b - ((b-c)*q - (b-a)*r)/(2.0*(sign(q-r)*max([abs(q-r), TINY]))); + ulimit = b + max_step*(c-b); + + if ((b-u)'*(u-c) > 0.0) + % Interpolant lies between b and c + fu = feval(f, u, varargin{:}); + num_evals = num_evals + 1; + if (fu < fc) + % Have a minimum between b and c + br_min = b; + br_mid = u; + br_max = c; + return; + elseif (fu > fb) + % Have a minimum between a and u + br_min = a; + br_mid = c; + br_max = u; + return; + end + % Quadratic interpolation didn't give a bracket, so take a golden step + u = c + phi*(c-b); + elseif ((c-u)'*(u-ulimit) > 0.0) + % Interpolant lies between c and limit + fu = feval(f, u, varargin{:}); + num_evals = num_evals + 1; + if (fu < fc) + % Move bracket along, and then take a golden section step + b = c; + c = u; + u = c + phi*(c-b); + else + bracket_found = 1; + end + elseif ((u-ulimit)'*(ulimit-c) >= 0.0) + % Limit parabolic u to maximum value + u = ulimit; + else + % Reject parabolic u and use golden section step + u = c + phi*(c-b); + end + if ~bracket_found + fu = feval(f, u, varargin{:}); + num_evals = num_evals + 1; + end + a = b; b = c; c = u; + fa = fb; fb = fc; fc = fu; + end % while loop +end % bracket found +br_mid = b; +if (a < c) + br_min = a; + br_max = c; +else + br_min = c; + br_max = a; +end diff --git a/PatRec/NetLab/netlab3_3/mlp.m b/PatRec/NetLab/netlab3_3/mlp.m new file mode 100644 index 0000000..d1dc1cf --- /dev/null +++ b/PatRec/NetLab/netlab3_3/mlp.m @@ -0,0 +1,92 @@ +function net = mlp(nin, nhidden, nout, outfunc, prior, beta) +%MLP Create a 2-layer feedforward network. +% +% Description +% NET = MLP(NIN, NHIDDEN, NOUT, FUNC) takes the number of inputs, +% hidden units and output units for a 2-layer feed-forward network, +% together with a string FUNC which specifies the output unit +% activation function, and returns a data structure NET. The weights +% are drawn from a zero mean, unit variance isotropic Gaussian, with +% varianced scaled by the fan-in of the hidden or output units as +% appropriate. This makes use of the Matlab function RANDN and so the +% seed for the random weight initialization can be set using +% RANDN('STATE', S) where S is the seed value. The hidden units use +% the TANH activation function. +% +% The fields in NET are +% type = 'mlp' +% nin = number of inputs +% nhidden = number of hidden units +% nout = number of outputs +% nwts = total number of weights and biases +% actfn = string describing the output unit activation function: +% 'linear' +% 'logistic +% 'softmax' +% w1 = first-layer weight matrix +% b1 = first-layer bias vector +% w2 = second-layer weight matrix +% b2 = second-layer bias vector +% Here W1 has dimensions NIN times NHIDDEN, B1 has dimensions 1 times +% NHIDDEN, W2 has dimensions NHIDDEN times NOUT, and B2 has dimensions +% 1 times NOUT. +% +% NET = MLP(NIN, NHIDDEN, NOUT, FUNC, PRIOR), in which PRIOR is a +% scalar, allows the field NET.ALPHA in the data structure NET to be +% set, corresponding to a zero-mean isotropic Gaussian prior with +% inverse variance with value PRIOR. Alternatively, PRIOR can consist +% of a data structure with fields ALPHA and INDEX, allowing individual +% Gaussian priors to be set over groups of weights in the network. Here +% ALPHA is a column vector in which each element corresponds to a +% separate group of weights, which need not be mutually exclusive. The +% membership of the groups is defined by the matrix INDX in which the +% columns correspond to the elements of ALPHA. Each column has one +% element for each weight in the matrix, in the order defined by the +% function MLPPAK, and each element is 1 or 0 according to whether the +% weight is a member of the corresponding group or not. A utility +% function MLPPRIOR is provided to help in setting up the PRIOR data +% structure. +% +% NET = MLP(NIN, NHIDDEN, NOUT, FUNC, PRIOR, BETA) also sets the +% additional field NET.BETA in the data structure NET, where beta +% corresponds to the inverse noise variance. +% +% See also +% MLPPRIOR, MLPPAK, MLPUNPAK, MLPFWD, MLPERR, MLPBKP, MLPGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +net.type = 'mlp'; +net.nin = nin; +net.nhidden = nhidden; +net.nout = nout; +net.nwts = (nin + 1)*nhidden + (nhidden + 1)*nout; + +outfns = {'linear', 'logistic', 'softmax'}; + +if sum(strcmp(outfunc, outfns)) == 0 + error('Undefined output function. Exiting.'); +else + net.outfn = outfunc; +end + +if nargin > 4 + if isstruct(prior) + net.alpha = prior.alpha; + net.index = prior.index; + elseif size(prior) == [1 1] + net.alpha = prior; + else + error('prior must be a scalar or a structure'); + end +end + +net.w1 = randn(nin, nhidden)/sqrt(nin + 1); +net.b1 = randn(1, nhidden)/sqrt(nin + 1); +net.w2 = randn(nhidden, nout)/sqrt(nhidden + 1); +net.b2 = randn(1, nout)/sqrt(nhidden + 1); + +if nargin == 6 + net.beta = beta; +end diff --git a/PatRec/NetLab/netlab3_3/mlpbkp.m b/PatRec/NetLab/netlab3_3/mlpbkp.m new file mode 100644 index 0000000..5e45c8b --- /dev/null +++ b/PatRec/NetLab/netlab3_3/mlpbkp.m @@ -0,0 +1,37 @@ +function g = mlpbkp(net, x, z, deltas) +%MLPBKP Backpropagate gradient of error function for 2-layer network. +% +% Description +% G = MLPBKP(NET, X, Z, DELTAS) takes a network data structure NET +% together with a matrix X of input vectors, a matrix Z of hidden unit +% activations, and a matrix DELTAS of the gradient of the error +% function with respect to the values of the output units (i.e. the +% summed inputs to the output units, before the activation function is +% applied). The return value is the gradient G of the error function +% with respect to the network weights. Each row of X corresponds to one +% input vector. +% +% This function is provided so that the common backpropagation +% algorithm can be used by multi-layer perceptron network models to +% compute gradients for mixture density networks as well as standard +% error functions. +% +% See also +% MLP, MLPGRAD, MLPDERIV, MDNGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Evaluate second-layer gradients. +gw2 = z'*deltas; +gb2 = sum(deltas, 1); + +% Now do the backpropagation. +delhid = deltas*net.w2'; +delhid = delhid.*(1.0 - z.*z); + +% Finally, evaluate the first-layer gradients. +gw1 = x'*delhid; +gb1 = sum(delhid, 1); + +g = [gw1(:)', gb1, gw2(:)', gb2]; diff --git a/PatRec/NetLab/netlab3_3/mlpderiv.m b/PatRec/NetLab/netlab3_3/mlpderiv.m new file mode 100644 index 0000000..9dd96c0 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/mlpderiv.m @@ -0,0 +1,47 @@ +function g = mlpderiv(net, x) +%MLPDERIV Evaluate derivatives of network outputs with respect to weights. +% +% Description +% G = MLPDERIV(NET, X) takes a network data structure NET and a matrix +% of input vectors X and returns a three-index matrix G whose I, J, K +% element contains the derivative of network output K with respect to +% weight or bias parameter J for input pattern I. The ordering of the +% weight and bias parameters is defined by MLPUNPAK. +% +% See also +% MLP, MLPPAK, MLPGRAD, MLPBKP +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check arguments for consistency +errstring = consist(net, 'mlp', x); +if ~isempty(errstring); + error(errstring); +end + +[y, z] = mlpfwd(net, x); + +ndata = size(x, 1); + +if isfield(net, 'mask') + nwts = size(find(net.mask), 1); + temp = zeros(1, net.nwts); +else + nwts = net.nwts; +end + +g = zeros(ndata, nwts, net.nout); +for k = 1 : net.nout + delta = zeros(1, net.nout); + delta(1, k) = 1; + for n = 1 : ndata + if isfield(net, 'mask') + temp = mlpbkp(net, x(n, :), z(n, :), delta); + g(n, :, k) = temp(logical(net.mask)); + else + g(n, :, k) = mlpbkp(net, x(n, :), z(n, :),... + delta); + end + end +end diff --git a/PatRec/NetLab/netlab3_3/mlperr.m b/PatRec/NetLab/netlab3_3/mlperr.m new file mode 100644 index 0000000..7e3efe4 --- /dev/null +++ b/PatRec/NetLab/netlab3_3/mlperr.m @@ -0,0 +1,62 @@ +function [e, edata, eprior] = mlperr(net, x, t) +%MLPERR Evaluate error function for 2-layer network. +% +% Description +% E = MLPERR(NET, X, T) takes a network data structure NET together +% with a matrix X of input vectors and a matrix T of target vectors, +% and evaluates the error function E. The choice of error function +% corresponds to the output unit activation function. Each row of X +% corresponds to one input vector and each row of T corresponds to one +% target vector. +% +% [E, EDATA, EPRIOR] = MLPERR(NET, X, T) additionally returns the data +% and prior components of the error, assuming a zero mean Gaussian +% prior on the weights with inverse variance parameters ALPHA and BETA +% taken from the network data structure NET. +% +% See also +% MLP, MLPPAK, MLPUNPAK, MLPFWD, MLPBKP, MLPGRAD +% + +% Copyright (c) Ian T Nabney (1996-2001) + +% Check arguments for consistency +errstring = consist(net, 'mlp', x, t); +if ~isempty(errstring); + error(errstring); +end +[y, z, a] = mlpfwd(net, x); + +switch net.outfn + + case 'linear' % Linear outputs + edata = 0.5*sum(sum((y - t).^2)); + + case 'logistic' % Logistic outputs + % Ensure that log(1-y) is computable: need exp(a) > eps + maxcut = -log(eps); + % Ensure that log(y) is computable + mincut = -log(1/realmin - 1); + a = min(a, maxcut); + a = max(a, mincut); + y = 1./(1 + exp(-a)); + edata = - sum(sum(t.*log(y) + (1 - t).*log(1 - y))); + + case 'softmax' % Softmax outputs + nout = size(a,2); + % Ensure that sum(exp(a), 2) does not overflow + maxcut = log(realmax) - log(nout); + % Ensure that exp(a) > 0 + mincut = log(realmin); + a = min(a, maxcut); + a = max(a, mincut); + temp = exp(a); + y = temp./(sum(temp, 2)*ones(1,nout)); + % Ensure that log(y) is computable + y(y