代码之家  ›  专栏  ›  技术社区  ›  Code_Sipra

训练集和测试集的随机森林回归精度不同[闭合]

  •  2
  • Code_Sipra  · 技术社区  · 7 年前

    我对机器学习和Python都是新手。我试图在UCI存储库中的一个数据集上构建一个随机森林回归模型。这是我的第一个ML模型。我的方法可能是完全错误的。

    https://archive.ics.uci.edu/ml/datasets/abalone

    下面是我编写的全部工作代码。我在Windows 7 x64操作系统上使用Python 3.6.4(请原谅我的代码太长)。

    import tkinter as tk # Required for enabling GUI options
    from tkinter import messagebox # Required for pop-up window
    from tkinter import filedialog # Required for getting full path of file
    import pandas as pd # Required for data handling
    from sklearn.model_selection import train_test_split # Required for splitting data into training and test set
    from sklearn.ensemble import RandomForestRegressor # Required to build random forest
    
    #------------------------------------------------------------------------------------------------------------------------#
    # Create an instance of tkinter and hide the window
    
    root = tk.Tk() # Create an instance of tkinter
    root.withdraw() # Hides root window
    #root.lift() # Required for pop-up window management
    root.attributes("-topmost", True) # To make pop-up window stay on top of all other windows
    
    #------------------------------------------------------------------------------------------------------------------------#
    # This block of code reads input file using tkinter GUI options
    
    print("Reading input file...")
    
    # Pop up window to ask user the input file
    File_Checker = messagebox.askokcancel("Random Forest Regression Prompt",
                                          "At The Prompt, Enter 'Abalone_Data.csv' File.")
    
    # Kill the execution if user selects "Cancel" in the above pop-up window
    if (File_Checker == False):
        quit()
    else:
        del(File_Checker)
    
    file_loop = 0
    
    while (file_loop == 0):
        # Get path of base file
        file_path =  filedialog.askopenfilename(initialdir = "/",
                                                title = "File Selection Prompt",
                                                filetypes = (("XLSX Files","*.*"), ))
    
        # Condition to check if user selected a file or not
        if (len(file_path) < 1):
            # Pop-up window to warn uer that no file was selected
            result = messagebox.askretrycancel("File Selection Prompt Error",
                                               "No file has been selected. \nWhat do you want to do?")
    
            # Condition to repeat the loop or quit program execution
            if (result == True):
                continue
            else:
                quit()
    
        # Get file name
        file_name = file_path.split("/") # Splits the file with "/" as the delimiter and returns a list
        file_name = file_name[-1] # extracts the last element of the list
    
        # Condition to check if correct file was selected or not
        if (file_name != "Abalone_Data.csv"):
            result = messagebox.askretrycancel("File Selection Prompt Error",
                                               "Incorrect file selected. \nWhat do you want to do?")
    
            # Condition to repeat the loop or quit program execution
            if (result == True):
                continue
            else:
                quit()
    
        # Read the base file
        input_file = pd.read_csv(file_path,
                                 sep = ',',
                                 encoding = 'utf-8',
                                 low_memory = True)
    
        break
    
    # Delete unwanted files
    del(file_loop, file_name)
    
    #------------------------------------------------------------------------------------------------------------------------#
    print("Preparing dependent and independent variables...")
    
    # Create Separate dataframe consisting of only dependent variable
    y = pd.DataFrame(input_file['Rings'])
    
    # Create Separate dataframe consisting of only independent variable
    X = input_file.drop(columns = ['Rings'], inplace = False, axis = 1)
    
    #------------------------------------------------------------------------------------------------------------------------#
    print("Handling Dummy Variable Trap...")
    
    # Create a new dataframe to handle categorical data
    # This method splits the dategorical data column into separate columns
    # This is to ensure we get rid of the dummy variable trap
    dummy_Sex = pd.get_dummies(X['Sex'], prefix = 'Sex', prefix_sep = '_', drop_first = True)
    
    # Remove the speciic columns from the dataframe
    # These are the categorical data columns which split into separae columns in the previous step
    X.drop(columns = ['Sex'], inplace = True, axis = 1)
    
    # Merge the new columns to the original dataframe
    X = pd.concat([X, dummy_sex], axis = 1)
    
    #------------------------------------------------------------------------------------------------------------------------#
    y = y.values 
    X = X.values
    
    #------------------------------------------------------------------------------------------------------------------------#
    print("Splitting datasets to training and test sets...")
    
    # Splitting the data into training set and test set
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)
    
    #------------------------------------------------------------------------------------------------------------------------#
    print("Fitting Random Forest regression on training set")
    
    # Fitting the regression model to the dataset
    regressor = RandomForestRegressor(n_estimators = 100, random_state = 50)
    regressor.fit(X_train, y_train.ravel()) # Using ravel() to avoid getting 'DataConversionWarning' warning message
    
    #------------------------------------------------------------------------------------------------------------------------#
    print("Predicting Values")
    
    # Predicting a new result with regression
    y_pred = regressor.predict(X_test)
    
    # Enter values for new prediction as a Dictionary
    test_values = {'Sex_I' : 0,
                   'Sex_M' : 0,
                   'Length' : 0.5,
                   'Diameter' : 0.35,
                   'Height' : 0.8,
                   'Whole_Weight' : 0.223,
                   'Shucked_Weight' : 0.09,
                   'Viscera_Weight' : 0.05,
                   'Shell_Weight' : 0.07}
    
    # Convert dictionary into dataframe
    test_values = pd.DataFrame(test_values, index = [0])
    
    # Rearranging columns as required
    test_values = test_values[['Length','Diameter','Height','Whole_Weight','Shucked_Weight','Viscera_Weight',
                               'Viscera_Weight', 'Sex_I', 'Sex_M']]
    
    # Applying feature scaling
    #test_values = sc_X.transform(test_values)
    
    # Predicting values of new data
    new_pred = regressor.predict(test_values)
    
    #------------------------------------------------------------------------------------------------------------------------#
    """
    print("Building Confusion Matrix...")
    
    # Making the confusion matrix
    cm = confusion_matrix(y_test, y_pred)
    """
    #------------------------------------------------------------------------------------------------------------------------#
    print("\n")
    print("Getting Model Accuracy...")
    
    # Get regression details
    #print("Estimated Coefficient = ", regressor.coef_)
    #print("Estimated Intercept = ", regressor.intercept_)
    print("Training Accuracy = ", regressor.score(X_train, y_train))
    print("Test Accuracy = ", regressor.score(X_test, y_test))
    
    print("\n")
    print("Printing predicted result...")
    print("Result_of_Treatment = ", new_pred)
    

    当我查看模型的准确性时,下面是我得到的。

    Getting Model Accuracy...
    Training Accuracy =  0.9359702279804791
    Test Accuracy =  0.5695080680053354
    

    下面是我的问题。 1) 为什么 Training Accuracy Test Accuracy 那么远?

    2) 如何知道此型号是否安装过度/不足?

    3) 随机森林回归是正确的模型吗?如果没有,我如何为这个用例确定正确的模型?

    3) 如何使用我创建的变量构建混淆矩阵?

    4) 如何验证模型的性能?

    我正在寻求您的指导,以便我也能从错误中吸取教训,提高我的建模技能。

    2 回复  |  直到 7 年前
        1
  •  12
  •   Vincenzo Lavorini    7 年前

    在回答您的观点之前,请先发表评论:我知道您使用的是一个回归器,其精度作为度量标准。但准确度是分类问题中使用的一个指标;在回归模型中,您通常使用其他指标,如均方误差(MSE)。看见 here .

    如果你只是切换到一个更适合的指标,也许你会发现你的模型并没有那么糟糕。

    无论如何,我会回答你的问题。

    为什么训练准确度和测试准确度相差如此之远? 这意味着您过度拟合了训练样本:您的模型在预测训练数据集的数据方面非常强大,但无法推广。就像让一个模特在一组猫的图片上训练,只相信那些图片是猫,而其他所有猫的图片都不是。事实上,测试集的精度约为0.5,这基本上是一个随机猜测。

    如何知道此型号是否安装过度/不足? 准确地形成两组之间的精度差异。它们之间的距离越近,模型就越能推广。你已经知道过胖的样子了。由于两组中的精度较低,通常可以识别出欠拟合。

    随机森林回归是正确的模型吗?如果没有,我如何为这个用例确定正确的模型? 没有合适的模型可供使用。在处理结构化数据时,随机森林和通常所有基于树的模型(LightGBM、XGBoost)都是机器学习的瑞士军刀,因为它们简单可靠。基于深度学习的模型在理论上表现更好,但建立起来要复杂得多。

    如何使用我创建的变量构建混淆矩阵? 在构建分类模型时,可以创建混淆矩阵,并基于模型的输出进行构建。 您使用的是回归器,它没有太多意义。

    如何验证模型的性能? 一般来说,为了可靠地验证性能,您将数据分为三部分:第一部分(也称为训练集)训练,第二部分(也称为验证集,这是您所称的测试集)调整模型,最后,当您对模型及其超参数满意时,您将在第三部分(也称为测试集,不要与您所称的测试集混淆)测试它。最后一个告诉您模型的泛化是否良好。这是因为,当您选择和优化模型时,您还可以过度拟合验证集(您称之为测试集的验证集),可能会选择一组仅在该集上运行良好的超参数。 此外,您必须选择一个可靠的指标,这取决于数据和模型。在回归中,MSE相当好。

        2
  •  3
  •   Nicolas M.    7 年前

    有了树和合奏,你必须注意一些设置。在您的情况下,差异来自“过度装配”。这意味着,您的模型学习了“太多”您的训练数据,无法推广到其他数据。

    要做的一件重要事情是限制树木的深度。对于每棵树,有一个分枝因子为2。这意味着在深度d,你会有2^d分支。

    假设您有1000个培训值。如果你不限制深度 (或/和min\u samples\u leaf),您可以使用 深度为10(因为2^10=1024>N\u培训)。

    您可以做的是比较一个深度范围内的训练精度和测试精度(从3到基数2的对数(n))。如果深度太低,两种精度都会很低,因为您需要更多分支来正确学习数据,它会上升一个峰值,然后训练数据会继续上升,但测试值会下降。它应该像下图一样,具有模型复杂性,这是您的深度。

    enter image description here

    你也可以玩 min\u samples\u split 和/或 min\u samples\u叶 这可以帮助您仅当此分支中有多个数据时才进行拆分。因此,这将限制深度,并允许每个分支具有不同深度的树。与前面解释的一样,您可以使用该值来查找最佳值(通过网格搜索)。

    我希望有帮助,