小 test_set xgb 预测

small test_set xgb predict

我想问一个关于我最近几天遇到的问题的问题。 首先,我是机器学习的初学者,这是我第一次使用 XGBoost 算法,如果有任何错误,请原谅。

我训练了我的模型来预测日志文件是否是恶意的。在我保存并在不同的会话中重新加载我的模型后,我使用了似乎正常工作的预测函数(概率有一些偏差,但这是另一个主题,我知道我在另一个主题中看到过它)

问题是这样的:有时当我尝试在加载后预测一个“小”csv 文件时,它似乎只预测零标签被打破,即使对于之前分类正确的索引也是如此。 例如,我加载了一个包含 20.000 个值的数据集,predict() 正在运行。我使用 pandas drop 仅保留这些值中的前 5 个,再次正常工作。如果我将 5 个值保存在不同的 csv 上并重新加载它,则它不起作用。如果我只是手动删除所有索引 (19.995) 并仅保存 5 个剩余的文件,则会发生同样的错误。

我敢打赌这是文件大小的问题,但是当我通过 pandas 将索引放在数据帧上时,它似乎可以正常工作 此外,数字 5(索引)是出于示例目的,如果我删除大部分数据集,也会发生同样的情况。 在尝试手动验证一些全新的日志后,我首先想到了这个问题,如果将这些日志扔进大的 csv 文件而不是自己的新文件中,这些日志似乎被正确分类。

这是我的加载和预测代码

##IMPORTS
import os
import pandas as pd
from pandas.compat import StringIO
from datetime import datetime
from langid.langid import LanguageIdentifier, model
import langid
import time
from sklearn.model_selection import train_test_split
from sklearn.linear_model import SGDClassifier
from sklearn.metrics import accuracy_score
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics import precision_score, recall_score
from sklearn.metrics import precision_recall_curve
from sklearn.externals import joblib
from ggplot import ggplot, aes, geom_line
from sklearn.pipeline import Pipeline
from xgboost import XGBClassifier
from sklearn.metrics import average_precision_score
import numpy as np
from sklearn.feature_extraction import DictVectorizer
from sklearn.pipeline import FeatureUnion
from sklearn.base import BaseEstimator, TransformerMixin
from collections import defaultdict
import pickle
df = pd.read_csv('big_test.csv')

df3 = pd.read_csv('small_test.csv')

#This one is necessary for the loaded_model
class ColumnSelector(BaseEstimator, TransformerMixin):
    def init(self, column_list):
        self.column_list = column_list

    def fit(self, x, y=None):
        return self

    def transform(self, x):
        if len(self.column_list) == 1:
            return x[self.column_list[0]].values
        else:
            return x[self.column_list].to_dict(orient='records')

loaded_model = joblib.load('finalized_model.sav')
result = loaded_model.predict(df)
print(result)

df2=df[:5]
result2 = loaded_model.predict(df2)
print(result2)

result3 = loaded_model.predict(df3)
print(result3)

我得到的结果是:

[1 0 1 ... 0 0 0]

[1 0 1 0 1]

[0 0 0 0 0]

如有必要,我可以提供来自训练或我的数据集的任何代码。

*编辑:我为我的数据使用管道。在使用 xgb 拟合虹膜数据后,我试图重现错误,但我做不到。也许我的管道有问题?代码如下:

df = pd.read_csv('big_test.csv')
# df.info()


# Split Dataset
attributes = ['uri','code','r_size','DT_sec','Method','http_version','PenTool','has_referer', 'Lang','LangProb','GibberFlag' ]
x_train, x_test, y_train, y_test = train_test_split(df[attributes], df['Scan'], test_size=0.2, 
stratify=df['Scan'], random_state=0)

x_train, x_dev, y_train, y_dev = train_test_split(x_train, y_train, test_size=0.2, 
                                                  stratify=y_train, random_state=0)
# print('Train:', len(y_train), 'Dev:', len(y_dev), 'Test:', len(y_test))

# set up graph function
def plot_precision_recall_curve(y_true, y_pred_scores):
    precision, recall, thresholds = precision_recall_curve(y_true, y_pred_scores)
    return ggplot(aes(x='recall', y='precision'), 
                  data=pd.DataFrame({"precision": precision, "recall": recall})) + geom_line()


# XGBClassifier

class ColumnSelector(BaseEstimator, TransformerMixin):
    def __init__(self, column_list):
        self.column_list = column_list
        
    def fit(self, x, y=None):
        return self
    
    def transform(self, x):
        if len(self.column_list) == 1:
            return x[self.column_list[0]].values
        else:
            return x[self.column_list].to_dict(orient='records')


count_vectorizer = CountVectorizer(analyzer='char', ngram_range=(1, 2), min_df=10)
dict_vectorizer = DictVectorizer()
xgb = XGBClassifier(seed=0)

pipeline = Pipeline([
    ("feature_union", FeatureUnion([
        ('text_features', Pipeline([
            ('selector', ColumnSelector(['uri'])), 
            ('count_vectorizer', count_vectorizer)
        ])),
        ('categorical_features', Pipeline([
            ('selector', ColumnSelector(['code','r_size','DT_sec','Method','http_version','PenTool','has_referer', 'Lang','LangProb','GibberFlag' ])),
            ('dict_vectorizer', dict_vectorizer)
        ]))
    ])),
    ('xgb', xgb)
])

pipeline.fit(x_train, y_train)

filename = 'finalized_model.sav'
joblib.dump(pipeline, filename)

这是由于大文件和小文件的 dtype 不同造成的。

当你这样做时:

df = pd.read_csv('big_test.csv')

数据类型是这些:

print(df.dtypes)

# Output
uri              object
code             object   # <== Observe this
r_size           object   # <== Observe this
Scan              int64
...
...
...

现在当你这样做时:

df3 = pd.read_csv('small_test.csv')

数据类型已更改:

print(df3.dtypes)

# Output
uri              object
code              int64   # <== Now this has changed
r_size            int64   # <== Now this has changed
Scan              int64
...
...

你看,pandas 将尝试自行确定列的数据类型。当你加载 big_test.csv 时,coder_size 列中有一些值是字符串类型,由于整个列 dtype 都更改为字符串,这在 small_test.csv.

现在由于这一变化,dictVectorizer 以与以前不同的方式对数据进行编码,特征也发生了变化,因此结果也发生了变化。

如果你这样做:

df3[['code', 'r_size']] = df3[['code', 'r_size']].astype(str)

再调用predict(),结果还是一样。