将 Python 翻译成 Rcpp
Translating Python to Rcpp
我无法将此 ptyhon 转换为 Rcpp
该脚本是分类和回归树逻辑的一部分:
# Calculate the Gini index for a split dataset
def gini_index(groups, classes):
# count all samples at split point
n_instances = float(sum([len(group) for group in groups]))
# sum weighted Gini index for each group
gini = 0.0
for group in groups:
size = float(len(group))
# avoid divide by zero
if size == 0:
continue
score = 0.0
# score the group based on the score for each class
for class_val in classes:
p = [row[-1] for row in group].count(class_val) / size
score += p * p
# weight the group score by its relative size
gini += (1.0 - score) * (size / n_instances)
return gini
# test Gini values
print(gini_index([[[1, 1], [1, 0]], [[1, 1], [1, 0]]], [0, 1]))
>>0.5
print(gini_index([[[1, 0], [1, 0]], [[1, 1], [1, 1]]], [0, 1]))
>>0
我试图通过简单地提供两个向量并循环来加快速度。
向量是实际组和建议组。
实际分组对应于上面每个嵌套列表中的最后一个元素:
1,0,1,0
提议的组对应于嵌套列表的分组方式(前两个元素在一个组中;后两个元素在另一个组中)
1,1,2,2
我的 C++/Rcpp 不够强大,看不出这里出了什么问题:
float gini_index(NumericVector y, NumericVector g){
int n_records = y.size();
float gini = 0.0;
NumericVector groups = unique(y);
int group_count = groups.size();
for(int i_g=0; i_g<group_count; i_g++){
float size = 0;
for(int i;i<n_records;i++){
if(g[i]==groups[i_g]){
size++;
}
}
float score = 0.0;
for(int i_y=0; i_y<n_records; i_y++){
float class_count=0;
if(y[i_y]==groups[i_g]){
class_count++;}
float p=0;
if(size==0){
p=0;
}
else{
p = class_count/size;
}
std::cout<<p<<std::endl;
score = score + p*p;
}
gini = gini+(1.0-score)*(size/n_records);
}
return(gini);
}
y<-c(1,1,2,2)
g<-c(1,2,1,2)
gini_index(y,g)
> gini_index(y,g)
0
0.5
0
0.5
0
0
0
0
[1] 0.25
这应该return0.5
您的循环之一出错:i
未初始化。在我的例子中,导致循环根本没有被评估。通过适当的修复,结果看起来更好:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
float gini_index(NumericVector y, NumericVector g){
int n_records = y.size();
float gini = 0.0;
NumericVector groups = unique(y);
int group_count = groups.size();
for(int i_g=0; i_g<group_count; i_g++){
float size = 0;
for(int i = 0;i<n_records;i++){ // !!!
if(g[i]==groups[i_g]){
size++;
}
}
float score = 0.0;
for(int i_y=0; i_y<n_records; i_y++){
float class_count=0;
if(y[i_y]==groups[i_g]){
class_count++;}
float p=0;
if(size==0){
p=0;
}
else{
p = class_count/size;
}
Rcpp::Rcout<<p<<std::endl;
score = score + p*p;
}
gini = gini+(1.0-score)*(size/n_records);
}
return(gini);
}
/*** R
y<-c(1,1,2,2)
g<-c(1,2,1,2)
gini_index(y,g)
*/
结果:
> gini_index(y,g)
0 2
0
0
0.5
0.5
1 2
0.5
0.5
0
0
[1] 0.5
顺便说一句:
- 为什么要返回
float
而不是 double
?
- 增量应写成
++i
等
- C++ 有
+=
.
这就是我最终使用的,如果有人试图重新创建的话。我最初接受的答案非常有帮助,但在其他情况下打印出错误的答案。
float gini_index(NumericVector y, NumericVector g){
float gini = 0.0;
NumericVector classes = unique(y);
int class_count = classes.size();
int n_instances = y.size();
float p;
for(int group=0; group<class_count; group++){
float size = 0;
for(int i=0; i<g.size();i++){
if(g[i]==classes[group]){
size++;
}
}
if(size==0){
p=0;
}
float score =0.0;
if(size!=0){
for(int class_val=0; class_val<classes.size(); class_val++){
float correctly_assigned = 0;
for(int i=0; i<g.size();i++){
if(g[i]==classes[group] && y[i]==classes[class_val])
correctly_assigned++;
}
p = correctly_assigned/size;
score = score +p*p;
}
gini = gini+ (1.0-score)*(size / n_instances);
}
}
return gini;
}
我无法将此 ptyhon 转换为 Rcpp
该脚本是分类和回归树逻辑的一部分:
# Calculate the Gini index for a split dataset
def gini_index(groups, classes):
# count all samples at split point
n_instances = float(sum([len(group) for group in groups]))
# sum weighted Gini index for each group
gini = 0.0
for group in groups:
size = float(len(group))
# avoid divide by zero
if size == 0:
continue
score = 0.0
# score the group based on the score for each class
for class_val in classes:
p = [row[-1] for row in group].count(class_val) / size
score += p * p
# weight the group score by its relative size
gini += (1.0 - score) * (size / n_instances)
return gini
# test Gini values
print(gini_index([[[1, 1], [1, 0]], [[1, 1], [1, 0]]], [0, 1]))
>>0.5
print(gini_index([[[1, 0], [1, 0]], [[1, 1], [1, 1]]], [0, 1]))
>>0
我试图通过简单地提供两个向量并循环来加快速度。 向量是实际组和建议组。 实际分组对应于上面每个嵌套列表中的最后一个元素:
1,0,1,0
提议的组对应于嵌套列表的分组方式(前两个元素在一个组中;后两个元素在另一个组中)
1,1,2,2
我的 C++/Rcpp 不够强大,看不出这里出了什么问题:
float gini_index(NumericVector y, NumericVector g){
int n_records = y.size();
float gini = 0.0;
NumericVector groups = unique(y);
int group_count = groups.size();
for(int i_g=0; i_g<group_count; i_g++){
float size = 0;
for(int i;i<n_records;i++){
if(g[i]==groups[i_g]){
size++;
}
}
float score = 0.0;
for(int i_y=0; i_y<n_records; i_y++){
float class_count=0;
if(y[i_y]==groups[i_g]){
class_count++;}
float p=0;
if(size==0){
p=0;
}
else{
p = class_count/size;
}
std::cout<<p<<std::endl;
score = score + p*p;
}
gini = gini+(1.0-score)*(size/n_records);
}
return(gini);
}
y<-c(1,1,2,2)
g<-c(1,2,1,2)
gini_index(y,g)
> gini_index(y,g)
0
0.5
0
0.5
0
0
0
0
[1] 0.25
这应该return0.5
您的循环之一出错:i
未初始化。在我的例子中,导致循环根本没有被评估。通过适当的修复,结果看起来更好:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
float gini_index(NumericVector y, NumericVector g){
int n_records = y.size();
float gini = 0.0;
NumericVector groups = unique(y);
int group_count = groups.size();
for(int i_g=0; i_g<group_count; i_g++){
float size = 0;
for(int i = 0;i<n_records;i++){ // !!!
if(g[i]==groups[i_g]){
size++;
}
}
float score = 0.0;
for(int i_y=0; i_y<n_records; i_y++){
float class_count=0;
if(y[i_y]==groups[i_g]){
class_count++;}
float p=0;
if(size==0){
p=0;
}
else{
p = class_count/size;
}
Rcpp::Rcout<<p<<std::endl;
score = score + p*p;
}
gini = gini+(1.0-score)*(size/n_records);
}
return(gini);
}
/*** R
y<-c(1,1,2,2)
g<-c(1,2,1,2)
gini_index(y,g)
*/
结果:
> gini_index(y,g)
0 2
0
0
0.5
0.5
1 2
0.5
0.5
0
0
[1] 0.5
顺便说一句:
- 为什么要返回
float
而不是double
? - 增量应写成
++i
等 - C++ 有
+=
.
这就是我最终使用的,如果有人试图重新创建的话。我最初接受的答案非常有帮助,但在其他情况下打印出错误的答案。
float gini_index(NumericVector y, NumericVector g){
float gini = 0.0;
NumericVector classes = unique(y);
int class_count = classes.size();
int n_instances = y.size();
float p;
for(int group=0; group<class_count; group++){
float size = 0;
for(int i=0; i<g.size();i++){
if(g[i]==classes[group]){
size++;
}
}
if(size==0){
p=0;
}
float score =0.0;
if(size!=0){
for(int class_val=0; class_val<classes.size(); class_val++){
float correctly_assigned = 0;
for(int i=0; i<g.size();i++){
if(g[i]==classes[group] && y[i]==classes[class_val])
correctly_assigned++;
}
p = correctly_assigned/size;
score = score +p*p;
}
gini = gini+ (1.0-score)*(size / n_instances);
}
}
return gini;
}