Saturday, February 25, 2023

Why should do One hot encoding

Many machine learning algorithms, instead, require all the input and output variables to be numeric. Although some like decision tree can work on categorical data. 


one-hot encoding comes in help because it transforms categorical data into numerical; in other words: it transforms strings into numbers so that we can apply our Machine Learning algorithms without any problems.


animals = ['dog', 'cat', 'mouse'] 

one-hot encoding will create new columns as much as the number of unique kinds of animals in the “animals” column, and the new columns will be filled with 0s and 1s. So, if you have 100 kinds of animals in your “animals” column, one-hot encoding will create 100 new columns all filled with 1s and 0s.



this process can lead to some troubles. In this case, the trouble is the so-called “Dummy Variable Trap”.



The Dummy Variable Trap is a scenario where the variables present become highly correlated to each other, and this means an important thing: one-hot encoding can lead to multicollinearity; it means that we always have to analyze the variables (the new features, aka: the new columns) and decide if it is the case to drop some of them



There is a much more simpler way to perform one-hot encoding and it can be done directly in pandas. Consider the data frame, df, as we created it earlier. To encode it we can simply write the following line of code:



#one-hot encoding

df3 = pd.get_dummies(df, dtype=int)

#showing new head

df3.head()



More convoluted way of doing this is using SK Learn 



SKLearn has one hot encoder 


import pandas as pd

from sklearn.preprocessing import OneHotEncoder


# initializing values

data = {'Name':['Tom', 'Jack', 'Nick', 'John',

                'Tom', 'Jack', 'Nick', 'John',

                'Tom', 'Jack', 'Nick', 'John',],

        'Time':[20, 21, 19, 18,

                20, 100, 19, 18,

                21, 22, 21, 20]

}

#creating dataframe

df = pd.DataFrame(data)

#showing head

df.head()


encoder = OneHotEncoder(handle_unknown='ignore')


encoder_df = pd.DataFrame(encoder.fit_transform(df[['Name']]).toarray())


#merge one-hot encoded columns back with original DataFrame

df2 = df.join(encoder_df)

#drop columns with strings

df2.drop('Name', axis=1, inplace=True)

#showing new head

df2.head()



references:

https://towardsdatascience.com/how-and-why-performing-one-hot-encoding-in-your-data-science-project-a1500ec72d85#:~:text=In%20these%20cases%2C%20one%2Dhot,Learning%20algorithms%20without%20any%20problems.

Wednesday, February 22, 2023

Docker-compose down gives active end point exists.

ERROR: network docker_default has active endpoints


docker network inspect <network>

docker network disconnect -f <network> <endpoint>


references:

https://stackoverflow.com/questions/42842277/docker-compose-down-default-network-error

Sunday, February 19, 2023

MLOps - simulating a streaming new data set

Approach is below . This assumes the use of MNIST dataset 

img_rows, img_cols = 28, 28

from keras.datasets import mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()

# Set train samples apart that will serve as streaming data later on

x_stream = x_train[:20000]

y_stream = y_train[:20000]

x_train = x_train[20000:]

y_train = y_train[20000:]


stream_sample = [x_stream, y_stream]

The stream_sample is the sample for streaming 


pickle.dump(stream_sample, open(os.getcwd() + kwargs['path_stream_sample'], "wb"))


The stream sample is now written to the pickle file 


Now lets construct the model 



model = Sequential()

model.add(Conv2D(32, kernel_size=(3, 3),

activation='relu',

input_shape=input_shape))

model.add(Conv2D(64, (3, 3), activation='relu'))

model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Dropout(0.25))

model.add(Flatten())

model.add(Dense(128, activation='relu'))

model.add(Dropout(0.5))

model.add(Dense(num_classes, activation='softmax'))


model.compile(loss=keras.losses.categorical_crossentropy,

  optimizer=keras.optimizers.Adadelta(),

  metrics=['accuracy'])


Now fitting the model is as below 



model.fit(x_train, y_train,

          batch_size=kwargs['batch_size'],

          epochs=kwargs['epochs'],

          verbose=1,

          validation_data=(x_test, y_test))



# now evaluate the model 


score = model.evaluate(x_test, y_test, verbose=0)


logging.info('Test - loss:', score[0])

logging.info('Test - accuracy:', score[1])


model.save(os.getcwd() + kwargs['initial_model_path'])



Now having both stream set and the trained model, lets feed additional data 


For it, using Kafka

 

Kafka is one of the go-to platforms when you have to deal with streaming data. Its framework basically consists of three players, being 1) brokers; 2) producers; and 3) consumers.


A broker is an instance of a Kafka server (also known as a Kafka node) that hosts named streams of records, which are called topics. A broker takes in messages from producers and stores them to a topic. It in turn enables consumers to fetch messages from a topic.



In its simplest form, you have one single producer pushing messages to one end of a topic, whilst one single consumer fetches messages from the other end of the topic (like for example an app). In the situation of our case where we have Kafka running locally, a single setup likes this (shown below) does the trick.


With the help of the Kafka-Python API we can now simulate a data stream by constructing a Producer that publishes messages to the topic. 



def generate_stream(**kwargs):


producer = KafkaProducer(bootstrap_servers=['kafka:9092'],                              # set up Producer

                         value_serializer=lambda x: dumps(x).encode('utf-8'))


stream_sample = pickle.load(open(os.getcwd() + kwargs['path_stream_sample'], "rb"))       # load stream sample file


rand = random.sample(range(0, 20000), 200)                                                # the stream sample consists of 20000 observations - and along this setup 200 samples are selected randomly


x_new = stream_sample[0]

y_new = stream_sample[1]


logging.info('Partitions: ', producer.partitions_for('TopicA'))


for i in rand:

json_comb = encode_to_json(x_new[i], y_new[i])                                         # pick observation and encode to JSON

producer.send('TopicA', value=json_comb)                                               # send encoded observation to Kafka topic

logging.info("Sent number: {}".format(y_new[i]))

sleep(1)


producer.close()




Now the task will be to receive the stream data 


To fetch the data from the Kafka topic, we turn again to the Kafka-Python API to construct a Consumer. This Consumer is wrapped in a function that sequentially retrieves observations from the topic, which it in turn converts back from JSON to its original format and groups together in a NumPy array which is stored (in pickle format) in the to_use_for_training folder. 



def get_data_from_kafka(**kwargs):


    consumer = KafkaConsumer(

        kwargs['topic'],                                # specify topic to consume from

        bootstrap_servers=[kwargs['client']],

        consumer_timeout_ms=3000,                       # break connection if the consumer has fetched anything for 3 secs (e.g. in case of an empty topic)

        auto_offset_reset='earliest',                   # automatically reset the offset to the earliest offset (should the current offset be deleted or anything)

        enable_auto_commit=True,                        # offsets are committed automatically by the consumer

        #group_id='my-group',

        value_deserializer=lambda x: loads(x.decode('utf-8')))



    logging.info('Consumer constructed')


    try:


        xs = []

        ys = []


        for message in consumer:                            # loop over messages


            logging.info( "Offset: ", message.offset)

            message = message.value

            x, y = decode_json(message)            # decode JSON


            xs.append(x)

            ys.append(y)


            logging.info('Image retrieved from topic')


        xs = np.array(xs).reshape(-1, 28, 28, 1)            # put Xs in the right shape for our CNN

        ys = np.array(ys).reshape(-1)                       # put ys in the right shape for our CNN


        new_samples = [xs, ys]


        pickle.dump(new_samples, open(os.getcwd()+kwargs['path_new_data']+str(time.strftime("%Y%m%d_%H%M"))+"_new_samples.p", "wb"))     # write data


        logging.info(str(xs.shape[0])+' new samples retrieved')


        consumer.close()


    except Exception as e:

        print(e)

        logging.info('Error: '+e)



The update_model function in update_functions.py does most of the heavy lifting:


it takes in the data we fetched from the Kafka topic


it loads the current model and gauges how it scores on the test set*


it does a number of epochs of gradient descent with the new data and accordingly adjusts the weights of the model**


it then tests whether the adjusted model scores better on the test set than the current version — and if it does, it replaces the current version and moves the latter to a model archive. If it doesn’t it sticks to the current version of the model


in addition, it moves the data it used for updating the model to the used_for_training folder and logs a set of metrics corresponding to each update run to MLFlow


references:

https://www.vantage-ai.com/en/blog/keeping-your-ml-model-in-shape-with-kafka-airflow-and-mlflow

 

MLOps using AirFlow, MLFlow and Kafka 

Apache Kafka is a distributed messaging platform that allows you to sequentially log streaming data into topic-specific feeds, which other applications in turn can tap into.
Apache Airflow is a task scheduling platform that allows you to create, orchestrate and monitor data workflows
MLFlow is an open-source tool that enables you to keep track of your ML experiments, amongst others by logging parameters, results, models and data of each trial .

In this hypothetical example, below are required 

a container which has Airflow and your typical data science
toolkit installed (in our case Pandas, NumPy and Keras) in order to create and update the model, whilst also schedule such tasks
a PostgreSQL container which serves as Airflow’s underlying metadata database
a Kafka container, which handles streaming data
a Zookeeper container, which amongst others is responsible for keeping track of Kafka topics, partitions and alike (later more on this!)
a MLFlow container, which keeps track of the results of the update runs and the characteristics of the resulting models




A typical. folder structure can be as below .
project_folder
├── dags
│ └── src
│ ├── data
│ ├── models
│ └── preprocessing
├── data
│ ├── to_use_for_training
│ ├── used_for_training
├── models
│ ├── current_model
│ └── archive
├── airflow_docker
├── mlflow_docker
└── docker_compose.yml


This example utilises the MNIST data set. One of the Airflow task DAG is to fetch the data and split into test, train and streaming set. Streaming set is to simulate the dynamic data that is coming in after the initial model is put into action. and puts them in the right format for training the CNN.

 Construct & fit the model - Task 2 amongst others fetches the train and test set from the previous step above. 

It then constructs and fits the CNN and stores it in the current_model folder






References 
https://www.vantage-ai.com/en/blog/keeping-your-ml-model-in-shape-with-kafka-airflow-and-mlflow


What is MNIST dataset?

 The MNIST database (Modified National Institute of Standards and Technology database) is a large collection of handwritten digits. It has a training set of 60,000 examples, and a test set of 10,000 examples. It is a subset of a larger NIST Special Database 3 (digits written by employees of the United States Census Bureau) and Special Database 1 (digits written by high school students) which contain monochrome images of handwritten digits. The digits have been size-normalized and centered in a fixed-size image. The original black and white (bilevel) images from NIST were size normalized to fit in a 20x20 pixel box while preserving their aspect ratio. The resulting images contain grey levels as a result of the anti-aliasing technique used by the normalization algorithm. the images were centered in a 28x28 image by computing the center of mass of the pixels, and translating the image so as to position this point at the center of the 28x28 field.


references

https://paperswithcode.com/dataset/mnist

Saturday, February 18, 2023

What is GXP

 





GxP is an acronym that refers to the regulations and guidelines applicable to life sciences organizations that make food and medical products such as drugs, medical devices, and medical software applications. The overall intent of GxP requirements is to ensure that food and medical products are safe for consumers and to ensure the integrity of data used to make product-related safety decisions.


The term GxP encompasses a broad range of compliance-related activities such as Good Laboratory Practices (GLP), Good Clinical Practices (GCP), Good Manufacturing Practices (GMP), and others, each of which has product-specific requirements that life sciences organizations must implement based on the 1) type of products they make and 2) country in which their products are sold. When life sciences organizations use computerized systems to perform certain GxP activities, they must ensure that the computerized GxP system is developed, validated, and operated appropriately for the intended use of the system.


References:

https://aws.amazon.com/compliance/gxp-part-11-annex-11/

What are benefits of using Multi Accounts in AWS

Below are the main topics involved in this 


Group workloads based on business purpose and ownership

Apply distinct security controls by environment

Constrain access to sensitive data

Promote innovation and agility

Limit scope of impact from adverse events

Support multiple IT operating models

Manage costs

Distribute AWS Service Quotas and API request rate limits



Group workloads based on business purpose and ownership

You can group workloads with a common business purpose in distinct accounts. As a result, you can align the ownership and decision making with those accounts and avoid dependencies and conflicts with how workloads in other accounts are secured and managed.



Different business units or product teams might have different processes. Depending on your overall business model, you might choose to isolate distinct business units or subsidiaries in different accounts. Isolation of business units can help them operate with greater decentralized control, but still provides the ability for you to provide overarching guardrails. This approach might also ease divestment of those units over time.


Guardrails are governance rules for security, operations, and compliance that you can define and apply to align with your overall requirements.


Apply distinct security controls by environment

Workloads often have distinct security profiles that require separate control policies and mechanisms to support them. For example, it’s common to apply different security and operational policies for the non-production and production environments of a given workload. By using separate accounts for the non-production and production environments, by default, the resources and data that make up a workload environment are separated from other environments and workloads.


Constrain access to sensitive data

When you limit sensitive data stores to an account that is built to manage it, you can more easily constrain the number of people and processes that can access and manage the data store. This approach simplifies the process of achieving least privilege access. Limiting access at the coarse-grained level of an account helps contain exposure to highly sensitive data.


For example, designating a set of accounts to house publicly accessible Amazon S3 buckets enables you to implement policies for all your other accounts to expressly forbid making S3 buckets publicly available.



Promote innovation and agility

At AWS, we refer to your technologists as builders because they are all responsible for building value using AWS products and services. Your builders likely represent diverse roles, such as application developers, data engineers, data scientists, data analysts, security engineers, and infrastructure engineers.


In the early stages of a workload’s lifecycle, you can help promote innovation by providing your builders with separate accounts in support of experimentation, development, and early testing. These environments often provide greater freedom than more tightly controlled production-like test and production environments by enabling broader access to AWS services while using guardrails to help prohibit access to and use of sensitive and internal data.


Sandbox accounts are typically disconnected from your enterprise services and do not provide access to your internal data, but offer the greatest freedom for experimentation.


Development accounts typically provide limited access to your enterprise services and development data, but can more readily support day-to-day experimentation with your enterprise approved AWS services, formal development, and early testing work.


In both cases, we recommend security guardrails and cost budgets so that you limit risks and proactively manage costs.




Limit scope of impact from adverse events

An AWS account provides security, access, and billing boundaries for your AWS resources that can help you achieve resource independence and isolation. By design, all resources provisioned within an account are logically isolated from resources provisioned in other accounts, even within your own AWS environment.


This isolation boundary provides you with a way to limit the risks of an application-related issue, misconfiguration, or malicious actions. If an issue occurs within one account, impacts to workloads contained in other accounts can be either reduced or eliminated.


Manage Costs 

An account is the default means by which AWS costs are allocated. Because of this fact, using different accounts for different business units and groups of workloads can help you more easily report, control, forecast, and budget your cloud expenditures.



In addition to cost reporting at the account level, AWS has built-in support to consolidate and report costs across your entire set of accounts. When you require fine-grained cost allocation, you can apply cost allocation tags to individual resources in each of your accounts.


Distribute AWS Service Quotas and API request rate limits

AWS Service Quotas, also known as limits, are the maximum number of service resources or operations that apply to an account. For example, the number of Amazon Simple Storage Service (Amazon S3) buckets that you can create for each account.


You can use Service Quotas to help protect you from unexpected excessive provisioning of AWS resources and malicious actions that could dramatically impact your AWS costs.


AWS services can also throttle or limit the rate of requests made to their API operations.


Because Service Quotas and request rate limits are allocated for each account, use of separate accounts for workloads can help distribute the potential impact of the quotas and limits.



references:

https://docs.aws.amazon.com/whitepapers/latest/organizing-your-aws-environment/benefits-of-using-multiple-aws-accounts.html