我想问一个关于我过去几天遇到的问题的问题。 首先,我是机器学习的初学者,这是我第一次使用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)
答案 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时,code
和r_size
列中有一些字符串类型的值,因为整个列dtype更改为字符串,而不是在small_test.csv中完成
现在由于这种变化,dictVectorizer以不同于以前的方式对数据进行编码,并且功能也会发生变化,因此结果也会发生变化。
如果你这样做:
df3[['code', 'r_size']] = df3[['code', 'r_size']].astype(str)
然后调用predict()
,结果再次相同。