small test_set xgb预测

时间:2018-04-18 05:08:55

标签: xgboost 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)

1 个答案:

答案 0 :(得分:0)

这是由于大小文件中的dtypes不同。

当你这样做时:

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

dtypes就是这些:

print(df.dtypes)

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

现在你做的时候:

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

更改了dtypes:

print(df3.dtypes)

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

你知道,pandas会尝试自己确定列的dtypes。加载big_test.csv时,coder_size列中有一些字符串类型的值,因为整个列dtype更改为字符串,而不是在small_test.csv中完成

现在由于这种变化,dictVectorizer以不同于以前的方式对数据进行编码,并且功能也会发生变化,因此结果也会发生变化。

如果你这样做:

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

然后调用predict(),结果再次相同。