<jupyter_start><jupyter_text>Metrics for Classification and Regression`deeplenstronomy` is designed for the purpose of facilitating machine and deep-learning studies of strong gravitational lensing. Supervised problems in these fields are typically framed as either classification problems or regression problems. This notebook will illustrate how you might utilize the features of `deeplenstronomy` to aid the development of your classification and regression algorithms.Let's start by simulating a dataset with the `demo_distributions.yaml` file, and we'll also utilize the `solve_lens_equation` and `return_planes` arguments of `deeplenstronomy.makedataset()`:<jupyter_code>import deeplenstronomy.deeplenstronomy as dl
dataset = dl.make_dataset("data/demo_distributions.yaml", solve_lens_equation=True, return_planes=True, verbose=True)<jupyter_output>Entering main organization loop
Organizing CONFIGURATION_1
Generating images for CONFIGURATION_1
	Progress: 100.0 %  ---  Elapsed Time: 0 H 1 M 57 S<jupyter_text>Classification A simple, straightforward approachFor classification tasks, we are trying to predict a discretely-valued variable. The simplest approach to do this in `deeplenstronomy` is to classify the images from one configuration against the images in another configuration, with the configuration label serving as your discrete variable. If you take that simple approach, structure each `CONFIGURATION` section in the `GEOMETRY` section to be one of the classes in your classification problem. A classic approachIn strong lensing searches, the terminology of "quads" and "doubles" are often used to describe the type of lensing going on (refering to the number of images of the source galaxy produced by the lensing). If you would like to classify based on the number of images of the source object, you can use the `solve_lens_equation` argument of `deeplenstronomy.makedataset()` to your advantage.Setting this argument to `True` will add several columns to your dataset's metadata:<jupyter_code>metric_cols = ['num_source_images-g',
               'num_source_images-r',
               'num_source_images-i',
               'num_source_images-z',
               'num_source_images-Y']

dataset.CONFIGURATION_1_metadata[metric_cols].head()<jupyter_output><empty_output><jupyter_text>There will be a column of `num_source_images` for each band you choose to simulate. Using these columns you can determine which images contain quads, doubles, or no lensing. There are also columns such as `x_mins_g`, `y_mins_g`, `x_mins_r`, etc. for each band. These columns contain the information of the locations of each of the found positions of the lensed source object in your images.  RegressionTraditionally, strong lensing has been treated as a classification problem. However, there exist corner cases of slightly aligned galaxies that may produce small amounts of lensing as opposed to magnificent arcs and multiple images. If these corner cases exist in your training dataset, your classification algorithm may struggle with them. Framing lens detection as a regression problem is an interesting solution where instead of asking "Is this a lens?" or "Is this a quad?" you ask "How lensy is this image?"To make this type of approach possible, you need to define a continuous variable that reflects the amount of lensing in the system. A mathematical approach to this is by calculating a quantity called the "Strong Lensing Cross Section," and as an open source framework, you are welcome to submit a pull-request to add this calculation to `deeplenstronomy`. Another option that is possible with the current implementation of `deeplenstronomy` is to utilize the light from the source plane separate from all other light. Naively, if there is a lot of lensing going on, there will be a lot of light in the source plane, and if there is only a small amount of lensing then one would also expect a small amount of light in the source plane. This argument has to be normalized by the un-lensed brightness of the objects in the source plane, but is still a useable metric.You can access this information by setting the `return_planes` argument to `True`. When you use this setting, your dataset will gain a new attribute for each configuration:<jupyter_code>[x for x in dir(dataset) if x.endswith('planes')]
type(dataset.CONFIGURATION_1_planes)
dataset.CONFIGURATION_1_planes.shape<jupyter_output><empty_output><jupyter_text>The `planes` for each configuration will be a numpy array with the following dimension structure:- 0: the index of the image- 1: the index of the plane- 2: the index of the band- 3: the row index in each image- 4: the column index in each imageSpecifically, the `plane` axis is ordered as ("Lens Plane", "Source Plane", "Point Sources", "Noise"). Thus you can access all the source planes like this:<jupyter_code>source_planes = dataset.CONFIGURATION_1_planes[:,1,:,:,:]<jupyter_output><empty_output><jupyter_text>From this point, you can define a metric of your choice to characterize the amount of lensing going on. A simple example could be the number of pixels with brightness above a certain threshold in a single band (the $g$-band in this case):<jupyter_code>import numpy as np
threshold = 5.0
metric = np.sum(np.where(source_planes[:,0,:,:] > threshold, 1, 0), axis=(-1,-2))
print(metric)<jupyter_output>[1398 1156  492 1714 2832  434  526  654  800 1552 1430 1258  274  818
 1190  720  418  724  620  798  724 3306  804  954  464  488  488 1276
  800  646  818 4962 1258  496  718 1548  470  588  800  670  244  956
  502  474  508  818 1478 3106 2286  998  778  522  468  614 2442  856
  566 1156 2688 1146  424  352  356  856 1198  218  438 1098  854 1002
  398  790  472  806  388  466  646  326 1076  994  882 1998  510  928
 1114 1056  540  634  880 2186 1616  656  782  642 1766 1502  704  402
  514 1098 2198  236  592  422 2054  946  416  944  754 1536 1028  630
 1548  548 1856 1012  888 1568  550 1498 1684  576  634  350 1618 1122
  184 1358  458  872 1478  820  952 2264 1730 1710  444 1598  750  412
  882  420 1178 1218 1574 1318 1890  680 1356  578  546  692  960  994
 1118  830 1664 1062 1050  642  354  444 3306  344  788 1554  832 1232
 1088  698  364  764  602  742  534 1116 1676  812  948 1604 1546 1294
  558  854  914 1034  378 1824 1584  430 1024  838 1780 1300  514  814
  880 [...]
{'fraction_non_alphanumeric': 0.0483160214038401, 'fraction_numerical': 0.10906515580736544, 'mean_word_length': 4.399320305862362, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '600267', 'license': 'MIT', 'n_tokens_mistral': 2286, 'n_tokens_neox': 1753, 'n_words': 902, 'path': 'Notebooks/Metrics.ipynb', 'repo_name': 'erikzaborowski/deeplenstronomy', 'size': '6354'}