Settings Results in 4 milliseconds

Preprocessing Data For Machine Learning
Category: Databases

M ...


Views: 288 Likes: 118
Computer Vision in PyTorch (Part 1): Building Your First CNN for Pneumonia Detection
Computer Vision in PyTorch (Part 1) Building Your ...

Have you ever wondered how computers can recognize faces in photos or detect obstacles for self-driving cars? This capability stems from computer vision, the field of deep learning focused on enabling machines to interpret and understand visual information from the world around them. But how can this technology tackle more complex challenges, like analyzing medical images to aid diagnoses? In this two-part tutorial, you'll explore exactly that by learning how to use Convolutional Neural Networks (CNNs), a powerful type of neural network designed specifically for image analysis. You'll build your first CNN in PyTorch to analyze real chest X-ray images and identify signs of pneumonia. Whether you're new to computer vision or looking to apply your deep learning skills to a real-world problem, this tutorial series will guide you step-by-step through building, training, and evaluating your own image classification model. By the time you complete this tutorial, you will not only build your initial model but also be able to Explain how CNNs automatically extract important features from images. Understand the purpose of core CNN components like convolutional and pooling layers. Recognize why object-oriented programming is frequently used by professional deep learning practitioners. Define and build your own custom CNN architecture in PyTorch. Understanding the Pneumonia Detection Dataset Before we start designing our CNN architecture, let's first understand the dataset we'll be working with. This understanding will inform our design choices as we build out our model. We'll be working with a dataset of chest X-ray images labeled as either "NORMAL" or "PNEUMONIA." These medical images have specific characteristics we should keep in mind They're grayscale images (single-channel) rather than color (three-channel RGB) They contain subtle patterns that distinguish healthy lungs from those with pneumonia They show similar anatomical structures (lungs, heart, ribs) across patients, but with individual variations They have high resolution to capture fine details necessary for accurate diagnosis Here's what a NORMAL X-ray looks like (left) compared to a typical PNEUMONIA one (right) Notice how pneumonia appears as cloudy white areas in the lungs (which normally should be dark). These patterns are precisely what our CNN will learn to identify. Why CNNs Excel at Image Tasks If you've worked with traditional neural networks before, you might wonder why we need a specialized architecture for images. Why not just use a standard fully-connected network? If you were to try to train a traditional neural network on these X-ray images, you'd immediately face two major challenges Overwhelming parameter count A modest 256×256 grayscale X-ray contains 65,536 pixels. If we connected each pixel to just 1,000 neurons in the first hidden layer, we'd need over 65 million parameters for that layer alone! This would make the model Extremely slow to train Prone to severe overfitting Impractical for deployment in medical settings For perspective, the first convolutional layer in the CNN we will build in this tutorial achieves its initial feature extraction using only 320 parameters. Loss of critical spatial relationships When diagnosing pneumonia, the pattern and location of opacities in the lung matter tremendously. Traditional networks would immediately flatten images into 1D arrays, destroying the spatial information that doctors rely on. CNNs elegantly solve these problems through two ingenious design principles Local connectivity Rather than connecting to every pixel, each CNN neuron connects only to a small patch of the previous layer, much like how different parts of the visual cortex in our brains respond to specific regions of our visual field. This dramatically reduces parameters while preserving the ability to detect local patterns like the edges of lung structures. Parameter sharing The same set of filters (weights) is applied across the entire image. This makes intuitive sense since the feature that identifies pneumonia-related opacity should work regardless of whether it appears in the upper or lower lung. These design choices make CNNs particularly effective for analyzing medical images where accurately identifying spatial patterns can literally be a matter of life and death. Understanding CNN Components Now that we understand why CNNs are well-suited for image analysis, let's learn about the building blocks that make them work. These components will form the foundation of our pneumonia detection model. Convolutional Layers Are The Feature Extractors The heart of any CNN is the convolutional layer. Unlike standard fully-connected layers that look at all input values globally, convolutional layers work more like a magnifying glass scanning across the image. They use a small sliding window to examine sections of the input image one patch at a time. This approach allows them to effectively detect specific local patterns, like edges, corners, or simple textures, regardless of where those patterns appear in the overall image. This ability to recognize patterns independent of their location is fundamental to how CNNs process visual information. Now, let's look at how this sliding window operates. In the animation above, you can see the core process the small sliding window, technically called a kernel (the grid of weights, shown in white), moves (or convolves) across the input (green grid). At each position, it performs an element-wise multiplication between the kernel's weights and the underlying input values, and then sums the results to produce a single output value. This value becomes part of the output feature map (blue grid), which highlights where the pattern detected by the kernel was found. Interestingly, the kernel's weights aren't fixed; they are learnable parameters, automatically adjusted during training via backpropagation to become effective at detecting relevant patterns. For our pneumonia detection task, the filters in early convolutional layers might learn to detect simple features like edges (e.g., rib and organ boundaries) or basic textures. Filters in deeper layers can then combine these simpler features to recognize more complex patterns relevant to pneumonia, such as the characteristic cloudy opacities within the lungs. When defining a convolutional layer, you'll typically configure these key hyperparameters Kernel Size This defines the dimensions (height and width) of the kernel?the sliding window of weights. Common sizes are 3×3 or 5×5. Smaller kernels generally capture more localized, finer details, while larger kernels can identify broader, more spread-out patterns. Number of Filters This specifies how many different pattern detectors the layer will have. Each filter acts as a unique feature detector and consists of its own learnable kernel (weights) plus a single learnable bias term. So, conceptually filter = kernel + bias. The bias is a value added to the result of the convolution calculation (the sum of element-wise products) at each position. This learnable parameter allows the filter to adjust its output threshold independently of the weighted sum of inputs, increasing the model's flexibility to learn patterns. Applying one filter across the input produces one 2D feature map in the output. Therefore, the number of filters you specify directly determines the number of output channels (the depth) of the layer's output volume. More filters allow the network to learn a richer set of features simultaneously, but also increase the number of parameters and computational load. Stride This controls how many pixels the kernel slides across the input at each step. A stride of 1 (as in the animation above) means it moves one pixel at a time. A larger stride (like 2, as shown in the animation below) causes the kernel to skip pixels, resulting in a smaller output feature map (dimensionally) and potentially faster computation, but with less spatial detail captured. Padding This parameter controls whether pixels are added around the border of the input before the convolution operation. The two main strategies are No Padding (sometimes called 'valid' padding) In this mode, the kernel only slides over positions where it fully overlaps the input data. This causes the output feature map's height and width to shrink relative to the input dimensions (unless the kernel size is 1×1). The convolution is only computed for 'valid' positions where the kernel fits entirely. Zero Padding Pixels with a value of zero are added symmetrically around the input's border. This technique gives you control over the output dimensions. A common goal is to calculate the right amount of padding (based on kernel size) to achieve 'same' padding, where the output feature map has the same height and width as the input map (this is typically used when the stride is 1). Using 'same' padding helps preserve information throughout the network, especially features located near the edges of the input, which can be valuable when analyzing medical images where abnormalities might appear anywhere. Input and Output Shapes (Channels) Convolutional layers operate on input data arranged as 3D volumes with dimensions (height × width × input channels). They also produce output feature maps arranged as a 3D volume (output height × output width × output channels). The number of output channels is set by the Number of Filters hyperparameter you choose for the layer, as we discussed; each filter produces one channel (feature map) in the output. The number of input channels for a layer isn't typically a hyperparameter you tune; instead, it must match the number of channels in the data coming into that layer. For the very first convolutional layer that processes the raw image, this depends on the image type Grayscale images (like our X-rays) These have only one channel (input_channels=1). Why? Because each pixel's value represents only a single piece of information its intensity or brightness (from black to white). Color images These typically have three channels (input_channels=3). Why? Because they represent the intensity of three primary colors Red, Green, and Blue (RGB), which are needed to create the full color spectrum at each pixel position. For any subsequent convolutional layer deeper in the network, its input_channels must be equal to the output_channels (the number of filters) of the layer immediately preceding it, ensuring the dimensions match up correctly. The output feature map's height and width will depend on the input dimensions combined with the layer's kernel size, stride, and padding settings. Pooling Layers Focusing on What Matters After applying convolutions and detecting features, pooling layers help the network Reduce the spatial dimensions of feature maps Focus on the most important information Gain some resistance to small translations or shifts in the image The animation demonstrates max pooling, which divides the input into regions and takes only the maximum value from each. For pneumonia detection, this helps the network focus on the strongest indicators of disease while ignoring less relevant details. Max pooling creates a form of translation invariance because the network cares more about whether a feature is present than its exact location. This is useful for our task since pneumonia patterns can appear in slightly different locations across patients. Batch Normalization Stabilizing Training Medical image datasets like our pneumonia X-rays can have high variability in pixel intensity and contrast. Batch normalization helps stabilize the learning process by standardizing the inputs to each layer. By normalizing each batch of data during training, batch normalization Enables faster and more stable training Makes the model less sensitive to poor weight initialization Adds a mild regularization effect Allows for higher learning rates without divergence When building deep CNNs for medical imaging, batch normalization can be particularly valuable for handling the variability across different X-ray machines and imaging protocols. These components are often grouped together in repeating blocks within modern CNNs. A frequently used and effective structure for such a block is Convolutional Layer Batch Normalization Layer Activation Function (e.g., ReLU) Pooling Layer (optional, depending on the specific architecture) Dropout Layers Preventing Overfitting Medical imaging datasets like chest X-rays often contain far fewer examples than large-scale datasets like ImageNet. That makes it easier for a model to memorize the training data instead of learning patterns that generalize to new patients. To combat this, we’ll use dropout—a regularization technique that reduces overfitting by randomly disabling neurons during training. In the animated example below, you can see how a dropout layer with a 0.5 probability temporarily disables two out of four nodes on each forward pass. Notice how it’s not always the same two—it changes every time, forcing the network to build redundant pathways. In our pneumonia classifier, we’ll apply dropout usually within the fully connected layers near the end of the network. This helps ensure that the final classification doesn’t rely too heavily on any single feature learned earlier, helping the model generalize better to new chest X-rays. From Components to Architecture Now that we understand the individual CNN components, let's consider how to assemble them into a complete model architecture for our pneumonia detection task. Before designing the specific architecture (what we'll build), it's helpful to discuss the standard programming approach used to define such models in PyTorch (how we'll build it). Why Object-Oriented Models Are the Standard PyTorch offers multiple ways to define neural networks, but the object-oriented programming (OOP) approach using the nn.Module class is widely recognized as the standard for professional development. Let's explore why this approach is so beneficial, both for our current project and for your future computer vision work. When you look at how complex deep learning models are built in practice, whether for image recognition, autonomous navigation, natural language processing, or scientific discovery, you'll find they’re typically defined using object-oriented principles. This approach offers several key advantages Modularity OOP allows us to define reusable building blocks (like custom convolutional blocks or specific layer sequences) that can be easily stacked, swapped, and reconfigured. This is valuable when experimenting with different architectural ideas for any computer vision task, including optimizing models for medical image analysis. Maintainability Real-world models often need to evolve as new research emerges or project requirements change. The clear structure provided by OOP makes models easier to understand, debug, update, and collaborate on, whether you're incorporating a new state-of-the-art technique or adapting your model for a different dataset. Flexibility Many computer vision tasks benefit from custom operations or network structures that go beyond simple sequential layer stacking. OOP readily supports building complex, non-sequential architectures or integrating custom components, which can be cumbersome with simpler definition methods. Scalability As projects grow in complexity (e.g., tackling more intricate tasks, using larger datasets, or integrating different types of data), the organized nature of OOP makes managing this increased scale much more feasible than flatter script-based approaches. Industry alignment Across diverse fields applying deep learning, from tech companies and research institutions to finance and healthcare, this object-oriented approach using classes like nn.Module is the common standard for professional development. Simply put, learning to define your models using an object-oriented approach (by subclassing nn.Module) is ideal for building powerful, adaptable, and reusable computer vision systems. Of course, for very simple sequential models or quick proof-of-concept tests, more direct methods like using nn.Sequential can be perfectly effective and faster to write. However, the OOP structure truly shines when it comes to managing complexity, promoting code maintainability, and enabling the flexibility needed for larger or evolving real-world applications, making it the standard professional approach. Understanding this method prepares you to take on challenging and worthwhile projects, from analyzing medical images like we are here, to developing advanced systems in countless other fields. Defining Your CNN in PyTorch Now let's implement our pneumonia detection CNN using PyTorch's object-oriented style. We'll build a model that can effectively analyze chest X-rays and distinguish between normal and pneumonia cases. First, let's make sure we have all the required dependencies to build the model import torch import torch.nn as nn import torch.nn.functional as F Next, we'll define our CNN by subclassing nn.Module, PyTorch's base class for all neural networks class PneumoniaCNN(nn.Module) def __init__(self) super().__init__() # First convolutional block self.conv_block1 = nn.Sequential( nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, padding=1), nn.BatchNorm2d(num_features=32), nn.ReLU(), nn.MaxPool2d(kernel_size=2) # Reduce spatial dimensions by half; see explanation below ) # Second convolutional block self.conv_block2 = nn.Sequential( nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1), nn.BatchNorm2d(num_features=64), nn.ReLU(), nn.MaxPool2d(kernel_size=2) # Further reduce spatial dimensions; see explanation below ) # Third convolutional block self.conv_block3 = nn.Sequential( nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=1), nn.BatchNorm2d(num_features=128), nn.ReLU(), nn.MaxPool2d(kernel_size=2) # Further reduce spatial dimensions; see explanation below ) # Flatten layer to convert 3D feature maps to 1D vector self.flatten = nn.Flatten() # Fully connected layers for classification self.fc1 = nn.Linear(in_features=128 * 32 * 32, out_features=512) # Adjust size based on input dimensions self.dropout1 = nn.Dropout(0.5) # Add 50% dropout for regularization self.fc2 = nn.Linear(in_features=512, out_features=128) self.dropout2 = nn.Dropout(0.5) self.fc3 = nn.Linear(in_features=128, out_features=2) # 2 output classes Normal and Pneumonia def forward(self, x) # Pass input through convolutional blocks x = self.conv_block1(x) x = self.conv_block2(x) x = self.conv_block3(x) # Flatten the features x = self.flatten(x) # Pass through fully connected layers x = F.relu(self.fc1(x)) x = self.dropout1(x) x = F.relu(self.fc2(x)) x = self.dropout2(x) logits = self.fc3(x) # Raw, unnormalized predictions return logits Let's break down what's happening in this model We start by creating three convolutional blocks using the nn.Sequential class. Each block contains nn.Conv2d() A convolutional layer that extracts features from images nn.BatchNorm2d() Batch normalization to stabilize training nn.ReLU() ReLU activation to introduce non-linearity nn.MaxPool2d() Max pooling to reduce spatial dimensions and focus on the most important features within local regions Notice we pass in_channels=1 to the first convolutional layer (conv_block1). This explicitly tells the layer to expect input data with a single channel, which is correct for our grayscale X-ray images where each pixel has only one intensity value. (Color images would typically use in_channels=3 for RGB). We gradually increase the number of filters (output channels) in subsequent blocks (32 ? 64 ? 128). This is a common CNN design pattern. Early layers with fewer filters tend to capture simpler, more general features (like edges or basic textures), while deeper layers with more filters can combine these simple features to learn more complex and abstract patterns specific to the task (like the visual characteristics of pneumonia). After the convolutional blocks, we flattenthe final 3D feature map (height × width × channels) into a 1D vector. This vector becomes the input to the first fully connected layer (self.fc1). To determine the required in_features for self.fc1, we need to know the shape of the feature map after the last pooling layer. We'll be resizing our input images to 256×256 pixels during data preparation (covered in the next tutorial). Given this 256×256 input size, let's trace how the dimensions change through the three max pooling layers, as each one halves the height and width Start 256×256 After 1st Pool layer 128×128 After 2nd Pool layer 64×64 After 3rd Pool layer 32×32 So, the feature map entering the flatten layer has spatial dimensions 32×32. Since the last convolutional block (conv_block3) outputs 128 channels (or feature maps), the total number of features in the flattened vector is 128×32×32=131,072. This is the value we need for in_features in self.fc1. The fully connected layers (nn.Linear), sometimes called dense layers, perform the final classification based on the extracted features. We intersperse nn.Dropout(0.5) layers between the fully connected layers. Dropout is a regularization technique that helps prevent overfitting, which is especially important when working with limited datasets. It randomly sets a fraction (here, 50%) of neuron outputs to zero during training, forcing the network to learn more robust representations. The final layer (self.fc3) outputs two values, corresponding to the scores for our two classes Normal and Pneumonia. Note that these outputs are raw scores, often called logits. We don't apply a final activation function like Softmax here because the standard PyTorch loss function for multi-class classification, nn.CrossEntropyLoss, conveniently expects raw logits as input (it applies the necessary transformations internally during training). The __init__ method defines all the network's layers and assigns them to instance attributes (like self.conv_block1, self.fc1, etc.). The forward method then defines the order in which input data x flows through these predefined layers to produce the final output. You might also notice we used the module nn.ReLU() inside the nn.Sequential blocks defined in __init__, but called the functional version F.relu() directly in the forward method after the first two fully connected layers. Both apply the exact same ReLU activation. nn.ReLU() is required within nn.Sequential because nn.Sequential expects nn.Module instances. Using F.relu() directly in forward is common and often slightly more concise for stateless operations like activation functions, as you don't need to define it in __init__ first. Both approaches are valid within the forward method itself. The .forward() method in our model defines how data flows through our network?it's the execution path that input takes as it's transformed into output predictions. When we later use our model with syntax like outputs = model(images), PyTorch automatically calls this .forward() method behind the scenes. This clean separation between model structure (defined in __init__()) and computation flow (defined in forward()) is one of the key benefits of PyTorch's object-oriented approach. Verifying Tensor Shapes When building CNNs, one of the most common sources of errors is mismatched tensor shapes between layers. For example, if the flattened output of your convolutional blocks doesn't produce the exact number of features expected by your first fully connected layer, PyTorch will raise a RuntimeError when you try to pass data through. Carefully tracking shapes is vital. A simple yet effective debugging technique is to perform a "dry run"?passing a correctly shaped dummy input through the model and printing the tensor shape after each major step. This can help you catch dimension mismatches early and save hours of troubleshooting. First, let's create an instance of our model and a dummy input tensor representing one grayscale image of the expected size (256×256 pixels) # Create model instance model = PneumoniaCNN() # Create a random dummy grayscale image (batch_size, channels, height, width) dummy_input = torch.randn(1, 1, 256, 256) Now, we can define a helper function that mimics the model's forward pass but includes print statements to show the shape transformations # Forward pass function with shape printing def forward_with_shape_printing(model, x) print(f"Input shape \t\t{x.shape}") # Using tabs for alignment # Pass through convolutional blocks x = model.conv_block1(x) print(f"After conv_block1 \t{x.shape}") x = model.conv_block2(x) print(f"After conv_block2 \t{x.shape}") x = model.conv_block3(x) print(f"After conv_block3 \t{x.shape}") # Flatten the features x = model.flatten(x) print(f"After flatten \t\t{x.shape}") # Pass through fully connected layers (only showing final output shape) x = F.relu(model.fc1(x)) x = model.dropout1(x) x = F.relu(model.fc2(x)) x = model.dropout2(x) logits = model.fc3(x) print(f"Output shape (logits) \t{x.shape}") # Corrected variable name return logits # Run the forward pass (output is ignored with _) print("Running shape verification pass") _ = forward_with_shape_printing(model, dummy_input) Running this code should produce output similar to this Running shape verification pass Input shape torch.Size([1, 1, 256, 256]) After conv_block1 torch.Size([1, 32, 128, 128]) After conv_block2 torch.Size([1, 64, 64, 64]) After conv_block3 torch.Size([1, 128, 32, 32]) After flatten torch.Size([1, 131072]) Output shape (logits) torch.Size([1, 2]) Interpreting the Shape Transformations These printouts confirm several key aspects of our architecture Spatial Dimensions Decrease, Channel Depth Increases Notice how the height and width are halved after each convolutional block (due to the MaxPool2d layer) 256?128?64?32. Simultaneously, the number of channels (features) increases 1?32?64?128. This is the common CNN pattern we discussed earlier, visualized here the network trades spatial resolution for richer feature representation depth, allowing it to capture increasingly complex patterns as data flows deeper. Flattening Connects Blocks The output from the last convolutional block (1×128×32×32) is correctly flattened into a 1D vector of size 1×131072, matching the in_features expected by self.fc1. This confirms our calculation from the previous section and shows the bridge between the convolutional feature extractor and the fully connected classifier head. Interpreting the Final Output Shape ([1, 2]) Finally, let's take a closer look at the output shape torch.Size([1, 2]). The first dimension (1) corresponds to the batch size. We passed in a single dummy image, so the batch size is 1. The second dimension (2) corresponds to the number of classes our model predicts. As established, these are the raw, unnormalized scores (logits) for 'Normal' (index 0) and 'Pneumonia' (index 1). These logits are the direct output suitable for the nn.CrossEntropyLoss function during training. However, to turn them into human-interpretable predictions, two more steps are typically needed (which we'll implement fully in the next tutorial) Convert to Probabilities Apply the softmax function along the class dimension (dim=1) to convert the raw logits into probabilities that sum to 1.0 for each image in the batch. Python # Example Convert logits to probabilities probabilities = F.softmax(logits, dim=1) # probabilities might look like tensor([[0.312, 0.688]]) Get Predicted Class Find the index (0 or 1) corresponding to the highest probability. This index represents the model's final prediction. Python # Example Get the predicted class index _, predicted_class = torch.max(probabilities, dim=1) # predicted_class might look like tensor([1]) (meaning Pneumonia) This shape verification process confirms our model's internal dimensions align correctly and helps clarify how the final output relates to the classification task. Practical Tips for CNN Development Let's explore some important practices to keep in mind when developing CNNs in PyTorch. GPU Usage and Device Management Training CNNs involves a huge number of calculations. While CPUs can perform these operations, Graphics Processing Units (GPUs) are specialized for massive parallel computation, which can make training deep learning models drastically faster, often by an order of magnitude or more! This speed-up is especially noticeable with complex models or large datasets found in many computer vision applications, from analyzing high-resolution photographs to processing video streams or large medical scans. If you have access to a GPU (like NVIDIA GPUs compatible with CUDA), you'll want to leverage its processing power. The key steps are to determine the appropriate device (cuda for NVIDIA GPU or cpu) and then explicitly move both your model and your data tensors to that device before performing operations # 1. Determine the target device (usually done early in your script) device = torch.device("cuda" if torch.cuda.is_available() else "cpu") print(f"Using device {device}") # 2. Move your model to the device (usually done once after creating the model) model = model.to(device) # 3. Move your data tensors to the device (done for EACH batch) images = images.to(device) labels = labels.to(device) In a typical workflow, you'd set the device variable early on. You'd move the model to the device right after creating it (step 2). Importantly, inside your training or evaluation loops, you must also move each batch of images and labels to the same device (step 3) before feeding them into the model. Consistently placing both your model and your input data on the same device is required. Performing operations between tensors residing on different devices (e.g., CPU tensor vs. GPU tensor) is a common source of RuntimeError messages in PyTorch, so diligent device management can save you many headaches. Switching Between Training and Evaluation Modes While we'll cover training our model in the next tutorial, it's good to be reminded that PyTorch models have two operational modes model.train() # Set the model to training mode model.eval() # Set the model to evaluation mode The difference is significant because In training mode, dropout layers randomly disable neurons In evaluation mode, dropout is disabled so all neurons are active Batch normalization behaves differently in each mode This will be especially important when we implement the training loop in the next tutorial, but it's good to be aware of these modes now. Review and Next Steps You've now completed the first step toward building a pneumonia detection system designing an effective CNN architecture in PyTorch. Let's recap what you've learned in this tutorial You understand why CNNs are well-suited for image analysis tasks, such as detecting patterns in X-rays, leveraging their ability to learn spatial hierarchies. You've learned about key CNN components like convolutional layers, pooling layers, batch normalization, and dropout layers. You've implemented a complete CNN model using PyTorch's object-oriented approach You've explored techniques for debugging potential shape issues in your model This is an important foundation, but a model architecture alone can't detect pneumonia. Next, we'll build on this foundation to create a complete working system by Loading and preprocessing real chest X-ray images Implementing training and validation loops Evaluating the model's diagnostic performance Interpreting results and improving the model In the next tutorial, we'll transform this architectural framework into a working pneumonia detection system by adding data processing, training, and evaluation. See you there! Key Takeaways CNNs reduce parameters through local connectivity and weight sharing, making them ideal for image analysis Core CNN components work together to extract increasingly complex features from images PyTorch's object-oriented approach provides a flexible, maintainable framework for implementing CNNs Debugging techniques like shape verification are essential for successful model development Medical applications like pneumonia detection showcase the real-world impact of computer vision


Data structure in C-Sharp Software Development Not ...
Category: Algorithms

In this article, I will keep notes about different #data #structures and why I should use ...


Views: 0 Likes: 39
Software Best Practices Learned by Experience
Category: System Design

[Updated] It is considered good practice to cache your data in memory, either o ...


Views: 0 Likes: 38
SVT Robotics - .NET Core Take Home Recruiting Asse ...
Category: Other

Question One of SVT's microserv ...


Views: 0 Likes: 46
AspNet Core Performance Tuning and Best Practices ...
Category: .Net 7

C# Best Practices and Performance Tuning</ ...


Views: 140 Likes: 66
What is New in C-Sharp 9 Programming Language
Category: .Net 7

C# is one of the high-level programming languages, it is used in many business applications, Game ...


Views: 278 Likes: 102
C-Sharp 11 Tips and Tricks
Category: Research

Linq- Did you know you could compair two sequences by using sequence operations li ...


Views: 90 Likes: 58
 How to use configuration with C# 9 top-level programs
How to use configuration with C# 9 top-level prog ...

I’ve been working with top-level programs in C# 9 quite a bit lately. When writing simple console apps in .NET 5, it allows you to remove the ceremony of a namespace and a Main(string[] args) method. It’s very beginner-friendly and allows developers to get going without worrying about learning about namespaces, arrays, arguments, and so on. While I’m not a beginner—although I feel like it some days—I enjoy using top-level programs to prototype things quickly.With top-level programs, you can work with normal functions, use async and await, access command-line arguments, use local functions, and more. For example, here’s me working with some arbitrary strings and getting a random quote from the Ron Swanson Quotes APIusing System; using System.Net.Http; var name = "Dave Brock"; var weekdayHobby = "code"; var weekendHobby = "play guitar"; var quote = await new HttpClient().GetStringAsync("https//ron-swanson-quotes.herokuapp.com/v2/quotes"); Console.WriteLine($"Hey, I'm {name}!"); Console.WriteLine($"During the week, I like to {weekdayHobby} and on the weekends I like to {weekendHobby}."); Console.WriteLine($"A quote to live by {quote}"); Add configuration to a top-level programCan we work with configuration with top-level programs? (Yes, should we is a different conversation, of course.)To be clear, there are many, many ways to work with configuration in .NET. If you’re used to it in ASP.NET Core, for example, you’ve most likely done it from constructor dependency injection, wiring up a ServiceCollection in your middleware, or using the Options pattern—so you may think you won’t be able to do it with top-level programs.Don’t overthink it. Using the ConfigurationBuilder, you can easily use configuration with top-level programs.Let’s create an appsettings.json file to replace our hard-coded values with configuration values.{ "Name" "Dave Brock", "Hobbies" { "Weekday" "code", "Weekend" "play guitar" }, "SwansonApiUri" "https//ron-swanson-quotes.herokuapp.com/v2/quotes" } Then, make sure your project file has the following packages installed, and that the appSettings.json file is being copied to the output directory <ItemGroup> <PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" /> </ItemGroup> <ItemGroup> <None Update="appsettings.json"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> </ItemGroup> In your top-level program, create a ConfigurationBuilder with the appropriate valuesvar config = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json") .Build(); With a config instance, you’re ready to simply read in your valuesvar name = config["Name"]; var weekdayHobby = config.GetSection("HobbiesWeekday"); var weekendHobby = config.GetSection("HobbiesWeekend"); var quote = await new HttpClient().GetStringAsync(config["SwansonApiUri"]); And here’s the entire top-level program in actionusing Microsoft.Extensions.Configuration; using System; using System.IO; using System.Net.Http; var config = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json") .Build(); var name = config["Name"]; var weekdayHobby = config.GetSection("HobbiesWeekdays"); var weekendHobby = config.GetSection("HobbiesWeekends"); var quote = await new HttpClient().GetStringAsync(config["SwansonApiUri"]); Console.WriteLine($"Hey, I'm {name}!"); Console.WriteLine($"During the week, I like to {weekdayHobby.Value}" + $" and on the weekends I like to {weekendHobby.Value}."); Console.WriteLine($"A quote to live by {quote}"); Review the generated codeWhen throwing this in the ILSpy decompilation tool, you can see there’s not a lot of magic here. The top-level program is merely wrapping the code in a Main(string[] args) method and replacing our implicit typingusing System; using System.IO; using System.Net.Http; using System.Runtime.CompilerServices; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; [CompilerGenerated] internal static class <Program>$ { private static async Task <Main>$(string[] args) { IConfigurationRoot config = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json").Build(); string name = config["Name"]; IConfigurationSection weekdayHobby = config.GetSection("HobbiesWeekday"); IConfigurationSection weekendHobby = config.GetSection("HobbiesWeekend"); string quote = await new HttpClient().GetStringAsync(config["SwansonApiUri"]); Console.WriteLine("Hey, I'm " + name + "!"); Console.WriteLine("During the week, I like to " + weekdayHobby.Value + " and on the weekends I like to " + weekendHobby.Value + "."); Console.WriteLine("A quote to live by " + quote); } } Wrap upIn this quick post, I showed you how to work with configuration in C# 9 top-level programs. We showed how to use a ConfigurationBuilder to read from an appsettings.json file, and we also reviewed the generated code.


RPlotExporter couldn't find Rscript.exe in your PA ...
Category: Algorithms

Question How do you solve the error in BenchmarkDotNet that says "RPlotExporter ...


Views: 0 Likes: 48

Login to Continue, We will bring you back to this content 0



For peering opportunity Autonomouse System Number: AS401345 Custom Software Development at ErnesTech Email Address[email protected]