from sklearn.model_selection import train_test_split
from sklearn.metrics import median_absolute_error
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVR
import pandas as pd
from sklearn.metrics import mean_squared_error, r2_score, median_absolute_error
from sklearn.model_selection import GridSearchCV
import numpy as np
from sklearn import svm
from sklearn.svm import LinearSVC
import matplotlib.pyplot as plt
# from pykalman import KalmanFilter
import pickle

def median_filter(signal, kernel_size):
    assert kernel_size % 2 == 1, "Kernel size must be odd!"
    padded_signal = np.pad(signal, (kernel_size // 2, kernel_size // 2), mode='reflect')
    filtered_signal = np.zeros_like(signal)
    for i in range(len(signal)):
        filtered_signal[i] = np.median(padded_signal[i:i + kernel_size])
    return filtered_signal

def best_params(X_train, y_train):
    param_grid = {'C': [0.1, 1, 10, 100], 'gamma': [0.1, 0.5, 1, 10], 'kernel': ['rbf', 'poly']}
    grid_search = GridSearchCV(SVR(), param_grid, cv=5)
    grid_search.fit(X_train, y_train)

    # Output the best hyperparameters
    best_params = grid_search.best_params_
    print(best_params)
    return best_params

def yuchuli():
    # Load data
    dataframe = pd.read_excel('2023-05-26.xlsx', sheet_name=2)

    # Prepare data, taking the first six columns as input features and the last column as output feature
    input_data = dataframe.iloc[:, 0:5].values
    output_data = dataframe.iloc[:, 5].values

    # Filter the first six columns of data
    X = np.apply_along_axis(lambda m: median_filter(m, kernel_size=3), axis=0, arr=input_data)
    # Filter the seventh column of data
    y = median_filter(output_data, kernel_size=3)

    return X, y

def z_xunlian(X, y):
    # Split the dataset into training and test sets
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.04,random_state=61)

    # Create an SVR instance with specific parameters
    ridge_svr = SVR(kernel='rbf', epsilon=0.001, C=15, gamma=0.5, degree=3, coef0=0.8, shrinking=True, tol=0.001, max_iter=-1, verbose=2)

    # Train the model
    ridge_svr.fit(X_train, y_train)

    # Predict with model
    y_pred = ridge_svr.predict(X_test)
    med = median_absolute_error(y_test, y_pred)
    mse = mean_squared_error(y_test, y_pred)
    # Calculate R2 score
    r2 = r2_score(y_test, y_pred)
    print("Mean squared error:", mse)
    print("Median absolute error:", med)
    print("R2 score:", r2)
    return y_test, y_pred

# Plotting the curve
def quxiantu(y_test, y_pred):
    # Plot the curves for actual and predicted values
    plt.plot(y_test[100:150], label='Actual Value', color='blue', linestyle='-')
    plt.plot(y_pred[100:150], label='Predicted Value', color='red', linestyle='--')

    # Set labels and title
    plt.xlabel('Sample Number')
    plt.ylabel('Qualification Rate')
    plt.title('Prediction Model for Qualification Rate')
    plt.rcParams['font.sans-serif'] = ['SimHei']
    # Show the legend
    plt.legend()

    # Display the plot
    plt.show()

if __name__ == "__main__":
    X, y = yuchuli()
    y_test, y_pred = z_xunlian(X, y)
    quxiantu(y_test, y_pred)