提高神经网络与 SVM 的性能
Improve performace of Neural Netkork vs SVC
我正在训练一个具有 100 个特征、64 个标签和 150K 个观察值(训练+测试)的分类模型。数据嘈杂并且已经过预处理。
使用 SVC 我达到了相当不错的结果,足以满足要求。
得分为97.8%
SVC模型提供了7700个支持向量,实时预测的过程要求高
我想知道神经网络是否可以执行类似的操作。我测试了 1 层和 2 层的几种配置,但最好的结果是 1 层。通过我的实验,我得到 94.8% 的隐藏层和 300 个神经元,不足以满足要求。
代码中包含数据集 (70MB)
我的 i7 8750H、16GB msi 笔记本电脑的安装尺寸约为 60'。
哪个层结构可以改进该实验?
import numpy as np
import pandas as pd
import time
from sklearn.svm import SVC
from sklearn.neural_network import MLPClassifier
local = 'data.csv'
url='https://www.dropbox.com/s/dccj9leppapy9pv/data.csv?dl=1'
print('Loading dataset')
X = pd.read_csv(url).values[:,1:]
train = X[ X[:,-1] == 1][:,:-1]
test = X[ X[:,-1] == 0][:,:-1]
X_train, y_train = train[:,:-1], train[:,-1]
X_test, y_test = test[:,:-1], test[:,-1]
now = time.time()
model = SVC(C=2500, gamma=10, kernel='rbf',verbose=True)
model.fit(X_train, y_train)
print('elapsed time:', time.time()-now)
score = model.score(X_test,y_test)
print('SVC score:', score)
print(len(model.support_vectors_) ,'support vectors')
now = time.time()
model = MLPClassifier(hidden_layer_sizes=(300,), activation='logistic',solver='adam',verbose=True,tol=1e-10,learning_rate_init=0.1,learning_rate='adaptive')
model.fit(X_train, y_train)
print('elapsed time:', time.time()-now)
score = model.score(X_test,y_test)
print('NN score:', score)
问题是你的问题措辞不当,但我知道你的问题是什么:
基本上你有一个非常大的高维度数据集,具有以下事实:
Number of cases: 150K
Number of Classes: 64
Number of Features: 99
N.B 你有 99
个特征(不是 100 个)不包括 responses/classes 列!
目标:
找到在 CPU 负载、内存负载和时间方面提供最高准确度和最佳性能的最佳算法!
已经尝试过:
SVM
算法给出了极好的精度结果,但它花了很多时间才完成。
问题:
应该调整哪些参数尤其是 hidden_layer_sizes
以获得比您已经94.8
使用hidden_layer_sizes=(300,)
得到的精度更高的精度Neural Network
?
回答
在你的问题中,有许多隐含的子问题需要回答。事实上,您需要对数据集进行完整的数据分析才能做出正确的决定;所以这不是一个简单直接的案例。尽管如此,让我将问题分解成子问题并尝试解决它们:
首先:
正如我在 中提到的,按照惯例选择分类算法有一个经验法则,如下所示:
- 对于少量特征,使用
Logistic Regression
。
- 对于很多功能但不是很多数据,请使用
SVM
。
- 对于很多功能和大量数据,请选择
Neural Network
。
有了 150K
的观察和 99
的特征,SVM
将永远完成!因此我们剩下 Logistic Regression
和 Neural Network
.
根据上面提到的经验法则,Neural Network
是一个更好的候选者,它确实给了你 94.8%
的准确度分数,这是一个很好的结果,但是,你确实需要 优秀得分(>97%)!.
其次:
对于Artificial Neural Network
,没有选择隐藏层大小的经验法则,而是有一些指导方针;来自 Jeff Heaton 的 Java 神经网络简介(第二版):
隐藏层数:
0只能表示线性可分函数或决策。
1可以逼近任何包含连续映射的函数
从一个有限的 space 到另一个。
2 可以表示任意精度的任意决策边界
具有有理激活函数并且可以逼近任何平滑
映射到 任意精度 。
另一方面,根据经验,在隐藏层中使用太少的神经元会导致欠拟合,而在隐藏层中使用过多的神经元可能会导致过拟合:
隐藏神经元的数量应该在输入层大小和输出层大小之间
隐藏神经元的数量应为输入层大小的 2/3 加上输出层大小。
隐藏神经元的数量应该小于输入层大小的两倍。
但问题是:如果我们尝试上述建议,需要多少时间?!
这里需要用到GridSearchCV,最后耗时比SVM
还多!!!
正如您所见,在准确性和性能之间存在权衡。你不能声称 outstanding 和良好的 real-time 性能同时针对您的特定数据集,因为它很大而且大部分都是零!!
怎么办?
您有以下选择:
1.Either 保持当前的 SVM
或 ANN
实现以实现 高精度 但实时性能最差!
2.Or搭配Gaussian Naive Bayes可以得到出色的性能(因为它基本上是为了在线分类!)但最差准确度如下:
import time
import pandas as pd
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import StratifiedShuffleSplit
import numpy as np
def getDataset(path, x_attr, y_attr, mapping=None):
"""
Extract dataset from CSV file
:param path: location of csv file
:param x_attr: list of Features Names
:param y_attr: Y header name in CSV file
:param mapping: dictionary of the classes integers
:return: tuple, (X, Y)
"""
df = pd.read_csv(path)
if mapping is not None:
df.replace(mapping, inplace=True)
X = np.array(df[x_attr]).reshape(len(df), len(x_attr))
Y = np.array(df[y_attr])
return X, Y
def run(X_data, Y_data):
sss = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=0)
train_index, test_index = next(sss.split(X_data, Y_data))
X_train, X_test = X_data[train_index], X_data[test_index]
Y_train, Y_test = Y_data[train_index], Y_data[test_index]
clf = GaussianNB()
print("Start Modeling...")
now = time.time()
clf.fit(X_train, Y_train)
print('Elapsed Time:', time.time() - now)
print("Finished Modeling...")
print(clf.score(X_test, Y_test))
X, Y = getDataset("data.csv", [str(x) for x in range(1,98)] + ["99"], "98")
run(X, Y)
结果
Start Modeling...
Elapsed Time: 0.12834382057189941
Finished Modeling...
0.6888808876959838
3.Or 介于两者之间并稍微降低您的准确性期望,然后您可以使用 Logistic Regression
实现适度的性能,如下所示:
import time
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedShuffleSplit
import numpy as np
def getDataset(path, x_attr, y_attr, mapping=None):
"""
Extract dataset from CSV file
:param path: location of csv file
:param x_attr: list of Features Names
:param y_attr: Y header name in CSV file
:param mapping: dictionary of the classes integers
:return: tuple, (X, Y)
"""
df = pd.read_csv(path)
if mapping is not None:
df.replace(mapping, inplace=True)
X = np.array(df[x_attr]).reshape(len(df), len(x_attr))
Y = np.array(df[y_attr])
return X, Y
def run(X_data, Y_data):
sss = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=0)
train_index, test_index = next(sss.split(X_data, Y_data))
X_train, X_test = X_data[train_index], X_data[test_index]
Y_train, Y_test = Y_data[train_index], Y_data[test_index]
clf = LogisticRegression(random_state=0, C=10)
print("Start Modeling...")
now = time.time()
clf.fit(X_train, Y_train)
print('Elapsed Time:', time.time() - now)
print("Finished Modeling...")
print(clf.score(X_test, Y_test))
X, Y = getDataset("data.csv", [str(x) for x in range(1,98)] + ["99"], "98")
run(X, Y)
结果
Start Modeling...
Elapsed Time: 80.22028756141663
Finished Modeling...
0.9141762953749468
4.Or 你最后可以做的是检查哪些特征对 类 最重要,你可以通过使用 Forests of Trees
来评估特征的重要性来实现。 Here 是一个完整而简单的示例,说明如何在 Scikit-Learn
中执行此操作,然后创建数据集的新版本,但这次仅包含最重要的功能。还建议通过删除大多数包含零输入的 rows/observations 来获取当前数据集的子样本!
我正在训练一个具有 100 个特征、64 个标签和 150K 个观察值(训练+测试)的分类模型。数据嘈杂并且已经过预处理。 使用 SVC 我达到了相当不错的结果,足以满足要求。 得分为97.8%
SVC模型提供了7700个支持向量,实时预测的过程要求高
我想知道神经网络是否可以执行类似的操作。我测试了 1 层和 2 层的几种配置,但最好的结果是 1 层。通过我的实验,我得到 94.8% 的隐藏层和 300 个神经元,不足以满足要求。
代码中包含数据集 (70MB) 我的 i7 8750H、16GB msi 笔记本电脑的安装尺寸约为 60'。
哪个层结构可以改进该实验?
import numpy as np
import pandas as pd
import time
from sklearn.svm import SVC
from sklearn.neural_network import MLPClassifier
local = 'data.csv'
url='https://www.dropbox.com/s/dccj9leppapy9pv/data.csv?dl=1'
print('Loading dataset')
X = pd.read_csv(url).values[:,1:]
train = X[ X[:,-1] == 1][:,:-1]
test = X[ X[:,-1] == 0][:,:-1]
X_train, y_train = train[:,:-1], train[:,-1]
X_test, y_test = test[:,:-1], test[:,-1]
now = time.time()
model = SVC(C=2500, gamma=10, kernel='rbf',verbose=True)
model.fit(X_train, y_train)
print('elapsed time:', time.time()-now)
score = model.score(X_test,y_test)
print('SVC score:', score)
print(len(model.support_vectors_) ,'support vectors')
now = time.time()
model = MLPClassifier(hidden_layer_sizes=(300,), activation='logistic',solver='adam',verbose=True,tol=1e-10,learning_rate_init=0.1,learning_rate='adaptive')
model.fit(X_train, y_train)
print('elapsed time:', time.time()-now)
score = model.score(X_test,y_test)
print('NN score:', score)
问题是你的问题措辞不当,但我知道你的问题是什么:
基本上你有一个非常大的高维度数据集,具有以下事实:
Number of cases: 150K
Number of Classes: 64
Number of Features: 99
N.B 你有 99
个特征(不是 100 个)不包括 responses/classes 列!
目标:
找到在 CPU 负载、内存负载和时间方面提供最高准确度和最佳性能的最佳算法!
已经尝试过:
SVM
算法给出了极好的精度结果,但它花了很多时间才完成。
问题:
应该调整哪些参数尤其是 hidden_layer_sizes
以获得比您已经94.8
使用hidden_layer_sizes=(300,)
得到的精度更高的精度Neural Network
?
回答
在你的问题中,有许多隐含的子问题需要回答。事实上,您需要对数据集进行完整的数据分析才能做出正确的决定;所以这不是一个简单直接的案例。尽管如此,让我将问题分解成子问题并尝试解决它们:
首先:
正如我在
- 对于少量特征,使用
Logistic Regression
。 - 对于很多功能但不是很多数据,请使用
SVM
。 - 对于很多功能和大量数据,请选择
Neural Network
。
有了 150K
的观察和 99
的特征,SVM
将永远完成!因此我们剩下 Logistic Regression
和 Neural Network
.
根据上面提到的经验法则,Neural Network
是一个更好的候选者,它确实给了你 94.8%
的准确度分数,这是一个很好的结果,但是,你确实需要 优秀得分(>97%)!.
其次:
对于Artificial Neural Network
,没有选择隐藏层大小的经验法则,而是有一些指导方针;来自 Jeff Heaton 的 Java 神经网络简介(第二版):
隐藏层数:
0只能表示线性可分函数或决策。
1可以逼近任何包含连续映射的函数 从一个有限的 space 到另一个。
2 可以表示任意精度的任意决策边界 具有有理激活函数并且可以逼近任何平滑 映射到 任意精度 。
另一方面,根据经验,在隐藏层中使用太少的神经元会导致欠拟合,而在隐藏层中使用过多的神经元可能会导致过拟合:
隐藏神经元的数量应该在输入层大小和输出层大小之间
隐藏神经元的数量应为输入层大小的 2/3 加上输出层大小。
隐藏神经元的数量应该小于输入层大小的两倍。
但问题是:如果我们尝试上述建议,需要多少时间?!
这里需要用到GridSearchCV,最后耗时比SVM
还多!!!
正如您所见,在准确性和性能之间存在权衡。你不能声称 outstanding 和良好的 real-time 性能同时针对您的特定数据集,因为它很大而且大部分都是零!!
怎么办?
您有以下选择:
1.Either 保持当前的 SVM
或 ANN
实现以实现 高精度 但实时性能最差!
2.Or搭配Gaussian Naive Bayes可以得到出色的性能(因为它基本上是为了在线分类!)但最差准确度如下:
import time
import pandas as pd
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import StratifiedShuffleSplit
import numpy as np
def getDataset(path, x_attr, y_attr, mapping=None):
"""
Extract dataset from CSV file
:param path: location of csv file
:param x_attr: list of Features Names
:param y_attr: Y header name in CSV file
:param mapping: dictionary of the classes integers
:return: tuple, (X, Y)
"""
df = pd.read_csv(path)
if mapping is not None:
df.replace(mapping, inplace=True)
X = np.array(df[x_attr]).reshape(len(df), len(x_attr))
Y = np.array(df[y_attr])
return X, Y
def run(X_data, Y_data):
sss = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=0)
train_index, test_index = next(sss.split(X_data, Y_data))
X_train, X_test = X_data[train_index], X_data[test_index]
Y_train, Y_test = Y_data[train_index], Y_data[test_index]
clf = GaussianNB()
print("Start Modeling...")
now = time.time()
clf.fit(X_train, Y_train)
print('Elapsed Time:', time.time() - now)
print("Finished Modeling...")
print(clf.score(X_test, Y_test))
X, Y = getDataset("data.csv", [str(x) for x in range(1,98)] + ["99"], "98")
run(X, Y)
结果
Start Modeling...
Elapsed Time: 0.12834382057189941
Finished Modeling...
0.6888808876959838
3.Or 介于两者之间并稍微降低您的准确性期望,然后您可以使用 Logistic Regression
实现适度的性能,如下所示:
import time
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedShuffleSplit
import numpy as np
def getDataset(path, x_attr, y_attr, mapping=None):
"""
Extract dataset from CSV file
:param path: location of csv file
:param x_attr: list of Features Names
:param y_attr: Y header name in CSV file
:param mapping: dictionary of the classes integers
:return: tuple, (X, Y)
"""
df = pd.read_csv(path)
if mapping is not None:
df.replace(mapping, inplace=True)
X = np.array(df[x_attr]).reshape(len(df), len(x_attr))
Y = np.array(df[y_attr])
return X, Y
def run(X_data, Y_data):
sss = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=0)
train_index, test_index = next(sss.split(X_data, Y_data))
X_train, X_test = X_data[train_index], X_data[test_index]
Y_train, Y_test = Y_data[train_index], Y_data[test_index]
clf = LogisticRegression(random_state=0, C=10)
print("Start Modeling...")
now = time.time()
clf.fit(X_train, Y_train)
print('Elapsed Time:', time.time() - now)
print("Finished Modeling...")
print(clf.score(X_test, Y_test))
X, Y = getDataset("data.csv", [str(x) for x in range(1,98)] + ["99"], "98")
run(X, Y)
结果
Start Modeling...
Elapsed Time: 80.22028756141663
Finished Modeling...
0.9141762953749468
4.Or 你最后可以做的是检查哪些特征对 类 最重要,你可以通过使用 Forests of Trees
来评估特征的重要性来实现。 Here 是一个完整而简单的示例,说明如何在 Scikit-Learn
中执行此操作,然后创建数据集的新版本,但这次仅包含最重要的功能。还建议通过删除大多数包含零输入的 rows/observations 来获取当前数据集的子样本!