Please add real data sets which are accessed without paid apis or subscription with goal of building a future predictive model : 

import numpy as np
import pandas as pd
import random

from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, mean_squared_error, f1_score
from sklearn.preprocessing import StandardScaler
from sklearn.utils import shuffle

class SelfOptimizingModel:
    def __init__(self, X, y, model_type='classification', algorithm='random_forest', random_state=42):
        """
        Initializes the self-optimizing model.

        Parameters:
        - X: Features dataset (numpy array or pandas DataFrame).
        - y: Target variable (numpy array or pandas Series).
        - model_type: 'classification' or 'regression'.
        - algorithm: Algorithm to use ('random_forest', 'neural_network', etc.).
        - random_state: Seed for reproducibility.
        """
        self.X = X
        self.y = y
        self.model_type = model_type
        self.algorithm = algorithm
        self.random_state = random_state

        self.best_params = None
        self.best_score = float('-inf') if model_type == 'classification' else float('inf')
        self.best_model = None

        self._prepare_data()

    def _prepare_data(self):
        """
        Prepares training and validation datasets.
        """
        # Shuffle and split the data
        self.X, self.y = shuffle(self.X, self.y, random_state=self.random_state)
        self.X_train, self.X_valid, self.y_train, self.y_valid = train_test_split(
            self.X, self.y, test_size=0.2, random_state=self.random_state
        )

        # Feature scaling for certain models
        if self.algorithm in ['neural_network', 'svm']:
            scaler = StandardScaler()
            self.X_train = scaler.fit_transform(self.X_train)
            self.X_valid = scaler.transform(self.X_valid)

    def _generate_hyperparameters(self):
        """
        Generates random hyperparameters based on the algorithm.
        """
        if self.algorithm == 'random_forest':
            params = {
                'n_estimators': random.choice([50, 100, 150, 200]),
                'max_depth': random.choice([None, 5, 10, 20]),
                'min_samples_split': random.choice([2, 5, 10]),
                'min_samples_leaf': random.choice([1, 2, 4]),
                'bootstrap': random.choice([True, False]),
            }
        elif self.algorithm == 'neural_network':
            params = {
                'hidden_layer_sizes': random.choice([(50,), (100,), (50,50)]),
                'activation': random.choice(['relu', 'tanh', 'logistic']),
                'solver': random.choice(['adam', 'sgd']),
                'learning_rate': random.choice(['constant', 'adaptive']),
                'max_iter': 200,
            }
        elif self.algorithm == 'svm':
            params = {
                'C': random.uniform(0.1, 10.0),
                'kernel': random.choice(['linear', 'rbf', 'poly']),
                'gamma': random.choice(['scale', 'auto']),
            }
        else:
            raise ValueError("Unsupported algorithm specified.")
        return params

    def _initialize_model(self, params):
        """
        Initializes the machine learning model with given parameters.
        """
        if self.algorithm == 'random_forest':
            if self.model_type == 'classification':
                from sklearn.ensemble import RandomForestClassifier
                model = RandomForestClassifier(random_state=self.random_state, **params)
            else:
                from sklearn.ensemble import RandomForestRegressor
                model = RandomForestRegressor(random_state=self.random_state, **params)

        elif self.algorithm == 'neural_network':
            if self.model_type == 'classification':
                from sklearn.neural_network import MLPClassifier
                model = MLPClassifier(random_state=self.random_state, **params)
            else:
                from sklearn.neural_network import MLPRegressor
                model = MLPRegressor(random_state=self.random_state, **params)

        elif self.algorithm == 'svm':
            if self.model_type == 'classification':
                from sklearn.svm import SVC
                model = SVC(random_state=self.random_state, **params)
            else:
                from sklearn.svm import SVR
                model = SVR(**params)

        else:
            raise ValueError("Unsupported algorithm specified.")

        return model

    def train_and_optimize(self, iterations=10):
        """
        Trains the model and optimizes hyperparameters over a number of iterations.

        Parameters:
        - iterations: Number of optimization iterations to perform.
        """
        for i in range(iterations):
            print(f"\nIteration {i+1}/{iterations}")
            # Randomly adjust hyperparameters
            params = self._generate_hyperparameters()
            print(f"Testing hyperparameters: {params}")

            # Initialize and train model
            model = self._initialize_model(params)
            model.fit(self.X_train, self.y_train)

            # Validate model
            score = self._validate_model(model)

            # Update best model if improvement is seen
            if self._is_improvement(score):
                self.best_score = score
                self.best_params = params
                self.best_model = model
                print(f"New best score: {self.best_score}")
            else:
                print(f"No improvement. Best score remains: {self.best_score}")

    def _validate_model(self, model):
        """
        Validates the model and returns the performance score.
        """
        y_pred = model.predict(self.X_valid)
        if self.model_type == 'classification':
            score = accuracy_score(self.y_valid, y_pred)
            print(f"Validation Accuracy: {score}")
        else:
            score = -mean_squared_error(self.y_valid, y_pred)
            print(f"Validation Negative MSE: {score}")
        return score

    def _is_improvement(self, score):
        """
        Checks if the new score is an improvement over the best score.
        """
        if self.model_type == 'classification':
            return score > self.best_score
        else:
            return score < self.best_score

    def evaluate(self):
        """
        Evaluates the best model on the validation set.
        """
        if self.best_model is None:
            raise Exception("No model has been trained yet.")
        print("\nEvaluating the best model on validation data...")
        y_pred = self.best_model.predict(self.X_valid)
        if self.model_type == 'classification':
            accuracy = accuracy_score(self.y_valid, y_pred)
            f1 = f1_score(self.y_valid, y_pred, average='weighted')
            print(f"Final Model Accuracy: {accuracy}")
            print(f"Final Model F1 Score: {f1}")
            return accuracy, f1
        else:
            mse = mean_squared_error(self.y_valid, y_pred)
            print(f"Final Model MSE: {mse}")
            return mse

# Example usage
if __name__ == '__main__':
    # Load dataset (example with Iris dataset)
    from sklearn.datasets import load_iris
    data = load_iris()
    X = data.data
    y = data.target

    # Initialize self-optimizing model
    model = SelfOptimizingModel(X, y, model_type='classification', algorithm='random_forest')

    # Train and optimize
    model.train_and_optimize(iterations=10)

    # Evaluate the best model
    model.evaluate()