0

私はこれを約 5 日間修正しようとしていますが、運が悪く、試したすべての解決策が失敗しました。

以下にSIGSEGVの原因をいくつか見つけましたが、何も 役に立ちませんでした

わかりました、これがコードです。いくつかのキーワード機能とそのスコアを含む 2 つのインスタンスがあります。

私はそれらのユークリッド距離を取得したいです。つまり、各インスタンスのすべてのキーワードを保存し、最初のキーワードと 2 番目のキーワードの差分を見つけてから、残りの 2 番目のキーワードの差分を見つける必要があります。実例。私が望むのは、最初のマップを繰り返しながら、2 番目のマップから要素を削除できるようにすることです。2 つのメッセージ コレクションがあり、最初のコレクションのすべてのメッセージが 2 番目のすべてのメッセージと比較されるため、次のメソッドは複数回呼び出されます。

私はこのコードを持っていますが、いくつかの場所に置いた複数のcoutで数秒間動作していることを確認しましたが、突然停止しました

これは大学のタスクのためであるため、boost などのすべてのトリックを使用できないことに注意してください。しかし、私が抱えている問題を回避する方法を知りたいです。

float KNNClassifier::distance(const Instance& inst1, const Instance& inst2) {   
map<string,unsigned> feat1;
map<string,unsigned> feat2;
for (unsigned i=0; i<inst1.getNumberOfFeatures(); i++) {
  feat1[inst1.getFeature(i)]=i;
}
for (unsigned i=0; i<inst2.getNumberOfFeatures(); i++) {
  feat2[inst2.getFeature(i)]=i;
}
float dist=0;

map<string,unsigned>::iterator it;
for (it=feat1.begin(); it!=feat1.end(); it++) {
  if (feat2.find(it->first)!=feat2.end()) {//if and only if it exists in inst2
    dist+=pow( (double) inst1.getScore(it->second) - inst2.getScore(feat2[it->first]) , 2.0);
    feat2.erase(it->first);
  }
  else {
    dist+=pow( (double) inst1.getScore(it->second) , 2.0);
  }
}

for (it=feat2.begin(); it!=feat2.end(); it++) {//for the remaining words
  dist+=pow( (double) inst2.getScore(it->second) , 2.0);
}
feat1.clear(); feat2.clear(); //ka8arizoume ta map gia thn epomenh xrhsh
return sqrt(dist);    
}

また、何かを削除する必要がないようにこのアイデアも試しましたが、突然停止します。

float KNNClassifier::distance(const Instance& inst1, const Instance& inst2) {
map<string,unsigned> feat1;
map<string,unsigned> feat2;
map<string,bool> exists;
for (unsigned i=0; i<inst1.getNumberOfFeatures(); i++) {
  feat1[inst1.getFeature(i)]=i;
}
for (unsigned i=0; i<inst2.getNumberOfFeatures(); i++) {
  feat2[inst2.getFeature(i)]=i;
  exists[inst2.getFeature(i)]=false;
  if (feat1.find(inst2.getFeature(i))!=feat1.end()) {
    exists[inst2.getFeature(i)]=true;
  }
}
float dist=0;
map<string,unsigned>::iterator it;
for (it=feat1.begin(); it!=feat1.end(); it++) {
  if (feat2.find(it->first)!=feat2.end()) {
    dist+=pow( (double) inst1.getScore(it->second) - inst2.getScore(feat2[it->first]) ,      2.0);
  }
  else {
    dist+=pow( (double) inst1.getScore(it->second) , 2.0);
  }
}

for (it=feat2.begin(); it!=feat2.end(); it++) {
  if(it->second==false){//if it is true, it means the diff was done in the previous iteration
    dist+=pow( (double) inst2.getScore(it->second) , 2.0);
  }
}

feat1.clear(); feat2.clear(); exists.clear();
return sqrt(dist);
}
4

1 に答える 1

1

コード自体は問題ないようです (以前に見つけたと思っていたエラーは 1 つではありませんでした)。ただし、より簡単なアプローチがある場合があります。

  1. 最初のセットから 2 番目のセットの文字列を検索する代わりに、2 つのリストを同時に移動して、反復子を小さい方の要素に進めるか、同じ文字列を使用している場合は両方の反復子に進めることができます。対応する計算は、それぞれの場合に直接行われます。
  2. std::vector<std::pair<std::string, unsigned int> >私は個人的にこれのためにソートされた2つを使用しますがstd::map<std::string, unsigned int>、同様に機能します。

私はあなたのInstanceクラスにアクセスできないため、テストしていませんが、以下のようなものが機能するはずです。

struct compare1st {
    bool operator()(std::pair<std::string, unsigned int> const& p1,
                    std::pair<std::string, unsigned int> const& p2) const {
        return p1.first < p2.first;
    }
};

std::vector<std::pair<std::string, unsigned int> > fill(Instance const& inst) {
    std::vector<std::pair<std::string, unsigned int> > rc;
    for (unsigned int i(0), end(inst.getNumberOfFeatures()); i != end; ++i) {
        rc.push_back(std::make_pair(inst.getFeature(i), i));
    }
    std::sort(rc.begin(), rc.end(), compare1st());
    return rc;
}
double square(double d) { // pow(d, 2.0) is fairly expensive
    return d * d;
}

float KNNClassifier::distance(const Instance& inst1, const Instance& inst2) {   
    typedef std::pair<std::string, unsigned int> Pair;
    std::vector<Pair> feat1 = fill(inst1);
    std::vector<Pair> feat2 = fill(inst2);

    std::vector<Pair>::const_iterator it1(feat1.begin()), end1(feat1.end());
    std::vector<Pair>::const_iterator it2(feat2.begin()), end2(feat2.end());
    double result(0.0);
    while (it1 != end1 && it2 != end2) {
        if (it1 != end1 && (it2 == end2 || it1->first < it2->first)) {
            result += square(inst1.getScore((it1++)->second);
        }
        else if (it2 != end2 && (it1 == end1 || it2->first < it1->first))
            result += square(inst2.getScore((it2++)->second);
        }
        else {
            result += square(inst1.getScore((it1++)->second)
                             -  inst2.getScore((it2++)->second);
        }
    }
    return sqrt(result);
}
于 2013-01-02T21:53:48.190 に答える