{
  "id": 7136,
  "title": "Is there any example code for this competition?",
  "url": "/competitions/galaxy-zoo-the-galaxy-challenge/discussion/7136",
  "author_name": "",
  "post_date": "2014-02-20T08:58:01.297Z",
  "votes": null,
  "comment_count": 1,
  "views": 2159,
  "content": "<p>Hi, all,</p>\n<p>I 'd rather to know that is there any example code for introduction to this competition? Becuase I'm new to this galaxy recognition domain.</p>\n<p>&nbsp;</p>\n<p>Thanks~</p>\n<p>Milton</p>",
  "messages": [
    {
      "id": "39127",
      "postDate": "02/20/2014 08:58:01",
      "content": "<p>Hi, all,</p>\n<p>I 'd rather to know that is there any example code for introduction to this competition? Becuase I'm new to this galaxy recognition domain.</p>\n<p>&nbsp;</p>\n<p>Thanks~</p>\n<p>Milton</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "40039",
      "postDate": "03/09/2014 11:54:15",
      "content": "<p>Hi,<br>Sorry for late response. Anyways, below is sample code I used to extract features from training data set. Similarly it needs to be run for test data set.&nbsp;<br><br><em>Remarks:</em> <br>- run time can be 3-6 days (separately for both training and test) depending from your hardware.<br>- images are not properly pre-processed (like histogram equalized). However I have checked that marginal distributions of features are roughly same for training and test data sets.<br>- Fourier transform is not proper (should be 2D and not 1D)<br>- I am converting RGB data to gray using formula: 0.21*red + 0.72*green + 0.07*blue - thus color information is lost (feel free to add colour channel features too)<br>- I my experiements I am fitting regression tree per class, this example just has sample code for Output1.1 class at the end. So you need to do either 37 separate trees (to output all classes), or you could do multivariate regression tree (which predicts all 37 simultaneously) - I am not sure how well it would perform.<br>- This sample fits only one regression tree (thus no ensemble). I have also tested linear regression, logistic regression, support vector regression and random forest. However I have found sgbm = stochastic gradient boosting to work best so far.<br><br><em>Required files:</em><br>-&nbsp;training_solutions_rev1.csv and training data jpg files must be in folder where R is being run (you can set working directory using setwd(&quot;c:\\\\temp&quot;) -&nbsp;if you have all files in c:\\temp.</p>\n<p><em>Required R packages </em>(these you must install, running R as admin, using command install.packages and if I recall correctly EBImage required a bit more complicated install)<em>:&nbsp;</em><br>-fractaldim<br>-biOps<br>-EBImage<br>-rpart</p>\n<p><br><strong>Sample R Code:</strong></p>\n<p># Include needed libraries<br>library(fractaldim) <br>library(biOps) <br>library(EBImage)<br>library(rpart)</p>\n<p># Set random number generator seed (so that results can be replicated later)<br>set.seed(1234)</p>\n<p># get training solutions (to figure out jpeg filenames and also to get Y values = ClassX.Y)<br>trSolutions &lt;- read.csv(&quot;training_solutions_rev1.csv&quot;, header=TRUE)</p>\n<p># Basic features<br>distinctValues &lt;- NULL<br>meanv &lt;- NULL<br>logmean &lt;- NULL<br>medianv &lt;- NULL<br>sd &lt;- NULL<br>qr &lt;- NULL<br>logsd &lt;- NULL<br>q25 &lt;- NULL<br>q75 &lt;- NULL</p>\n<p># Fractal features<br>fd1 &lt;- NULL<br>fd2 &lt;- NULL<br>fd3 &lt;- NULL</p>\n<p># Fourier features<br>fftConcentration &lt;- NULL<br>fftReal &lt;- NULL<br>fftImaginary &lt;- NULL</p>\n<p># Gray tail mass distribution features<br>linFitAlpha &lt;- NULL<br>linFitBeta &lt;- NULL</p>\n<p># Blob features<br>blobs &lt;- NULL<br>meanMass &lt;- NULL<br>medianMass &lt;- NULL<br>sdMass &lt;- NULL<br>maxMass &lt;- NULL<br>countSD1Mass &lt;- NULL<br>countSD2Mass &lt;- NULL<br>countSD3Mass &lt;- NULL<br>countSD4Mass &lt;- NULL</p>\n<p>#<br># Loop over all training data (= images)<br>#<br>for(imgi in 1:nrow(trSolutions)){</p>\n<p># Load JPEG file<br>print(sprintf(&quot;Processing %s (%d/%d)&quot;, trSolutions$GalaxyID[imgi], imgi, nrow(trSolutions)))<br>flush.console()<br>x &lt;- readJpeg(sprintf(&quot;%s.jpg&quot;, trSolutions$GalaxyID[imgi]))</p>\n<p>#<br># Extract features from images<br>#</p>\n<p># Calculate number of blobs<br>y = thresh(x, 10, 10, 0.10)<br>y = opening(y, makeBrush(5, shape=&quot;disc&quot;))<br>z = bwlabel(y)<br>blobs[imgi] &lt;- max(z)</p>\n<p># Calculate blob segments<br>blobMassDistribution &lt;- table(z)<br>segment &lt;- rownames(blobMassDistribution)<br>mass &lt;- as.numeric(blobMassDistribution)<br>massTable &lt;- data.frame(segment,mass)</p>\n<p># Remove background blob<br>massTableFiltered &lt;- massTable[ massTable$mass &lt; max(massTable$mass),]</p>\n<p># Calculate blob mass distribution features (simple statistics)<br>meanMass[imgi] &lt;- mean(massTableFiltered$mass)<br>medianMass[imgi] &lt;- median(massTableFiltered$mass)<br>sdMass[imgi] &lt;- sd(massTableFiltered$mass)<br>maxMass[imgi] &lt;- max(massTableFiltered$mass)</p>\n<p># Calculate number of &quot;big blobs&quot;, defined by 1,2,3 and 4 standard mass deviations from mean mass<br>countSD1Mass[imgi] &lt;- sum(massTableFiltered$mass &gt;= meanMass[imgi] + 1*sdMass[imgi])<br>countSD2Mass[imgi] &lt;- sum(massTableFiltered$mass &gt;= meanMass[imgi] + 2*sdMass[imgi])<br>countSD3Mass[imgi] &lt;- sum(massTableFiltered$mass &gt;= meanMass[imgi] + 3*sdMass[imgi])<br>countSD4Mass[imgi] &lt;- sum(massTableFiltered$mass &gt;= meanMass[imgi] + 4*sdMass[imgi])</p>\n<p>dims &lt;- dim(x)<br>plot(x) <br>img &lt;- data.frame(x)</p>\n<p>xsize &lt;- min (dim(img))<br>ysize &lt;- xsize</p>\n<p># get R,G,B channels data<br>red &lt;- (img[, 1:ysize])<br>green &lt;- (img[, (ysize+1):(ysize*2)])<br>blue &lt;- (img[, (ysize*2+1):(ysize*3)])</p>\n<p># convert to gray levels<br>gray &lt;- as.integer(unlist(0.21 * red + 0.72 * green + 0.07 * blue))</p>\n<p><br>plevels &lt;- table(gray)<br>distinctValues[imgi] &lt;- length(rownames(plevels))<br>levelValues &lt;- as.integer( rownames(plevels) )</p>\n<p>densityValues &lt;- as.numeric (plevels)<br>cumulativeValues &lt;- cumsum(densityValues)<br>cumulativeProbabilityValues &lt;- cumulativeValues / max(cumulativeValues)</p>\n<p>standardizedLevelValues &lt;- (levelValues - min(levelValues)) / (max(levelValues)-min(levelValues))<br>massd &lt;- data.frame(rowIndex=1:length(levelValues),standardizedLevelValues,cumulativeProbabilityValues)</p>\n<p># Left truncate by 10% (to remove &quot;darkness from background&quot; and focus to more interesting part of mass distribution)<br>dropIndex &lt;- as.integer(length(levelValues) * 0.10)<br>massd &lt;- massd[massd$rowIndex &gt; dropIndex,]</p>\n<p>massd$standardizedLevelValues &lt;- massd$standardizedLevelValues - min(massd$standardizedLevelValues)<br>massd$standardizedLevelValues &lt;- sqrt(massd$standardizedLevelValues)<br>linfit &lt;- lm(cumulativeProbabilityValues~standardizedLevelValues, data=massd)<br>linFitAlpha[imgi] &lt;- as.numeric(linfit$coefficients[1])<br>linFitBeta[imgi] &lt;- as.numeric(linfit$coefficients[2])</p>\n<p># Calculate basic features<br>meanv[imgi] &lt;- mean(gray)<br>logmean[imgi] &lt;- mean(log(1+gray))<br>medianv[imgi] &lt;- median(gray)<br>sd[imgi] &lt;- sd(gray)<br>logsd[imgi] &lt;- sd(log(1+gray))<br>q25[imgi] &lt;- quantile(gray, 0.25)<br>q75[imgi] &lt;- quantile(gray, 0.75)<br>qr[imgi] &lt;- q75[imgi] - q25[imgi]</p>\n<p># Calculate Fourier transform features<br>fourierTrans &lt;- fft(gray)<br>fftConcentration[imgi] &lt;- mean( abs(fourierTrans) ) # the more peaked around 0,0 at complex space the more periodical<br>fftReal[imgi] &lt;- mean( abs(Re(fourierTrans)) )<br>fftImaginary[imgi] &lt;- mean( abs(Im(fourierTrans)) )</p>\n<p># Calculate fractal dimension (3 diff. estimates)<br>dim(gray) &lt;- c(xsize, ysize)<br>d1 &lt;- fd.estim.isotropic(gray, p.index = 1, direction='hv', plot.loglog = FALSE, plot.allpoints = FALSE)<br>fd1[imgi] &lt;- d1$fd</p>\n<p>d2 &lt;- fd.estim.squareincr(gray, p.index = 1, plot.loglog = FALSE, plot.allpoints = FALSE)<br>fd2[imgi] &lt;- d2$fd</p>\n<p>d3 &lt;- fd.estim.filter1(gray, p.index = 1, plot.loglog = FALSE, plot.allpoints = FALSE)<br>fd3[imgi] &lt;- d3$fd<br>}</p>\n<p>#<br># Attach training data and gathered features<br>#<br>outputData &lt;- trSolutions<br>outputData$distinctValues &lt;- distinctValues<br>outputData$meanv &lt;- meanv<br>outputData$logmean &lt;- logmean<br>outputData$medianv &lt;- medianv<br>outputData$sd &lt;- sd<br>outputData$qr &lt;- qr<br>outputData$logsd &lt;- logsd<br>outputData$q25 &lt;- q25<br>outputData$q75 &lt;- q75<br>outputData$fd1 &lt;- fd1<br>outputData$fd2 &lt;- fd2<br>outputData$fd3 &lt;- fd3<br>outputData$fftConcentration &lt;-fftConcentration<br>outputData$fftReal &lt;-fftReal<br>outputData$fftImaginary &lt;- fftImaginary<br>outputData$linFitAlpha &lt;- linFitAlpha<br>outputData$linFitBeta &lt;- linFitBeta<br>outputData$meanMass &lt;- meanMass<br>outputData$medianMass &lt;- medianMass<br>outputData$sdMass &lt;- sdMass<br>outputData$maxMass &lt;- maxMass<br>outputData$countSD1Mass &lt;- countSD1Mass<br>outputData$countSD2Mass &lt;- countSD2Mass<br>outputData$countSD3Mass &lt;- countSD3Mass<br>outputData$countSD4Mass &lt;- countSD4Mass<br>outputData$blobs &lt;- blobs<br>outputData$GalaxyID &lt;- NULL</p>\n<p><br># Save outputs<br>write.csv(outputData, &quot;outputData.csv&quot;)</p>\n<p># Fit sample regression tree to predict Class1.1 (you need to do similarly for others classes).<br># and feel free to add variable selection etc<br>fit &lt;- rpart(Class1.1 ~ meanMass+medianMass+countSD1Mass+countSD2Mass+countSD3Mass+countSD4Mass+blobs+linFitAlpha+linFitBeta <br>+fftConcentration+fftReal+fftImaginary+meanv+sd+logsd+medianv+fd1+fd2+fd3+distinctValues+maxMass+sdMass, data=outputData)<br># Calculate mean squared error for tree prediction and for unconditional mean prediction<br>mseTree &lt;- mean( (predict(fit) - outputData$Class1.1)^2 )<br>mseMean &lt;- mean( (mean(outputData$Class1.1) - outputData$Class1.1)^2 )</p>\n<p># If improvement is clearly &lt; 1 then fitting regression tree was worth it, provided it did not over-fit <br># to data which you need to check separately,&nbsp;(= result is better than unconditional mean estimate)<br>improvement &lt;- mseTree/mseMean</p>",
      "rawMarkdown": "",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 40039,
      "author_name": "sfin2015",
      "author_url": "",
      "post_date": "03/09/2014 11:54:15",
      "content": "<p>Hi,<br>Sorry for late response. Anyways, below is sample code I used to extract features from training data set. Similarly it needs to be run for test data set.&nbsp;<br><br><em>Remarks:</em> <br>- run time can be 3-6 days (separately for both training and test) depending from your hardware.<br>- images are not properly pre-processed (like histogram equalized). However I have checked that marginal distributions of features are roughly same for training and test data sets.<br>- Fourier transform is not proper (should be 2D and not 1D)<br>- I am converting RGB data to gray using formula: 0.21*red + 0.72*green + 0.07*blue - thus color information is lost (feel free to add colour channel features too)<br>- I my experiements I am fitting regression tree per class, this example just has sample code for Output1.1 class at the end. So you need to do either 37 separate trees (to output all classes), or you could do multivariate regression tree (which predicts all 37 simultaneously) - I am not sure how well it would perform.<br>- This sample fits only one regression tree (thus no ensemble). I have also tested linear regression, logistic regression, support vector regression and random forest. However I have found sgbm = stochastic gradient boosting to work best so far.<br><br><em>Required files:</em><br>-&nbsp;training_solutions_rev1.csv and training data jpg files must be in folder where R is being run (you can set working directory using setwd(&quot;c:\\\\temp&quot;) -&nbsp;if you have all files in c:\\temp.</p>\n<p><em>Required R packages </em>(these you must install, running R as admin, using command install.packages and if I recall correctly EBImage required a bit more complicated install)<em>:&nbsp;</em><br>-fractaldim<br>-biOps<br>-EBImage<br>-rpart</p>\n<p><br><strong>Sample R Code:</strong></p>\n<p># Include needed libraries<br>library(fractaldim) <br>library(biOps) <br>library(EBImage)<br>library(rpart)</p>\n<p># Set random number generator seed (so that results can be replicated later)<br>set.seed(1234)</p>\n<p># get training solutions (to figure out jpeg filenames and also to get Y values = ClassX.Y)<br>trSolutions &lt;- read.csv(&quot;training_solutions_rev1.csv&quot;, header=TRUE)</p>\n<p># Basic features<br>distinctValues &lt;- NULL<br>meanv &lt;- NULL<br>logmean &lt;- NULL<br>medianv &lt;- NULL<br>sd &lt;- NULL<br>qr &lt;- NULL<br>logsd &lt;- NULL<br>q25 &lt;- NULL<br>q75 &lt;- NULL</p>\n<p># Fractal features<br>fd1 &lt;- NULL<br>fd2 &lt;- NULL<br>fd3 &lt;- NULL</p>\n<p># Fourier features<br>fftConcentration &lt;- NULL<br>fftReal &lt;- NULL<br>fftImaginary &lt;- NULL</p>\n<p># Gray tail mass distribution features<br>linFitAlpha &lt;- NULL<br>linFitBeta &lt;- NULL</p>\n<p># Blob features<br>blobs &lt;- NULL<br>meanMass &lt;- NULL<br>medianMass &lt;- NULL<br>sdMass &lt;- NULL<br>maxMass &lt;- NULL<br>countSD1Mass &lt;- NULL<br>countSD2Mass &lt;- NULL<br>countSD3Mass &lt;- NULL<br>countSD4Mass &lt;- NULL</p>\n<p>#<br># Loop over all training data (= images)<br>#<br>for(imgi in 1:nrow(trSolutions)){</p>\n<p># Load JPEG file<br>print(sprintf(&quot;Processing %s (%d/%d)&quot;, trSolutions$GalaxyID[imgi], imgi, nrow(trSolutions)))<br>flush.console()<br>x &lt;- readJpeg(sprintf(&quot;%s.jpg&quot;, trSolutions$GalaxyID[imgi]))</p>\n<p>#<br># Extract features from images<br>#</p>\n<p># Calculate number of blobs<br>y = thresh(x, 10, 10, 0.10)<br>y = opening(y, makeBrush(5, shape=&quot;disc&quot;))<br>z = bwlabel(y)<br>blobs[imgi] &lt;- max(z)</p>\n<p># Calculate blob segments<br>blobMassDistribution &lt;- table(z)<br>segment &lt;- rownames(blobMassDistribution)<br>mass &lt;- as.numeric(blobMassDistribution)<br>massTable &lt;- data.frame(segment,mass)</p>\n<p># Remove background blob<br>massTableFiltered &lt;- massTable[ massTable$mass &lt; max(massTable$mass),]</p>\n<p># Calculate blob mass distribution features (simple statistics)<br>meanMass[imgi] &lt;- mean(massTableFiltered$mass)<br>medianMass[imgi] &lt;- median(massTableFiltered$mass)<br>sdMass[imgi] &lt;- sd(massTableFiltered$mass)<br>maxMass[imgi] &lt;- max(massTableFiltered$mass)</p>\n<p># Calculate number of &quot;big blobs&quot;, defined by 1,2,3 and 4 standard mass deviations from mean mass<br>countSD1Mass[imgi] &lt;- sum(massTableFiltered$mass &gt;= meanMass[imgi] + 1*sdMass[imgi])<br>countSD2Mass[imgi] &lt;- sum(massTableFiltered$mass &gt;= meanMass[imgi] + 2*sdMass[imgi])<br>countSD3Mass[imgi] &lt;- sum(massTableFiltered$mass &gt;= meanMass[imgi] + 3*sdMass[imgi])<br>countSD4Mass[imgi] &lt;- sum(massTableFiltered$mass &gt;= meanMass[imgi] + 4*sdMass[imgi])</p>\n<p>dims &lt;- dim(x)<br>plot(x) <br>img &lt;- data.frame(x)</p>\n<p>xsize &lt;- min (dim(img))<br>ysize &lt;- xsize</p>\n<p># get R,G,B channels data<br>red &lt;- (img[, 1:ysize])<br>green &lt;- (img[, (ysize+1):(ysize*2)])<br>blue &lt;- (img[, (ysize*2+1):(ysize*3)])</p>\n<p># convert to gray levels<br>gray &lt;- as.integer(unlist(0.21 * red + 0.72 * green + 0.07 * blue))</p>\n<p><br>plevels &lt;- table(gray)<br>distinctValues[imgi] &lt;- length(rownames(plevels))<br>levelValues &lt;- as.integer( rownames(plevels) )</p>\n<p>densityValues &lt;- as.numeric (plevels)<br>cumulativeValues &lt;- cumsum(densityValues)<br>cumulativeProbabilityValues &lt;- cumulativeValues / max(cumulativeValues)</p>\n<p>standardizedLevelValues &lt;- (levelValues - min(levelValues)) / (max(levelValues)-min(levelValues))<br>massd &lt;- data.frame(rowIndex=1:length(levelValues),standardizedLevelValues,cumulativeProbabilityValues)</p>\n<p># Left truncate by 10% (to remove &quot;darkness from background&quot; and focus to more interesting part of mass distribution)<br>dropIndex &lt;- as.integer(length(levelValues) * 0.10)<br>massd &lt;- massd[massd$rowIndex &gt; dropIndex,]</p>\n<p>massd$standardizedLevelValues &lt;- massd$standardizedLevelValues - min(massd$standardizedLevelValues)<br>massd$standardizedLevelValues &lt;- sqrt(massd$standardizedLevelValues)<br>linfit &lt;- lm(cumulativeProbabilityValues~standardizedLevelValues, data=massd)<br>linFitAlpha[imgi] &lt;- as.numeric(linfit$coefficients[1])<br>linFitBeta[imgi] &lt;- as.numeric(linfit$coefficients[2])</p>\n<p># Calculate basic features<br>meanv[imgi] &lt;- mean(gray)<br>logmean[imgi] &lt;- mean(log(1+gray))<br>medianv[imgi] &lt;- median(gray)<br>sd[imgi] &lt;- sd(gray)<br>logsd[imgi] &lt;- sd(log(1+gray))<br>q25[imgi] &lt;- quantile(gray, 0.25)<br>q75[imgi] &lt;- quantile(gray, 0.75)<br>qr[imgi] &lt;- q75[imgi] - q25[imgi]</p>\n<p># Calculate Fourier transform features<br>fourierTrans &lt;- fft(gray)<br>fftConcentration[imgi] &lt;- mean( abs(fourierTrans) ) # the more peaked around 0,0 at complex space the more periodical<br>fftReal[imgi] &lt;- mean( abs(Re(fourierTrans)) )<br>fftImaginary[imgi] &lt;- mean( abs(Im(fourierTrans)) )</p>\n<p># Calculate fractal dimension (3 diff. estimates)<br>dim(gray) &lt;- c(xsize, ysize)<br>d1 &lt;- fd.estim.isotropic(gray, p.index = 1, direction='hv', plot.loglog = FALSE, plot.allpoints = FALSE)<br>fd1[imgi] &lt;- d1$fd</p>\n<p>d2 &lt;- fd.estim.squareincr(gray, p.index = 1, plot.loglog = FALSE, plot.allpoints = FALSE)<br>fd2[imgi] &lt;- d2$fd</p>\n<p>d3 &lt;- fd.estim.filter1(gray, p.index = 1, plot.loglog = FALSE, plot.allpoints = FALSE)<br>fd3[imgi] &lt;- d3$fd<br>}</p>\n<p>#<br># Attach training data and gathered features<br>#<br>outputData &lt;- trSolutions<br>outputData$distinctValues &lt;- distinctValues<br>outputData$meanv &lt;- meanv<br>outputData$logmean &lt;- logmean<br>outputData$medianv &lt;- medianv<br>outputData$sd &lt;- sd<br>outputData$qr &lt;- qr<br>outputData$logsd &lt;- logsd<br>outputData$q25 &lt;- q25<br>outputData$q75 &lt;- q75<br>outputData$fd1 &lt;- fd1<br>outputData$fd2 &lt;- fd2<br>outputData$fd3 &lt;- fd3<br>outputData$fftConcentration &lt;-fftConcentration<br>outputData$fftReal &lt;-fftReal<br>outputData$fftImaginary &lt;- fftImaginary<br>outputData$linFitAlpha &lt;- linFitAlpha<br>outputData$linFitBeta &lt;- linFitBeta<br>outputData$meanMass &lt;- meanMass<br>outputData$medianMass &lt;- medianMass<br>outputData$sdMass &lt;- sdMass<br>outputData$maxMass &lt;- maxMass<br>outputData$countSD1Mass &lt;- countSD1Mass<br>outputData$countSD2Mass &lt;- countSD2Mass<br>outputData$countSD3Mass &lt;- countSD3Mass<br>outputData$countSD4Mass &lt;- countSD4Mass<br>outputData$blobs &lt;- blobs<br>outputData$GalaxyID &lt;- NULL</p>\n<p><br># Save outputs<br>write.csv(outputData, &quot;outputData.csv&quot;)</p>\n<p># Fit sample regression tree to predict Class1.1 (you need to do similarly for others classes).<br># and feel free to add variable selection etc<br>fit &lt;- rpart(Class1.1 ~ meanMass+medianMass+countSD1Mass+countSD2Mass+countSD3Mass+countSD4Mass+blobs+linFitAlpha+linFitBeta <br>+fftConcentration+fftReal+fftImaginary+meanv+sd+logsd+medianv+fd1+fd2+fd3+distinctValues+maxMass+sdMass, data=outputData)<br># Calculate mean squared error for tree prediction and for unconditional mean prediction<br>mseTree &lt;- mean( (predict(fit) - outputData$Class1.1)^2 )<br>mseMean &lt;- mean( (mean(outputData$Class1.1) - outputData$Class1.1)^2 )</p>\n<p># If improvement is clearly &lt; 1 then fitting regression tree was worth it, provided it did not over-fit <br># to data which you need to check separately,&nbsp;(= result is better than unconditional mean estimate)<br>improvement &lt;- mseTree/mseMean</p>",
      "votes": null,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "39127": "",
    "40039": ""
  },
  "source": "meta"
}