基于大特征向量的分段故障LibSVM
Segfault with large feature vector LibSVM
我在Android应用程序(NDK)上运行LibSVM。我已经在一个Mac应用程序上实现了类似的代码,它适用于所有的特征向量大小。当我给出一个有408个特征的向量时,我做多类分类没有问题。但是,任何409或更高的值,以及(我最终将输入16800)在这里似乎都失败了:
0-16 23:28:41.084 30997-31028/? A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0xaf000000 in tid 31028 (GLThread 17147)
10-16 23:28:41.190 27393-27393/? I/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
10-16 23:28:41.191 27393-27393/? I/DEBUG: Build fingerprint: 'google/hammerhead/hammerhead:5.1.1/LMY48M/2167285:user/release-keys'
10-16 23:28:41.191 27393-27393/? I/DEBUG: Revision: '11'
10-16 23:28:41.191 27393-27393/? I/DEBUG: ABI: 'arm'
10-16 23:28:41.191 27393-27393/? I/DEBUG: pid: 30997, tid: 31028, name: GLThread 17147 >>> cc.openframeworks.androidEmptyExample <<<
10-16 23:28:41.191 27393-27393/? I/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xaf000000
10-16 23:28:41.202 27393-27393/? I/DEBUG: r0 aef3e000 r1 aef5ed10 r2 00000001 r3 af000000
10-16 23:28:41.202 27393-27393/? I/DEBUG: r4 aec29eb8 r5 00000001 r6 b4b2c608 r7 12d090c0
10-16 23:28:41.202 27393-27393/? I/DEBUG: r8 12d15660 r9 b4a39400 sl 00000000 fp af37d824
10-16 23:28:41.202 27393-27393/? I/DEBUG: ip b6e417dc sp af37d810 lr a301ff78 pc a301ff04 cpsr 000f0010
10-16 23:28:41.202 27393-27393/? I/DEBUG: #00 pc 00167f04 /data/app/cc.openframeworks.androidEmptyExample-1/lib/arm/libOFAndroidApp.so (Kernel::dot(svm_node const*, svm_node const*)+192)
下面是我正在学习的相关代码:
ofxSvm mSvm;
void ofApp::update()
{ //Runs in loop
for(int i =0; i<8400; ++i)
{
HandDataVector.push_back((double)tempValue[i]);//tempValue is incoming data from a serial port (8400 doubles per packet)
}
//If I exclude this I get segfaults:
HandDataVector.resize(150);
if(learningToggleBoxTicked)
{
mSvm.addData(HandDataVector,label)
mSvm.train();
} else {
ofLogNotice("Classified As")<< mSvm.classify();
}
}
int ofApp::classify()
{
return mSvm.predict(HandDataVector);
}
这是我使用的ofxSvm库
int ofxSvm::addData(int label, vector<double>& vec)
{
checkDimension(vec.size());
mData.insert(make_pair(label, vec));
mDimension = vec.size();
stringstream ss;
for (const auto v : vec) ss << v << " ";
ss << "EOS";
ofLogNotice(LOG_MODULE, "add data, label: " + ofToString(label) + " size: "+ofToString(vec.size())+" vec: " + ss.str());
return mData.size();
}
void ofxSvm::train()
{
svm_problem prob;
prob.l = mData.size();
prob.y = new double[prob.l];
{
data_type::iterator it = mData.begin();
int i = 0;
while (it != mData.end())
{
prob.y[i] = it->first;
++it; ++i;
}
}
if(mParam.gamma == 0)
{
mParam.gamma = 1.0 / mDimension;
}
int nodeLength = mDimension + 1;
svm_node* node = new svm_node[prob.l * nodeLength];
prob.x = new svm_node*[prob.l];
{
data_type::iterator it = mData.begin();
int i = 0;
while (it != mData.end())
{
prob.x[i] = node + i * nodeLength;
for (int j = 0; j < mDimension; ++j)
{
prob.x[i][j].index = j + 1;
prob.x[i][j].value = it->second[j];
}
prob.x[i][mDimension].index = -1; // delimiter
++it; ++i;
}
}
ofLogNotice(LOG_MODULE, "Start train...");
mModel = svm_train(&prob, &mParam);
ofLogNotice(LOG_MODULE, "Finished train!");
int x = mModel->nr_class;
ofLogNotice("TRAINED MODEL LABELS: " + ofToString(x));
delete[] node;
delete[] prob.x;
delete[] prob.y;
}
int ofxSvm::predict(vector<double>& testVec)
{
if (mModel == NULL)
{
ofLogNotice(LOG_MODULE, "null model, before do train or load model file");
return -5;
}
if (testVec.size() != mDimension)
{
ofLogNotice(LOG_MODULE, "different dimension");
return -6;
}
svm_node* node = new svm_node[mDimension + 1];
for (int i = 0; i < mDimension; ++i)
{
node[i].index = i + 1;
node[i].value = testVec[i];
ofLogNotice("node") << node[i].value <<"-" << i;
}
node[mDimension].index = -1;
int res = static_cast<int>(svm_predict(mModel, node));
stringstream ss;
for (const auto v : testVec) ss << v << " ";
ss << "EOS";
ofLogNotice(LOG_MODULE, "add data, label: size: "+ofToString(testVec.size())+" vec: " + ss.str());
ofLogNotice("ANSWER")<< res;
delete[] node;
return res;
}
下面是LibSVM库中发生故障的函数:
double Kernel::dot(const svm_node *px, const svm_node *py)
{
double sum = 0;
while(px->index != -1 && py->index != -1)
{
if(px->index == py->index)
{
sum += px->value * py->value;
++px;
++py;
}
else
{
if(px->index > py->index)
++py;
else
++px;
}
}
return sum;
}
编辑:在这里点函数被调用(k_function in svm_predict_values)
double svm_predict_values(const svm_model *model, const svm_node *x, double* dec_values)
{
int i;
if(model->param.svm_type == ONE_CLASS ||
model->param.svm_type == EPSILON_SVR ||
model->param.svm_type == NU_SVR)
{
double *sv_coef = model->sv_coef[0];
double sum = 0;
for(i=0;i<model->l;i++)
sum += sv_coef[i] * Kernel::k_function(x,model->SV[i],model->param);
sum -= model->rho[0];
*dec_values = sum;
if(model->param.svm_type == ONE_CLASS)
return (sum>0)?1:-1;
else
return sum;
}
else
{
int nr_class = model->nr_class;
int l = model->l;
double *kvalue = Malloc(double,l);
for(i=0;i<l;i++)
kvalue[i] = Kernel::k_function(x,model->SV[i],model->param);
int *start = Malloc(int,nr_class);
start[0] = 0;
for(i=1;i<nr_class;i++)
start[i] = start[i-1]+model->nSV[i-1];
int *vote = Malloc(int,nr_class);
for(i=0;i<nr_class;i++)
vote[i] = 0;
int p=0;
for(i=0;i<nr_class;i++)
for(int j=i+1;j<nr_class;j++)
{
double sum = 0;
int si = start[i];
int sj = start[j];
int ci = model->nSV[i];
int cj = model->nSV[j];
int k;
double *coef1 = model->sv_coef[j-1];
double *coef2 = model->sv_coef[i];
for(k=0;k<ci;k++)
sum += coef1[si+k] * kvalue[si+k];
for(k=0;k<cj;k++)
sum += coef2[sj+k] * kvalue[sj+k];
sum -= model->rho[p];
dec_values[p] = sum;
if(dec_values[p] > 0)
++vote[i];
else
++vote[j];
p++;
}
int vote_max_idx = 0;
for(i=1;i<nr_class;i++)
if(vote[i] > vote[vote_max_idx])
vote_max_idx = i;
free(kvalue);
free(start);
free(vote);
return model->label[vote_max_idx];
}
}
double Kernel::k_function(const svm_node *x, const svm_node *y,
const svm_parameter& param)
{
switch(param.kernel_type)
{
case LINEAR:
return dot(x,y);
case POLY:
return powi(param.gamma*dot(x,y)+param.coef0,param.degree);
case RBF:
{
double sum = 0;
while(x->index != -1 && y->index !=-1)
{
if(x->index == y->index)
{
double d = x->value - y->value;
sum += d*d;
++x;
++y;
}
else
{
if(x->index > y->index)
{
sum += y->value * y->value;
++y;
}
else
{
sum += x->value * x->value;
++x;
}
}
}
while(x->index != -1)
{
sum += x->value * x->value;
++x;
}
while(y->index != -1)
{
sum += y->value * y->value;
++y;
}
return exp(-param.gamma*sum);
}
case SIGMOID:
return tanh(param.gamma*dot(x,y)+param.coef0);
case PRECOMPUTED: //x: test (validation), y: SV
return x[(int)(y->value)].value;
default:
return 0; // Unreachable
}
}
double kernel_linear(int i, int j) const
{
return dot(x[i],x[j]);
}
介绍
我很难找到任何关于libSVM的c++文档。所以我的答案主要是基于你给我们看的代码,没有真正的参考文档。
如果你能发布一个链接到你的文档,这将是非常有帮助的:)
潜在的问题
您展示了在您的训练代码中初始化svm_node*
的代码:
prob.x[i][mDimension].index = -1;
您正在初始化svm_problem
实例。显然,在您的dot()
函数中,您希望看到这样的节点具有负索引,以标记svm_node
列表的结束。
但是像这样调用你的代码会失败:
Kernel::k_function(x,model->SV[i],model->param);
这里,model
是svm_model
,而不是svm_problem
,所以我猜这是在训练模型后由libSVM 返回的。您确定svm_model
遵循使用node->index = -1
标记节点列表结束的约定吗?
所以可能标记节点不存在而你跑出了边界
为什么409项会突然中断
你得到的信号是一个SIGSEGV,它表明你试图访问一个没有映射到你的进程中的页中的字节。
当访问超出边界的项时,通常不会得到SIGSEGV,因为先前分配的项位于内存页的中间,并且在页面中有足够的字节。可能第409项正好在当前分配的页面之后,触发信号。
我在'dot'函数中遇到了类似的问题,我通过不包含'0'作为值来解决。正如@fjardon所提到的,该函数期望索引为'-1'和值为'0'来标记svm_nodes(训练向量)列表的结束。
当然这对你来说有点晚了,但希望它能帮助未来的libsvm用户:)
- 分段故障(堆芯转储)矢量
- 数组的指针从不分段故障
- Windows 10-使用gtkmm-3.0库和g++[包括再现]的分段故障
- 分段故障 运行C++代码时出现 SIGSEGV
- 分段故障背包问题
- 分段故障 11,从类函数显示动态 C 字符串
- 面临分段故障 使用 ffmpeg 读取视频时,因为"pFormatCtx-> streams [i]-> codecpar"的地址0x00
- 在C++中,当指向删除和指向不同对象时,分段故障指针
- 分段故障说明
- 分段故障(核心转储)-不知道为什么
- 分段故障线程
- hiredis SET遇到分段故障
- 分段故障,合并排序算法
- 多线程程序中的分段故障和gdb回溯上的不完整信息
- 到达主C++之前分段故障
- 分段故障核心使用 IF流转储
- 使用向量的移动键盘排列(分段故障)
- 在二进制树插入和遍历期间,我得到了分段故障
- 分段故障在类之间返回整数
- C++分段故障BST