Lesson · 40 min · Free
Your First Neural Network
Your First Neural Network Your First Neural Network Welcome to the exciting world of neural networks! In this lesson, we'll build our very first neural network from the ground up. Don't worry if terms like "neurons" or "
Your First Neural Network
Welcome to the exciting world of neural networks! In this lesson, we'll build our very first neural network from the ground up. Don't worry if terms like "neurons" or "layers" sound intimidating; we'll break down the core concepts into understandable components relevant to drug discovery. Our goal here isn't to build a state-of-the-art model, but rather to grasp the fundamental architecture and how information flows through it. At its core, a neural network is a computational model inspired by the human brain. It consists of interconnected nodes (neurons) organized into layers. Each connection has a weight, and each neuron has an activation function. When data is fed into the network, it passes through these layers, with each neuron performing a simple calculation before passing its output to the next layer. This process allows the network to learn complex patterns and make predictions. For drug discovery, neural networks are invaluable. They can be used for tasks such as predicting molecular properties, identifying potential drug candidates, understanding drug-target interactions, and even designing novel compounds. The ability of these networks to learn non-linear relationships from vast datasets makes them a powerful tool in modern pharmaceutical research.
The Perceptron: The Simplest Neural Network
Our journey begins with the perceptron, the simplest form of a neural network. A perceptron is a single-layer neural network used for binary classification. It takes multiple binary inputs, computes a weighted sum of these inputs, and then passes this sum through an activation function (typically a step function) to produce a single binary output. This output classifies the input into one of two categories. Let's consider a practical example. Imagine we want to predict if a compound is "active" or "inactive" against a specific protein target based on two simple features: its molecular weight (MW) and its logP value (lipophilicity). We can represent these as inputs to our perceptron. The perceptron's decision-making process can be summarized as follows: Each input feature (e.g., MW, logP) is multiplied by a corresponding weight. These weighted inputs are summed together. A bias term is added to this sum. The result is passed through an activation function (e.g., a step function) to produce the final output (0 or 1). Here's a conceptual Python representation of a single perceptron: import numpy as np class Perceptron: def __init__(self, num_inputs, learning_rate=0.01): self.weights = np.random.rand(num_inputs) # Initialize weights randomly self.bias = np.random.rand(1) # Initialize bias randomly self.learning_rate = learning_rate def activate(self, summation): # Step activation function return 1 if summation >= 0 else 0 def predict(self, inputs): summation = np.dot(inputs, self.weights) + self.bias return self.activate(summation) def train(self, training_inputs, labels, epochs): for _ in range(epochs): for inputs, label in zip(training_inputs, labels): prediction = self.predict(inputs) error = label - prediction # Update weights and bias self.weights += self.learning_rate * error * inputs self.bias += self.learning_rate * error # Example usage: # Let's say we have two features: [Molecular Weight, logP] # And we want to classify if a drug is active (1) or inactive (0) training_inputs = np.array([ [150, 2.5], # Inactive [300, 4.0], # Active [200, 1.0], # Inactive [450, 3.5] # Active ]) labels = np.array([0, 1, 0, 1]) perceptron = Perceptron(num_inputs=2) perceptron.train(training_inputs, labels, epochs=100) print("Perceptron training complete.") print(f"Learned Weights: {perceptron.weights}") print(f"Learned Bias: {perceptron.bias}") # Test the trained perceptron print(f"Prediction for [180, 1.5]: {perceptron.predict(np.array([180, 1.5]))}") # Should be 0 (inactive) print(f"Prediction for [350, 3.0]: {perceptron.predict(np.array([350, 3.0]))}") # Should be 1 (active) While the perceptron is simple, it can only solve linearly separable problems. This means it can only classify data that can be perfectly separated by a straight line (or hyperplane in higher dimensions). Many real-world problems in drug discovery, however, are non-linear. This limitation led to the development of multi-layer perceptrons (MLPs), also known as feedforward neural networks, which can model much more complex relationships. A multi-layer perceptron introduces one or more "hidden layers" between the input and output layers. Each neuron in these hidden layers also uses an activation function, but often a non-linear one like the sigmoid or ReLU function. This non-linearity is crucial as it allows the network to learn and represent non-linear decision boundaries, making it capable of solving more complex problems. Let's look at a very basic example of a neural network with one hidden layer using the popular Keras library, which simplifies the process significantly. We'll use a slightly more abstract example for clarity, but imagine these inputs could represent various physicochemical properties of a molecule. from tensorflow import keras from tensorflow.keras import layers import numpy as np # Sample data: 4 features, binary output # Imagine inputs are molecular descriptors and output is binding affinity (high/low) X_train = np.array([ [0.1, 0.2, 0.3, 0.4], [0.5, 0.6, 0.7, 0.8], [0.9, 0.8, 0.7, 0.6], [0.2, 0.3, 0.4, 0.5], [0.6, 0.7, 0.8, 0.9], [0.1, 0.1, 0.1, 0.1] ]) y_train = np.array([0, 1, 1, 0, 1, 0]) # Binary labels (e.g., inactive/active) # Define the neural network model model = keras.Sequential([ # Input layer (implicitly defined by the first Dense layer's input_shape) # Hidden layer with 8 neurons and ReLU activation layers.Dense(8, activation='relu', input_shape=(4,)), # Output layer with 1 neuron and sigmoid activation for binary classification layers.Dense(1, activation='sigmoid') ]) # Compile the model # optimizer: how the network updates weights based on error # loss: function to measure how well the model performs # metrics: what to monitor during training model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) # Train the model # epochs: number of times to iterate over the entire training dataset # batch_size: number of samples per gradient update print("Training the Keras model...") model.fit(X_train, y_train, epochs=50, batch_size=2, verbose=0) # verbose=0 for less output print("\nModel training complete.") # Make predictions predictions = model.predict(X_train) print("Predictions (raw output from sigmoid):") print(predictions) # Convert predictions to binary (0 or 1) binary_predictions = (predictions > 0.5).astype(int) print("\nBinary Predictions:") print(binary_predictions.flatten()) # Evaluate the model (optional for this small example) loss, accuracy = model.evaluate(X_train, y_train, verbose=0) print(f"\nTraining Loss: {loss:.4f}") print(f"Training Accuracy: {accuracy:.4f}") In this Keras example, layers.Dense represents a fully connected layer where every neuron in the previous layer connects to every neuron in the current layer. The activation='relu' (Rectified Linear Unit) is a common non-linear activation function for hidden layers, while activation='sigmoid' is typical for binary classification output layers as it squashes the output between 0 and 1, which can be interpreted as a probability. The optimizer='adam' and loss='binary_crossentropy' are standard choices for binary classification tasks.
Key Takeaways:
Neural networks are computational models inspired by the brain, capable of learning complex patterns. The perceptron is the simplest neural network, performing binary classification on linearly separable data. Multi-layer perceptrons (MLPs) introduce hidden layers and non-linear activation functions, allowing them to solve non-linear problems. Weights and biases are parameters learned during training, determining the strength of connections and neuron activation thresholds. Activation functions introduce non-linearity, which is crucial for learning complex relationships in data. Libraries like Keras (built on TensorFlow) simplify the process of building and training neural networks.
Practice Exercise:
Modify the Keras code example to include a second hidden layer with 4 neurons. Keep the activation functions the same. Retrain the model and observe if there are any changes in the training accuracy for this small dataset. What might be the implications of adding more layers or neurons for larger, more complex drug discovery datasets?
Watch the full lesson — free
This topic is part of AI in Drug Discovery, a complete AI-narrated video course. Press play once and watch the entire lecture like a movie.
Start the course free →