One of the biggest challenges in machine learning is staying up to date with new releases of code libraries. I noticed that Keras released a new version 2.6 a few days ago so I figured I’d do a complete end-to-end example of installation and the Iris Dataset classification problem. I use Windows but the process is almost the same for Linux and Mac.
In the old days, you would install TensorFlow first, then Keras second. Now TensorFlow contains Keras.
First, I installed the Anaconda3-2020.02 distribution which contains Python 3.7.6 and over 500 Python packages. But before I did this, I uninstalled a couple of phantom Pythons (3.5, 3.6) that appeared on my machine. Many programs “helpfully” install a Python for you without being asked, which creates versioning collisions and errors.

Left: I uninstalled an old Python to prevent Python version collisions. Right: I like the Anaconda distribution of Python.
Next I looked for the correct TensorFlow/Keras 2.6.0 whl (“wheel”) installation file. The default .whl file at pypi.org gives you a combined CPU – GPU version. If you install the dual version, when you run a program, TensorFlow/Keras will attempt to determine if your machine has a GPU or not and then run the correct version. Because I was installing on a machine that didn’t have a GPU, I looked for a CPU-only version of TensorFlow/Keras. I eventually found a whl file for a CPU-only version of TensorFlow/Keras — but finding it wasn’t easy.

The standard location for the whl install files gives only the combined GPU-CPU version of TensorFlow/Keras. It’s very easy to get the wrong version of anythind related to machine learning — versioning hell is a significant problem.

Left: While searching for a CPU-only whl file for Windows, I found a URL for a CPU-only version for Linux. Right: After a bit of experimenting with the URL, I eventually found a CPU-only version for Windows at https://storage.googleapis.com/tensorflow/windows/cpu/tensorflow_cpu-2.6.0-cp37-cp37m-win_amd64.whl. I saved the whl file to my local machine, and then installed TensorFlow/Keras, 2.6, CPU-only, for Python 3.7, for Windows.
I used pip to install the CPU-only 2.6.0 version of TensorFlow without any problems. Minor miracle.
Next, I coded up a Iris Dataset demo. I found the 150-item Iris Dataset online — it’s in dozens of places. I manually one-hot encoded the labels by replacing “setosa” with 1, 0, 0 and replacing “versicolor” with 0, 1, 0 and replacing “virginica” with 0, 0, 1.
An alternative strategy is to first manually ordinal encode setosa = 0, versocolor = 1, virginica = 2, and then use tf.keras.utils.to_categorical() to programmatically convert the ordinal values to one-hot values.
I ran the demo without too much trouble. There were about six errors I had to deal with, but that’s to be expected.
Good fun. I’m satisfied that I’m meeting the challenge of keeping up to date with Keras versions, and if I need to work on a Keras project, I can get up to speed quickly.

One of the challenges for people who have an inexplicable desire to follow Hollywood actors is keeping up to date with their wife versions. Here is American actor Nicolas Cage with wife version 1.0, wife version 2.0, wife version 3.0, and wife version 4.0.
Code below.
# iris_tfk.py
# Iris classification
# Anaconda3-2020.02 (Python 3.7.6)
# TensorFlow 2.6.0 (includes KerasTF 2.6.0)
# Windows 10 August 2021
import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
import numpy as np
import tensorflow as tf
from tensorflow import keras as K
class MyLogger(K.callbacks.Callback):
def __init__(self, n):
self.n = n # print loss and acc every n epochs
def on_epoch_end(self, epoch, logs={}):
if epoch % self.n == 0:
curr_loss =logs.get('loss')
curr_acc = logs.get('accuracy') * 100
print("epoch = %4d loss = %0.6f acc = %0.2f%%" % \
(epoch, curr_loss, curr_acc))
def main():
print("\nIris dataset using Keras/TensorFlow ")
np.random.seed(1)
tf.random.set_seed(1)
print("\nLoading Iris data into memory ")
data_file = ".\\Data\\iris_data.txt"
train_x = np.loadtxt(data_file, usecols=[0,1,2,3],
delimiter=",", skiprows=0, dtype=np.float32)
train_y = np.loadtxt(data_file, usecols=[4,5,6],
delimiter=",", skiprows=0, dtype=np.np.int64)
# train_y = np.loadtxt(data_file, usecols=4,
# delimiter=",", skiprows=0, dtype=np.np.int64) # ordinal
# train_y = tf.keras.utils.to_categorical(train_y) # one-hot
print("\nCreating 4-5-3 neural network ")
model = K.models.Sequential()
model.add(K.layers.Dense(units=5, input_dim=4,
activation='tanh', kernel_initializer='glorot_uniform',
bias_initializer='zeros'))
model.add(K.layers.Dense(units=3, activation='softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='sgd', metrics=['accuracy']) # default LR
my_logger = MyLogger(n=3)
print("\nStarting training ")
h = model.fit(train_x, train_y, batch_size=1,
epochs=12, verbose=0, callbacks=[my_logger]) # 1 = chatty
print("Training finished ")
eval = model.evaluate(train_x, train_y, verbose=0)
print("\nModel evaluation: loss = %0.6f accuracy = %0.2f%% " \
% (eval[0], eval[1]*100) )
print("\nSaving trained model as file iris_model.h5 ")
# model.save_weights(".\\Models\\iris_model.h5")
model.save(".\\Models\\iris_model.h5")
# --------------
np.set_printoptions(precision=4, suppress=True)
wts = model.get_weights()
print("\nTrained model weights and biases: ")
for ar in wts:
print(ar)
print("")
# --------------
np.set_printoptions(precision=4)
unknown = np.array([[6.1, 3.1, 5.1, 1.1]],
dtype=np.float32)
predicted = model.predict(unknown)
print("\nUsing model to predict species for features: ")
print(unknown)
print("\nPredicted species is: ")
print(predicted)
if __name__ == "__main__":
main()

.NET Test Automation Recipes
Software Testing
SciPy Programming Succinctly
Keras Succinctly
R Programming
2026 Visual Studio Live
2025 Summer MLADS Conference
2026 DevIntersection Conference
2025 Machine Learning Week
2025 Ai4 Conference
2026 G2E Conference
2026 iSC West Conference
You must be logged in to post a comment.