{"metadata":{"kernelspec":{"display_name":"R","language":"R","name":"ir"},"language_info":{"codemirror_mode":"r","file_extension":".r","mimetype":"text/x-r-source","name":"R","pygments_lexer":"r","version":"4.4.0"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":112509,"databundleVersionId":14254895,"isSourceIdPinned":false,"sourceType":"competition"}],"dockerImageVersionId":30749,"isInternetEnabled":false,"language":"r","sourceType":"notebook","isGpuEnabled":false},"papermill":{"default_parameters":{},"duration":6250.94778,"end_time":"2025-05-28T16:47:04.832479","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2025-05-28T15:02:53.884699","version":"2.6.0"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"\n# <div align=\"center\"> CSIRO - Image2Biomass Prediction\n    \n\n<div align=\"center\"> <img src=\"https://www.kaggle.com/competitions/112509/images/header\" width=\"300\"></div><br>\n\n**From the competition material**: Build models that predict pasture biomass from images, ground-truth measurements, and publicly available datasets. Farmers will use these models to determine when and how to graze their livestock. Your file must contain one row per (image, target) pair, i.e., 5 rows for each image in the test set.\n\n**Evaluation**: The model performance is evaluated using a weighted average of R2 scores across the five output dimensions. ","metadata":{"papermill":{"duration":0.009826,"end_time":"2025-05-28T15:02:57.461519","exception":false,"start_time":"2025-05-28T15:02:57.451693","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"# 📚 Libraries","metadata":{"papermill":{"duration":0.008642,"end_time":"2025-05-28T15:02:57.479987","exception":false,"start_time":"2025-05-28T15:02:57.471345","status":"completed"},"tags":[]}},{"cell_type":"code","source":"library(tidyverse) # metapackage of all tidyverse packages\nlibrary(ggthemes)\nlibrary(RColorBrewer)\nlibrary(jpeg)","metadata":{"_execution_state":"idle","_kg_hide-input":true,"_kg_hide-output":true,"_uuid":"051d70d956493feee0c6d64651c6a088724dca2a","execution":{"iopub.status.busy":"2025-10-29T20:07:25.484693Z","iopub.execute_input":"2025-10-29T20:07:25.486568Z","iopub.status.idle":"2025-10-29T20:07:25.503653Z","shell.execute_reply":"2025-10-29T20:07:25.501958Z"},"papermill":{"duration":10.26197,"end_time":"2025-05-28T15:03:07.750417","exception":false,"start_time":"2025-05-28T15:02:57.488447","status":"completed"},"tags":[],"trusted":true,"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 🔍 Exploratory Data Analysis (EDA)","metadata":{"papermill":{"duration":0.010092,"end_time":"2025-05-28T15:03:07.770272","exception":false,"start_time":"2025-05-28T15:03:07.760180","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# Reading in the competition material\ntrain <- read.csv('//kaggle/input/csiro-biomass/train.csv') \ntest <- read.csv('//kaggle/input/csiro-biomass/test.csv') \nsample_submission <- read.csv('/kaggle/input/csiro-biomass/sample_submission.csv')","metadata":{"execution":{"iopub.status.busy":"2025-10-29T20:07:25.506352Z","iopub.execute_input":"2025-10-29T20:07:25.507719Z","iopub.status.idle":"2025-10-29T20:07:25.563516Z","shell.execute_reply":"2025-10-29T20:07:25.561815Z"},"papermill":{"duration":1.225242,"end_time":"2025-05-28T15:03:09.005366","exception":false,"start_time":"2025-05-28T15:03:07.780124","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### train.csv","metadata":{"papermill":{"duration":0.008873,"end_time":"2025-05-28T15:03:09.023119","exception":false,"start_time":"2025-05-28T15:03:09.014246","status":"completed"},"tags":[]}},{"cell_type":"code","source":"print(paste('train_sequences has', dim(train)[1], 'rows and', dim(train)[2], 'columns'))\nprint(paste('train_sequences has', sum(is.na(train)), 'NAs.'))\n\n# Quick look at the data\ntrain %>% head(3)\n\n# There are no NAs in this dataset","metadata":{"execution":{"iopub.status.busy":"2025-10-29T20:07:25.566251Z","iopub.execute_input":"2025-10-29T20:07:25.567584Z","iopub.status.idle":"2025-10-29T20:07:25.606249Z","shell.execute_reply":"2025-10-29T20:07:25.604485Z"},"papermill":{"duration":0.057249,"end_time":"2025-05-28T15:03:09.089340","exception":false,"start_time":"2025-05-28T15:03:09.032091","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Sampling_Date — Date of sample collection.","metadata":{}},{"cell_type":"code","source":"\nunique_dates_cnt <- train %>% select(Sampling_Date) %>% unique() %>% count()\nprint(paste(\"There are\",unique_dates_cnt,\"unique Sampling_Dates in the dataset.\"))\nprint('There are 0 samples for the month of March 2015.')\n\noptions(repr.plot.width=15, repr.plot.height=8)\ntrain %>% mutate(Sampling_Month = month(ymd(Sampling_Date))) %>% group_by(Sampling_Month) %>% summarize(total = n()) %>% \nggplot(aes(x=as.factor(Sampling_Month), y=total)) + geom_bar(fill = 'steelblue', color='black', stat='identity') + geom_text(aes(label = total),vjust=-1) + \nggtitle(\"Samples per month for 2015\") + xlab('Sampling Month') + theme_minimal()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-29T20:07:25.608939Z","iopub.execute_input":"2025-10-29T20:07:25.610287Z","iopub.status.idle":"2025-10-29T20:07:26.166873Z","shell.execute_reply":"2025-10-29T20:07:26.165058Z"},"_kg_hide-input":true,"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### State — Australian state where sample was collected.","metadata":{}},{"cell_type":"code","source":"\nunique_state_cnt <- train %>% select(State) %>% unique() %>% count()\nprint(paste(\"There are\",unique_state_cnt,\"unique States in the dataset.\"))\n\noptions(repr.plot.width=15, repr.plot.height=8)\ntrain %>%  group_by(State) %>% summarize(total = n()) %>% \nggplot(aes(x=State, y=total)) + geom_bar(fill = 'slategray2', color='black', stat='identity') + geom_text(aes(label = total),hjust=-.5) + \nggtitle(\"Samples per Australian State\") + xlab('State') + coord_flip() + theme_minimal() + theme(axis.text.y = element_text(size = 15)) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-29T20:07:26.169849Z","iopub.execute_input":"2025-10-29T20:07:26.171193Z","iopub.status.idle":"2025-10-29T20:07:26.559499Z","shell.execute_reply":"2025-10-29T20:07:26.557632Z"},"_kg_hide-input":true,"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nunique_species_cnt <- train %>% select(Species) %>% unique() %>% count()\nprint(paste(\"There are\",unique_species_cnt,\"unique Species in the dataset.\"))\n\noptions(repr.plot.width=20, repr.plot.height=8)\ntrain %>%  group_by(Species) %>% summarize(total = n()) %>% \nggplot(aes(x=Species, y=total)) + geom_bar(fill = 'turquoise', color='black', stat='identity') + geom_text(aes(label = total),hjust=-.5) + \nggtitle(\"Species counts in train dataset\") + xlab('Species') + coord_flip() + theme_minimal() + theme(axis.text.y = element_text(size = 15)) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-29T20:07:26.562185Z","iopub.execute_input":"2025-10-29T20:07:26.563586Z","iopub.status.idle":"2025-10-29T20:07:26.924353Z","shell.execute_reply":"2025-10-29T20:07:26.922401Z"},"_kg_hide-input":true,"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Pre_GSHH_NDVI — Normalized Difference Vegetation Index (GreenSeeker) reading.","metadata":{}},{"cell_type":"markdown","source":"##### Initial look at all values:","metadata":{}},{"cell_type":"code","source":"\noptions(repr.plot.width=12, repr.plot.height=8)\ntrain %>% select(Pre_GSHH_NDVI) %>% ggplot(aes(x=Pre_GSHH_NDVI)) + geom_boxplot(outliers=TRUE) + theme_bw() + ggtitle('Pre_GSHH_NDVI readings in train dataset.')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-29T20:07:26.927079Z","iopub.execute_input":"2025-10-29T20:07:26.928459Z","iopub.status.idle":"2025-10-29T20:07:27.264183Z","shell.execute_reply":"2025-10-29T20:07:27.262266Z"},"_kg_hide-input":true,"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### Another look by Species:","metadata":{}},{"cell_type":"code","source":"\noptions(repr.plot.width=18, repr.plot.height=12)\nmy_palette <- colorRampPalette(RColorBrewer::brewer.pal(12,name = 'Set3'))(length(unique(train$Species)))\ntrain %>%  select(Pre_GSHH_NDVI, Species) %>% \nggplot(aes(x=Pre_GSHH_NDVI,y=Species,fill=Species)) + geom_boxplot() + coord_flip() + \ntheme_minimal()+ theme(axis.text.x = element_text(angle = 45, hjust = 1,size=16),legend.position = \"none\") +\nggtitle('Pre_GSHH_NDVI readings by Species in train dataset.') + scale_fill_manual(values = my_palette)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-29T20:07:27.266901Z","iopub.execute_input":"2025-10-29T20:07:27.268278Z","iopub.status.idle":"2025-10-29T20:07:27.927776Z","shell.execute_reply":"2025-10-29T20:07:27.925894Z"},"_kg_hide-input":true,"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Height_Ave_cm — Average pasture height measured by falling plate (cm).","metadata":{}},{"cell_type":"markdown","source":"##### Initial look at all values:","metadata":{}},{"cell_type":"code","source":"\noptions(repr.plot.width=12, repr.plot.height=8)\ntrain %>% select(Height_Ave_cm) %>% ggplot(aes(x=Height_Ave_cm)) + geom_boxplot(outliers=TRUE) + theme_bw() + ggtitle('Height_Ave_cm readings in train dataset.')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-29T20:07:27.930450Z","iopub.execute_input":"2025-10-29T20:07:27.931817Z","iopub.status.idle":"2025-10-29T20:07:28.241424Z","shell.execute_reply":"2025-10-29T20:07:28.239394Z"},"_kg_hide-input":true,"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### Again all values, without outliers:","metadata":{}},{"cell_type":"code","source":"\noptions(repr.plot.width=12, repr.plot.height=8)\ntrain %>% select(Height_Ave_cm) %>% ggplot(aes(x=Height_Ave_cm)) + geom_boxplot(outliers=FALSE) + theme_bw() + ggtitle('Height_Ave_cm readings in train dataset.(no outliers)')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-29T20:07:28.244225Z","iopub.execute_input":"2025-10-29T20:07:28.245623Z","iopub.status.idle":"2025-10-29T20:07:28.535043Z","shell.execute_reply":"2025-10-29T20:07:28.533082Z"},"_kg_hide-input":true,"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\noptions(repr.plot.width=18, repr.plot.height=12)\nmy_palette <- colorRampPalette(RColorBrewer::brewer.pal(12,name = 'Paired'))(length(unique(train$Species)))\ntrain %>%  select(Height_Ave_cm, Species) %>% \nggplot(aes(x=Height_Ave_cm,y=Species,fill=Species)) + geom_boxplot() + coord_flip() + \ntheme_minimal()+ theme(axis.text.x = element_text(angle = 45, hjust = 1,size=16),legend.position = \"none\") +\nggtitle('Height_Ave_cm readings by Species in train dataset.(no outliers)') + scale_fill_manual(values = my_palette)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-29T20:07:28.537859Z","iopub.execute_input":"2025-10-29T20:07:28.539241Z","iopub.status.idle":"2025-10-29T20:07:29.261370Z","shell.execute_reply":"2025-10-29T20:07:29.259299Z"},"_kg_hide-input":true,"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### target_name — Biomass component name for this row (Dry_Green_g, Dry_Dead_g, Dry_Clover_g, GDM_g, or Dry_Total_g).\n### target — Ground-truth biomass value (grams) corresponding to target_name for this image.","metadata":{}},{"cell_type":"code","source":"\nunique_target_name_cnt <- train %>% select(target_name) %>% unique() %>% count()\nprint(paste(\"There are\",unique_target_name_cnt,\"unique target_name in the dataset.\"))\nprint('The target is evenly distributed in the train dataset.')\n\noptions(repr.plot.width=15, repr.plot.height=8)\ntrain %>%  group_by(target_name) %>% summarize(total = n()) %>% \nggplot(aes(x=target_name, y=total)) + geom_bar(fill = 'slategray2', color='black', stat='identity') + geom_text(aes(label = total),hjust=-.5) + \nggtitle(\"Target_name distribution in train\") + xlab('target_name') + coord_flip() + theme_minimal() + theme(axis.text.y = element_text(size = 15)) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-29T20:07:29.264180Z","iopub.execute_input":"2025-10-29T20:07:29.265671Z","iopub.status.idle":"2025-10-29T20:07:29.615899Z","shell.execute_reply":"2025-10-29T20:07:29.613353Z"},"_kg_hide-input":true,"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\noptions(repr.plot.width=18, repr.plot.height=12)\n\ntrain %>%  select(target_name, target) %>% \nggplot(aes(x=target_name,y=target,fill=target_name)) + geom_boxplot() + \ntheme_minimal()+ theme(axis.text.x = element_text(angle = 45, hjust = 1,size=16),legend.position = \"none\") +\nggtitle('target readings by target_name in train dataset.') + scale_fill_brewer(palette = 'OrRd')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-29T20:07:29.618948Z","iopub.execute_input":"2025-10-29T20:07:29.620569Z","iopub.status.idle":"2025-10-29T20:07:30.084699Z","shell.execute_reply":"2025-10-29T20:07:30.082794Z"},"_kg_hide-input":true,"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\noptions(repr.plot.width=22, repr.plot.height=8)\ntrain %>% ggplot(aes(x=Height_Ave_cm,y=Pre_GSHH_NDVI,color=Species)) + geom_point(aes(size=target)) + theme_minimal() + ggtitle('Pre_GSHH_NDVI, Height_Ave_cm, by target size and Species.')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-29T20:07:30.087499Z","iopub.execute_input":"2025-10-29T20:07:30.088962Z","iopub.status.idle":"2025-10-29T20:07:31.007616Z","shell.execute_reply":"2025-10-29T20:07:31.005310Z"},"_kg_hide-input":true,"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Submission format","metadata":{"papermill":{"duration":0.019574,"end_time":"2025-05-28T15:03:16.381666","exception":false,"start_time":"2025-05-28T15:03:16.362092","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# This is our submission format\nsample_submission <- read.csv('/kaggle/input/csiro-biomass/sample_submission.csv')\nprint(paste('There are ',dim(sample_submission)[1], 'rows and',dim(sample_submission)[2], 'columns.'))\nsample_submission %>% head(6)\n\n# Note: The submission file must contain one row per (image, target) pair, i.e., 5 rows for each image in the test set.","metadata":{"papermill":{"duration":0.094022,"end_time":"2025-05-28T15:03:16.495808","exception":false,"start_time":"2025-05-28T15:03:16.401786","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-10-29T20:07:31.010571Z","iopub.execute_input":"2025-10-29T20:07:31.012067Z","iopub.status.idle":"2025-10-29T20:07:31.066908Z","shell.execute_reply":"2025-10-29T20:07:31.064617Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 🚜 Displaying images","metadata":{}},{"cell_type":"code","source":"img <- readJPEG(\"/kaggle/input/csiro-biomass/train/ID1011485656.jpg\")\n\nplot(1, 1, xlim = c(0, dim(img)[2]), ylim = c(0, dim(img)[1]),\n     asp = 1, type = 'n', xaxs = 'i', yaxs = 'i', xaxt = 'n', yaxt = 'n',\n     xlab = '', ylab = '', bty = 'n')\n\nrasterImage(img, 0, 0, dim(img)[2], dim(img)[1])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-29T20:07:31.069721Z","iopub.execute_input":"2025-10-29T20:07:31.071184Z","iopub.status.idle":"2025-10-29T20:07:33.213965Z","shell.execute_reply":"2025-10-29T20:07:33.209292Z"}},"outputs":[],"execution_count":null}]}