text:
# PYME.Acquire.ActionManager module¶

Created on Sat May 28 23:12:24 2016

@author: david

class PYME.Acquire.ActionManager.ActionManager(scope)

Bases: object

This implements a queue for actions which should be called sequentially.

The main purpose of the ActionManager is to facilitate automated imaging by allowing multiple operations to be queued. Rather than being strictly FIFO, different tasks can be asigned different priorities, with higher priority tasks bubbling up and and being executed before lower priority tasks. This allows high priority “imaging” tasks to be inserted into a stream of lower priority “monitoring” tasks if something interesting is detected during monitoring.

An individual action is a function which can be found within the scope of our microscope object (for more details see the QueueAction method).

To function correctly the Tick() method should be called regularly - e.g. from a GUI timer.

Methods

 QueueAction(functionName, args[, nice, timeout]) Add an action to the queue Tick(**kwargs) Polling function to check if the current action is finished and, if so, start the next action if available.

Initialise our action manager

Parameters: scope : PYME.Acquire.microscope.microscope object The microscope. The function object to call for an action should be accessible within the scope namespace, and will be resolved by calling eval(‘scope.functionName’)

Methods

 QueueAction(functionName, args[, nice, timeout]) Add an action to the queue Tick(**kwargs) Polling function to check if the current action is finished and, if so, start the next action if available.
QueueAction(functionName, args, nice=10, timeout=1000000.0)

Add an action to the queue

Parameters: functionName : string The name of a function relative to the microscope object. e.g. to call scope.spoolController.StartSpooling(), you would use a functionName of ‘spoolController.StartSpooling’. The function should either return None if the operation has already completed, or function which evaluates to True once the operation has completed. See scope.spoolController.StartSpooling() for an example. args : dict a dictionary of arguments to pass the function nice : int (or float) The priority with which to execute the function. Functions with a lower nice value execute first. timeout : float A timeout in seconds from the current time at which the action becomes irrelevant and should be ignored.
Tick(**kwargs)

Polling function to check if the current action is finished and, if so, start the next action if available.

Should be called regularly for a timer or event loop.


text:
Practical Deep Learning for Computer Vision with Python - Image Classification with Transfer Learning - Creating Cutting Edge CNN Models

# Image Classification with Transfer Learning - Creating Cutting Edge CNN Models

David Landup

New models are being released and benchmarked against community-accepted datasets frequently, and keeping up with all of them is getting harder.

Most of these models are open source, and you can implement them yourself as well.

This means that the average enthusiast can load in and play around with the cutting edge models in their home, on very average machines, not only to gain a deeper understanding and appreciation of the craft, but also to contribute to the scientific discourse and publish their own improvements whenever they're made.

In this lesson, you'll learn how to use pre-trained, cutting edge Deep Learning models for Image Classification and repurpose them for your own specific application. This way, you're leveraging their high performance, ingenious architectures and someone else's training time - while applying these models to your own domain!

### Transfer Learning for Computer Vision and Convolutional Neural Networks

Knowledge and knowledge representations are very universal. A computer vision model trained on one dataset learns to recognize patterns that might be very prevalent in many other datasets.

Notably, in "Deep Learning for the Life Sciences", by Bharath Ramsundar, Peter Eastman, Patrick Walters and Vijay Pande, it's noted that:

"There have been multiple studies looking into the use of recommendation system algorithms for use in molecular binding prediction. Machine learning architectures used in one field tend to carry over to other fields, so it’s important to retain the flexibility needed for innovative work."

For instance, straight and curved lines, which are typically learned at a lower level of a CNN hierarchy are bound to be present in practically all datasets. Some high-level features, such as the ones that distinguish a bee from an ant are going to be represented and learned much higher in the hierarchy:

The "fine line" between these is what you can reuse! Depending on the level of similarity between your dataset and the one a model's been pre-trained on, you may be able to reuse a small or large portion of it.

A model that classifies human-made structures (trained on a dataset such as the Places365) and a model that classifies animals (trained on a dataset such as ImageNet) are bound to have some shared patterns, although, not a lot.

You might want to train a model to distinguish, say, buses and cars for a self-driving car's vision system. You may also reasonably choose to use a very performant architecture that has proven to work well on datasets similar to yours. Then, the long process of training begins, and you end up having a performant model of your own!

However, if another model is likely to have similar representations on lower and higher levels of abstraction, there's no need to re-train a model from scratch. You may decide to use some of the already pre-trained weights, which are just as applicable to your own application of the model as they were applicable to the creator of the original architecture. You'd be transferring some of the knowledge from an already existing model to a new one, and this is known as Transfer Learning. The importance and versatility of transfer learning is, in my opinion, understated. It's oftentimes put to the side, or briefly mentioned at the end of lessons and lectures, and it's oftentimes the last concept covered when learning about CNNs.

Whenever you're reading about the application of computer vision to a specific problem - chances are, it's transfer learning in the background. If you spend your afternoons like me reading research papers in various fields (that I have barely any knowledge in), you'll notice how commonly transfer learning is used, even when not mentioned by that name. It's so prevalent that it's practically assumed that transfer learning is used. With pre-loaded models and transferred knowledge - almost anyone can utilize the power of deep learning to further a field.

• Doctors can use computer vision models to diagnose images (X-ray, histology, retinoscopy, etc.)
• Cities can use computer vision to detect pedestrians and cars on streets and adapt traffic lights to optimize the flow of transportation
• Malls can use computer vision to detect parking occupancy
• Marine biologists can use computer vision to detect endangered coral reefs (example
• Manufacturers can use computer vision to detect defects in production lines (such as missing pills in medicine)
• News outlets can use computer vision to digitize old newspaper issues
• Agricultural plants can use computer vision to detect crop yields and health (and insects/other pests)

From optimizing workflows and investments to saving human lives - computer vision is very applicable. Though - read through the list again. Who are the people using these technologies? Doctors, biologists, farmers, city planners. They might not have a extensive computer/data science background or powerful hardware required to train large networks, but they can see benefits from those networks even if they're not optimized. Through democratized models, they don't need a data science background. Through free and cheap cloud training providers and pre-trained networks, they don't need powerful hardware.

Training with pre-built architectures and downloadable weights has become so streamlined that a kid with a slow internet connection and barely working computer can create more accurate models than top-of-the-line equipment and professionals could a decade or two ago.

The benefit of transfer learning isn't limited to shortening training. If you don't have a lot of data, a network won't be able to learn some of the distinctions early on. If you train it extensively on one dataset, and then transfer to another one, a lot of the representations are already learned and it can be fine-tuned on the new dataset. In the case of CIFAR100 we've worked with in the last lesson - many of the images can be found (in larger sizes) in datasets like ImageNet, and a lot could've been transferred with a pretrained model. This would, in effect, be what data augmentation saught to be - expanding the dataset (albeit, indirectly), with instances of data from another dataset. While you don't really expand the new dataset, the knowledge encoded in the model being fine-tuned is transfered between them.

The closer the dataset of a pre-trained model is to your own, the more you can transfer. The more you can transfer, the more of your own time and computation you can save. It's worth remembering that training neural networks does have a carbon footprint, so you're not only saving time!

Typically, transfer learning is done by loading a pre-trained model, and freezing its layers. In many cases, you can just cut off the classification layer (the final layers, or, head/densly-connected layer) and just re-train the classification layer, while keeping all of the other abstraction layers intact. This is paramount to using the convolutional base as a feature extractor, and you just re-train the classifier which contains all of the domain knowledge (the convolutional blocks are much more generic). In other cases, you may decide to re-train several layers in the convolutional hierarchy alongside the top, and this is typically done when the datasets contain sufficiently different data points that re-training multiple layers is warranted. You may also decide to re-train the entirety of the model to fine-tune all of the layers.

These two approaches can be summarized as:

• Using the Convolutional Network as a Feature Extractor
• Fine-Tuning the Convolutional Network

In the former, you use the underlying model as a fixed feature extractor, and just train a dense network on top to discern between these features. In the latter, you fine-tune the entire (or portion of the) convolutional network, if it doesn't already have representative feature maps for some other more specific dataset, while also relying on the already trained feature maps and just updating them to also fit your own needs.

Here's a visual representation of how Transfer Learning works:

### Established and Cutting Edge Image Classification Models

Many models exist out there, and for well-known datasets, you're likely to find hundreds of well-performing models published in online repositories and papers. A good holistic view of models trained on the ImageNet dataset can be seen at PapersWithCode.

Some of the well-known published architectures that have subsequently been ported into many Deep Learning frameworks include:

• EfficientNet
• SENet
• Inception and Xception
• ResNet
• VGGNet
• AlexNet
• LeNet-5

The list of models on PapersWithCode is constantly being updated, and you shouldn't hang up on the position of these models there. Many of the new models that take the top places are actually based on the ones outlined in the list above. It's worth noting that Transfer Learning actually played an important role in the newer, higher accuracy models!

Unfortunately, some of the newest models aren't ported as pre-trained models within frameworks such as Tensorflow and PyTorch, though, the teams are pretty dilligent in porting them with pre-trained weights. It's not like you'll be losing out on a lot of the performance, so going with any of the well-established ones isn't really bad at all.

### Transfer Learning with Keras - Adapting Existing Models

With Keras, the pre-trained models are available under the tensorflow.keras.applications module. Each model has its own sub-module and class. When loading a model in, you can set a couple of optional arguments to control how the models are being loaded.

Note: You can find the ported models at Keras.io, but the list doesn't include the newest and experimental models. For a more up-to-date list, visit TensorFlow's Docs.

For instance, the weights argument, if present, defines which pre-trained weights are to be used. If omitted, only the architecture (untrained network) will be loaded in. If you supply the name of a dataset - a pre-trained network will be returned for that dataset. Alternatively, you can provide a path to a file with the weights you want to load in (as long as it's the exact same architecture).

Additionally, since you'll most likely be removing the top layer(s) for Transfer Learning, the include_top argument is used to define whether the top layer(s) should be present or not!

import tensorflow.keras.applications as models

# 98 MB
resnet = models.resnet50.ResNet50(weights='imagenet', include_top=False)
# 528MB
vgg16 = models.vgg16.VGG16(weights='imagenet', include_top=False)
# 23MB
nnm = models.NASNetMobile(weights='imagenet', include_top=False)
# etc...

Note: If you've never loaded pre-trained models before, they'll be downloaded over an internet connection. This may take anywhere between a few seconds and a couple of minutes, depending on your internet speed and the size of the models. The size of pre-trained models spans from as little as 14MB (typically lower for Mobile models) to as high as 549MB.

EfficientNet is a family of networks that are quite performant, scalable and, well, efficient. They were made with reducing learnable parameters in mind, so they only have 4M parameters to train. While 4M is still a large number, consider that VGG16, for instance, has 20M. On a home setup, this also helps with training times significantly!

Let's load in one of the members of the EfficientNet family - EfficientNetB0:

effnet = keras.applications.EfficientNetB0(weights='imagenet', include_top=False)
effnet.summary()

This results in:

Model: "efficientnetb0"
__________________________________________________________________________________________________
Layer (type)                   Output Shape         Param #     Connected to
==================================================================================================
input_2 (InputLayer)           [(None, None, None,  0           []
3)]

rescaling_1 (Rescaling)        (None, None, None,   0           ['input_2[0][0]']
3)

...
...

block7a_project_bn (BatchNorma  (None, None, None,   1280       ['block7a_project_conv[0][0]']
lization)                      320)

top_conv (Conv2D)              (None, None, None,   409600      ['block7a_project_bn[0][0]']
1280)

top_bn (BatchNormalization)    (None, None, None,   5120        ['top_conv[0][0]']
1280)

top_activation (Activation)    (None, None, None,   0           ['top_bn[0][0]']
1280)

==================================================================================================
Total params: 4,049,571
Trainable params: 4,007,548
Non-trainable params: 42,023
__________________________________________________________________________________________________

On the other hand, if we were to load in EfficientNetB0 with the top included, we'd also have a few new layers at the end, that were trained to classify the data for ImageNet. This is the top of the model that we'll be training ourselves for our own application:

effnet = keras.applications.EfficientNetB0(weights='imagenet', include_top=True)
effnet.summary()

This would include the final top layers, with a Dense classifier in the end:

Model: "efficientnetb0"
__________________________________________________________________________________________________
Layer (type)                   Output Shape         Param #     Connected to
==================================================================================================
input_1 (InputLayer)           [(None, 224, 224, 3  0           []
)]

rescaling (Rescaling)          (None, 224, 224, 3)  0           ['input_1[0][0]']

...
...

block7a_project_bn (BatchNorma  (None, 7, 7, 320)   1280        ['block7a_project_conv[0][0]']
lization)

top_conv (Conv2D)              (None, 7, 7, 1280)   409600      ['block7a_project_bn[0][0]']

top_bn (BatchNormalization)    (None, 7, 7, 1280)   5120        ['top_conv[0][0]']

top_activation (Activation)    (None, 7, 7, 1280)   0           ['top_bn[0][0]']

avg_pool (GlobalAveragePooling  (None, 1280)        0           ['top_activation[0][0]']
2D)

top_dropout (Dropout)          (None, 1280)         0           ['avg_pool[0][0]']

predictions (Dense)            (None, 1000)         1281000     ['top_dropout[0][0]']

==================================================================================================
Total params: 5,330,571
Trainable params: 5,288,548
Non-trainable params: 42,023
__________________________________________________________________________________________________

Their names start with top_ to annotate the fact that they belong to the top classifier.

Note: This structure may change through time. In an earlier version of Keras, the top_conv, top_bn and top_activation weren't loaded in if the include_top argument was set to False, while in the newest version, they do (and their names still have the top_ prefix, making it a bit more confusing. Always check what the "top" is in a model, before defining your own, whether it's inspired by the original implementation or not.

We won't be using the top layers, as we'll be adding our own top to the EfficientNet model and re-training only the ones we add on top (before fine-tuning the convolutional base). It is worth noting what the architecture is originally using for the top, though! They seem to be using a GlobalAveragePooling2D and Dropout before the final Dense classification layer. While we don't have to strictly follow this approach (and other approaches may prove to be better for another dataset), it's reasonable to remember how the original top looked like.

#### Preprocessing Input for Pre-trained Models

Note: Data preprocessing plays a crucial role in model training, and most models will have different preprocessing pipelines. You don't have to perform guesswork here! Where applicable, a model comes with its own preprocess_input() function.

The preprocess_input() function applies the same preprocessing steps to the input as they were applied during training. You can import the function from the respective module of the model, if a model resides in its own module. For instance, VGG16 has its own preprocess_input function:

from keras.applications.vgg16 import preprocess_input

That being said, loading in a model, preprocessing input for it and predicting a result in Keras is as easy as:

import tensorflow.keras.applications as models
from keras.applications.vgg16 import preprocess_input

vgg16 = models.vgg16.VGG16(weights='imagenet', include_top=True)

img = # get data
img = preprocess_input(img)
pred = vgg16.predict(img)

Note: Not all models have a dedicated preprocess_input() function, because the preprocessing is done within the model itself. For instance, EfficientNet that we'll be using doesn't have its own dedicated preprocessing function, as the Rescaling layer takes care of that.

That's it! Now, since the pred array doesn't really contain human-readable data, you can also import the decode_predictions() function alongside the preprocess_input() function from a module. Alternatively, you can import the generic decode_predictions() function that also applies to models that don't have their dedicated modules:

from keras.applications.model_name import preprocess_input, decode_predictions
# OR
from keras.applications.imagenet_utils import decode_predictions
# ...
print(decode_predictions(pred))

Tying this together, let's get an image of a black bear via urllib, save that file into a target size suitable for EfficientNet (the input layer expects a shape of (batch_size, 224, 224, 3)) and classify it with the pre-trained model:

from tensorflow import keras
from keras.applications.vgg16 import preprocess_input, decode_predictions
from tensorflow.keras.preprocessing import image

import urllib.request
import matplotlib.pyplot as plt
import numpy as np

# Public domain image
urllib.request.urlretrieve(url, 'bear.jpg')

# Load image and resize (doesn't keep aspect ratio)
# Turn to array of shape (224, 224, 3)
img = image.img_to_array(img)
# Expand array into (1, 224, 224, 3)
img = np.expand_dims(img, 0)
# Preprocess for models that have specific preprocess_input() function
# img_preprocessed = preprocess_input(img)

# Load model and run prediction
effnet = keras.applications.EfficientNetB0(weights='imagenet', include_top=True)
pred = effnet.predict(img)
print(decode_predictions(pred))

We got the image from a URL, however - you can fetch the image from a mobile device, a REST API call, or any other source and classify it. Really - using a pre-trained classifier is as easy as importing it, feeding an image into it and decoding the results. You can serve a computer vision model to an end-user with only a few lines of code! This results in:

[[
('n02133161', 'American_black_bear', 0.6024658),
('n02132136', 'brown_bear', 0.1457715),
('n02134418', 'sloth_bear', 0.09819221),
('n02510455', 'giant_panda', 0.0069221947),
('n02509815', 'lesser_panda', 0.005077324)
]]

It's fairly certain that the image is an image of an American Black Bear, which is right! When preprocessed with a preprocessing function, the image may change significantly. For instance, VGG16's preprocessing function would change the color of the bear's fur:

It looks a lot more brown now! If we were to feed this image into EfficientNet, it'd think it's a brown bear:

[[
('n02132136', 'brown_bear', 0.7152758),
('n02133161', 'American_black_bear', 0.15667434),
('n02134418', 'sloth_bear', 0.012813852),
('n02134084', 'ice_bear', 0.0067828503), ('n02117135', 'hyena', 0.0050422684)
]]

It's important not to mix and match preprocessing functions between models. For instance, VGG16 learns that what we see as brown is called black, since the color got changed through preprocessing, and it only ever saw what we call "brown" with the label "black". Now, it wasn't trained to classify colors - but it was trained to classify between a black bear and a brown bear, and the colors are definitely mixed.

Is this a good thing or a bad thing?

Depends on who you ask. John Locke, one of the most influential philosophers of all time classified properties of objects into primary and secondary qualities and made a clear distinction between them. Primary qualities are those that exist independent of an observer. A book is a book and it has a size, irrespective of how I see it. That's a primary quality. Secondary qualities are those that depend on an observer (color, taste, smell), etc. and these are quite subjective. From an early age, many people have asked themselves whether "my yellow" is the same as "your yellow". We might see different colors but were thaught to call it "yellow". This doesn't change the fact that a yellow book is a book!

Regardless of whether it's true or not, it's conceivable that we all see the world in a slightly different way. There is no clear reason why that would stop us from communicating, building and understanding the world, especially since we can assign numerical, ubiqutous values to explain the sources of subjective experience. This isn't "yellow" - it's an electromagnetic wave with a wavelength of around 600nm. Your red and green receptors in the eye react to it and you "see yellow"! Nowadays, we can describe secondary qualities, such as color as non-disputable properties as well. It is true that it's easier to provide a raw image into a model, have the model do the preprocessing (like EfficientNet does) rather than having a separate function, since you then don't have to think about the preprocessing as much. However - it's not objectively better or worse that VGG16 "mixes up" colors. As a matter of fact, this diversity in knowledge can actually lead to some beautiful visualizations down the line. We'll see what that entails in another lesson when we cover the DeepDream algorithm.

Awesome! The model works. Now, let's add a new top to it and re-train the top to perform classification for something outside of the ImageNet set.

#### Adding a New Top to a Pre-trained Model

When performing transfer learning, you'll typically be loading models without tops, or remove them manually:

# When adding new layers, we also need to define the input_shape
effnet_base = keras.applications.EfficientNetB0(weights='imagenet',
include_top=False,
input_shape=((224, 224, 3)))

# Or load the full model
full_effnet = keras.applications.EfficientNetB0(weights='imagenet',
include_top=True,
input_shape=((224, 224, 3)))

# And then remove X layers from the top
trimmed_effnet = keras.Model(inputs=full_effnet.input, outputs=full_effnet.layers[-3].output)

We'll be going with the first option since it's more convenient. Depending on whether you'd like to fine-tune the convolutional blocks or not - you'll either freeze or won't freeze them. Say we want to use the underlying pre-trained feature maps and freeze the layers so that we only re-train the new classification layers at the top:

effnet_base.trainable = False

You don't need to iterate through the model and set each layer to be trainable or not, though you can. If you'd like to turn off the first n layers, and allow some higher-level feature maps to be fine-tuned, but leave the lower-level ones untouched, you can:

for layer in effnet_base.layers[:-2]:
layer.trainable = False

Here, we've set all layers in the base model to be untrainable, except for the last two. If we check the model, there are only ~2.5K trainable parameters now:

effnet_base.summary()
# ...
=========================================================================================
Total params: 4,049,571
Trainable params: 2,560
Non-trainable params: 4,047,011
_________________________________________________________________________________________

Now, let's define a Sequential model that'll be put on top of this effnet_base. Fortunately, chaining models in Keras is as easy as making a new model and putting it on top of another one! You can leverage the Functional API and just chain a few new layers on top of a model.

Let's add a GlobalAveragePooling2D layer, some Dropout and a dense classification layer:

gap = keras.layers.GlobalAveragePooling2D()(effnet_base.output, training=False)
do = keras.layers.Dropout(0.2)(gap)
output = keras.layers.Dense(100, activation='softmax')(do)

new_model = keras.Model(inputs=effnet_base.input, outputs=output)

Note: When adding the layers of the EfficientNet, we set the training to False. This puts the network in inference mode instead of training mode and it's a different parameter than the trainable we've set to False earlier. This is a crucial step if you wish to unfreeze layers later on! BatchNormalization computes moving statistics. When unfrozen, it'll start applying updates to parameters again, and will "undo" the training done before fine-tuning. Since TF 2.0, setting the model's trainable as False also turns training to False but only for BatchNormalization layers, so this step is unnecessary for versions after TF 2.0, though it's better to be safe than sorry.

Alternatively, you can use the Sequential API and call the add() method multiple times, or pass it in in the list of layers:

new_model = keras.Sequential([
effnet_base,
keras.layers.GlobalAveragePooling2D(),
keras.layers.Dropout(0.2),
keras.layers.Dense(100, activation='softmax')
])

new_model.layers[0].trainable = False

This adds the entire model as a layer itself, so it's treated as one entity:

Layer: 0, Trainable: False # Entire EfficientNet model
Layer: 1, Trainable: True
Layer: 2, Trainable: True
...

If a model is sequential, you can simply add it as:

new_model = keras.Sequential()
...

Though, this fails for non-sequential models. It's advised to use the Functional API for applications like these, since the Sequential API doesn't offer the required flexibility and not all models are sequential (as a matter of fact, since TF 2.4.0, all pre-trained models are functional). Additionally, you can't easily put the base network into inference mode - there's no training argument. The fact that the entire EfficientNet model is a black-box layer doesn't help us work easily with it, so the minor convenience of the Sequential API doesn't really benefit us much, and has several cons.

Back to our moedel - there are 100 output neurons for the CIFAR100 classes, with a softmax activation. Let's take a look at the trainable layers in the network:

for index, layer in enumerate(new_model.layers):
print("Layer: {}, Trainable: {}".format(index, layer.trainable))

This results in:

Layer: 0, Trainable: False
Layer: 1, Trainable: False
Layer: 2, Trainable: False
...
Layer: 235, Trainable: False
Layer: 236, Trainable: False
Layer: 237, Trainable: True
Layer: 238, Trainable: True
Layer: 239, Trainable: True
Layer: 240, Trainable: True
Layer: 241, Trainable: True

Awesome! Let's load in the dataset, preprocess it and re-train the classification layers on it. We'll be using the same CIFAR100 dataset from the last lesson, since it proved to be a difficult one to train a CNN on. The lack of data and limitations of data augmentation made it difficult to create a powerful classifier. Let's see if we can employ transfer learning to help us!

### TensorFlow Datasets

We'll be working with the CIFAR100 dataset, again. Though, this time around, we won't be loading it as a bare NumPy array from Keras. We'll be working with TensorFlow Datasets!

Keras' datasets module contains a few datasets, but these are mainly meant for benchmarking and learning and aren't too useful beyond that point. We can use tensorflow_datasets to get access to a much larger corpora of datasets! Additionally, all of the datasets from the module are standardized, so you don't have to bother with different preprocessing steps for every single dataset you're testing your models out on. While it may sound just like a simple convenience, rather than a game-changer - if you train a lot of models, the time it takes to do overhead work gets beyond annoying. The library provides access to datasets from MNIST to Google Open Images (11MB - 565GB), spanning several categories:

• Audio
• D4rl
• Graphs
• Image
• Image Classification
• Object Detection
• Ranking
• Rlds
• Robomimic
• Robotics
• Text
• Time Series
• Text Simplification
• Vision Language
• Video
• Translate
• etc...

And the list is growing! As of 2022, there are 278 datasets available, the names of which you can obtain via tfds.list_builders(). Additionally, TensorFlow Datasets supports community datasets, with over 700 Huggingface datasets and the Kubric dataset generator. If you're building a general intelligent system, there's a very good chance there's a public dataset there. For all other purposes - you can download public datasets and work with them, with custom pre-processing steps. Kaggle, Huggingface and academic repositories are popular choices.

Additionally, in a similar effort, TensorFlow released an amazing GUI tool - Know Your Data, which is still in beta (as of writing) and aims to answer important questions on data corruption (broken images, bad labels, etc.), data sensitivity (does your data contain sensitive content), data gaps (obvious lack of samples), data balance, etc.

A lot of these can help with avoiding bias and data skew - arguably one of the most important things to do when working on projects that can have an impact on other humans.

Another amazing feature is that datasets coming from TensorFlow Datasets are optimized. They're packed into a tf.data.Dataset object, with which you can maximize the performance of your network through pre-fetching, automated optimization (on the back of TensorFlow), easy transformations on the entirety of the dataset, etc.

Note: If you're not a fan of proprietary classes, such as Dataset - you can convert it back into a simple NumPy array for framework-agnosticism.

The module can be installed through:

\$ pip install tensorflow_datasets

Once installed, you can access the list of available datasets via:

print(tfds.list_builders())
print(f'Number of Datasets: {len(tfds.list_builders())}')
['abstract_reasoning', 'accentdb', 'aeslc', 'aflw2k3d', ...]
Number of Datasets: 278

Though, you're more likely to use the relevant web pages on the TensorFlow Datasets website, which offers more information, sample images, etc. rather than this list. To load a dataset, you can use the load() function:

dataset, info = tfds.load("cifar100", as_supervised=True, with_info=True)
class_names = info.features["label"].names
n_classes = info.features["label"].num_classes
print('Class names:', class_names)
print('Num of classes:', n_classes)

Datasets can be imported as unsupervised or supervised, and with or without additional information, such as the label names and the number of classes. In the code snippet above, we've loaded in "cifar100" as a supervised dataset (with labels) and information:

Class names: ['apple', 'aquarium_fish', 'baby', ...]
Num of classes: 100

The info.features["label"].names list can come in handy! It's a list of human-readable labels that correspond to the numerical labels in the dataset. We don't have to find a list manually online or type it out this way!

#### Train, Test and Validation Splits with TensorFlow Datasets

One of the optional arguments you can pass into the load() function is the split argument. The new Split API allows you to define which splits of the dataset you want to split out. By default, for this dataset, it only supports a 'train' and 'test' split - these are the "official" splits for this dataset. There's no valid split.

Note: Each dataset has an "official" split. Some only have the 'train' split, some have a 'train' and 'test' split and some even include a 'validation' split. This is the intended split and only if a dataset supports a split, can you use that split's string alias. If a dataset contains only a 'train' split, you can split that training data into a train/test/valid set without issues.

These correspond to the tfds.Split.TRAIN and tfds.Split.TEST and tfds.Split.VALIDATION enums, which used to be exposed through the API in an earlier version.

You can really slice a Dataset into any arbitrary number of sets, though, we typically do three - train_set, test_set, valid_set:

(test_set, valid_set, train_set), info = tfds.load("cifar100",
split=["test", "train[0%:20%]", "train[20%:]"],
as_supervised=True, with_info=True)

class_names = info.features["label"].names
n_classes = info.features["label"].num_classes
print(f'Class names: {class_names[:10]}...', ) # ['apple', 'aquarium_fish', 'baby', 'bear', 'beaver', 'bed', 'bee', 'beetle', 'bicycle', 'bottle']...
print('Num of classes:', n_classes) # Num of classes: 100

print("Train set size:", len(train_set)) # Train set size: 40000
print("Test set size:", len(test_set)) # Test set size: 10000
print("Valid set size:", len(valid_set)) # Valid set size: 10000

We've taken 'test' split and extracted it into the test_set. The slice between 0% and 20% of the 'train' split is assigned to the valid_set and everything beyond 25% is the train_set. This is validated through the sizes of the sets themselves as well.

Instead of percentages, you can use absolute values or a mix of percentage and absolute values:

# Absolute value split
split=["test", "train[0:10000]", "train[10000:]"],
as_supervised=True)

print("Train set size:", len(train_set)) # Train set size: 40000
print("Test set size:", len(test_set)) # Test set size: 10000
print("Valid set size:", len(valid_set)) # Valid set size: 10000

# Mixed notation split
# 5000 - 50% (25000) left unassigned
split=["test[:2500]", # First 2500 of 'test' are assigned to test_set
"train[0:10000]",    # 0-10000 of 'train' are assigned to valid_set
"train[50%:]"],        # 50% - 100% of 'train' (25000) assigned to train_set
as_supervised=True)

You can additionally do a union of sets, which is less commonly used, as sets are interleaved then:

split=['train+test', 'train[:50%]+test'],
as_supervised=True)

print("Train+test: ", len(train_and_test))               # Train+test:  60000
print("Train[:50%]+test: ", len(half_of_train_and_test)) # Train[:50%]+test:  35000

These two sets are now heavily interleaved.

#### Even Splits for N Sets

Again, you can create any arbitrary number of splits, just by adding more splits to the split list:

split=["train[:10%]", "train[10%:20%]", "train[20%:30%]", "train[30%:40%]", ...]

However, if you're creating many splits, especially if they're even - the strings you'll be passing in are very predictable. This can be automated by creating a list of strings, with a given equal interval (such as 10%) instead. For exactly this purpose, the tfds.even_splits() function generates a list of strings, given a prefix string and the desired number of splits:

import tensorflow_datasets as tfds

s1, s2, s3, s4, s5 = tfds.even_splits('train', n=5)
# Each of these elements is just a string
split_list = [s1, s2, s3, s4, s5]
print(f"Type: {type(s1)}, contents: '{s1}'")
# Type: <class 'str'>, contents: 'train[0%:20%]'

for split in split_list:
split=split,
as_supervised=True)
print(f"Test set length for Split {split}: ", len(test_set))

This results in:

Test set length for Split train[0%:20%]: 10000
Test set length for Split train[20%:40%]: 10000
Test set length for Split train[40%:60%]: 10000
Test set length for Split train[60%:80%]: 10000
Test set length for Split train[80%:100%]: 10000

Alternatively, you can pass in the entire split_list as the split argument itself, to construct several split datasets outside of a loop:

ts1, ts2, ts3, ts4, ts5 = tfds.load("cifar100",
split=split_list,
as_supervised=True)

With a working understanding of tfds under your belt - let's load the CIFAR100 dataset in:

import tensorflow_datasets as tfds
import tensorflow as tf

(test_set, valid_set, train_set), info = tfds.load("cifar100",
split=["test", "train[0%:20%]", "train[20%:]"],
as_supervised=True, with_info=True)

class_names = info.features["label"].names
n_classes = info.features["label"].num_classes
print(f'Class names: {class_names[:10]}...', ) # ['apple', 'aquarium_fish', 'baby', 'bear', 'beaver', 'bed', 'bee', 'beetle', 'bicycle', 'bottle']...
print('Num of classes:', n_classes) # Num of classes: 100

print("Train set size:", len(train_set)) # Train set size: 40000
print("Test set size:", len(test_set)) # Test set size: 10000
print("Valid set size:", len(valid_set)) # Valid set size: 10000

Let's take note of a couple of relevant variables in a config dictionary:

config = {
'TRAIN_SIZE' : len(train_set),
'BATCH_SIZE' : 32
}

Now, the CIFAR100 images are significantly different from the ImageNet images! Namely, CIFAR100 images are just 32x32, while our EfficientNet model expects 224x224 images. We'll want to resize the images in any case. We might also want to apply some transformation functions on duplicate images to artificially expand the sample size per class since the dataset doesn't have enough of them. With ImageDataGenerator, we've seen that you have a very loose degree of freedom when it comes to augmentation, and the process is highly automated. When dealing with TensorFlow Datasets, in order to get to use every little bit of optimization they provide - you'll typically use tf.image operations to translate, rotate, etc. images in the preprocess_image() function.

Instead of a dedicated preprocess_image() function, you can simply chain several map() calls with lambda functions, but this approach is significantly less readable and isn't recommended for any larger number of operations.

The downside is - tf.image is fairly rudimentary. Unlike Keras' rich operations, there are surprisingly enough only a few that can be used for random augmentation, and they offer a smaller degree of freedom. As of writing, it's still in a stage early enough that it's not the ideal approach to data augmentation, but it's better than nothing. You can, always, use ImageDataGenerator with the raw NumPy sequences instead, however this requires us to convert them, which means we lose out on some of the optimizations.

Note: A great alternative, making your model more preprocessing-agnostic is to embed preprocessing layers into the model, such as keras.layers.RandomFlip() and keras.layers.RandomRotation(0.2).

Let's define a preprocessing function for each image and its associated label:

def preprocess_image(image, label):
resized_image = tf.image.resize(image, [224, 224])
img = tf.image.random_flip_left_right(resized_image)
img = tf.image.random_brightness(img, 0.4)
# Preprocess image with model-specific function if it has one
# processed_image = preprocess_input(resized_image)
return img, label

Additionally, since we don't want to perform any random transformations to the validation and testing sets, let's define a separate function for those:

def preprocess_test_valid(image, label):
resized_image = tf.image.resize(image, [224, 224])
# Preprocess image with model-specific function if it has one
# processed_image = preprocess_input(resized_image)
return resized_image, label

And finally, we'll want to apply this function to each image in the sets! This is easily done via the map() function. Since the input into the network also expects batches ((batch_size, 224, 224, 3) instead of (224, 224, 3)) - we'll also batch() the datasets after mapping:

train_set = train_set.map(preprocess_image).batch(32).repeat().prefetch(tf.data.AUTOTUNE)
test_set = test_set.map(preprocess_test_valid).batch(32).prefetch(tf.data.AUTOTUNE)
valid_set = valid_set.map(preprocess_test_valid).batch(32).prefetch(tf.data.AUTOTUNE)

In this example, we're using tf.data - the built-in module for creating data pipelines and optimizing their usage. It's not to be confused with tfds, which is just a library for fetching datasets, while tf.data does the heavy lifting on the hardware. The prefetch() function is optional but helps with efficiency and the tf.data.AUTOTUNE call lets TensorFlow optimize how to perform prefetching. As the model is training on a single batch, the prefetch() function pre-fetches the next batch so it's not waited upon when the training step is finished. Similarly enough, you could use functions like cache() and interleave() to further optimize IO and data extraction, though, these aren't to be used blindly. If used at an incorrect place or time, they're likely to make your pipelines slower! We'll dedicate a lesson to optimizing data pipelines later. For now - let's just prefetch().

We have a repeat() call on the train_set, which isn't present in other sets. This is analogous to the ImageDataGenerator class, which produces an infinite number of training samples, with random transformations. On each request, the preprocess_image() function we wrote will randomly transform the incoming images, so we have a fresh steady stream of slightly altered data. We don't want to do this for the testing and validation sets, other than making the images the same size and applying the common pre-processing step if there is one (EfficientNetB0 doesn't have an external preprocessing function).

Note: Test-time augmentation is a thing too. We'll talk about it later.

Let's quickly take a look at some of the images from any of the sets:

fig = plt.figure(figsize=(10, 10))

i = 1
for entry in test_set.take(25):

sample_image = np.squeeze(entry[0].numpy()[0])
sample_label = class_names[entry[1].numpy()[0]]

ax.imshow(np.array(sample_image, np.int32))
ax.set_title(f"Class: {sample_label}")
ax.axis('off')
i = i+1

plt.tight_layout()
plt.show()

### Training a Model with Transfer Learning

With the data loaded, preprocessed and split into adequate sets - we can finally train the model on it.

Since we're doing sparse classification, a sparse_categorical_crossentropy loss should work well, and the Adam optimizer is a reasonable default optimizer. Let's compile the model, and train it on a few epochs. It's worth remembering that most of the layers in the network are frozen! We're only training the new classifier on top of the extracted feature maps.

Only once we train the top layers, we may decide to unfreeze the feature extraction layers, and let them fine-tune a bit more. This step is optional but usually allows you to really squeeze out the best of a model, but be weary if they're fairly large, since it'll take a lot longer to train the entire network. A good rule of thumb is to try and compare the datasets and guesstimate which levels of the hierarchy you can re-use without re-training, to avoid re-training some of the levels that might be redundant to re-train.

If they're really different, you probably chose a network pre-trained on the wrong dataset. It wouldn't be efficient to use feature extraction of Places365 (man-made objects) for classifying animals. However, it would make sense to use a network trained on ImageNet (which has various objects, animals, plants and humans) and then use it for a different dataset with relatively similar categories, such as CIFAR100. It's actually surprising how well ImageNet weights transfer to most datasets, even if they don't appear to have any remote connection to the domain. We'll especially see this in the next Guided Project on breast cancer classification from histology images.

Note: Depending on the architecture you're using, unfreezing all of the layers might result in an Out-Of-Memory exception. When possible, try to find an architecture pre-trained on a dataset that's sufficiently similar to yours that you don't have to change all of the feature extractors.

Let's compile the network and check its structure:

checkpoint = keras.callbacks.ModelCheckpoint(filepath='effnet_transfer_learning.h5', save_best_only=True)

new_model.compile(loss="sparse_categorical_crossentropy",
metrics=["accuracy", keras.metrics.SparseTopKCategoricalAccuracy(k=3)])

new_model.summary()

This is a great time to validate whether you've correctly frozen the layers:

...
==================================================================================================
Total params: 4,177,671
Trainable params: 128,100
Non-trainable params: 4,049,571
__________________________________________________________________________________________________

Only 128k trainable parameters! Naturally, it'll take longer to train this network than a 128k MLP, since there's a lot more going on - data loading, augmentation, passing it through all of the filters, performing convolutions, etc. but it'll take significantly less than training the entire network. Let's train the new network (really, only the top of it) for 10 epochs:

history = new_model.fit(train_set,
epochs=10,
steps_per_epoch = config['TRAIN_SIZE']/config['BATCH_SIZE'],
callbacks=[checkpoint],
validation_data=valid_set)

Since the train_set is infinite, we'll want to define the steps_per_epoch. This may take some time and is ideally done on a GPU. Depending on how large the model is, and the dataset being fed into it. If you don't have access to a GPU, it's advised to run this code on any of the cloud providers that give you access to a free GPU, such as Google Collab, Kaggle Notebooks, etc. Each epoch can take anywhere from 60 seconds on stronger GPUs to 10 minutes, on weaker ones.

This is the point in which you sit back and go grab a coffee (or tea)! After 10 epochs, the train and validation accuracy are looking good:

Epoch 1/10
1250/1250[==============================] - 97s 76ms/step - loss: 1.9179 - accuracy: 0.5196 - sparse_top_k_categorical_accuracy: 0.7216 - val_loss: 1.3436 - val_accuracy: 0.6324 - val_sparse_top_k_categorical_accuracy: 0.8225
...
Epoch 10/10
1250/1250[==============================] - 86s 74ms/step - loss: 0.8610 - accuracy: 0.7481 - sparse_top_k_categorical_accuracy: 0.9015 - val_loss: 1.0820 - val_accuracy: 0.6935 - val_sparse_top_k_categorical_accuracy: 0.8651

It has a 69% validation accuracy, and an 86% Top-3 validation accuracy. These are far from the potential of the network though - the classification top has probably done all it could with the feature extractors as they are now. Let's take a look at the learning curves!

#### Evaluating Before Fine-Tuning

Let's first test this model out, before trying to unfreeze all of the layers. We'll perform some basic evaluation - metric, learning curves and a confusion matrix. Let's start with the metrics:

new_model.evaluate(test_set)
# 157/157 [==============================] - 10s 65ms/step - loss: 1.0806 - accuracy: 0.6884 - sparse_top_k_categorical_accuracy: 0.8718

~69% on the testing set, and close to the accuracy on the validation set. It has a pretty decent 87% Top-3 accuracy. Looks like our model is generalizing well, but there's still room for improvement. Let's take a look at the learning curves:

The training curves are to be expected - they're pretty short since we only trained for 10 epochs, but they've quickly plateaued, so we probably wouldn't have gotten much better performance with more epochs. The validation loss and accuracy dance together with the training loss and accuracy, so we would've overfit the model if we were to train it further as it is. While oscillations do occur and the accuracy could very well rise in Epoch 11 - it's not too likely, so we'll miss out on the chance.

Let's predict the test set and extract the labels from the set to produce a classification report and confusion matrix:

y_pred = new_model.predict(test_set)
labels = tf.concat([y for x, y in test_set], axis=0)

Since we have 100 classes - both the classification report and confusion matrix are going to be very large and hardly readable:

from sklearn import metrics
print(metrics.classification_report(labels, np.argmax(y_pred, axis=1)))
precision    recall  f1-score   support

0       0.89      0.89      0.89        55
1       0.76      0.78      0.77        49
2       0.45      0.64      0.53        45
3       0.45      0.58      0.50        52
...

We only have around 50 images per class in the testing set, but we can't really get more than that. It's clear that some classes are better-learned than other classes, such as 0 having significantly higher recall and precision than, say, class 3.

This is actually surprising, since class 0 is apple and 3 is bear! ImageNet has images of bears, and even classifies different types of bears, so you'd expect the network to generalize to bears well, transfering the knowledge from ImageNet. If anything - this speaks about how much "prescription" this network effectively has, given how small the images are.

Let's plot the confusion matrix:

from sklearn.metrics import confusion_matrix
import seaborn as sns

matrix = confusion_matrix(labels, y_pred.argmax(axis=1))

# Plot on heatmap
fig, ax = plt.subplots(figsize=(15, 15))
sns.heatmap(matrix, ax=ax, fmt='g')

# Stylize heatmap
ax.set_xlabel('Predicted labels')
ax.set_ylabel('True labels')
ax.set_title('Confusion Matrix')

# Set ticks
ax.xaxis.set_ticks(np.arange(0, 100, 1))
ax.yaxis.set_ticks(np.arange(0, 100, 1))
ax.xaxis.set_ticklabels(class_names, rotation=90, fontsize=8)
ax.yaxis.set_ticklabels(class_names, rotation=0, fontsize=8)

This results in:

Again - the confusion matrix is pretty large, since we have 100 classes. Though, for the most part, it looks like it's actually generalizing to classses well, albeit, not ideal.

Can we fine-tune this network further? We've replaced and re-trained the top layers concerned with classification of feature maps, but the feature maps themselves might not be ideal! While they are pretty good, these images are simply different from ImageNet, so it's worth taking the time to update the feature extraction layers as well. Let's try unfreezing the convolutional layers and fine-tuning them as well.

#### Unfreezing Layers - Fine-Tuning a Network Trained with Transfer Learning

Once you've finished re-training the top layers, you can close the deal and be happy with your model. For instance, suppose you got a 95% accuracy - you seriously don't need to go further. However, why not?

If you can squeeze out an additional 1% in accuracy, it might not sound like a lot, but consider the other end of the trade. If your model has a 95% accuracy on 100 samples, it misclassified 5 samples. If you up that to 96% accuracy, it misclassified 4 samples.

The 1% of accuracy translates to a 25% decrease in false classifications.

Whatever you can further squeeze out of your model can actually make a significant difference on the number of incorrect classifications. Again, the images in CIFAR100 are much smaller than ImageNet images, and it's almost as if someone with great eyesight suddenly gained a huge prescription and only saw the world through blurry eyes. The feature maps have to be at least somewhat different!

Let's save the model into a file so we don't lose the progress, and unfreeze/fine-tune a loaded copy, so we don't accidentally mess up the weights on the original one:

new_model.save('effnet_transfer_learning.h5')

Now, we can fiddle around and change the loaded_model without impacting new_model. To start out, we'll want to change the loaded_model from inference mode back to training mode - i.e. unfreeze the layers so that they're trainable again.

Note: Again, if a network uses BatchNormalization (and most do), you'll want to keep them frozen while fine-tuning a network. Since we're not freezing the entire base network anymore, we'll just freeze the BatchNormalization layers instead and allow other layers to be altered.

Let's turn off the BatchNormalization layers so our training doesn't go down the drain:

if isinstance(layer, keras.layers.BatchNormalization):
layer.trainable = False
else:
layer.trainable = True

print("Layer: {}, Trainable: {}".format(index, layer.trainable))

Let's check if that worked:

Layer: 0, Trainable: True
Layer: 1, Trainable: True
Layer: 2, Trainable: True
Layer: 3, Trainable: True
Layer: 4, Trainable: True
Layer: 5, Trainable: False
Layer: 6, Trainable: True
Layer: 7, Trainable: True
Layer: 8, Trainable: False
...

Awesome! Before we can do anything with the model, to "solidify" the trainability, we have to recompile it. This time around, we'll be using a smaller learning_rate, since we don't want to train the network, but rather just fine-tune what's already there:

checkpoint = keras.callbacks.ModelCheckpoint(filepath='effnet_transfer_learning_finetuned.h5', save_best_only=True)

# Recompile after turning to trainable
metrics=["accuracy", keras.metrics.SparseTopKCategoricalAccuracy(k=3)])

epochs=15,
steps_per_epoch = config['TRAIN_SIZE']/config['BATCH_SIZE'],
callbacks=[checkpoint],
validation_data=valid_set)

Again, this may take some time - so sip on another beverage of your choice (stay hydrated) while this runs in the background. The fine-tuning time heavily depends on the architecture you chose to go with but most of the cutting-edge architectures will take some time on a home-grade setup.

Once it finishes, it should reach up to around 80% in accuracy and around 93% on Top-3 accuracy on the validation set:

Epoch 1/15
1250/1250[==============================] - 384s 322ms/step - loss: 0.6567 - accuracy: 0.8024 - sparse_top_k_categorical_accuracy: 0.9356 - val_loss: 0.8687 - val_accuracy: 0.7520 - val_sparse_top_k_categorical_accuracy: 0.9069
...
Epoch 15/15
1250/1250[==============================] - 377s 322ms/step - loss: 0.3858 - accuracy: 0.8790 - sparse_top_k_categorical_accuracy: 0.9715 - val_loss: 0.7071 - val_accuracy: 0.7971 - val_sparse_top_k_categorical_accuracy: 0.9331

Additionally, if you take a look at the learning curves, they appear to have not plateaued, and we could've probably increased the performance of the model further if we were just to train it for longer:

Note: We probably could've seen further performance increases through further training. Note that training for longer, naturally, takes time. While comparatively low to many other architectures and datasets, a 100 epochs on this dataset took over 10h to train on a home GPU. It's understandable if you're antsy about waiting this long, but unfortunately, 10h isn't even too long to wait for a network to train.

Let's evaluate it and visualize some of the predictions:

# 157/157 [==============================] - 10s 61ms/step - loss: 0.7041 - accuracy: 0.7920 - sparse_top_k_categorical_accuracy: 0.9336
fig = plt.figure(figsize=(10, 10))

i = 1
for entry in test_set.take(25):
# Predict, get the raw Numpy prediction probabilities
# Reshape entry to the model's expected input shape
pred = np.argmax(loaded_model.predict(entry[0].numpy()[0].reshape(1, 224, 224, 3)))

# Get sample image as numpy array
sample_image = entry[0].numpy()[0]
# Get associated label
sample_label = class_names[entry[1].numpy()[0]]
# Get human label based on the prediction
prediction_label = class_names[pred]
# Plot image and sample_label alongside prediction_label
ax.imshow(np.array(sample_image, np.int32))
ax.set_title(f"Actual: {sample_label}\nPred: {prediction_label}")
ax.axis('off')
i = i+1

plt.tight_layout()
plt.show()

A couple of misclassifications, as you'd expect of an 80% accurate model. A raccoon was classified as a shrew which is a mole-like animal (not too far from the truth). A chimpanzee was classified as a lamp (I'd have classified it as a beer bottle). A bus was classified as a pickup truck. This one is curious - as the blue stripe on the bus makes it appear a bit like a pickup truck. It looks like the model understood the blue stripe as the end of the bed of a pickup truck, instead of recognizing the grey top as part of the bus. Finally, a spider was classified as a trout, which is a very different class, but the image is so blurred and small that It's totally understandable.

Our previous model, a custom one, built and trained on this dataset had a 66% Top-1 accuracy, which means we've decreased the error-rate by 39% (from 33 per 100 images to 20 per 100 images). If we'd have sacrificed some time-wise performance for accuracy and used the ImageDataGenerator class which offers more data augmentation options (making the model more robust), we could've very likely seen better accuracy with the model.

If you want to obtain the Top-K predictions (not just the most probable one), instead of using argmax() you can utilize TensorFlow's top_k method:

top_probas, top_indices = tf.nn.top_k(pred, k=k)

print(top_probas)  # tf.Tensor([[0.900319   0.07157221 0.00889194]], shape=(1, 3), dtype=float32)
print(top_indices) # tf.Tensor([[66 88 21]], shape=(1, 3), dtype=int32)

If you'd like to display this information alongside the input and the predictions - you could plot the input image, next to a bar chart of the confidence of the network:

for entry in test_set.take(1):
img = entry[0][0].numpy().astype('int')
label = entry[1][1]

# Predict and get top-k classes
top_probas, top_indices = tf.nn.top_k(pred, k=3)
# Convert to NumPy, squeeze and convert to list for ease of plotting
top_probas = top_probas.numpy().squeeze().tolist()
# Turn indices into classes
pred_classes = []
for index in top_indices.numpy().squeeze():
pred_classes.append(class_names[index])

fig, ax = plt.subplots(1, 2, figsize=(16, 4))
ax[0].imshow(img)
ax[0].axis('off')
ax[1].bar(pred_classes, top_probas)

plt.tight_layout()

Here, the network is pretty confident that the image is an image of a raccoon. There's a bit of a tiger and a chimpanzee there, but the probabilities are really low:

What about the spider-trout from before?

The network is fairly lost here - all of the probabilities are low, and none of them are right. If you take the top probability at face value and return that class, it sounds like the model was seriously wrong, but when you inspect its confidence, its "line of reasoning" can become a lot clearer. Generally, and especially when returning results to an end-user, you'll want to display the confidence of the model, and potentially other Top-K classes and their probabilities, if the highest probability isn't too high.

For instance, if the top probability is below, say, 50% - you could return multiple classes and their probabilities, such as in the second input image. If the model is fairly certain, you could return just the top class and its probability.

Finally, let's take a look at the confusion matrix compared to the previous one:

While it's still not perfect - it's looking much cleaner!

### Conclusion

Transfer learning is the process of transferring already learned knowledge representations from one model to another, when applicable. This concludes the lesson on transfer learning for Image Classification with Keras and Tensorflow. We've started out with taking a look at what transfer learning is and how knowledge representations can be shared between models and architectures.

Then, we've taken a look at some of the most popular and cutting edge models for Image Classification released publically, and piggy-backed on one of them - EfficientNet - to help us in classifying some of our own data. We've taken a look at how to load and examine pre-trained models, how to work with their layers, predict with them and decode the results, as well as how to define your own layers and intertwine them with the existing architecture.

This lesson introduced TensorFlow Datasets, the benefits of using the module and the basics of working with it. Finally, we've loaded and preprocessed a dataset, and trained our new classification top layers on it, before unfreezing the layers and fine-tuning it further through several additional epochs.

Lessson 3/15
You must first start the course before tracking progress.
Mark completed

format: plain


text:
Sales Toll Free No: 1-855-666-7446

Integration by Parts Calculator

Top
Integration by parts is one of the procedure of integration. Integration by parts method will integrate the product of functions and is derived by differentiation the product rule.

Consider the product rule,
$(g(x)h(x))^{'} = g(x)h^{'}(x)+g^{'}(x)h(x)$

Integrating both sides and rearranging,
$(g(x)h(x))^{'} = \int g(x)h^{'}(x) dx+\int g^{'}(x)h(x) dx$
$\int g(x)h^{'}(x)dx = (g(x)h(x))^{'}dx - \int g^{'}(x)h(x) dx$

or

By replacing g(x) and h(x) by u and v,
$\int u \ dv = uv - \int v \ du$

This is the integration by parts formula.

Plug in the function into the integration by parts calculator, this online calculator will integrate the given function.

Steps

Step 1 : Read the given problem and consider first and second function as u and v.

Step 2 : Substitute those values into the integration by parts formula i.e.,
$\int u \ dv = uv - \int v \ du$

and get the integrated function.

Problem

Based on Integration by parts, some of the problems are given below.

Solved Examples

Question 1: Evaluate $\int e^x \ cosx \ dx$.
Solution:

Step 1: Given : $\int e^x \ cosx \ dx$
Let us take,
$u = e^x$ ; $dv = cosx \ dx$
$du = e^x \ dx$ ; $v = sinx$

Step2 : Integrating by parts,
$\int u \ dv = uv - \int v \ du$
$\int e^x \ cosx \ dx = e^x \ sinx - \int e^x \ sinx \ dx$

Again integrating by parts and taking,
$u = e^x$ ; $dv = sinx \ dx$
$du = e^x \ dx$ ; $v = -cosx$

$\int e^x \ cosx \ dx = e^x \ sinx - {e^x \ -cosx - \int e^x \ -cosx \ dx}$
$\int e^x \ cosx \ dx = e^x \ sinx + e^x \ cosx - \int e^x \ cosx \ dx$
$2\int e^x \ cosx \ dx = e^x \ sinx + e^x \ cosx$ + C
$\int e^x \ cosx \ dx = \frac{1}{2}(e^x \ sinx + e^x \ cosx)$ + C

Question 2: Evaluate $\int x^{5}e^{x^3} dx$.
Solution:

Step 1: Given : $\int x^{5}e^{x^3} dx$ = $\int x^{3}x^{2}e^{x^3} dx$
Let us take,
$u = x^3$ ; $dv = x^{2}e^{x^3} dx$
$du = 3x^2 dx$ ; $v = \frac{1}{3}e^{x^3}$

Step2 : Integrating by parts,
$\int u \ dv = uv - \int v \ du$
$\int x^{5}e^{x^3} dx = x^3 \ \frac{1}{3}e^{x^3} - \int \frac{1}{3}e^{x^3} \ (3x^2) dx$
$\int x^{5}e^{x^3} dx = \frac{1}{3}x^{3}e^{x^3} - \int x^{2}e^{x^3}dx$
$\int x^{5}e^{x^3} dx = \frac{1}{3}x^{3}e^{x^3} - \frac{1}{3}e^{x^3}dx$ + C


text:
### Spectrophotometric Determination of Certain Vicinal Dihydroxybenzene Derivatives in Pharmaceutical PreparationsSpectrophotometric Determination of Certain Vicinal Dihydroxybenzene Derivatives in Pharmaceutical Preparations

Access Restriction
Open

 Author Gowda, Babu G. ♦ Melwanki, Mahaveer B. ♦ Seetharamappa, Jaldappa Source J-STAGE Content type Text Publisher The Japan Society for Analytical Chemistry Language English
 Abstract A simple, rapid and sensitive spectrophotometric method for the assay of certain adrenergic drugs, [pyrocatechol (PC), levodopa (LD), methyldopa (MD) and dopamine (DP)] is described. The method involves the oxidation of o-dihydroxybenzene derivatives by $K_{2}CrO_{4}$ followed by oxidative coupling with sulfanilic acid (SPA), leading to the formation of a red or violet colored product having maximum absorbance at 490 - 495 nm for LD, MD and DP or at 560 nm for PC. This method has been successfully applied to the determination of LD, MD and DP in tablets and injections of pharmaceutical preparation. The common excipients do not interfere with the proposed method. A statistical comparison of these results with those of a reported method shows good agreement and indicates no significant difference in precision. ISSN 09106340 Learning Resource Type Article Publisher Date 2001-01-01 e-ISSN 13482246 Journal Analytical Sciences(analsci) Volume Number 17 Issue Number 4 Page Count 2 Starting Page 533 Ending Page 534


text:
Notice

# IEEE Transactions on Electron Devices

## Filter Results

Displaying Results 1 - 25 of 66
• ### Front cover

Publication Year: 2014, Page(s): C1
| PDF (363 KB)
• ### IEEE Transactions on Electron Devices publication information

Publication Year: 2014, Page(s): C2
| PDF (149 KB)

Publication Year: 2014, Page(s):217 - 219
| PDF (165 KB)
• ### A warm welcome to a new T-ED Editor

Publication Year: 2014, Page(s): 220
| PDF (310 KB) | HTML
• ### Foreword Special Issue on Compact Modeling of Emerging Devices

Publication Year: 2014, Page(s):221 - 224
| | PDF (258 KB) | HTML

The 13 papers in this special issue focus on compact modeling of emerging devices. View full abstract»

• ### Compact Models and the Physics of Nanoscale FETs

Publication Year: 2014, Page(s):225 - 233
Cited by:  Papers (27)
| | PDF (1194 KB) | HTML

The device physics of nanoscale MOSFETs is related to traditional compact models. Beginning with the virtual source model, a model for nanoscale MOSFETs expressed in traditional form, we show how the Landauer approach gives a clear physical interpretation to the parameters in the model. The analysis shows that transport in the channel is limited by diffusion near the virtual source both below and ... View full abstract»

• ### BSIM6: Analog and RF Compact Model for Bulk MOSFET

Publication Year: 2014, Page(s):234 - 244
Cited by:  Papers (30)
| | PDF (1957 KB) | HTML

BSIM6 is the latest industry-standard bulk MOSFET model from the BSIM group developed specially for accurate analog and RF circuit designs. The popular real-device effects have been brought from BSIM4. The model shows excellent source-drain symmetry during both dc and small signal analysis, thus giving excellent results during analog and RF circuit simulations, e.g., harmonic balance simulation. T... View full abstract»

• ### RF-Noise Modeling in Advanced CMOS Technologies

Publication Year: 2014, Page(s):245 - 254
Cited by:  Papers (11)
| | PDF (1590 KB) | HTML

RF circuit design in deep-submicrometer CMOS technologies relies heavily on accurate modeling of thermal noise. Based on Nyquist's law, predictive modeling of thermal noise in MOSFETs was possible for a long time, provided that parasitic resistances and short-channel effects were properly accounted for. In sub-100-nm technologies, however, microscopic excess noise starts to play a significant role... View full abstract»

• ### Compact Modeling of SOI MOSFETs With Ultrathin Silicon and BOX Layers

Publication Year: 2014, Page(s):255 - 265
Cited by:  Papers (3)
| | PDF (1938 KB) | HTML

The reported compact SOI-MOSFET model hiroshima university starc igfet model-silicon on thin buried oxide (HiSIM-SOTB) has been developed for devices with ultrathin silicon on insulator (SOI) and buried oxide (BOX) layers. The potential distribution determined by the Poisson equation is accurately solved with the Newton iteration method across the SOI layer and in the substrate on the backside of ... View full abstract»

• ### Compact Modeling and Contact Effects in Thin Film Transistors

Publication Year: 2014, Page(s):266 - 277
Cited by:  Papers (12)
| | PDF (1007 KB) | HTML

A compact model for the current-voltage characteristics of organic thin-film transistors (OTFTs), which includes the effects of the contact regions, is proposed. Different physical and morphological aspects of contacts with organic or other emerging materials such as graphene, semiconducting dichalcogenides such as MoS2, or NW devices are described. The electrical behavior of the contacts is studi... View full abstract»

• ### Compact DC Modeling of Organic Field-Effect Transistors: Review and Perspectives

Publication Year: 2014, Page(s):278 - 287
Cited by:  Papers (28)
| | PDF (1639 KB) | HTML

In spite of impressive improvements achieved for organic field-effect transistors (OFETs), there is still a lack of theoretical understanding of their behaviors. Furthermore, it is challenging to develop a universal model that would cover a huge variety of materials and device structures available for state-of-the-art OFETs. Nonetheless, currently there is a strong need for specific OFET compact m... View full abstract»

• ### Compact Model for Short-Channel Junctionless Accumulation Mode Double Gate MOSFETs

Publication Year: 2014, Page(s):288 - 299
Cited by:  Papers (33)
| | PDF (2081 KB) | HTML

A 2-D closed form, analytical compact model for long- and short-channel junctionless accumulation mode double gate MOSFETs is presented. The physics-based 2-D model for the potential is derived with the help of Poisson's equation and the conformal mapping technique by Schwarz-Christoffel. From this closed-form solution, we derive simple equations for the calculation of the threshold voltage VT and... View full abstract»

• ### SPICE Modeling of Double-Gate Tunnel-FETs Including Channel Transports

Publication Year: 2014, Page(s):300 - 307
Cited by:  Papers (22)
| | PDF (1063 KB) | HTML

SPICE modeling of double-gate (DG) tunnel FETs (TFETs) including channel transports is reported. An ideal drain current model neglecting the channel transport is developed first. It captures the interband tunneling characteristics, describes their geometry dependences, and is suitable for DG TFETs with limited drivability. The ideal current model and previously proposed charge model are then exten... View full abstract»

• ### Compact Model for Ultrathin Low Electron Effective Mass Double Gate MOSFET

Publication Year: 2014, Page(s):308 - 313
Cited by:  Papers (5)
| | PDF (1320 KB) | HTML

We present a core compact model for undoped, high mobility, and low density of states materials in a double gate device architecture. Analytical equations for calculating current and charge are presented in a drift-diffusion compact modeling framework. This model accurately handles both Fermi-Dirac statistics and bias-dependent diffusivity. The results from analytical equations are validated again... View full abstract»

• ### A Compact Model for Generic MIS-HEMTs Based on the Unified 2DEG Density Expression

Publication Year: 2014, Page(s):314 - 323
Cited by:  Papers (9)
| | PDF (2070 KB) | HTML

In this paper, the 2-D electron gas density (ns) and Fermi level (Ef) analytical expressions as an explicit function of the terminal biases that covers the strong- and moderate-inversion and subthreshold regions and scalable with physical parameters are developed. It is validated by the comparison with the (exact) numerical solutions for different device parameters, in which ... View full abstract»

• ### Compact Modeling of Nanoscale Trapezoidal FinFETs

Publication Year: 2014, Page(s):324 - 332
Cited by:  Papers (10)
| | PDF (4620 KB) | HTML

An analytical compact model for the drain current of undoped or lightly doped nanoscale FinFETs with trapezoidal cross section is proposed. The compact model of rectangular FinFETs is extended to trapezoidal FinFETs using equivalent nonplanar device parameters and corner effects. The model has been validated by comparing the results with those of 3-D numerical device simulations. The very good acc... View full abstract»

• ### Floating-Body Effect in Partially/Dynamically/Fully Depleted DG/SOI MOSFETs Based on Unified Regional Modeling of Surface and Body Potentials

Publication Year: 2014, Page(s):333 - 341
Cited by:  Papers (1)
| | PDF (2066 KB) | HTML

A compact terminal current/charge model for partially/dynamically/fully depleted (PD)/(DD)/(FD) double-gate (DG) and silicon-on-insulator (SOI) MOSFETs with floating-body (FB) effect based on unified regional modeling of the surface and body potentials is presented. The model accurately describes the physical behavior of the impact-ionization current that gives rise to the hump in the C-V characte... View full abstract»

• ### Modeling of Distance-Dependent Mismatch and Across-Chip Variations in Semiconductor Devices

Publication Year: 2014, Page(s):342 - 350
Cited by:  Papers (2)
| | PDF (595 KB) | HTML

We present a simple and general method of modeling distance-dependent mismatch and across-chip variations (ACV). We are able to model various shapes of spatial correlation of a process/device/circuit parameter exactly in a compact device model. Examples include Gaussian and exponential types of spatial correlations. There are no grid points, groups, and brackets in our method. The resulting spatia... View full abstract»

• ### Analysis of Carrier Transport in Short-Channel MOSFETs

Publication Year: 2014, Page(s):351 - 358
Cited by:  Papers (12)
| | PDF (1159 KB) | HTML

A method for extracting transport parameters in short-channel FETs is presented in the context of the Lundstrom model for quasi-ballistic short-channel FETs. The parameters extracted from measured data are unidirectional thermal velocity, critical length, and mean free path at low and high drain biases. The method is based on an analysis of the channel length dependence of apparent mobility and vi... View full abstract»

• ### Investigation of the Subthreshold Swing in Vertical Tunnel-FETs Using ${\rm H}_{2}$ and ${\rm D}_{2}$ Anneals

Publication Year: 2014, Page(s):359 - 364
Cited by:  Papers (8)
| | PDF (2538 KB) | HTML

This paper analyzes both experimentally and by simulation the impact of traps on the transfer characteristics of tunnel-FETs (TFETs). The interface trap density in vertical heterojunction TFETs is varied by annealing in hydrogen or deuterium ambient. We show that a high-interface trap density (~2×1012/cm2) results in a peak current in the device transfer characteristic... View full abstract»

• ### Measurements of Process Variability in 40-nm Regular and Nonregular Layouts

Publication Year: 2014, Page(s):365 - 371
Cited by:  Papers (2)
| | PDF (1353 KB) | HTML

As technology scales down, IC design is becoming more difficult due to the increase in process variations, which translates into a dispersion of circuit parameter values thus degrading manufacturing yield. Regular layouts are recommended to reduce variability with the cost of area overhead with respect to conventional layouts. The aim of this paper is to measure the impact of variability in two im... View full abstract»

• ### Modeling of Thermoelectric Effects in Phase Change Memory Cells

Publication Year: 2014, Page(s):372 - 378
Cited by:  Papers (15)
| | PDF (1683 KB) | HTML

Thermoelectric effects on phase change memory elements are computationally analyzed through 2-D rotationally symmetric finite-element simulations of reset operation on a Ge2Sb2Te5 (GST) mushroom cell with 10-nm critical dimension. Temperature-dependent material parameters are used to determine the thermoelectric contributions at the junctions (Peltier heat) and wit... View full abstract»

• ### Impacts of 3-D Integration Processes on Memory Retention Characteristics in Thinned DRAM Chip for High-Reliable 3-D DRAM

Publication Year: 2014, Page(s):379 - 385
Cited by:  Papers (6)
| | PDF (2354 KB) | HTML

The impacts of 3-D integration processes on memory retention characteristics in thinned DRAM chip were evaluated. The retention characteristics of DRAM cell in a DRAM chip which was face-down bonded to an interposer with under-fill degraded depending on the decreased chip thickness, especially dramatically degraded below 40- μm thickness. Meanwhile, the retention characteristics of DRAM cel... View full abstract»

• ### Discrete Dopant Impurity Scattering in $p$ -Channel Silicon Nanowire Transistors: A $k.p$ Approach

Publication Year: 2014, Page(s):386 - 393
Cited by:  Papers (2)
| | PDF (1462 KB) | HTML

In this paper, we present the results of a numerical study on the influence of discrete dopant atom distribution and crystal orientation on the electrical characteristics of p-channel silicon nanowire-based transistors using 3-D quantum simulations. The valence band was modeled employing a three-band k.p Hamiltonian with optimized Lüttinger parameters, while the device characteristics were... View full abstract»

• ### An Improvement of the Capacitance–Voltage Method to Determine the Band Offsets in a-Si:H/c-Si Heterojunctions

Publication Year: 2014, Page(s):394 - 399
Cited by:  Papers (4)
| | PDF (1275 KB) | HTML

Due to the strong inversion layer at the c-Si interface, there may be errors in the determination of the band offsets in a-Si:H/c-Si heterojunctions from the usual capacitance-voltage (C-V) method. Considering the charge effect in the strong inversion layer, the theoretical differential capacitance in (n+) a-Si:H/(p) c-Si heterojunctions at high frequency is developed. The calculated re... View full abstract»

## Aims & Scope

IEEE Transactions on Electron Devices publishes original and significant contributions relating to the theory, modeling, design, performance and reliability of electron and ion integrated circuit devices and interconnects.

Full Aims & Scope

## Meet Our Editors

Editor-in-Chief

Giovanni Ghione
Politecnico di Torino,
10129 Torino, Italy


text:
# how to write simultaneous subscript and superscript for a symbol with matplotlib

I'd like to get something like that: $E^{\alpha}_{\beta}$, where there are simutaneous subscript \beta and superscript \alpha for the symbol E. I type in matplotlib (1.2.x with python 2.7.1) the following code:

ax.text(0.,0.,r'E$^{\alpha}_{\beta}$')

and I get an error message:

Subscript/superscript sequence is too long. Use braces { } to remove ambiguity.

When I added extra braces to separate the superscript and subscript like

ax.text(0.,0.,r'E${^{\alpha}}_{\beta}$')

matplotlib can handle it this time, but the result is not a SIMULTANEOUS superscript and subscript, it seems the symbol E$^{\alpha}$ with a subscript \beta, where \alpha and \beta are not vertically aligned.

-
Move your E into the TeX so that the processor knows what alpha and beta are hanging off of:
text(0.25, 0.5, r'$E^{\alpha}_{\beta}$', size=200)


text:
13
views
0
recommends
+1 Recommend
0 collections
0
shares
• Record: found
• Abstract: found
• Article: found
Is Open Access

# Delayed Effects of Obese and Overweight Population Conditions on All-Cause Adult Mortality Rate in the USA

Frontiers in Public Health

Frontiers Media S.A.

Bookmark
There is no author summary for this article yet. Authors can add summaries to their articles on ScienceOpen to make them more accessible to a non-specialist audience.

### Abstract

Currently, there are few studies separating the linkage of pathological obese and overweight body mass indices (BMIs) to the all-cause mortality rate in adults. Consequently, this paper, using annual Behavioral Risk Factor Surveillance System data of the 50 US states and the District of Columbia, estimates empirical regression models linking the US adult overweight (25 ≤ BMI < 30) and obesity (BMI ≥ 30) rates to the all-cause deaths rate. The biochemistry of multi-period cumulative adiposity (saturated fatty acid) from unexpended caloric intakes (net energy storage) provides the natural theoretical foundation for tracing unhealthy BMI to all-cause mortality. Cross-sectional and panel data regression models are separately estimated for the delayed effects of obese and overweight BMIs on the all-cause mortality rate. Controlling for the independent effects of economic, socio-demographic, and other factors on the all-cause mortality rate, our findings confirm that the estimated panel data models are more appropriate. The panel data regression results reveal that the obesity-mortality link strengthens significantly after multiple years in the condition. The faster mortality response to obesity detected here is conjectured to arise from the significantly more obese. Compared with past studies postulating a static (rather than delayed) effects, the statistically significant lagged effects of adult population BMI pathology in this study are novel and insightful. And, as expected, these lagged effects are more severe in the obese than overweight population segment. Public health policy implications of this social science study findings agree with those of the clinical sciences literature advocating timely lifestyle modification interventions (e.g., smoking cessation) to slow premature mortality linked with unhealthy BMIs.

### Most cited references33

• Record: found

### A Heteroskedasticity-Consistent Covariance Matrix Estimator and a Direct Test for Heteroskedasticity

(1980)
Bookmark
• Record: found
• Abstract: found

### Prevalence of childhood and adult obesity in the United States, 2011-2012.

(2014)
More than one-third of adults and 17% of youth in the United States are obese, although the prevalence remained stable between 2003-2004 and 2009-2010. To provide the most recent national estimates of childhood obesity, analyze trends in childhood obesity between 2003 and 2012, and provide detailed obesity trend analyses among adults. Weight and height or recumbent length were measured in 9120 participants in the 2011-2012 nationally representative National Health and Nutrition Examination Survey. In infants and toddlers from birth to 2 years, high weight for recumbent length was defined as weight for length at or above the 95th percentile of the sex-specific Centers for Disease Control and Prevention (CDC) growth charts. In children and adolescents aged 2 to 19 years, obesity was defined as a body mass index (BMI) at or above the 95th percentile of the sex-specific CDC BMI-for-age growth charts. In adults, obesity was defined as a BMI greater than or equal to 30. Analyses of trends in high weight for recumbent length or obesity prevalence were conducted overall and separately by age across 5 periods (2003-2004, 2005-2006, 2007-2008, 2009-2010, and 2011-2012). In 2011-2012, 8.1% (95% CI, 5.8%-11.1%) of infants and toddlers had high weight for recumbent length, and 16.9% (95% CI, 14.9%-19.2%) of 2- to 19-year-olds and 34.9% (95% CI, 32.0%-37.9%) of adults (age-adjusted) aged 20 years or older were obese. Overall, there was no significant change from 2003-2004 through 2011-2012 in high weight for recumbent length among infants and toddlers, obesity in 2- to 19-year-olds, or obesity in adults. Tests for an interaction between survey period and age found an interaction in children (P = .03) and women (P = .02). There was a significant decrease in obesity among 2- to 5-year-old children (from 13.9% to 8.4%; P = .03) and a significant increase in obesity among women aged 60 years and older (from 31.5% to 38.1%; P = .006). Overall, there have been no significant changes in obesity prevalence in youth or adults between 2003-2004 and 2011-2012. Obesity prevalence remains high and thus it is important to continue surveillance.
Bookmark
• Record: found
• Abstract: found

### Annual medical spending attributable to obesity: payer-and service-specific estimates.

(2015)
In 1998 the medical costs of obesity were estimated to be as high as $78.5 billion, with roughly half financed by Medicare and Medicaid. This analysis presents updated estimates of the costs of obesity for the United States across payers (Medicare, Medicaid, and private insurers), in separate categories for inpatient, non-inpatient, and prescription drug spending. We found that the increased prevalence of obesity is responsible for almost$40 billion of increased medical spending through 2006, including $7 billion in Medicare prescription drug costs. We estimate that the medical costs of obesity could have risen to$147 billion per year by 2008.
Bookmark

### Author and article information

###### Affiliations
1Department of Economics, Fogelman College of Business and Economics, The University of Memphis , Memphis, TN, USA
2Medical Center, The University of Mississippi School of Medicine , Jackson, MS, USA
###### Author notes

Edited by: Mihajlo Jakovljevic, University of Kragujevac, Serbia; Hosei University Tokyo, Japan

Reviewed by: Patricia Coelho Soarez, University of São Paulo, Brazil; Ewelina Marta Wierzejska, Poznan University of Medical Sciences, Poland; Mihajlo Jakovljevic, University of Kragujevac, Serbia; Hosei University Tokyo, Japan

Specialty section: This article was submitted to Health Economics, a section of the journal Frontiers in Public Health

###### Contributors
URI : http://frontiersin.org/people/u/334157
###### Journal
Front Public Health
Front Public Health
Front. Public Health
Frontiers in Public Health
Frontiers Media S.A.
2296-2565
28 September 2016
2016
: 4
5039184
10.3389/fpubh.2016.00212

This is an open-access article distributed under the terms of the Creative Commons Attribution License (CC BY). The use, distribution or reproduction in other forums is permitted, provided the original author(s) or licensor are credited and that the original publication in this journal is cited, in accordance with accepted academic practice. No use, distribution or reproduction is permitted which does not comply with these terms.

###### Counts
Figures: 0, Tables: 3, Equations: 1, References: 45, Pages: 9, Words: 7542
###### Categories
Public Health
Original Research


text:
# Math Help - Calculus w/ Paramatrized Curves

1. ## Calculus w/ Paramatrized Curves

Find $\frac{dy}{dx}$

$x = \frac{2}{t}$

$y = \sqrt{t}e^{-t}$

$x' = 2ln(t)$

$y' = \frac{1-2t}{2\sqrt{t}e^t}$

$\frac{dy}{dx} = \frac{1-2t}{4\sqrt{t}ln(t)e^{2t}}$

This is wrong, can someone tell me where I am wrong?

Thanks!

2. You've integrated x instead of differentiating it.

Have you also done the same for y?