├── Data └── Colorbar_Tsao.mat ├── Subfunctions ├── fun_FSI.m ├── fun_InvRange_ImgCorr.m ├── fun_IntraInterSI.m ├── fun_ResZscoreRe.m ├── fun_FindNeuron.m ├── fun_ResZscore.m ├── fun_InvRange_Resp.m ├── fun_Initializeweight.m ├── toolbox_chk.m ├── fun_SVM.m └── shadedErrorBar.m ├── LICENSE ├── README.md ├── Run_Trained.m ├── Run_Invariance.m ├── Main.m ├── Run_SVM.m ├── Run_View.m ├── Run_PFI.m └── Run_Unit.m /Data/Colorbar_Tsao.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cogilab/Face/HEAD/Data/Colorbar_Tsao.mat -------------------------------------------------------------------------------- /Subfunctions/fun_FSI.m: -------------------------------------------------------------------------------- 1 | function [d] = fun_FSI(rep) 2 | % idx_nan = find(isnan(sum(mean(rep,3),2))); rep(idx_nan,:,:) = []; 3 | 4 | d = zeros(size(rep,1),1); 5 | for ii = 1:size(d,1) 6 | [~,indOrder] = sort(mean(rep(ii,:,:),3),'descend'); 7 | d(ii) = (mean(rep(ii,1,:),3)-mean(rep(ii,indOrder(2),:),3))./sqrt((std(rep(ii,1,:),[],3).^2+std(rep(ii,indOrder(2),:),[],3).^2)./2); 8 | end 9 | end -------------------------------------------------------------------------------- /Subfunctions/fun_InvRange_ImgCorr.m: -------------------------------------------------------------------------------- 1 | function [corr_mat,corr_cont_mat] = fun_InvRange_ImgCorr(IMG_var,cls_idx) 2 | 3 | class_idx = cls_idx == 1; 4 | IMG_cls = squeeze(IMG_var(:,:,1,class_idx)); 5 | corr_mat = zeros(200,13); 6 | corr_cont_mat = zeros(200,13); 7 | for ii = 1:200 8 | IMG_cen = IMG_cls(:,:,(ii-1)*13+7); 9 | 10 | IMG_cont = squeeze(IMG_var(:,:,1,cls_idx ==(randi(4)+1))); 11 | for vv = 1:13 12 | IMG_temp = IMG_cls(:,:,(ii-1)*13+vv); 13 | corr_temp = corrcoef(IMG_cen,IMG_temp); 14 | corr_mat(ii,vv) = corr_temp(1,2); 15 | 16 | IMG_temp = IMG_cont(:,:,(randi(200)-1)*13+vv); 17 | corr_temp = corrcoef(IMG_cen,IMG_temp); 18 | corr_cont_mat(ii,vv) = corr_temp(1,2); 19 | end 20 | end 21 | 22 | end 23 | 24 | -------------------------------------------------------------------------------- /Subfunctions/fun_IntraInterSI.m: -------------------------------------------------------------------------------- 1 | function [array_Intra,array_Inter,array_Sindex] = fun_IntraInterSI(Y,numCLS,numIMG,labels) 2 | array_Intra = zeros(numCLS,numIMG); 3 | array_Inter = zeros(numCLS,numIMG); 4 | array_Sindex = zeros(numCLS,numIMG); 5 | 6 | for cc = 1:numCLS 7 | restClass = setdiff([1:numCLS],cc); 8 | tmpintra = find(labels == cc); 9 | for ii = 1:numIMG 10 | intra = setdiff(tmpintra,ii); 11 | array_Intra(cc,ii) = mean(sqrt((Y(intra,1)-Y(ii,1)).^2+(Y(intra,2)-Y(ii,2)).^2)); 12 | %% raw image 13 | interD = []; 14 | for ccc = 1:length(restClass) 15 | inter = find(double(labels) == restClass(ccc)); 16 | interD = [interD; mean(sqrt((Y(inter,1)-Y(ii,1)).^2+(Y(inter,2)-Y(ii,2)).^2))]; 17 | end 18 | array_Inter(cc,ii) = min(interD); 19 | array_Sindex(cc,ii) = (array_Inter(cc,ii)-array_Intra(cc,ii))./max(array_Intra(cc,ii),array_Inter(cc,ii)); 20 | end 21 | end 22 | end -------------------------------------------------------------------------------- /Subfunctions/fun_ResZscoreRe.m: -------------------------------------------------------------------------------- 1 | function [resp_obj_z,resp_obj_z_3D] = fun_ResZscoreRe(resp_reshape,face_idx,numCLS,numIMG) 2 | resp_obj = resp_reshape(face_idx,1:numCLS*numIMG); 3 | resp_obj_3D = zeros(length(face_idx),numCLS,numIMG); 4 | for ii = 1:numCLS 5 | resp_obj_ii = resp_obj(:,(ii-1)*numIMG+1:numIMG*ii); 6 | resp_obj_3D(:,ii,:) = resp_obj_ii; 7 | end 8 | 9 | resp_obj_z = zeros(length(face_idx),numCLS*numIMG); 10 | resp_obj_z_3D = zeros(length(face_idx),numCLS,numIMG); 11 | resp_obj_max_z = zeros(length(face_idx),numIMG); 12 | for ii = 1:length(face_idx) 13 | resp_obj_ii = resp_obj(ii,:); 14 | resp_obj_3D_ii = squeeze(resp_obj_3D(ii,:,:)); 15 | [~,max_obj_idx] = max(mean(resp_obj_3D_ii(2:end,:),2)); 16 | norm_mean = mean(resp_obj_3D_ii(max_obj_idx+1,:)); 17 | norm_std = std(resp_obj_3D_ii(max_obj_idx+1,:)); 18 | resp_obj_z(ii,:) = (resp_obj_ii-norm_mean)/norm_std; 19 | resp_obj_z_3D(ii,:,:) = (resp_obj_3D_ii-norm_mean)/norm_std; 20 | resp_obj_max_z(ii,:) = (resp_obj_3D_ii(max_obj_idx+1,:)-norm_mean)/norm_std; 21 | end 22 | end -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 vsnnlab 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Subfunctions/fun_FindNeuron.m: -------------------------------------------------------------------------------- 1 | function [cell_idx] = fun_FindNeuron(act_rand,num_cell,numCLS,numIMG,pThr,indClass) 2 | 3 | act_reshape = reshape(act_rand,num_cell,numCLS*numIMG); 4 | act_3D = zeros(num_cell,numCLS,numIMG); 5 | 6 | for cc = 1:numCLS 7 | act_3D(:,cc,:) = act_reshape(:,(cc-1)*numIMG+1:cc*numIMG); 8 | end 9 | 10 | pref_class = zeros(num_cell,1); 11 | sel_p_val = zeros(num_cell,1); 12 | 13 | for cc = 1:num_cell 14 | mean_FR = []; 15 | for cls = 1:numCLS 16 | mean_FR = [mean_FR,mean(act_reshape(cc,(cls-1)*numIMG+1:cls*numIMG))]; 17 | end 18 | 19 | [~,sort_ind] = sort(mean_FR,'descend'); 20 | pref_class(cc) = sort_ind(1); 21 | 22 | resp1 = act_reshape(cc,(sort_ind(1)-1)*numIMG+1:numIMG*sort_ind(1)); 23 | pval_temp = []; 24 | for ee = 2:numCLS 25 | resp2 = act_reshape(cc,(sort_ind(ee)-1)*numIMG+1:numIMG*sort_ind(ee)); 26 | pval_temp(ee-1) = ranksum(resp1,resp2); 27 | end 28 | sel_p_val(cc) = max(pval_temp); 29 | end 30 | 31 | for ii = indClass 32 | cell_idx = find((pref_class==ii) & (sel_p_val= 2017; 15 | else 16 | release_chk_matlab = false; 17 | end 18 | 19 | if isempty(Index_matlab) || ~release_chk_matlab 20 | warning('MATLAB must be upgraded to version R2017a or above') 21 | end 22 | 23 | Index_vision = find(contains(toolbox_names,'Deep Learning Toolbox')); 24 | if ~isempty(Index_vision) 25 | release_yr_vision=str2double(regexp(toolbox_Release{Index_vision},'\d+','match')); 26 | release_chk_vision = release_yr_vision >= 2017; 27 | else 28 | release_chk_vision = false; 29 | end 30 | 31 | if isempty(Index_vision) || ~release_chk_vision 32 | disp('Deep Learning Toolbox must be installed or upgraded to version R2017a or above','r') 33 | disp('INSTALLATION INSTRUCTIONS') 34 | disp(' 1. You can download Deep Learning Toolbox at https://www.mathworks.com/products/deep-learning.html') 35 | disp(' 2. You can download Deep Learning Toolbox in Matlab add-on manager') 36 | disp(' - Go to the Home tabr') 37 | disp(' - Click add-on icon') 38 | disp(' - Search and download Deep Learning Toolbox Model for AlexNet Network') 39 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Demo codes for 2 | ### "Face Detection in Untrained Deep Neural Networks"
3 | 4 | Seungdae Baek, Min Song, Jaeson Jang, Gwangsu Kim, and Se-Bum Paik* 5 | 6 | *Contact: sbpaik@kaist.ac.kr 7 | 8 | ### 1. System requirements 9 | - MATLAB 2019b or later version 10 | - Installation of the Deep Learning Toolbox (https://www.mathworks.com/products/deep-learning.html) 11 | - Installation of the pretrained AlexNet (https://de.mathworks.com/matlabcentral/fileexchange/59133-deep-learning-toolbox-model-for-alexnet-network) 12 | - No non-standard hardware is required. 13 | - Uploaded codes were tested using MATLAB 2019b. 14 | 15 | ### 2. Installation 16 | - Download all files and folders. ("Clone or download" -> "Download ZIP") 17 | - Download 'Data.zip', 'Stimulus.zip' from below link and unzip files in the same directory 18 | - [Data URL] : https://doi.org/10.5281/zenodo.5637812 19 | - Expected Installation time is about 45 minutes, but may vary by system conditions. 20 | 21 | ### 3. Instructions for demo 22 | - Run "Main.m" and select result numbers (from 1 to 6) that you want to perform a demo simulation. 23 | - Expected running time is about 5 minutes for each figure, but may vary by system conditions. 24 | 25 | ### 4. Expected output for demo 26 | - Below results for untrained AlexNet will be shown. 27 | - Result 1) Run_Unit: Spontaneous emergence of face-selectivity in untrained networks (Fig.1, Fig.S1-3) 28 | - Result 2) Run_PFI: Preferred feature images of face-selective units in untrained networks (Fig.2, Fig.S4) 29 | - Result 3) Run_SVM: Detection of face images using the response of face units in untrained networks (Fig.3, Fig.S11-12) 30 | - Result 4) Run_Trained: Effect of training on face-selectivity in untrained networks (Fig.4) 31 | - Result 5) Run_Invariance: Invariant characteristics of face-selective units in untrained networks (Fig.S5) 32 | - Result 6) Run_View: Viewpoint invariance of face-selective units in untrained networks (Fig.S8) 33 | -------------------------------------------------------------------------------- /Subfunctions/fun_SVM.m: -------------------------------------------------------------------------------- 1 | function [array_SVM_face_multi,array_SVM_face_multi_shuf] = fun_SVM(net_rand,num_cell,IND_Face,IMG_cell,idx_mat,layersSet,indLayer,numNeuron) 2 | 3 | numIMGtot = 120; idx_class = [1,2,3,5,6,7]; 4 | IMG = zeros(227,227,3,numIMGtot); 5 | for cc = 1:6 6 | IMG_mat = IMG_cell{idx_class(cc),1}(:,:,idx_mat{idx_class(cc),2}); 7 | IMG_mat = repmat(permute(IMG_mat,[1 2 4 3]),[1 1 3 1]); 8 | switch cc 9 | case 1 10 | idx_IMG = 1:numIMGtot/2; 11 | IMG(:,:,:,idx_IMG) = IMG_mat(:,:,:,randperm(size(IMG_mat,4),numIMGtot/2)); 12 | otherwise 13 | idx_IMG = numIMGtot/(2*5)*(cc-2)+1:numIMGtot/(2*5)*(cc-1); idx_IMG = idx_IMG+numIMGtot/2; 14 | IMG(:,:,:,idx_IMG) = IMG_mat(:,:,:,randperm(size(IMG_mat,4),numIMGtot/(2*5))); 15 | end 16 | end 17 | IMG = single(IMG); 18 | 19 | %% SVM 20 | reN = 1; 21 | ratio_Tr_Te = 3; 22 | numFace_ratio = 1; 23 | array_ratio = [numNeuron]; 24 | 25 | % multiple neuron (305 neurons) 26 | array_SVM_face_multi = zeros(reN,numFace_ratio); 27 | array_SVM_face_multi_shuf = zeros(reN,numFace_ratio); 28 | % split train / test 29 | iFace = [1:numIMGtot/2]; iObject = [numIMGtot/2+1:numIMGtot]; iObject = iObject(randperm(length(iObject))); 30 | iFaceTrain = iFace(randperm(numIMGtot/2,numIMGtot/2/ratio_Tr_Te*2)); iFaceTest = setdiff(iFace,iFaceTrain); 31 | iObjectTrain = iObject(randperm(numIMGtot/2,numIMGtot/2/ratio_Tr_Te*2)); iObjectTest = setdiff(iObject,iObjectTrain); 32 | 33 | indTrain = [iFaceTrain';iObjectTrain']; indTest = [iFaceTest';iObjectTest']; 34 | YTrain = [ones(numIMGtot/2/ratio_Tr_Te*2,1); zeros(numIMGtot/2/ratio_Tr_Te*2,1)]; 35 | YTest = [ones(numIMGtot/2/ratio_Tr_Te,1); zeros(numIMGtot/2/ratio_Tr_Te,1)]; 36 | 37 | % response 38 | act_rand = activations(net_rand,IMG,layersSet{indLayer}); 39 | act = reshape(act_rand,num_cell,size(IMG,4)); 40 | 41 | XTrain1 = act(IND_Face,indTrain); XTest1 = act(IND_Face,indTest); 42 | sXTrain1 = reshape(XTrain1(randperm(length(IND_Face)*length(indTrain))),[length(IND_Face),length(indTrain)]); 43 | %% Multiple neuron SVM 44 | for ii = 1:numFace_ratio 45 | tmpN = array_ratio(ii); 46 | % disp([' # neuron =',num2str(tmpN)]) 47 | for rr = 1:reN 48 | ind_f = randperm(length(IND_Face),tmpN); 49 | Mdl = fitcecoc(XTrain1(ind_f,:)',YTrain); 50 | YPredict = predict(Mdl,XTest1(ind_f,:)'); 51 | array_SVM_face_multi(rr,ii) = length(find(YTest == YPredict))./length(YTest); 52 | 53 | Mdl = fitcecoc(sXTrain1(ind_f,:)',YTrain); 54 | YPredict = predict(Mdl,XTest1(ind_f,:)'); 55 | array_SVM_face_multi_shuf(rr,ii) = length(find(YTest == YPredict))./length(YTest); 56 | end 57 | end 58 | end -------------------------------------------------------------------------------- /Run_Trained.m: -------------------------------------------------------------------------------- 1 | %% Effect of training on face-selectivity in untrained networks (Fig.4) 2 | addpath('Data\PretrainedNet') 3 | load('orderNetdesceding.mat') 4 | load('IMG_cntr_210521.mat','IMG_cell','idx_mat') 5 | 6 | %% Analysis for training effect (Fig 6b-f) 7 | NN_type = 4; % number of types of networks. 1: "Untrained", 2: "Face-deprived", 3: "Original", 4: "Face" 8 | 9 | if SimER == 1 10 | NN_trained = 3; % number of trained networks used in the anaylsis, N = 10 in the manuscript 11 | reN = 10; % number of repetition for SVM training, N = 100 in the manuscript 12 | num_minTotal = 100; % number of randomly sampled units, all units was used in the manuscript 13 | 14 | Cell_Idx_trained = cell(NN_type,NN_trained); 15 | Cell_FSI_trained = cell(NN_type,NN_trained); 16 | Cell_SVM_trained = cell(NN_type,NN_trained); 17 | 18 | %% Training effect of face-units (Fig 6b-d) 19 | for nn = 1:NN_trained 20 | tic 21 | disp(['Trial',num2str(nn),' - Net',num2str(orderNetdesceding(nn))]) 22 | for tt = 1:NN_type 23 | %% Load networks 24 | switch tt 25 | case 1 26 | disp('Untrained') 27 | dirNet = 'Data\PretrainedNet\Net_Untrained'; 28 | load([dirNet,'\Net_N',num2str(orderNetdesceding(nn)),'_std1.mat'],'net_rand'); 29 | act_rand = activations(net_rand,IMG_ORI,layersSet{length(layerArray)}); 30 | 31 | case 2 32 | disp('Face-deprived') 33 | dirNet = 'Data\PretrainedNet\Net_FD_ImageNet'; 34 | load([dirNet,'\Result_ImageNet_FD_Net',num2str(orderNetdesceding(nn)),'_210106.mat'],'net'); net_rand = net; 35 | act_rand = activations(net_rand,IMG_ORI,layersSet{length(layerArray)}); 36 | 37 | case 3 38 | disp('Original') 39 | dirNet = 'Data\PretrainedNet\Net_ImageNet'; 40 | load([dirNet,'\Result_ImageNet_Net',num2str(orderNetdesceding(nn)),'_210106.mat'],'net'); net_rand = net; 41 | act_rand = activations(net_rand,IMG_ORI,layersSet{length(layerArray)}); 42 | 43 | case 4 44 | disp('ImageNet+Face') 45 | dirNet = 'Data\PretrainedNet\Net_ImageNetwFace'; 46 | load([dirNet,'\Result_ImageNetwFace_Net',num2str(orderNetdesceding(nn)),'_210106.mat'],'net'); net_rand = net; 47 | act_rand = activations(net_rand,IMG_ORI,layersSet{length(layerArray)}); 48 | end 49 | 50 | %% Find face units 51 | num_cell = prod(array_sz(layerArray(length(layerArray)),:)); 52 | [cell_idx] = fun_FindNeuron(act_rand,num_cell,numCLS,numIMG,pThr,idxClass); 53 | Cell_Idx_trained{tt,nn} = cell_idx; 54 | 55 | %% Caculate face-selectivity 56 | [~,rep_mat_3D] = fun_ResZscore(act_rand,num_cell,cell_idx,numCLS,numIMG); 57 | fsi_mat = fun_FSI(rep_mat_3D); 58 | Cell_FSI_trained{tt,nn} = fsi_mat; 59 | 60 | %% Perform face detection task 61 | array_SVM = zeros(reN,1); 62 | for rr = 1:reN 63 | [array_SVM(rr),~] = fun_SVM(net_rand,num_cell,cell_idx,IMG_cell,idx_mat,layersSet,length(layerArray),num_minTotal); 64 | end 65 | Cell_SVM_trained{tt,nn} = array_SVM; 66 | end 67 | toc 68 | end 69 | clearvars IMG_cell idx_mat 70 | 71 | array_num = zeros(NN_trained,NN_type); 72 | array_fsi = zeros(NN_trained,NN_type); 73 | array_svm = zeros(NN_trained,NN_type); 74 | 75 | for nn = 1:NN_trained 76 | for tt = 1:NN_type 77 | array_num(nn,tt) = length(Cell_Idx_trained{tt,nn}); 78 | array_fsi(nn,tt) = nanmean(Cell_FSI_trained{tt,nn}); 79 | array_svm(nn,tt) = mean(Cell_SVM_trained{tt,nn}); 80 | end 81 | end 82 | end 83 | 84 | if SimER == 0 85 | load('Data_Trained.mat') 86 | end 87 | 88 | figure('units','normalized','outerposition',[0 0.5 1 0.5]); drawnow 89 | sgtitle('Effect of training on face-selectivity in untrained networks (Fig 4b-d)') 90 | subplot(2,6,[1,2,7,8]) 91 | boxplot([array_fsi(:,1),array_fsi(:,2),array_fsi(:,3),array_fsi(:,4)]) 92 | xticks([1:4]); ylim([0.3 0.5]) 93 | xticklabels({'Untrained','Face-deprived','Original','Face'}); ylabel('Face-selectivity index'); 94 | 95 | subplot(2,6,[3,4,9,10]) 96 | boxplot([array_num(:,1),array_num(:,2),array_num(:,3),array_num(:,4)]) 97 | xticks([1:4]); ylim([100 600]) 98 | xticklabels({'Untrained','Face-deprived','Original','Face'}); ylabel('Number of face units'); 99 | 100 | subplot(2,6,[5,6,11,12]) 101 | boxplot([array_svm(:,1),array_svm(:,2),array_svm(:,3),array_svm(:,4)]) 102 | xticks([1:4]); ylim([0.85 1.05]) 103 | xticklabels({'Untrained','Face-deprived','Original','Face'}); ylabel('Correct ratio'); 104 | -------------------------------------------------------------------------------- /Run_Invariance.m: -------------------------------------------------------------------------------- 1 | %% Invariant characteristics of face-selective units in untrained networks (Fig.S5,7) 2 | 3 | %% Analysis for invariance to image variation (Fig.S5a-f) 4 | net_rand = Cell_Net{1,1,1}; % untrained AlexNet 5 | Idx_Face = Cell_Idx{1,1,1,length(layerArray)}; % indices of face units in the untrained AlexNet 6 | num_cell = prod(array_sz(layerArray(length(layerArray)),:)); 7 | 8 | Cell_var_axis = cell(TT,1); 9 | Cell_resp = cell(TT,1); 10 | Cell_face_resp = cell(TT,1); 11 | Cell_nonface_resp = cell(TT,1); 12 | 13 | StrTitle = {'Translation','Scaling','Rotation'}; 14 | StrUnit = {'r_R_F','%','deg'}; 15 | arrayXlim = [-1.5, 0, -200;1.5, 250, 200]; 16 | StrXlabel = {'Translation (r_R_F)','Face size change (%)','Rotation (deg)'}; 17 | arrayYlim = [3, 300, 400]; 18 | StrYlabel = {'Effective range (r_R_F)','Effective range (%)','Effective range (deg)'}; 19 | 20 | for vtype = 1:TT 21 | tic 22 | %% Load feature variant stimulus set 23 | switch vtype 24 | case 1 25 | disp('Position') 26 | load('IMG_var_pos_210521.mat'); IMG_var = single(repmat(permute(IMG_pos,[1 2 4 3]),[1 1 3])); clearvars IMG_pos 27 | var_idx = pos_idx; clearvars pos_idx 28 | RF_size = 163/2; 29 | var_axis = (-120:20:120)/RF_size; 30 | case 2 31 | disp('Size') 32 | load('IMG_var_size_210521.mat'); IMG_var = single(repmat(permute(IMG_size,[1 2 4 3]),[1 1 3])); clearvars IMG_size 33 | var_idx = size_idx; clearvars size_idx 34 | RF_size = 163; 35 | var_axis = (41:25:341)/RF_size*100; 36 | case 3 37 | disp('Rotation') 38 | load('IMG_var_rot_210521.mat'); IMG_var = single(repmat(permute(IMG_rot,[1 2 4 3]),[1 1 3])); clearvars IMG_rot 39 | var_idx = rot_idx; clearvars rot_idx 40 | RF_size = 1; 41 | var_axis = -180:30:180; 42 | end 43 | Cell_var_axis{vtype} = var_axis; 44 | 45 | %% Measure network response 46 | act_rand = activations(net_rand,IMG_var,layersSet{layerArray(length(layerArray))}); 47 | act_re = reshape(act_rand,num_cell,size(IMG_var,4)); 48 | act_face = act_re(Idx_Face,:); 49 | num_face_cell = size(Idx_Face,1); 50 | clearvars act_rand act_re 51 | 52 | %% Measure effective range 53 | [resp_z_mat,face_resp_z_mat,max_resp_z_mat] = fun_InvRange_Resp(act_face,num_face_cell,cls_idx,var_idx); 54 | 55 | Cell_resp{vtype} = resp_z_mat; 56 | Cell_face_resp{vtype} = face_resp_z_mat; 57 | Cell_nonface_resp{vtype} = max_resp_z_mat; 58 | 59 | %% Plot figure for each image variation 60 | figure('units','normalized','outerposition',[0 0 1 1]); drawnow 61 | sgtitle(['Invariant charateristics of face units (',StrTitle{vtype},') (Fig.S5)']) 62 | 63 | % stimulus (Fig.S5a) 64 | pos_subplot = [1:5]; pos_img = linspace(1,13,5); img_idx = find(cls_idx == 1); 65 | for ii = 1:5 66 | subplot(4,5,pos_subplot(ii)); imagesc(IMG_var(:,:,1,img_idx(pos_img(ii)))); axis image off; colormap(gray); 67 | end 68 | pos_subplot = [6:10]; pos_img = linspace(1,13,5); img_idx = find(cls_idx == 5); 69 | for ii = 1:5 70 | subplot(4,5,pos_subplot(ii)); imagesc(IMG_var(:,:,1,img_idx(pos_img(ii)))); axis image off; colormap(gray); 71 | switch vtype 72 | case 1 73 | title([num2str(round(Cell_var_axis{vtype}(pos_img(ii)),1)),' ',StrUnit{vtype}]) 74 | otherwise 75 | title([num2str(round(Cell_var_axis{vtype}(pos_img(ii)),0)),' ',StrUnit{vtype}]) 76 | end 77 | end 78 | 79 | % face tuning curve (Fig.S5b) 80 | resp_cat_mat = squeeze(nanmean(Cell_resp{vtype},1)); 81 | pos_img = [7,10,13]; 82 | subplot(4,5,[11 12 16 17]); hold on 83 | s1 = plot([0 1 2 3 4 5 6],[0 mean(resp_cat_mat(:,:,pos_img(1))) 0],'color',[1 0 0]); 84 | s2 = plot([0 1 2 3 4 5 6],[0 mean(resp_cat_mat(:,:,pos_img(2))) 0],'color',[1 0 1]); 85 | s3 = plot([0 1 2 3 4 5 6],[0 mean(resp_cat_mat(:,:,pos_img(3))) 0],'color',[0 0 1]); 86 | xticks([1:numCLS-1]); xlim([0.5 numCLS-1+0.5]); xticklabels(STR_LABEL); 87 | Str_leg = cell(1,3); 88 | switch vtype 89 | case 1 90 | for ii = 1:3 91 | Str_leg{ii} = [num2str(round(Cell_var_axis{vtype}(pos_img(ii)),1)),' ',StrUnit{vtype}]; 92 | end 93 | otherwise 94 | for ii = 1:3 95 | Str_leg{ii} = [num2str(round(Cell_var_axis{vtype}(pos_img(ii)),0)),' ',StrUnit{vtype}]; 96 | end 97 | end 98 | legend([s1,s2,s3],Str_leg,'Location','southeast'); ylabel('Response (z-scored)'); 99 | title('Face tuning curve (Fig.S5b)') 100 | 101 | % Response of face units to image variation (Fig.S5c-d) 102 | subplot(4,5,[14 15 19 20]); hold on 103 | face_resp_z_mat = Cell_face_resp{vtype}; 104 | max_resp_z_mat = Cell_nonface_resp{vtype}; 105 | 106 | face_resp_z_mat(face_resp_z_mat==inf) = nan; 107 | face_resp_z_mean = squeeze(nanmean(face_resp_z_mat,1)); 108 | max_resp_z_mean = squeeze(nanmean(max_resp_z_mat,1)); 109 | 110 | shadedErrorBar(Cell_var_axis{vtype},nanmean(face_resp_z_mean,2),nanstd(face_resp_z_mean,[],2)./sqrt(10),'lineprops','r'); 111 | shadedErrorBar(Cell_var_axis{vtype},nanmean(max_resp_z_mean,2),nanstd(max_resp_z_mean,[],2)./sqrt(10),'lineprops','k'); 112 | s1 = plot(Cell_var_axis{vtype},nanmean(face_resp_z_mean,2),'color',[1 0 0]); 113 | s2 = plot(Cell_var_axis{vtype},nanmean(max_resp_z_mean,2),'color',[0 0 0]); 114 | xlim([arrayXlim(1,vtype),arrayXlim(2,vtype)]); ylim([-0.4 1.2]); xlabel(StrXlabel{vtype}); ylabel('Response (z-scored)') 115 | title('Response of face units (Fig.S5c,d)'); legend([s1,s2],{'Face stimulus','Non-face stimulus'},'Location','northeast') 116 | 117 | clearvars IMG_cls IMG_var 118 | toc 119 | end -------------------------------------------------------------------------------- /Subfunctions/shadedErrorBar.m: -------------------------------------------------------------------------------- 1 | function varargout=shadedErrorBar(x,y,errBar,varargin) 2 | % generate continuous error bar area around a line plot 3 | % 4 | % function H=shadedErrorBar(x,y,errBar, ...) 5 | % 6 | % Purpose 7 | % Makes a 2-d line plot with a pretty shaded error bar made 8 | % using patch. Error bar color is chosen automatically. 9 | % 10 | % 11 | % Inputs (required) 12 | % x - vector of x values [optional, can be left empty] 13 | % y - vector of y values or a matrix of n observations by m cases 14 | % where m has length(x); 15 | % errBar - if a vector we draw symmetric errorbars. If it has a size 16 | % of [2,length(x)] then we draw asymmetric error bars with 17 | % row 1 being the upper bar and row 2 being the lower bar 18 | % (with respect to y -- see demo). ** alternatively ** 19 | % errBar can be a cellArray of two function handles. The 20 | % first defines statistic the line should be and the second 21 | % defines the error bar. 22 | % 23 | % Inputs (optional, param/value pairs) 24 | % 'lineProps' - ['-k' by default] defines the properties of 25 | % the data line. e.g.: 26 | % 'or-', or {'-or','markerfacecolor',[1,0.2,0.2]} 27 | % 'transparent' - [true by default] if true, the shaded error 28 | % bar is made transparent. However, for a transparent 29 | % vector image you will need to save as PDF, not EPS, 30 | % and set the figure renderer to "painters". An EPS 31 | % will only be transparent if you set the renderer 32 | % to OpenGL, however this makes a raster image. 33 | % 'patchSaturation'- [0.2 by default] The saturation of the patch color. 34 | % 35 | % 36 | % 37 | % Outputs 38 | % H - a structure of handles to the generated plot objects. 39 | % 40 | % 41 | % Examples: 42 | % y=randn(30,80); 43 | % x=1:size(y,2); 44 | % 45 | % 1) 46 | % shadedErrorBar(x,mean(y,1),std(y),'lineprops','g'); 47 | % 48 | % 2) 49 | % shadedErrorBar(x,y,{@median,@std},'lineprops',{'r-o','markerfacecolor','r'}); 50 | % 51 | % 3) 52 | % shadedErrorBar([],y,{@median,@(x) std(x)*1.96},'lineprops',{'r-o','markerfacecolor','k'}); 53 | % 54 | % 4) 55 | % Overlay two transparent lines: 56 | % clf 57 | % y=randn(30,80)*10; 58 | % x=(1:size(y,2))-40; 59 | % shadedErrorBar(x,y,{@mean,@std},'lineprops','-r','transparent',1); 60 | % hold on 61 | % y=ones(30,1)*x; y=y+0.06*y.^2+randn(size(y))*10; 62 | % shadedErrorBar(x,y,{@mean,@std},'lineprops','-b','transparent',1); 63 | % hold off 64 | % 65 | % 66 | % Rob Campbell - November 2009 67 | 68 | 69 | 70 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 71 | % Parse input arguments 72 | narginchk(3,inf) 73 | 74 | params = inputParser; 75 | params.CaseSensitive = false; 76 | params.addParameter('lineProps', '-k', @(x) ischar(x) | iscell(x)); 77 | params.addParameter('transparent', true, @(x) islogical(x) || x==0 || x==1); 78 | params.addParameter('patchSaturation', 0.2, @(x) isnumeric(x) && x>=0 && x<=1); 79 | 80 | params.parse(varargin{:}); 81 | 82 | %Extract values from the inputParser 83 | lineProps = params.Results.lineProps; 84 | transparent = params.Results.transparent; 85 | patchSaturation = params.Results.patchSaturation; 86 | 87 | if ~iscell(lineProps), lineProps={lineProps}; end 88 | 89 | 90 | %Process y using function handles if needed to make the error bar dynamically 91 | if iscell(errBar) 92 | fun1=errBar{1}; 93 | fun2=errBar{2}; 94 | errBar=fun2(y); 95 | y=fun1(y); 96 | else 97 | y=y(:).'; 98 | end 99 | 100 | if isempty(x) 101 | x=1:length(y); 102 | else 103 | x=x(:).'; 104 | end 105 | 106 | 107 | %Make upper and lower error bars if only one was specified 108 | if length(errBar)==length(errBar(:)) 109 | errBar=repmat(errBar(:)',2,1); 110 | else 111 | s=size(errBar); 112 | f=find(s==2); 113 | if isempty(f), error('errBar has the wrong size'), end 114 | if f==2, errBar=errBar'; end 115 | end 116 | 117 | if length(x) ~= length(errBar) 118 | error('length(x) must equal length(errBar)') 119 | end 120 | 121 | 122 | %Log the hold status so we don't change 123 | initialHoldStatus=ishold; 124 | if ~initialHoldStatus, hold on, end 125 | 126 | H = makePlot(x,y,errBar,lineProps,transparent,patchSaturation); 127 | 128 | if ~initialHoldStatus, hold off, end 129 | 130 | if nargout==1 131 | varargout{1}=H; 132 | end 133 | 134 | 135 | 136 | function H = makePlot(x,y,errBar,lineProps,transparent,patchSaturation) 137 | 138 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 139 | % Plot to get the parameters of the line 140 | 141 | H.mainLine=plot(x,y,lineProps{:}); 142 | 143 | 144 | % Work out the color of the shaded region and associated lines. 145 | % Here we have the option of choosing alpha or a de-saturated 146 | % solid colour for the patch surface. 147 | mainLineColor=get(H.mainLine,'color'); 148 | edgeColor=mainLineColor+(1-mainLineColor)*0.55; 149 | 150 | if transparent 151 | faceAlpha=patchSaturation; 152 | patchColor=mainLineColor; 153 | else 154 | faceAlpha=1; 155 | patchColor=mainLineColor+(1-mainLineColor)*(1-patchSaturation); 156 | end 157 | 158 | 159 | %Calculate the error bars 160 | uE=y+errBar(1,:); 161 | lE=y-errBar(2,:); 162 | 163 | 164 | %Add the patch error bar 165 | 166 | 167 | 168 | %Make the patch 169 | yP=[lE,fliplr(uE)]; 170 | xP=[x,fliplr(x)]; 171 | 172 | %remove nans otherwise patch won't work 173 | xP(isnan(yP))=[]; 174 | yP(isnan(yP))=[]; 175 | 176 | 177 | if(isdatetime(x)) 178 | H.patch=patch(datenum(xP),yP,1); 179 | else 180 | H.patch=patch(xP,yP,1); 181 | end 182 | 183 | set(H.patch,'facecolor',patchColor, ... 184 | 'edgecolor','none', ... 185 | 'facealpha',faceAlpha) 186 | 187 | 188 | %Make pretty edges around the patch. 189 | % H.edge(1)=plot(x,lE,'-','color',edgeColor); 190 | % H.edge(2)=plot(x,uE,'-','color',edgeColor); 191 | 192 | 193 | 194 | uistack(H.mainLine,'top') % Bring the main line to the top 195 | 196 | 197 | -------------------------------------------------------------------------------- /Main.m: -------------------------------------------------------------------------------- 1 | %% Demo code ver. 11/01/2021 2 | %================================================================================================================================================== 3 | % Face Detection in Untrained Deep Neural Networks 4 | % Seungdae Baek, Min Song, Jaeson Jang, Gwangsu Kim & Se-Bum Paik* 5 | % 6 | % *Contact: sbpaik@kaist.ac.kr 7 | % 8 | % Prerequirement 9 | % 1) MATLAB 2019b or later version is recommended. 10 | % 2) Install deeplearning toolbox. 11 | % 3) Please download 'Data.zip', 'Stimulus.zip' from below link 12 | % 13 | % - [Data URL] : https://doi.org/10.5281/zenodo.5637812 14 | % 15 | % and unzip these files in the same directory 16 | 17 | % Output of the code 18 | % Below results for untrained AlexNet will be shown. 19 | % Result 1) Run_Unit: Spontaneous emergence of face-selectivity in untrained networks (Fig.1, Fig.S1-3) 20 | % Result 2) Run_PFI: Preferred feature images of face-selective units in untrained networks (Fig.2, Fig.S4) 21 | % Result 3) Run_SVM: Detection of face images using the response of face units in untrained networks (Fig.3, Fig.S11-12) 22 | % Result 4) Run_Trained: Effect of training on face-selectivity in untrained networks (Fig.4) 23 | % Result 5) Run_Invariance: Invariant characteristics of face-selective units in untrained networks (Fig.S5) 24 | % Result 6) Run_View: Viewpoint invariance of face-selective units in untrained networks (Fig.S8) 25 | %================================================================================================================================================== 26 | close all;clc;clear; 27 | seed = 1; rng(seed) % fixed random seed for regenerating same result 28 | 29 | addpath('Data') 30 | addpath('Stimulus') 31 | addpath('Subfunctions') 32 | toolbox_chk; % checking matlab version and toolbox 33 | 34 | tic 35 | 36 | %% Setting parameters 37 | % Demo code 38 | res1 = 1; res2 = 0; res3 = 0; res4 = 0; res5 = 0; res6 = 1; % flag for analysis corresponding each figure 39 | NN = 1; % number of networks for analysis 40 | 41 | % Image 42 | STR_LABEL = {'Face','Hand','Horn','Flower','Chair','Scrambled'}; % label of classes in the object stimulus 43 | numIMG = 200; % number of images of a class in the object stimulus 44 | numCLS = 6; % number of classes in the object stimulus 45 | inpSize = 227; % width or hieght of each image in the object stimulus 46 | 47 | % Network 48 | layersSet = {'relu1', 'relu2', 'relu3', 'relu4', 'relu5'}; % names of feature extraction layers 49 | array_sz = [55 55 96; 27 27 256; 13 13 384; 13 13 384; 13 13 256]; % dimensions of activation maps of each layer 50 | layerArray = [1:5]; % target layers 51 | stdArray = [1 0.01 0.5 1.5 2]; % std of gaussian kernel for randomly initialized network 52 | verSet = {'LeCun - Normal dist','LeCun - Uniform dist'}; 53 | verArray = [1 2]; % version of initialization 54 | % 1: LeCun / 2: LeCun uniform 55 | % Analysis 56 | pThr = 0.001; % p-value threshold of selective response 57 | idxClass = 1; % index of face class in the dataset 58 | 59 | %% Step 1. Loading pretrained Alexnet and image dataset 60 | disp(['Load imageset and networks ... (~ 10 sec)']) 61 | tic 62 | net = alexnet; % pretained AlexNet 63 | load('IMG_cntr_210521.mat','IMG') % object stimulus 64 | 65 | toc 66 | IMG = IMG(:,:,1:numIMG*numCLS); IMG_ORI = single(repmat(permute(IMG,[1 2 4 3]),[1 1 3])); clearvars IMG 67 | % IMG = IMG(:,:,:,1:numIMG*numCLS); IMG_ORI = single(IMG); clearvars IMG 68 | 69 | disp(['Find face unit in untrained network ... (~ 30 sec)']) 70 | Cell_Net = cell(length(verArray),length(stdArray),NN); 71 | Cell_Idx = cell(length(verArray),length(stdArray),NN,length(layerArray)); 72 | 73 | for nn = 1:NN 74 | tic 75 | disp(['%%% Trial : ',num2str(nn),' (',num2str(nn),'/',num2str(NN),')']) 76 | for vv = 1 77 | disp(['%% Version : ',verSet{vv},' (',num2str(vv),'/',num2str(length(vv)),')']) 78 | for ss = 1 79 | disp(['% Weight variation : ',num2str(stdArray(ss)),' (',num2str(ss),'/',num2str(length(ss)),')']) 80 | %% Step 2. Loading and generating untrained AlexNet 81 | net_rand = fun_Initializeweight(net,verArray(vv),stdArray(ss)); 82 | 83 | for ll = length(layerArray) 84 | %% Step 3. Measuring responses of neurons in the target layer 85 | num_cell = prod(array_sz(layerArray(ll),:)); 86 | act_rand = activations(net_rand,IMG_ORI,layersSet{layerArray(ll)}); 87 | 88 | %% Step 4. Finding selective neuron to target class 89 | [cell_idx] = fun_FindNeuron(act_rand,num_cell,numCLS,numIMG,pThr,idxClass); 90 | Cell_Idx{vv,ss,nn,ll} = cell_idx; clearvars cell_idx 91 | end 92 | Cell_Net{vv,ss,nn} = net_rand; clearvars act_rand net_rand 93 | end 94 | end 95 | toc 96 | end 97 | 98 | if res1 == 1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 99 | %% Run_Unit: Spontaneous emergence of face-selectivity in untrained networks 100 | disp('Result 1 ... (~ 10 min)') 101 | tic 102 | Run_Unit; 103 | toc 104 | end 105 | 106 | if res2 == 1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 107 | %% Run_PFI: Preferred feature images of face-selective units in untrained networks 108 | disp('Result 2 ... (~ 2 min)') 109 | tic 110 | % Decide the simulation type 111 | % 0 : Fast version of PFI simulation. The saved PFI would be displayed. 112 | % 1 : Actual calculation process would be run. It takes around 30 minutes. 113 | Sim = 0; 114 | Figure2; 115 | toc 116 | end 117 | 118 | if res3 == 1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 119 | %% Run_SVM: Detection of face images using the response of face units in untrained networks 120 | disp('Result 3 ... (~ 5 min)') 121 | tic 122 | Run_SVM; 123 | toc 124 | end 125 | 126 | if res4 == 1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 127 | %% Run_Trained: Effect of training on face-selectivity in untrained networks 128 | disp('Result 4 ... (~ 5 min)') 129 | tic 130 | % 0 : Loading data in our manuscript (Number of networks = 10, in manuscript) 131 | % 1 : Fast version of analysis for training effect (Number of networks = 3) 132 | SimER = 0; 133 | toc 134 | end 135 | 136 | if res5 == 1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 137 | %% Run_Invariance: Invariant characteristics of face-selective units in untrained networks 138 | disp('Result 5 ... (~ 5 min)') 139 | tic 140 | % Decide the simulation type (TT) 141 | % 1 : Fast version of invariance analysis. Results for translation invariance would be displayed. 142 | % 3 : Result for translation, size, rotation invariance would be displayed. It takes around 10 minutes. 143 | TT = 1; 144 | Run_Invariance; 145 | toc 146 | end 147 | 148 | if res6 == 1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 149 | %% Run_View: Viewpoint invariance of face-selective units in untrained networks 150 | disp('Result 6 ... (~ 5 min)') 151 | tic 152 | Run_View; 153 | toc 154 | end 155 | -------------------------------------------------------------------------------- /Run_SVM.m: -------------------------------------------------------------------------------- 1 | %% Detection of face images using the response of face units in untrained networks (Fig.3, Fig.S11-12) 2 | 3 | %% Train SVM using response of an untrained network (Fig 3b-d) 4 | net_rand = Cell_Net{1,1,1}; % untrained AlexNet 5 | num_cell = prod(array_sz(layerArray(length(layerArray)),:)); 6 | load('IMG_cntr_210521.mat','IMG_cell','idx_mat') 7 | 8 | %% Find neuron 9 | disp('Prepare SVM training for face detection task ... (~ 40 sec)') 10 | tic 11 | act_rand = activations(net_rand,IMG_ORI,layersSet{length(layerArray)}); 12 | actORIre = reshape(act_rand,num_cell,size(IMG_ORI,4)); 13 | 14 | Idx_All = [1:num_cell]'; 15 | Idx_Face = Cell_Idx{1,1,1,length(layerArray)}; 16 | 17 | p = zeros(num_cell,1); 18 | for mm = 1:num_cell 19 | meanRF =[mean(actORIre(mm,1:numIMG)),mean(actORIre(mm,numIMG+1:2*numIMG)),mean(actORIre(mm,2*numIMG+1:3*numIMG)),... 20 | mean(actORIre(mm,3*numIMG+1:4*numIMG)),mean(actORIre(mm,4*numIMG+1:5*numIMG)),mean(actORIre(mm,5*numIMG+1:6*numIMG))]; 21 | if sum(meanRF) == 0 22 | p(mm) = 1; 23 | else 24 | [~,cls_max] = max(meanRF); [~,cls_min] = min(meanRF); 25 | p(mm) = ranksum(actORIre(mm,numIMG*(cls_max-1)+1:numIMG*cls_max),actORIre(mm,numIMG*(cls_min-1)+1:numIMG*cls_min)); 26 | end 27 | end 28 | arrayClass = [ones(numIMG,1);2.*ones(numIMG,1);3.*ones(numIMG,1);4.*ones(numIMG,1);5.*ones(numIMG,1);6.*ones(numIMG,1)]; 29 | p2 = zeros(num_cell,1); for mm = 1:num_cell;p2(mm) = anova1(actORIre(mm,:),arrayClass,'off');end 30 | Idx_NS = intersect(find(p>0.9),find(p>0.9)); 31 | toc 32 | 33 | %% SVM train using response of single unit (Fig 3b) 34 | reN = 5; % number of repetition for SVM training, N = 100 in the manuscript 35 | num_Sample_singe = 20; % number of randomly sampled units, all units was used in the manuscript 36 | Cell_SVM_single = cell(3,1); % 1: Face-selective; 2: Response shuffled; 3: Non-selective 37 | 38 | % Face-unit 39 | disp('Train SVM using response of singe face unit... (~ 1 min 30 sec)') 40 | cell_list = Idx_Face(randperm(length(Idx_Face),num_Sample_singe)); 41 | array_SVM = zeros(length(cell_list),reN); 42 | array_SVM_shuf = zeros(length(cell_list),reN); 43 | tic 44 | for ii = 1:length(cell_list) 45 | if mod(ii,10) == 0; disp(['% ',num2str(ii),' / ',num2str(length(cell_list))]); end 46 | for rr = 1:reN 47 | [array_SVM(ii,rr),array_SVM_shuf(ii,rr)] = fun_SVM(net_rand,num_cell,cell_list(ii),IMG_cell,idx_mat,layersSet,length(layerArray),length(cell_list(ii))); 48 | end 49 | end 50 | toc 51 | Cell_SVM_single{1} = array_SVM; Cell_SVM_single{2} = array_SVM_shuf; 52 | 53 | % Non-selective 54 | disp('Train SVM using response of singe non-selective unit... (~ 1 min 30 sec)') 55 | cell_list = Idx_NS(randperm(length(Idx_NS),num_Sample_singe)); 56 | array_SVM = zeros(length(cell_list),reN); 57 | array_SVM_shuf = zeros(length(cell_list),reN); 58 | tic 59 | for ii = 1:length(cell_list) 60 | if mod(ii,10) == 0; disp(['% ',num2str(ii),' / ',num2str(length(cell_list))]); end 61 | for rr = 1:reN 62 | [array_SVM(ii,rr),~] = fun_SVM(net_rand,num_cell,cell_list(ii),IMG_cell,idx_mat,layersSet,length(layerArray),length(cell_list(ii))); 63 | end 64 | end 65 | toc 66 | Cell_SVM_single{3} = array_SVM; 67 | 68 | %% SVM train using response of multiple units (Fig 3c,d) 69 | reN = 10; % number of repetition for SVM training, N = 100 in the manuscript 70 | numFace_ratio = 10; 71 | array_ratio = round(logspace(log10(1),log10(length(Idx_Face)),numFace_ratio)); 72 | array_ratio(end) = length(Idx_Face); 73 | Cell_SVM_mult = cell(3,1); % 1: Face-selective; 2: Non-selective; 3: Conv5 74 | 75 | % Face-unit 76 | disp('Train SVM using response of multi face units... (~ 1 min 30 sec)') 77 | tic 78 | cell_list = Idx_Face; 79 | array_SVM = zeros(length(array_ratio),reN); 80 | for vv = 1:length(array_ratio) 81 | if mod(vv,5) == 0; disp(['% ',num2str(vv),' / ',num2str(length(array_ratio))]); end 82 | for ii = 1:reN 83 | [array_SVM(vv,ii),~] = fun_SVM(net_rand,num_cell,cell_list,IMG_cell,idx_mat,layersSet,length(layerArray),array_ratio(vv)); 84 | end 85 | end 86 | Cell_SVM_mult{1} = array_SVM; 87 | toc 88 | 89 | 90 | % Non-selective 91 | disp('Train SVM using response of multi non-selective units... (~ 1 min 30 sec)') 92 | tic 93 | cell_list = Idx_NS; 94 | array_SVM = zeros(length(array_ratio),reN); 95 | for vv = 1:length(array_ratio) 96 | if mod(vv,5) == 0; disp(['% ',num2str(vv),' / ',num2str(length(array_ratio))]); end 97 | for ii = 1:reN 98 | [array_SVM(vv,ii),~] = fun_SVM(net_rand,num_cell,cell_list,IMG_cell,idx_mat,layersSet,length(layerArray),array_ratio(vv)); 99 | end 100 | end 101 | Cell_SVM_mult{2} = array_SVM; 102 | toc 103 | 104 | 105 | % Conv5 106 | disp('Train SVM using response all Conv5 units... (~ 30 sec)') 107 | tic 108 | cell_list = Idx_All; 109 | array_SVM = zeros(1,reN); 110 | for ii = 1:reN 111 | [array_SVM(1,ii),~] = fun_SVM(net_rand,num_cell,cell_list,IMG_cell,idx_mat,layersSet,length(layerArray),length(cell_list)); 112 | end 113 | Cell_SVM_mult{3} = array_SVM; 114 | toc 115 | clearvars IMG_cell idx_mat 116 | 117 | 118 | figure('units','normalized','outerposition',[0 0.5 1 0.5]); drawnow 119 | sgtitle('Face detection task using the response of face units (Fig 3b-d)') 120 | tmpColor_SVM = [1 0 0;1 0 0;0.7 0.7 0.7]; 121 | subplot(2,6,[1,2,7,8]); hold on 122 | for ii = 1:3 123 | bar([ii],mean(mean(Cell_SVM_single{ii},2),1),0.5,'facecolor',tmpColor_SVM(ii,:)) 124 | errorbar([ii],mean(mean(Cell_SVM_single{ii},2),1),std(mean(Cell_SVM_single{ii},2),1),'k') 125 | end 126 | xticks([1:3]); xlim([0.5 3.5]); ylim([0.4 1.1]) 127 | xticklabels({['Face-selective\newline{ unit}'];['Response\newline{ shuffled}'];['Non-selective\newline{ unit}']}); ylabel('Correct ratio'); 128 | title('Single-unit performance (Fig 3b)') 129 | 130 | subplot(2,6,[3,4,9,10]); hold on 131 | shadedErrorBar(array_ratio,mean(Cell_SVM_mult{1},2),std(Cell_SVM_mult{1},[],2),'lineprops','r'); 132 | s1 = plot(array_ratio,mean(Cell_SVM_mult{1},2),'r'); 133 | shadedErrorBar(array_ratio,mean(Cell_SVM_mult{2},2),std(Cell_SVM_mult{2},[],2),'lineprops','k'); 134 | s2 = plot(array_ratio,mean(Cell_SVM_mult{2},2),'k'); 135 | s3 = line([1 length(Idx_Face)],[mean(Cell_SVM_mult{3},2) mean(Cell_SVM_mult{3},2)],'Color','k','LineStyle','--'); 136 | set(gca, 'XScale', 'log'); xlim([1 length(Idx_Face)]); ylim([0.4 1.1]) 137 | xlabel('Number of units'); ylabel('Correct ratio'); 138 | legend([s1,s2,s3],'Face-selective unit','Non-selective unit','All units (n=43,264)','Location','northwest') 139 | title('Multi-unit performance (Fig 3c)') 140 | 141 | subplot(2,6,[5,6,11,12]); hold on 142 | bar([1],mean(Cell_SVM_mult{3},2),0.5,'facecolor','k') 143 | errorbar([1],mean(Cell_SVM_mult{3},2),std(Cell_SVM_mult{3},[],2),'k') 144 | bar([2],mean(Cell_SVM_mult{1}(end,:),2),0.5,'facecolor','r') 145 | errorbar([2],mean(Cell_SVM_mult{1}(end,:),2),std(Cell_SVM_mult{1}(end,:),[],2),'k') 146 | xticks([1:2]); xlim([0.5 2.5]); ylim([0.4 1.1]) 147 | xticklabels({['All\newline{unit}'];['Face-selective\newline{ unit}']}); ylabel('Correct ratio'); 148 | title('Multi-unit performance (Fig 3d)') 149 | 150 | %% Face detection performance with variation of the low-level features (Fig.S11) 151 | % This section shows the data of figures in our manuscript 152 | 153 | load('Data_SVM_invariance.mat') 154 | figure('units','normalized','outerposition',[0 0 2/3 0.5]); 155 | subplot(2,6,[1 2 7 8]); hold on; iVar = 1; 156 | bar([1],mean(Cell_SVM_Var{iVar,1}),0.5,'facecolor',[.7 .7 .7]); errorbar([1],mean(Cell_SVM_Var{iVar,1}),std(Cell_SVM_Var{iVar,1}),'k') 157 | bar([2],mean(Cell_SVM_Var{iVar,2}),0.5,'facecolor',[1 0 0]); errorbar([2],mean(Cell_SVM_Var{iVar,2}),std(Cell_SVM_Var{iVar,2}),'k') 158 | bar([3],mean(Cell_SVM_Var{iVar,3}),0.5,'facecolor',[0 0 0]); errorbar([3],mean(Cell_SVM_Var{iVar,3}),std(Cell_SVM_Var{iVar,3}),'k') 159 | ylim([0.4 1]); ylabel('Correct ratio'); xticks([1:3]); xlim([0.5 3.5]); xticklabels({['Test 1'];['Test 2'];['Response\newline{ shuffled}']}); title('Translation') 160 | 161 | subplot(2,6,[3 4 9 10]); hold on; iVar = 2; 162 | bar([1],mean(Cell_SVM_Var{iVar,1}),0.5,'facecolor',[.7 .7 .7]); errorbar([1],mean(Cell_SVM_Var{iVar,1}),std(Cell_SVM_Var{iVar,1}),'k') 163 | bar([2],mean(Cell_SVM_Var{iVar,2}),0.5,'facecolor',[1 0 0]); errorbar([2],mean(Cell_SVM_Var{iVar,2}),std(Cell_SVM_Var{iVar,2}),'k') 164 | bar([3],mean(Cell_SVM_Var{iVar,3}),0.5,'facecolor',[0 0 0]); errorbar([3],mean(Cell_SVM_Var{iVar,3}),std(Cell_SVM_Var{iVar,3}),'k') 165 | ylim([0.4 1]); ylabel('Correct ratio'); xticks([1:3]); xlim([0.5 3.5]); xticklabels({['Test 1'];['Test 2'];['Response\newline{ shuffled}']}); title('Scaling') 166 | 167 | subplot(2,6,[5 6 11 12]); hold on; iVar = 3; 168 | bar([1],mean(Cell_SVM_Var{iVar,1}),0.5,'facecolor',[.7 .7 .7]); errorbar([1],mean(Cell_SVM_Var{iVar,1}),std(Cell_SVM_Var{iVar,1}),'k') 169 | bar([2],mean(Cell_SVM_Var{iVar,2}),0.5,'facecolor',[1 0 0]); errorbar([2],mean(Cell_SVM_Var{iVar,2}),std(Cell_SVM_Var{iVar,2}),'k') 170 | bar([3],mean(Cell_SVM_Var{iVar,3}),0.5,'facecolor',[0 0 0]); errorbar([3],mean(Cell_SVM_Var{iVar,3}),std(Cell_SVM_Var{iVar,3}),'k') 171 | ylim([0.4 1]); ylabel('Correct ratio'); xticks([1:3]); xlim([0.5 3.5]); xticklabels({['Test 1'];['Test 2'];['Response\newline{ shuffled}']}); title('Rotation') 172 | sgtitle('Face detection performance with variation of the low-level features (Fig.S11)') 173 | 174 | %% Face detection performance of selective units in untrained networks (Fig.S12) 175 | % This section shows the data of figures in our manuscript 176 | 177 | load('Data_SVM_NeuronType.mat') 178 | figure('units','normalized','outerposition',[2/3 0 1/3 0.5]); hold on 179 | bar([1],mean(Cell_SVM_Neuron{1}),0.5,'facecolor','w'); errorbar([1],mean(Cell_SVM_Neuron{1}),std(Cell_SVM_Neuron{1}),'k') 180 | bar([2],mean(Cell_SVM_Neuron{2}),0.5,'facecolor','c'); errorbar([2],mean(Cell_SVM_Neuron{2}),std(Cell_SVM_Neuron{2}),'k') 181 | bar([3],mean(Cell_SVM_Neuron{3}),0.5,'facecolor','r'); errorbar([3],mean(Cell_SVM_Neuron{3}),std(Cell_SVM_Neuron{3}),'k') 182 | bar([4],mean(Cell_SVM_Neuron{4}),0.5,'facecolor',[.7 .7 .7]); errorbar([4],mean(Cell_SVM_Neuron{4}),std(Cell_SVM_Neuron{4}),'k') 183 | bar([5],mean(Cell_SVM_Neuron{5}),0.5,'facecolor','r'); errorbar([5],mean(Cell_SVM_Neuron{5}),std(Cell_SVM_Neuron{5}),'k') 184 | ylim([0.4 1]); ylabel('Correct ratio'); xticks([1:5]); xlim([0.5 5.5]); 185 | xticklabels({[' All\newline{selective unit}'];[' Non-face-\newline{selective unit}'];[' Face-\newline{ selective unit}'];... 186 | [' Non-\newline{ selective unit}'];['Response\newline{ shuffled}']}); 187 | sgtitle('Face detection performance of selective units in untrained networks (Fig.S12) ') -------------------------------------------------------------------------------- /Run_View.m: -------------------------------------------------------------------------------- 1 | %% Viewpoint invariance of face-selective units in untrained networks (Fig.S8-10) 2 | 3 | %% Analysis for viewpoint invariance (Fig.S8a,f-h) 4 | net_rand = Cell_Net{1,1,1}; % untrained AlexNet 5 | 6 | load('IMG_var_view_210106.mat'); % viewpoint stimulus 7 | IMG_view = single(IMG_viewpoint); clearvars IMG_viewpoint 8 | numIMG_view = 10; % number of images of a class in the object stimulus 9 | numCLS_view = 5; % number of classes in the viewpoint stimulus 10 | arrayClass = [ones(numIMG_view,1);2.*ones(numIMG_view,1);3.*ones(numIMG_view,1);4.*ones(numIMG_view,1);5.*ones(numIMG_view,1)]; 11 | 12 | %% Find face units on each L3, L4 13 | disp(['Find face units on L3, L4 ... (~ 2 min)']) 14 | tic 15 | for ll = 3:4 16 | num_cell = prod(array_sz(layerArray(ll),:)); 17 | act_rand = activations(net_rand,IMG_ORI,layersSet{layerArray(ll)}); 18 | [cell_idx] = fun_FindNeuron(act_rand,num_cell,numCLS,numIMG,pThr,idxClass); 19 | Cell_Idx{1,1,1,ll} = cell_idx; clearvars cell_idx act_rand 20 | end 21 | toc 22 | 23 | %% Find viewpoint specfic / invariant face units 24 | Cell_view_p = cell(5,1); 25 | Cell_view_pref = cell(5,1); 26 | Cell_view_peak = cell(5,1); 27 | Cell_view_stat = cell(5,1); 28 | 29 | for ll = 3:5 30 | indLayer = ll; 31 | num_cell = prod(array_sz(indLayer,:)); 32 | Idx_Face = Cell_Idx{1,1,1,ll}; 33 | 34 | act_rand = activations(net_rand,IMG_view,layersSet{indLayer}); 35 | act_reshape = reshape(act_rand,num_cell,size(IMG_view,4)); clearvars act_rand 36 | act_reshape3D = zeros(num_cell,numCLS_view,numIMG_view); 37 | for cc = 1:numCLS_view 38 | act_reshape3D(:,cc,:) = act_reshape(:,(cc-1)*numIMG_view+1:cc*numIMG_view); 39 | end 40 | act_reshape = act_reshape(Idx_Face,:); 41 | act_reshape3D = act_reshape3D(Idx_Face,:,:); clearvars act_rand 42 | 43 | p = zeros(length(Idx_Face),1); 44 | pref = zeros(length(Idx_Face),numCLS_view); 45 | peak = zeros(length(Idx_Face),numCLS_view); % peak location 46 | vstat = zeros(length(Idx_Face),1); 47 | 48 | for ii = 1:length(Idx_Face) 49 | p(ii) = anova1(act_reshape(ii,:),arrayClass,'off'); 50 | 51 | meanFR = squeeze(mean(act_reshape3D(ii,:,:),3))'; 52 | [~,peakView] = findpeaks([min(meanFR);meanFR;min(meanFR)]); peak(ii,peakView-1) = 1; 53 | 54 | if sum(meanFR) == 0 55 | pref(ii,:) = 0; 56 | else 57 | [~,pref(ii,:)] = sort(meanFR,'descend'); 58 | vstat(ii,1) = std(meanFR); 59 | end 60 | end 61 | 62 | Cell_view_p{ll} = p; 63 | Cell_view_pref{ll} = pref; 64 | Cell_view_peak{ll} = peak; 65 | Cell_view_stat{ll} = vstat; 66 | end 67 | 68 | sel_cellview_mat = cell(length(layerArray),5); % index : inv / spe / spe_pre / mirro (-90, 90) / mirro (-45, 45) 69 | for ll = 3:5 70 | idx = Cell_Idx{1,1,1,ll}; 71 | p = Cell_view_p{ll}; 72 | pref = Cell_view_pref{ll}; 73 | peak = Cell_view_peak{ll}; 74 | 75 | sel_cellview_mat{ll,1} = idx((pref(:,1) ~= 0)&(p(:,1)>=0.05)); 76 | sel_cellview_mat{ll,2} = idx((pref(:,1) ~= 0)&(p(:,1)<0.05)&(sum(peak,2) == 1)); 77 | sel_cellview_mat{ll,3} = pref((pref(:,1) ~= 0)&(p(:,1)<0.05)&(sum(peak,2) == 1)); 78 | 79 | sel_cellview_mat{ll,4} = idx((pref(:,1) ~= 0)&(p(:,1)<0.05)&(sum(peak,2) > 1)&((pref(:,1) == 1)|(pref(:,1) == 5))&(pref(:,1) ~= 3)); 80 | sel_cellview_mat{ll,5} = idx((pref(:,1) ~= 0)&(p(:,1)<0.05)&(sum(peak,2) > 1)&((pref(:,1) == 2)|(pref(:,1) == 4))&(pref(:,1) ~= 3)); 81 | end 82 | 83 | figure('units','normalized','outerposition',[0 0 1 1]); drawnow 84 | sgtitle(['Increasing viewpoint invariance of face-selective units along the network hierarchies']) 85 | 86 | % Viewpoint variation (Fig.S8a) 87 | pos_subplot = [5:-1:1]; pos_img = [1:numIMG_view:41]; 88 | for ii = 1:5 89 | subplot(4,8,pos_subplot(ii)); imagesc(IMG_view(:,:,1,pos_img(ii))); axis image off; colormap(gray); caxis([0 255]) 90 | end 91 | pos_subplot = [13:-1:9]; pos_img = [2:numIMG_view:42]; 92 | for ii = 1:5 93 | subplot(4,8,pos_subplot(ii)); imagesc(IMG_view(:,:,1,pos_img(ii))); axis image off; colormap(gray); caxis([0 255]); title([num2str(-90+(ii-1)*45),' deg']) 94 | end 95 | 96 | % Face unit response (Conv5) (Fig.S8a) 97 | act_rand = activations(net_rand,IMG_view,layersSet{length(layerArray)}); 98 | act_reshape = reshape(act_rand,num_cell,size(IMG_view,4)); 99 | act_Norm = act_reshape./mean(act_reshape,2); 100 | act_Norm3D = zeros(num_cell,numCLS_view,numIMG_view); 101 | for cc = 1:numCLS_view 102 | act_Norm3D(:,cc,:) = act_Norm(:,(cc-1)*numIMG_view+1:cc*numIMG_view); 103 | end 104 | 105 | cell_list_inv = sel_cellview_mat{5,1}; 106 | cell_list_spe3 = sel_cellview_mat{5,2}(sel_cellview_mat{5,3} == 3); 107 | 108 | subplot(4,8,[7,8,15,16]); hold on 109 | shadedErrorBar([-90:45:90],mean(nanmean(act_Norm3D(cell_list_spe3,:,:),1),3),std(nanmean(act_Norm3D(cell_list_spe3,:,:),1),[],3)./sqrt(numIMG_view),'lineprops',{'b','markerfacecolor','b'}); 110 | shadedErrorBar([-90:45:90],mean(nanmean(act_Norm3D(cell_list_inv,:,:),1),3),std(nanmean(act_Norm3D(cell_list_inv,:,:),1),[],3)./sqrt(numIMG_view),'lineprops',{'r','markerfacecolor','r'}); 111 | s1 = plot([-90:45:90],mean(nanmean(act_Norm3D(cell_list_spe3,:,:),1),3),'color','b'); 112 | s2 = plot([-90:45:90],mean(nanmean(act_Norm3D(cell_list_inv,:,:),1),3),'color','r'); 113 | line([-90 90],[1 1],'Color','k','LineStyle','--') 114 | legend([s1,s2],{'Viewpoint-specific (0 deg)','Viewpoint-invariant'},'Location','southeast') 115 | xticks([-90:45:90]); xticklabels({'-90 deg','-45 deg','0 deg','45 deg','90 deg'}); xlim([-90 90]); 116 | ylim([0 mean(nanmean(act_Norm3D(cell_list_spe3,3,:),1),3)+std(nanmean(act_Norm3D(cell_list_spe3,3,:),1),[],3)./sqrt(numIMG_view)+0.2]); ylabel('Normalized Response (A.U.)'); title('Face unit response (Fig.S8a)') 117 | 118 | % Average tuning curves of face units in each layer (Fig.S8f) 119 | Cell_align_tuning = cell(3,1); 120 | for ll = 1:3 121 | idx = Cell_Idx{1,1,1,ll+2}; num_cell = prod(array_sz(ll+2,:)); 122 | act_rand = activations(net_rand,IMG_view,layersSet{ll+2}); 123 | act_reshape = reshape(act_rand,num_cell,size(IMG_view,4)); clearvars act_rand 124 | act_Norm = act_reshape; 125 | act_Norm3D = zeros(num_cell,numCLS_view,numIMG_view); 126 | for cc = 1:numCLS_view 127 | act_Norm3D(:,cc,:) = act_Norm(:,(cc-1)*numIMG_view+1:cc*numIMG_view); 128 | end 129 | act_Norm3D = act_Norm3D(idx,:,:); 130 | tuning_curve = mean(act_Norm3D,3); tuning_curve(prod(tuning_curve,2) == 0,:) = []; 131 | array_align = zeros(size(tuning_curve,1),2*numCLS_view-1); 132 | for ii = 1:size(tuning_curve,1) 133 | [~,indMax] = max(tuning_curve(ii,:),[],2); 134 | switch indMax 135 | case 1 136 | array_align(ii,[5:9]) = array_align(ii,[5:9])+tuning_curve(ii,1:numCLS_view); 137 | array_align(ii,[5:-1:1]) = array_align(ii,[5:-1:1])+tuning_curve(ii,1:numCLS_view); 138 | array_align(ii,5) = array_align(ii,5)/2; 139 | case 2 140 | array_align(ii,[4:8]) = array_align(ii,[4:8])+tuning_curve(ii,1:numCLS_view); 141 | array_align(ii,[6:-1:2]) = array_align(ii,[6:-1:2])+tuning_curve(ii,1:numCLS_view); 142 | array_align(ii,[4:6]) = array_align(ii,[4:6])/2; 143 | case 3 144 | array_align(ii,[3:7]) = array_align(ii,[3:7])+tuning_curve(ii,1:numCLS_view); 145 | array_align(ii,[7:-1:3]) = array_align(ii,[7:-1:3])+tuning_curve(ii,1:numCLS_view); 146 | array_align(ii,[3:7]) = array_align(ii,[3:7])/2; 147 | case 4 148 | array_align(ii,[2:6]) = array_align(ii,[2:6])+tuning_curve(ii,1:numCLS_view); 149 | array_align(ii,[8:-1:4]) = array_align(ii,[8:-1:4])+tuning_curve(ii,1:numCLS_view); 150 | array_align(ii,[4:6]) = array_align(ii,[4:6])/2; 151 | case 5 152 | array_align(ii,[1:5]) = array_align(ii,[1:5])+tuning_curve(ii,1:numCLS_view); 153 | array_align(ii,[9:-1:5]) = array_align(ii,[9:-1:5])+tuning_curve(ii,1:numCLS_view); 154 | array_align(ii,5) = array_align(ii,5)/2; 155 | end 156 | end 157 | Cell_align_tuning{ll} = array_align./(numCLS_view*size(array_align,2)); 158 | end 159 | 160 | subplot(4,8,[17,18,25,26]); hold on 161 | s1 = plot([-180:45:180],nanmean(Cell_align_tuning{1},1)+(1-mean(nanmean(Cell_align_tuning{1},1))),'k'); 162 | shadedErrorBar([-180:45:180],nanmean(Cell_align_tuning{1},1)+(1-mean(nanmean(Cell_align_tuning{1},1))),nanstd(Cell_align_tuning{1},1),'lineprops',{'k','markerfacecolor','k'}); 163 | s2 = plot([-180:45:180],nanmean(Cell_align_tuning{2},1)+(1-mean(nanmean(Cell_align_tuning{2},1))),'b'); 164 | shadedErrorBar([-180:45:180],nanmean(Cell_align_tuning{2},1)+(1-mean(nanmean(Cell_align_tuning{2},1))),nanstd(Cell_align_tuning{1},1),'lineprops',{'b','markerfacecolor','b'}); 165 | s3 = plot([-180:45:180],nanmean(Cell_align_tuning{3},1)+(1-mean(nanmean(Cell_align_tuning{3},1))),'r'); 166 | shadedErrorBar([-180:45:180],nanmean(Cell_align_tuning{3},1)+(1-mean(nanmean(Cell_align_tuning{3},1))),nanstd(Cell_align_tuning{1},1),'lineprops',{'r','markerfacecolor','r'}); 167 | line([-180 180],[1 1],'Color','k','LineStyle','--') 168 | xlim([-180 180]); xticks([-180:45:180]); ylim([0.5 1.5]); 169 | xlabel('Viewpoint difference (deg)'); ylabel('Normalized response (A.U.)'); legend([s1,s2,s3],'Conv3','Conv4','Conv5','Location','northeast'); title('Untrained network (Fig.S8f)'); 170 | 171 | % Viewpoint invariance (Fig.S8g) 172 | array_vi_mean = zeros(3,1); array_vi_std = zeros(3,1); 173 | for ll = 1:3 174 | vstat = Cell_view_stat{ll+2}; tmp_vi = 1./vstat(:,1); tmp_vi(isinf(tmp_vi)) = []; tmp_vi(isnan(tmp_vi)) = []; 175 | [tmp_sort,~] = sort(tmp_vi); 176 | q1 = tmp_sort(floor(0.25*numel(tmp_vi))); 177 | q3 = tmp_sort(floor(0.75*numel(tmp_vi))); 178 | iqr = q3-q1; 179 | idx_outlier = find((tmp_vi>(q3+1.5*iqr))|(tmp_vi<(q1-1.5*iqr))); 180 | tmp_vi = setdiff(tmp_vi,tmp_vi(idx_outlier)); 181 | array_vi_mean(ll) = mean(tmp_vi); array_vi_std(ll) = std(tmp_vi); 182 | end 183 | 184 | subplot(4,8,[20,21,28,29]); hold on 185 | for ll = 1:3 186 | errorbar([ll+2],array_vi_mean(ll),array_vi_std(ll),'k') 187 | end 188 | plot([3:5],array_vi_mean,'-ok') 189 | xticks([3:5]); xlim([2.5 5.5]); ylim([0 2]) 190 | xticklabels({'Conv3','Conv4','Conv5'}); xlabel('Network hierarchy'); ylabel('Invariance index'); title('Viewpoint invariance (Fig.S8g)') 191 | 192 | % Number of invariant units (Fig.S8h) 193 | array_ratio_inv = zeros(3,1); 194 | for ll = 1:3 195 | array_ratio_inv(ll) = length(sel_cellview_mat{ll+2,1})/length(Cell_Idx{1,1,1,ll+2}); 196 | end 197 | subplot(4,8,[23,24,31,32]); hold on 198 | plot([3:5],array_ratio_inv(:)-array_ratio_inv(3),'-ok') 199 | xticks([3:5]); xlim([2.5 5.5]); ylim([min(array_ratio_inv(:)-array_ratio_inv(3))-0.1 max(array_ratio_inv(:)-array_ratio_inv(3))+0.1]) 200 | xticklabels({'Conv3','Conv4','Conv5'}); xlabel('Network hierarchy'); ylabel('Ratio change of viewpoint-invariant units'); title('Number of units (Fig.S8h)') -------------------------------------------------------------------------------- /Run_PFI.m: -------------------------------------------------------------------------------- 1 | %% Preferred feature images of face-selective units in untrained networks (Fig.2, Fig.S4) 2 | 3 | %% Preferred feature images (PFI) (Fig 2c) 4 | Cell_PFI = cell(numCLS-1,2); 5 | if Sim == 0 % 1 : Fast version of PFI simulation. The saved PFI would be displayed. 6 | load('Data_PFI_XDream_ClsUnit.mat','PFI_XDream_mat') 7 | load('Data_PFI_RevCorr_ClsUnit.mat','PFI_RevCorr_mat') 8 | 9 | for cc = 1:numCLS-1 10 | for ii = 1:2 11 | switch ii 12 | case 1 13 | Cell_PFI{cc,1} = PFI_XDream_mat{cc}; 14 | case 2 15 | Cell_PFI{cc,2} = PFI_RevCorr_mat{cc}; 16 | end 17 | end 18 | end 19 | elseif Sim == 1 % 2 : Actual calculation process would be run. It takes around 30 minutes. 20 | net_rand = Cell_Net{1,1,1}; IND_face = Cell_Idx{1,1,1,length(layerArray)}; 21 | 22 | %% Reverse correlation (Fig 2a) 23 | % Stimulus parameters 24 | N_image = 2500; % Number of stimulus images 25 | iteration = 100; % Number of iteration 26 | img_size = 227; % Image size 27 | dot_size = 5; % Size of 2D Gaussian filter 28 | 29 | % Generate 2D Gaussian filters 30 | [pos_xx,pos_yy] = meshgrid(linspace(1+dot_size,img_size-dot_size,sqrt(N_image)),linspace(1+dot_size,img_size-dot_size,sqrt(N_image))); 31 | pos_xy_list = pos_xx(:) + 1i*pos_yy(:); 32 | [xx_field,yy_field] = meshgrid(1:img_size,1:img_size); xy_field = xx_field + 1i*yy_field; 33 | 34 | img_list = zeros(img_size,img_size,3,length(pos_xy_list)); 35 | count = 1; 36 | for pp = 1:length(pos_xy_list) 37 | pos_tmp = pos_xy_list(pp); 38 | img_tmp = repmat(exp(-(abs(xy_field-pos_tmp).^2)/2/dot_size.^2)*0.5,1,1,3); 39 | img_list(:,:,:,count) = -img_tmp; 40 | count = count + 1; 41 | end 42 | Gau_stimulus = cat(4,img_list,-img_list); 43 | 44 | % Iterative PFI calculation 45 | PFI = zeros(img_size,img_size,3)+255/2; %Initial PFI 46 | PFI_mat = zeros(img_size,img_size,iteration+1); PFI_mat(:,:,1) = PFI(:,:,1); 47 | 48 | for iter = 1:iteration 49 | tic 50 | PFI_0 = PFI; % Save previous PFI 51 | 52 | % Generate stimulus as a summation of previous PFI and gaussian stimulus 53 | IMG = repmat(PFI/255,[1,1,1,size(Gau_stimulus,4)])+Gau_stimulus; 54 | IMG = uint8(IMG*255); IMG(IMG<0) = 0; IMG(IMG>255) = 255; 55 | 56 | % Measure the response of random AlexNet 57 | act_rand = activations(net_rand,IMG,'relu5'); % Response of 'relu5' layer in random AlexNet 58 | act_reshape = reshape(act_rand,43264,size(IMG,4)); % Reshape the response in 2D form 59 | act_reshape_sel = act_reshape(IND_face,:); % Find the response of face-selective neurons 60 | mean_act = mean(act_reshape_sel,1); % Average response of face-selective neurons 61 | 62 | % Calculate the PFI 63 | norm_act_reshape = repmat(permute(mean_act-min(mean_act),[1,3,4,2]),img_size,img_size,3); 64 | PFI = sum(norm_act_reshape.*double(IMG),4)/sum(mean_act-min(mean_act)); 65 | PFI_diff = PFI-PFI_0; PFI = PFI_0 + PFI_diff*10; 66 | PFI(PFI<0) = 0; PFI(PFI>255) = 255; 67 | PFI_mat(:,:,iter+1) = PFI(:,:,1); 68 | toc 69 | end 70 | Cell_PFI{1,2} = PFI_mat(:,:,end); 71 | 72 | %% XDream (Fig 2b) 73 | % If you want to regenerate XDream PFI, please install the XDream from https://github.com/willwx/XDream 74 | 75 | % Alternatively, there is a customized XDream code we wrote. you can also refer to the code below. 76 | % ===================================================================== 77 | % dlnetGenerator = // pretrained GAN // % you should download or train GAN network 78 | % numIteration = 101; 79 | % pElite = 0.01; 80 | % pHeredity = 0.75; 81 | % pMutant = 0.01; 82 | % stdMutant = 0.75; 83 | % 84 | % numValid = 10*10; 85 | % numLatentInputs = 500; 86 | % executionEnvironment = "auto"; 87 | % 88 | % Zvalidation = randn(1,1, numLatentInputs, numValid, 'single'); 89 | % dlZValidation = dlarray(Zvalidation, 'SSCB'); 90 | % 91 | % if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu" 92 | % dlZValidation = gpuArray(dlZValidation); 93 | % end 94 | % 95 | % array_act = zeros(numIteration,numValid); 96 | % iter_dlZValidation = dlZValidation; 97 | % Cell_data = cell(numIteration,1); 98 | % 99 | % figure; start = tic; 100 | % for iteration = 1:numIteration 101 | % tic 102 | % % generate images 103 | % dlXGeneratedValidation = predict(dlnetGenerator, iter_dlZValidation); 104 | % iterIMG = imresize(gather(255.*rescale(extractdata(dlXGeneratedValidation))),[227 227]); 105 | % 106 | % % estimate score (face neurons) 107 | % act_reshape_mat = []; 108 | % act_rand = activations(net_rand,iterIMG,layersSet{5}); act = reshape(act_rand,num_cell,numValid); 109 | % actNorm = act; 110 | % ind_Neuron = IND_face; 111 | % act_reshape_mat = cat(1,act_reshape_mat,actNorm(ind_Neuron,:)); 112 | % 113 | % tmpScore = mean(act_reshape_mat,1); 114 | % 115 | % array_act(iteration,:) = tmpScore; 116 | % Cell_data{iteration,1} = iterIMG; 117 | % 118 | % disp(['Iteration = ',num2str(iteration-1),' / Score = ',num2str(mean(tmpScore))]) 119 | % if mod(iteration, 1) == 0 || iteration == 1 120 | % I = imtile(extractdata(dlXGeneratedValidation)); 121 | % I = rescale(I); image(I) 122 | % 123 | % D = duration(0,0,toc(start), 'Format', 'hh:mm:ss'); 124 | % title(['Iteration: ', num2str(iteration), ', Elapsed: ', char(D)]); 125 | % drawnow 126 | % end 127 | % 128 | % % optimize score 129 | % % current population 130 | % next_dlZValidation = zeros(1,1,numLatentInputs,numValid,'single'); 131 | % tmp_dlZValidation = gather(extractdata(iter_dlZValidation)); 132 | % 133 | % % elite population 134 | % [~,order] = sort(tmpScore,'descend'); % select elite 135 | % indElite = order(1:floor(pElite*numValid)); 136 | % next_dlZValidation(:,:,:,1:length(indElite)) = tmp_dlZValidation(:,:,:,indElite); 137 | % 138 | % % recombination population 139 | % indRest = setdiff([1:numValid],indElite); 140 | % 141 | % w = exp(tmpScore(indRest) - min(tmpScore(indRest)))./std(tmpScore(indRest)); p = w./sum(w); 142 | % tmpExpectNum = round(length(indRest).*p); 143 | % ind_list = []; for ii = 1:length(indRest); ind_list = [ind_list; ii.*ones(tmpExpectNum(ii),1)];end % roulette wheel selection 144 | % 145 | % new_dlZValidation = zeros(1,1,numLatentInputs,length(indRest),'single'); 146 | % for ii = 1:length(indRest) 147 | % % cross-over 148 | % indParent = ind_list(randperm(length(ind_list),2)); 149 | % parants = [squeeze(tmp_dlZValidation(:,:,:,indRest(indParent(1))))... 150 | % squeeze(tmp_dlZValidation(:,:,:,indRest(indParent(2))))]; 151 | % 152 | % tmpPoint = randi(numLatentInputs-floor(numLatentInputs*pHeredity),1); 153 | % indPre = tmpPoint:tmpPoint+floor(numLatentInputs*pHeredity); indCross = setdiff([1:numLatentInputs],indPre); 154 | % 155 | % child = parants(:,1); child(indCross) = parants(indCross,2); 156 | % % mutation 157 | % if rand(1)0)); 125 | [tmp_sort_num,tmp_order] = sort(tmp_numFaceUnit_filter,'descend'); 126 | 127 | % response matrix with face unit 128 | figure('units','normalized','outerposition',[0 0 2/3 0.5]); 129 | sgtitle('Result 1 : Response and distribution of face units (Fig S2b,d)') 130 | load('Colorbar_Tsao.mat'); idx_subplot = [1 2 5 6]; 131 | for ii = 1:length(idx_subplot) 132 | subplot(2,4,idx_subplot(ii)) 133 | act_reshape = reshape(squeeze(act_rand(:,:,tmp_order(ii),:)),[prod(array_sz(layerArray(5),1:2)) numCLS*numIMG]); 134 | [rep_mat,rep_mat_3D] = fun_ResZscoreRe(act_reshape,[1:prod(array_sz(layerArray(5),1:2))],numCLS,numIMG); 135 | rep_mat_3D_reshape = reshape(rep_mat_3D,[array_sz(layerArray(5),1), array_sz(layerArray(5),1), numCLS, numIMG]); 136 | 137 | MAT = mean(rep_mat_3D_reshape(:,:,1,:),4); MAT(isnan(MAT)) = 0; 138 | imagesc(MAT); axis image off; colormap(cmap); caxis([-1 1]); 139 | title(['# ', num2str(tmp_order(ii))]) 140 | end; clearvars cmap 141 | 142 | % XY location with face unit 143 | tmpMatrix = zeros(array_sz(layerArray(5),1),array_sz(layerArray(5),2),numFilter_existFaceUnit); 144 | for ii = 1:numFilter_existFaceUnit 145 | tmp_idx_FaceUnit_aFilter = tmp_idx_FaceUnit(idx_FaceUnit_Filter == tmp_order(ii)); 146 | [I,J,~] = ind2sub([array_sz(layerArray(5),1),array_sz(layerArray(5),2),array_sz(layerArray(5),3)],tmp_idx_FaceUnit_aFilter); 147 | for jj = 1:length(tmp_idx_FaceUnit_aFilter) 148 | tmpMatrix(I(jj),J(jj),ii) = 1; 149 | end 150 | end 151 | load('Colorbar_Tsao.mat'); idx_subplot = [3 4 7 8]; 152 | for ii = 1:length(idx_subplot) 153 | subplot(2,4,idx_subplot(ii)) 154 | imagesc(tmpMatrix(:,:,ii)); axis image off; colormap(cmap); caxis([0 1]); 155 | title(['# ', num2str(tmp_order(ii))]) 156 | end; clearvars cmap 157 | 158 | % Average distribution 159 | figure('units','normalized','outerposition',[2/3 0 1/3 0.5]); 160 | sgtitle('Result 1 : Distribution of face units (Fig S2d)'); title(['Averaged distribution']) 161 | subplot(2,2,[1 2 3 4]); imagesc(mean(tmpMatrix./prod(array_sz(layerArray(5),1:2)),3)); axis image; colormap(hot); caxis([0 inf]); 162 | 163 | %% Face units in untrained networks when varying inital weight distribution (Fig 1f,g) 164 | disp(['Find face unit in untrained networks when varying inital weight distribution ... (~ 4 min)']) 165 | tic 166 | for nn = 1:NN 167 | disp(['%%% Trial : ',num2str(nn),' (',num2str(nn),'/',num2str(NN),')']) 168 | for vv = 1:length(verArray) 169 | disp(['%% Version : ',verSet{vv},' (',num2str(vv),'/',num2str(length(verArray)),')']) 170 | for ss = 1:length(stdArray) 171 | if vv*ss == 1; continue; end 172 | disp(['% Weight variation : ',num2str(stdArray(ss)),' (',num2str(ss),'/',num2str(length(stdArray)),')']) 173 | net_rand = fun_Initializeweight(net,verArray(vv),stdArray(ss)); 174 | 175 | for ll = length(layerArray) 176 | num_cell = prod(array_sz(layerArray(ll),:)); 177 | act_rand = activations(net_rand,IMG_ORI,layersSet{layerArray(ll)}); 178 | 179 | [cell_idx] = fun_FindNeuron(act_rand,num_cell,numCLS,numIMG,pThr,idxClass); 180 | Cell_Idx{vv,ss,nn,ll} = cell_idx; 181 | end 182 | Cell_Net{vv,ss,nn} = net_rand; clearvars act_rand net_rand 183 | end 184 | end 185 | end 186 | 187 | array_fsi_var = zeros(NN,length(verArray),length(stdArray)); 188 | array_num_var = zeros(NN,length(verArray),length(stdArray)); 189 | for nn = 1:NN 190 | for vv = 1:length(verArray) 191 | [stdArray_sort,stdArray_order] = sort(stdArray); 192 | for ss = 1:length(stdArray) 193 | net_rand = Cell_Net{vv,stdArray_order(ss),nn}; 194 | Idx_Face = Cell_Idx{vv,stdArray_order(ss),nn,5}; 195 | array_num_var(nn,vv,stdArray_order(ss)) = length(Idx_Face); 196 | 197 | act_rand = activations(net_rand,IMG_ORI,layersSet{layerArray(5)}); 198 | [~,rep_mat_3D] = fun_ResZscore(act_rand,num_cell,Idx_Face,numCLS,numIMG); 199 | fsi_mat = fun_FSI(rep_mat_3D); 200 | array_fsi_var(nn,vv,stdArray_order(ss)) = nanmean(fsi_mat); 201 | end 202 | end 203 | end 204 | toc 205 | 206 | figure('units','normalized','outerposition',[0 0 1 0.5]); 207 | sgtitle('Result 1 : Face units in untrained networks when varying inital weight distribution (Fig 1f-g)') 208 | % Figure : distribution of initial weight 209 | rand_layers_ind = [2,6,10,12,14]; 210 | tmpStdArray = [0.5 1 1.5]; 211 | tmpColorStd_Gau = [153/255 0 0; 1 0 0; 1 153/255 0]; 212 | tmpColorStd_Uni = [0 0 153/255; 0 0 1; 0 153/255 1]; 213 | edge = [-0.2:0.01:0.2]; 214 | 215 | subplot(2,6,[1,2]); hold on 216 | for ss = 1:3 217 | tmpnet = Cell_Net{1,find(stdArray == tmpStdArray(ss)),1}; 218 | W = []; 219 | for ll = 1:5 220 | targetlayer_ind = rand_layers_ind(1); 221 | weight_conv = tmpnet.Layers(targetlayer_ind ,1).Weights; 222 | fan_in = size(weight_conv,1)*size(weight_conv,2)*size(weight_conv,3); 223 | Wtmp = tmpStdArray(ss)*randn(size(weight_conv))*sqrt(1/fan_in); 224 | W = [W;Wtmp(:)]; 225 | end 226 | 227 | tmp_rato = histcounts(W,edge,'Normalization', 'probability'); 228 | plot(edge,[0 tmp_rato],'color',tmpColorStd_Gau(ss,:)) 229 | end 230 | ylabel('Ratio'); xlim([-0.2 0.2]); ylim([0 0.2]) 231 | title('Distribution of intial weights (Gaussian)');legend('x0.5','x1','x1.5','Location','northeast') 232 | 233 | subplot(2,6,[7,8]); hold on 234 | for ss = 1:3 235 | tmpnet = Cell_Net{2,find(stdArray == tmpStdArray(ss)),1}; 236 | W = []; 237 | for ll = 1:5 238 | targetlayer_ind = rand_layers_ind(1); 239 | weight_conv = tmpnet.Layers(targetlayer_ind ,1).Weights; 240 | fan_in = size(weight_conv,1)*size(weight_conv,2)*size(weight_conv,3); 241 | Wtmp = tmpStdArray(ss)*(rand(size(weight_conv))-0.5)*2*sqrt(3/fan_in); 242 | end 243 | W = [W; Wtmp(:)]; 244 | tmp_rato = histcounts(W,edge,'Normalization', 'probability'); 245 | plot(edge,[0 tmp_rato],'color',tmpColorStd_Uni(ss,:)) 246 | end 247 | xlabel('Weight'); ylabel('Ratio'); xlim([-0.2 0.2]); ylim([0 0.2]) 248 | title('Distribution of intial weights (Uniform)'); legend('x0.5','x1','x1.5','Location','northeast'); 249 | 250 | % Figure 1f: variation of weights vs Number of face units 251 | subplot(2,6,[3,4,9,10]); hold on 252 | if NN == 1 253 | s1 = plot(stdArray_sort,squeeze(array_num_var(1,1,:)),'r'); 254 | s2 = plot(stdArray_sort,squeeze(array_num_var(1,2,:)),'b'); 255 | else 256 | shadedErrorBar(stdArray_sort,squeeze(mean(array_num_var(:,1,:),1)),squeeze(std(array_num_var(:,1,:),1)),'lineprops','r'); 257 | s1 = plot(stdArray_sort,squeeze(mean(array_num_var(:,1,:),1)),'r'); 258 | shadedErrorBar(stdArray_sort,squeeze(mean(array_num_var(:,2,:),1)),squeeze(std(array_num_var(:,2,:),1)),'lineprops','b'); 259 | s2 = plot(stdArray_sort,squeeze(mean(array_num_var(:,2,:),1)),'b'); 260 | end 261 | ylim([0 600]); ylabel('Number of units'); xlabel('Variation of weights'); 262 | title('Number of face units (Fig 1f)'); legend([s1,s2],'Gaussian','Uniform','Location','northeast') 263 | 264 | % Figure 1g: variation of weights vs FSI 265 | subplot(2,6,[5,6,11,12]); hold on 266 | if NN == 1 267 | s1 = plot(stdArray_sort,squeeze(array_fsi_var(1,1,:)),'r'); 268 | s2 = plot(stdArray_sort,squeeze(array_fsi_var(1,2,:)),'b'); 269 | else 270 | shadedErrorBar(stdArray_sort,squeeze(mean(array_fsi_var(:,1,:),1)),squeeze(std(array_fsi_var(:,1,:),1)),'lineprops','r'); 271 | s1 = plot(stdArray_sort,squeeze(mean(array_fsi_var(:,1,:),1)),'r'); 272 | shadedErrorBar(stdArray_sort,squeeze(mean(array_fsi_var(:,2,:),1)),squeeze(std(array_fsi_var(:,2,:),1)),'lineprops','b'); 273 | s2 = plot(stdArray_sort,squeeze(mean(array_fsi_var(:,2,:),1)),'b'); 274 | end 275 | ylim([0 0.6]); ylabel('Face-selectivity index (FSI)'); xlabel('Variation of weights'); 276 | title('Single unit selectivity (Fig 1g)'); legend([s1,s2],'Gaussian','Uniform','Location','northeast') --------------------------------------------------------------------------------