Ml Lab Programs
Ml Lab Programs
Aim:
To apply the following Pre-processing techniques for a given dataset.
a. Attribute selection
b. Handling Missing Values
c. Discretization
d. Elimination of Outliers
Description:
Pre processing is a crucial step in the machine learning pipeline to ensure the data is in a usable
format for training algorithms. Below, we'll demonstrate how to apply the following pre
processing techniques to a given dataset:
1. Attribute Selection: Selecting a subset of relevant features (attributes) for use in the
model.
2. Handling Missing Values: Dealing with missing or NaN values in the dataset.
3. Discretization: Converting continuous features into categorical bins or intervals.
4. Elimination of Outliers: Identifying and removing outliers that may affect the model's
performance.
Program:
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from [Link] import SimpleImputer
from [Link] import KBinsDiscretizer
from scipy import stats
data = {
'age': [25, 30, 35, [Link], 40, 45, 50, 55, 60, 65],
'income': [50000, 55000, 60000, 65000, [Link], 70000, 75000, 80000, 85000, 90000],
'score': [70, 85, 90, 78, 88, 92, 76, 95, 91, 100],
'outlier_column': [10, 12, 11, 13, 10, 150, 10, 14, 11, 10] # Contains an outlier
}
df = [Link](data)
selected_features = df[['age', 'income', 'score']]
imputer = SimpleImputer(strategy='most_frequent')
df_imputed = [Link](imputer.fit_transform(selected_features),
columns=selected_features.columns)
discretizer = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='uniform')
df_imputed['age_binned'] = discretizer.fit_transform(df_imputed[['age']])
z_scores = [Link]([Link](df_imputed[['age', 'income', 'score']]))
df_no_outliers = df_imputed[(z_scores < 3).all(axis=1)]
print("Original DataFrame:")
print(df)
print("\nDataFrame after Attribute Selection and Imputation:")
print(df_imputed)
print("\nDataFrame after Discretization (Binned Age):")
print(df_imputed[['age', 'age_binned']])
print("\nDataFrame after Outlier Elimination:")
print(df_no_outliers)
Output:
Original DataFrame:
age income score outlier_column
0 25.0 50000.0 70 10
1 30.0 55000.0 85 12
2 35.0 60000.0 90 11
3 NaN 65000.0 78 13
4 40.0 NaN 88 10
5 45.0 70000.0 92 150
6 50.0 75000.0 76 10
7 55.0 80000.0 95 14
8 60.0 85000.0 91 11
9 65.0 90000.0 100 10
Classification Report:
precision recall f1-score support
accuracy 1.00 45
macro avg 1.00 1.00 1.00 45
weighted avg 1.00 1.00 1.00 45
[Link] decision tree algorithm for a regression problem
Aim: To demonstrate decision tree algorithm for are gression problem
Description:
The decision tree algorithm can be used for regression problems to predict a continuous target
variable. In a regression decision tree, the data is split into subsets based on the feature that
minimizes the variance (or another criterion like mean squared error, MSE) in each subset. This
process continues until the tree reaches a stopping criterion, such as a maximum depth or minimum
number of data points in a node.
Steps in a Decision Tree Regression:
1. Choose a feature to split on: At each node, the decision tree algorithm chooses the feature
that minimizes the sum of squared errors (SSE) or variance within the resulting subsets.
2. Split the data: Based on the chosen feature, the data is split into two subsets.
3. Repeat the process: This splitting process is recursively applied to each subset.
4. Stopping condition: The process stops when a certain condition is met (e.g., maximum tree
depth or minimum samples per leaf).
Program:
import numpy as np
import pandas as pd
from [Link] import make_regression
from sklearn.model_selection import train_test_split
from [Link] import DecisionTreeRegressor
from [Link] import mean_squared_error, r2_score
from [Link] import StandardScaler
import [Link] as plt
data=pd.read_csv("/content/housing_large_data.csv")
X=data[['housing_median_age','total_rooms','total_bedrooms','population','households','median_inc
ome']]
y=data[['median_house_value']]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = [Link](X_test)
dt_regressor = DecisionTreeRegressor(random_state=42)
dt_regressor.fit(X_train, y_train)
y_pred = dt_regressor.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"Mean Squared Error (MSE): {mse:.2f}")
print(f"R-squared (R²) Score: {r2:.2f}")
X_grid = [Link](X['housing_median_age'].min(), X['housing_median_age'].max(), 0.01)[:,
[Link]]
X_grid_df = [Link](X_grid, columns=['housing_median_age'])
for col in [Link][1:]:
X_grid_df[col] = 0
y_grid_pred = dt_regressor.predict([Link](X_grid_df))
[Link](figsize=(10, 6))
[Link](X['housing_median_age'], y, color='red', label='Data')
[Link](X_grid, y_grid_pred, color='blue', label='Model Prediction')
[Link]("Decision Tree Regression")
[Link]("Housing Median Age")
[Link]("Target")
[Link]()
[Link]()
from [Link] import plot_tree
[Link](figsize=(12, 8))
plot_tree(dt_regressor, filled=True, feature_names=X_train,
rounded=True, fontsize=10)
[Link]("Decision Tree Regression Visualization")
[Link]()
6. Apply Random Forest algorithm for classification and regression
Aim: To apply Random Forest algorithm for classification and regression
Description:
Random Forest for Classification:
We use the Iris dataset, which is a commonly used dataset for classification tasks. It has
multiple class labels (species of flowers).
The dataset is split into training and test sets (70% training and 30% testing) using
train_test_split.
The features are standardized using StandardScaler (optional for Random Forest, but
useful for algorithms that are sensitive to scale).
A RandomForestClassifier with 100 trees is initialized and trained on the training set.
After training, the model is evaluated on the test set using accuracy.
Random Forest for Regression:
For the regression task, we create a synthetic dataset using numpy. The features (X_reg)
are random numbers between 0 and 10, and the target (y_reg) has a linear relationship
with added Gaussian noise.
The dataset is again split into training and test sets.
A RandomForestRegressor is initialized and trained with 100 trees.
The model is then evaluated using Mean Squared Error (MSE) and R-squared (R²) score.
Visualizing the Results:
For the regression task, we plot the true vs. predicted values to visualize how well the
Random Forest model performs.
The plot shows true values in blue and predicted values in red.
Program:
import numpy as np
import pandas as pd
from [Link] import load_iris, make_regression
from sklearn.model_selection import train_test_split
from [Link] import RandomForestClassifier, RandomForestRegressor
from [Link] import accuracy_score, mean_squared_error, r2_score
from [Link] import StandardScaler
import [Link] as plt
data=pd.read_csv("/content/iris (2).csv")
X=data[['sepal length','sepal width','petal length','petal width']]
y=data['class']
X_train_class, X_test_class, y_train_class, y_test_class = train_test_split(X, y, test_size=0.3,
random_state=42)
scaler_class = StandardScaler()
X_train_class = scaler_class.fit_transform(X_train_class)
X_test_class = scaler_class.transform(X_test_class)
rf_classifier = RandomForestClassifier(n_estimators=100, random_state=42)
rf_classifier.fit(X_train_class, y_train_class)
y_pred_class = rf_classifier.predict(X_test_class)
accuracy = accuracy_score(y_test_class, y_pred_class)
print(f"Random Forest Classification Accuracy: {accuracy * 100:.2f}%")
data=pd.read_csv("/content/housing_large_data.csv")
X=data[['housing_median_age','total_rooms','total_bedrooms','population','households','median_i
ncome']]
y=data['median_house_value']
X_train_reg, X_test_reg, y_train_reg, y_test_reg = train_test_split(X, y, test_size=0.3,
random_state=42)
rf_regressor = RandomForestRegressor(n_estimators=100, random_state=42)
rf_regressor.fit(X_train_reg, y_train_reg.ravel()) # Flatten y_train_reg since it's a 2D array
y_pred_reg = rf_regressor.predict(X_test_reg)
mse = mean_squared_error(y_test_reg, y_pred_reg)
r2 = r2_score(y_test_reg, y_pred_reg)
print(f"Random Forest Regression Mean Squared Error (MSE): {mse:.2f}")
print(f"Random Forest Regression R-squared (R²) Score: {r2:.2f}")
[Link](figsize=(8, 6))
for feature in X_test_reg.columns:
[Link](X_test_reg[feature].values, y_test_reg.values, color='blue', label='True values',
alpha=0.5)
[Link](X_test_reg[feature].values, y_pred_reg, color='red', label='Predicted values',
alpha=0.5)
[Link](feature)
[Link]('Target')
[Link](f'Random Forest Regression: True vs Predicted Values ({feature})')
[Link]()
[Link]()
7. Demonstrate Naïve Bayes Classification algorithm
Description:
Data Preprocessing:
The data is split into training and test sets using train_test_split with 30% of the data
reserved for testing (test_size=0.3).
We standardize the features using StandardScaler. Although Naïve Bayes does not require
scaling, it is useful for visualizations and other algorithms.
Model Initialization:
We initialize the Gaussian Naïve Bayes model using GaussianNB() from scikit-learn.
This variant assumes the features follow a Gaussian (normal) distribution, which is
reasonable for continuous data like the Iris dataset.
Model Training:
We train the model using nb_classifier.fit(X_train, y_train), where X_train is the training
features, and y_train is the target labels.
Model Prediction:
We make predictions on the test set using nb_classifier.predict(X_test).
Model Evaluation:
We calculate the accuracy of the model using accuracy_score, which compares the
predicted labels with the actual labels.
We also display a classification report using classification_report, which includes metrics
such as precision, recall, and F1-score.
A confusion matrix is displayed using confusion_matrix, which shows how many
samples were correctly and incorrectly classified.
Visualization:
We plot a scatter plot of the test data points, where the true labels are shown in one color,
and the predicted labels are shown in another color.
Program:
import numpy as np
import pandas as pd
from [Link] import load_iris
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from [Link] import accuracy_score, classification_report, confusion_matrix
from [Link] import StandardScaler
import [Link] as plt
data = pd.read_csv("/content/[Link]")
X = data[['sepal length', 'sepal width', 'petal length', 'petal width']]
y = data['class']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = [Link](X_test)
nb_classifier = GaussianNB()
nb_classifier.fit(X_train, y_train)
y_pred = nb_classifier.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"Naïve Bayes Classification Accuracy: {accuracy * 100:.2f}%")
print("\nClassification Report:")
print(classification_report(y_test, y_pred))
print("\nConfusion Matrix:")
print(confusion_matrix(y_test, y_pred))
[Link](figsize=(8, 6))
Classification Report:
precision recall f1-score support
accuracy 0.98 45
macro avg 0.98 0.97 0.97 45
weighted avg 0.98 0.98 0.98 45
Confusion Matrix:
[[19 0 0]
[ 0 12 1]
[ 0 0 13]]
8. Apply Support Vector algorithm for classification
Description:
The Support Vector Machine (SVM) is a powerful classification algorithm that works by finding
the hyperplane that best separates different classes in the feature space. In this code example, we
will apply Support Vector Classification (SVC) to a dataset, using the popular Iris dataset available
in scikit-learn.
Data Preprocessing:
The dataset is split into training and test sets using train_test_split with 30% of the data
reserved for testing.
We use StandardScaler to standardize the features. This is an important preprocessing step
because SVMs perform better when the features are on a similar scale.
Model Initialization:
We initialize the Support Vector Classifier (SVC) from scikit-learn. Here, we use a linear
kernel, which is appropriate for linearly separable data. However, you can also experiment
with other kernels like polynomial or RBF (Radial Basis Function).
Model Training:
We train the model using [Link](X_train, y_train), where X_train is the training set of
features and y_train is the corresponding target labels.
Prediction:
After training the model, we use it to predict the target labels for the test set (X_test) using
[Link](X_test).
Model Evaluation:
We evaluate the model using accuracy, classification report, and confusion matrix:
o Accuracy: The proportion of correctly predicted samples.
o Classification Report: Displays precision, recall, F1-score for each class.
o Confusion Matrix: A matrix that shows the number of correct and incorrect
predictions for each class.
Visualization:
Since the Iris dataset has four features, we reduce the dimensionality by using only the first
two features (X_test[:, 0] and X_test[:, 1]) to create a 2D scatter plot.
True labels are shown in one color, and predicted labels are shown in another color,
allowing us to visually compare the true vs. predicted values.
Program:
import numpy as np
import pandas as pd
from [Link] import load_iris
from sklearn.model_selection import train_test_split
from [Link] import SVC
from [Link] import accuracy_score, classification_report, confusion_matrix
from [Link] import StandardScaler
import [Link] as plt
data = pd.read_csv("/content/[Link]")
X = data[['sepal length', 'sepal width', 'petal length', 'petal width']]
y = data['class']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = [Link](X_test)
svc = SVC(kernel='linear', random_state=42)
[Link](X_train, y_train)
y_pred = [Link](X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"Support Vector Classification Accuracy: {accuracy * 100:.2f}%")
print("\nClassification Report:")
print(classification_report(y_test, y_pred))
print("\nConfusion Matrix:")
print(confusion_matrix(y_test, y_pred))
[Link](figsize=(8, 6))
Classification Report:
precision recall f1-score support
accuracy 0.98 45
macro avg 0.98 0.97 0.97 45
weighted avg 0.98 0.98 0.98 45
Confusion Matrix:
[[19 0 0]
[ 0 12 1]
[ 0 0 13]]
9. Demonstrate simple linear regression algorithm for a regression problem
Description:
Train-Test Split:
We use train_test_split from scikit-learn to split the data into training and testing sets. We
use 70% of the data for training and 30% for testing (test_size=0.3).
Model Initialization and Training:
We initialize the LinearRegression model from scikit-learn and train it using
[Link](X_train, y_train) on the training data.
Prediction:
After training, we use the model to predict the target variable for the test data (y_pred =
[Link](X_test)).
Model Evaluation:
Mean Squared Error (MSE): We calculate the Mean Squared Error using
mean_squared_error(). A lower MSE indicates a better fit of the model to the data.
R-squared (R²): We also calculate the R-squared value using r2_score(). The R² value
explains the proportion of the variance in the dependent variable that is predictable from
the independent variable. A value closer to 1 indicates a good fit.
Visualization:
We plot the true values of the test set as blue dots and the regression line (predicted
values) as a red line.
This allows us to visually compare how well the model fits the data.
Program:
import numpy as np
import pandas as pd
import [Link] as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from [Link] import mean_squared_error, r2_score
data=pd.read_csv("/content/housing_large_data.csv")
X=data[['housing_median_age','total_rooms','total_bedrooms','population','households','median_i
ncome']]
y=data['median_house_value']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
model = LinearRegression()
[Link](X_train, y_train)
y_pred = [Link](X_test)
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"Mean Squared Error: {mse:.2f}")
print(f"R-squared Value: {r2:.2f}")
[Link](figsize=(8,6))
[Link](X_test['housing_median_age'], y_test, color='blue', label='True Values')
[Link](X_test['housing_median_age'], y_pred, color='red', label='Predicted Values')
[Link]('Simple Linear Regression: True vs Predicted')
[Link]('Independent Variable (X)')
[Link]('Dependent Variable (y)')
[Link]()
[Link]()
10. Apply Logistic regression algorithm for a classification problem
Description:
Logistic Regression is a popular and straightforward algorithm used for classification problems
in machine learning. Despite its name, Logistic Regression is actually a classification algorithm,
not a regression algorithm. Here’s a brief description:
Purpose: Logistic Regression predicts the probability of an instance belonging to a specific class.
It is widely used for binary classification problems but can be extended to multiclass
classification using techniques like one-vs-rest or softmax regression.
Working Principle:
Logistic Regression models the relationship between the independent variables (features) and the
dependent variable (target) using a logistic/sigmoid function.
The sigmoid function maps any real-valued number into a range between 0 and 1, representing
probabilities.
The predicted probability is then used to classify the instance into a specific class (e.g., 0 or 1).
For example, if the probability is greater than 0.5, the instance is classified as 1; otherwise, it is
classified as 0.
Program:
import numpy as np
import pandas as pd
data=pd.read_csv("/content/[Link]")
X=data[['Pregnancies','Glucose','BloodPressure','SkinThickness','Insulin','BMI','DiabetesPedigree
Function','Age','Outcome']]
y=data['Outcome']
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = [Link](X_test)
model = LogisticRegression()
[Link](X_train, y_train)
y_pred = [Link](X_test)
print(f"Accuracy: {accuracy:.2f}")
print(f"Confusion Matrix:\n{conf_matrix}")
print(f"Classification Report:\n{class_report}")
Output:
Accuracy: 1.00
Confusion Matrix:
[[99 0]
[ 0 55]]
Classification Report:
accuracy 1.00 30
macro avg 1.00 1.00 1.00 30
weighted avg 1.00 1.00 1.00 30
12. Implement the K-means algorithm and apply it to the data you selected. Evaluate
performancebymeasuringthesumoftheEuclideandistanceofeachexamplefrom its class
center. Test the performance of the algorithm as a function of the parameters K
Description:
1. Dataset Loading:
The load_iris() function from [Link] is used to load the Iris dataset.
We use X (the features) for clustering, and y (the true labels) for evaluation (though K-
means is unsupervised, the labels are useful for performance comparison).
2. Feature Scaling:
Since K-means is sensitive to the scale of the data, we apply StandardScaler to
standardize the features (zero mean and unit variance).
3. Sum of Euclidean Distances:
After clustering, we compute the Euclidean distance between each data point and its
corresponding cluster center. The Euclidean distance for a data point xixi and its cluster
center ckck is given by:
We compute this for each data point and sum the distances to get a measure of
clustering quality.
4. K-means Clustering:
The K-means algorithm is applied for different values of KK (from 1 to 10).
For each KK, we fit the K-means model on the scaled data and compute the sum of
Euclidean distances for each cluster configuration.
5. Evaluation:
We evaluate the performance by calculating and printing the sum of Euclidean
distances for each value of KK.
A plot is generated to show how the sum of Euclidean distances changes with the
number of clusters KK. This is useful for determining the optimal number of clusters
using the Elbow Method.
Program:
import numpy as np
import pandas as pd
from [Link] import load_iris
from [Link] import StandardScaler
from [Link] import KMeans
import [Link] as plt
iris = load_iris()
data=pd.read_csv("/content/[Link]")
X=data[['sepal length','sepal width','petal length','petal width']]
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
def compute_sum_of_distances(X, kmeans):
distances = [Link](X - kmeans.cluster_centers_[kmeans.labels_], axis=1)
return [Link](distances)
k_values = range(1, 11)
distances = []
for k in k_values:
kmeans = KMeans(n_clusters=k, random_state=42)
[Link](X_scaled)
sum_distances = compute_sum_of_distances(X_scaled, kmeans)
[Link](sum_distances)
print(f"Sum of Euclidean distances for K={k}: {sum_distances:.2f}")
[Link](figsize=(8, 6))
[Link](k_values, distances, marker='o')
[Link]('Sum of Euclidean Distances vs. Number of Clusters (K)')
[Link]('Number of Clusters (K)')
[Link]('Sum of Euclidean Distances')
[Link](True)
[Link]()
[Link] the use of Fuzzy C-Means Clustering
Description:
Fuzzy C-Means (FCM) is a clustering algorithm similar to K-means, but it allows for partial
membership of data points in multiple clusters rather than assigning each point to exactly one
cluster. This makes it useful in situations where clusters are not well-separated.
In this implementation, we will use the Fuzzy C-Means clustering algorithm available in
the fcmeans library (a Python library for Fuzzy C-Means). If you haven't already installed it, you
can install it via pip:
pip install fcmeans
1. Standardization:
The features are scaled using StandardScaler to make sure the Fuzzy C-Means
algorithm performs optimally, as it is sensitive to the scale of the data.
2. Fuzzy C-Means (FCM) Clustering:
We initialize the FCM class from the fcmeans package and fit it to the data. The
number of clusters is set to 3 (since we generated data with 3 centers).
After fitting, we get the cluster centers and the membership matrix, which indicates
the degree to which each point belongs to each cluster. Each point can belong to
multiple clusters with varying degrees of membership.
3. Prediction:
We predict the cluster label for each point. The label is assigned based on the
maximum membership value (the cluster the point is most strongly associated
with).
4. Visualization:
We use matplotlib to plot the data points and color them according to the predicted
cluster labels.
The cluster centers are marked with red X markers for visualization.
5. Membership Matrix:
The membership matrix is printed for the first 5 data points. This shows the degree
of membership for each point in each cluster. Each row of the matrix corresponds to
a data point, and each column corresponds to a cluster. The values are between 0
and 1, where higher values indicate stronger membership.
Program:
import numpy as np
import pandas as pd
data=pd.read_csv("/content/iris (1).csv")
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
[Link](X_scaled)
centers = [Link]
membership = fcm.u
labels = [Link](X_scaled)
[Link](figsize=(8, 6))
[Link]("Feature 1")
[Link]("Feature 2")
[Link]()
[Link]()
[Link] the use of Expectation Maximization based clustering algorithm
Description:
EM-based Clustering (Gaussian Mixture Model):
1. Fit the Gaussian Mixture Model (GMM) on the data.
2. Predict cluster labels for each data point.
3. Visualize the clustering result.
4. Evaluate the performance by comparing the predicted labels with true labels (optional)
Gaussian Mixture Model (GMM):
1. We initialize and fit the GaussianMixture class from [Link] to
the standardized data. The n_components=3 parameter specifies that we
want to fit 3 Gaussian distributions (clusters).
2. The fit() method estimates the parameters of the Gaussians, including the
mean vectors and covariance matrices.
Prediction:
3. We use [Link]() to predict the most likely cluster for each data
point.
4. We also use gmm.predict_proba() to get the probability that each point
belongs to each cluster. This is a soft clustering result, where each point
has a probability of belonging to each cluster.
Visualization:
5. We plot the data points, color-coded according to the predicted cluster
labels using matplotlib.
6. The cluster centers are marked with red X markers. These are the means
of the Gaussian distributions estimated by GMM.
Cluster Parameters:
7. After fitting the GMM, we print the means (centers of the Gaussian
distributions) and the covariances of the distributions. These represent the
cluster parameters that GMM has learned.
Program:
import numpy as np
import pandas as pd
import [Link] as plt
from [Link] import make_blobs
from [Link] import GaussianMixture
from [Link] import StandardScaler
data=pd.read_csv("/content/iris (1).csv")
X=data[['sepal length','sepal width','petal length','petal width']]
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
gmm = GaussianMixture(n_components=3, random_state=42)
[Link](X_scaled)
labels = [Link](X_scaled)
[Link](figsize=(8, 6))
[Link](X_scaled[:, 0], X_scaled[:, 1], c=labels, cmap='viridis', alpha=0.6)
centers = gmm.means_
[Link](centers[:, 0], centers[:, 1], marker='X', s=200, c='red', label='Cluster Centers')
[Link]("Expectation Maximization (GMM) Clustering")
[Link]("Feature 1")
[Link]("Feature 2")
[Link]()
[Link]()
print("Cluster Centers (Means of Gaussians):")
print(centers)
print("\nCovariances of the Gaussians:")
print(gmm.covariances_)
probs = gmm.predict_proba(X_scaled)
print("\nProbabilities of the first 5 points belonging to each cluster:")
print(probs[:5])
Output:
Cluster Centers (Means of Gaussians):
[[ 0.50728932 -0.42115345 0.65243901 0.62756416]
[-0.93419037 0.98506351 -1.30343641 -1.24712613]
[-1.58675099 -0.17377379 -1.31514142 -1.31208711]]