amazon-ec2 - 将H2O生成的POJO部署到Jetty :/predict returns 404

标签 amazon-ec2 jetty pojo h2o jetty-9

我已经从 H2O 模型生成了 POJO。

在一个单独的 EC2 实例上,我想将此模型部署到 Jetty serverlet 以用作 API 评分端点。我怎样才能做到这一点?

1。 POJO 示例

这是一个最小的示例,demo_glm,通过年龄、票价等级和性别的逻辑回归来预测泰坦尼克号乘客的生存:

/*
  Licensed under the Apache License, Version 2.0
    http://www.apache.org/licenses/LICENSE-2.0.html

  AUTOGENERATED BY H2O at 2017-09-13T17:30:17.931Z
  3.13.0.3908

  Standalone prediction code with sample test data for GLMModel named demo_glm

  How to download, compile and execute:
      mkdir tmpdir
      cd tmpdir
      curl http://XXX.XX.XX.XXX:54321/3/h2o-genmodel.jar > h2o-genmodel.jar
      curl http://XXX.XX.XX.XXX:54321/3/Models.java/demo_glm > demo_glm.java
      javac -cp h2o-genmodel.jar -J-Xmx2g -J-XX:MaxPermSize=128m demo_glm.java

     (Note:  Try java argument -XX:+PrintCompilation to show runtime JIT compiler behavior.)
*/
import java.util.Map;
import hex.genmodel.GenModel;
import hex.genmodel.annotations.ModelPojo;

@ModelPojo(name="demo_glm", algorithm="glm")
public class demo_glm extends GenModel {
  public hex.ModelCategory getModelCategory() { return hex.ModelCategory.Binomial; }

  public boolean isSupervised() { return true; }
  public int nfeatures() { return 3; }
  public int nclasses() { return 2; }

  // Names of columns used by model.
  public static final String[] NAMES = NamesHolder_demo_glm.VALUES;
  // Number of output classes included in training data response column.
  public static final int NCLASSES = 2;

  // Column domains. The last array contains domain of response column.
  public static final String[][] DOMAINS = new String[][] {
    /* pclass */ demo_glm_ColInfo_0.VALUES,
    /* sex */ demo_glm_ColInfo_1.VALUES,
    /* age */ null,
    /* survived */ demo_glm_ColInfo_3.VALUES
  };
  // Prior class distribution
  public static final double[] PRIOR_CLASS_DISTRIB = null;
  // Class distribution used for model building
  public static final double[] MODEL_CLASS_DISTRIB = null;

  public demo_glm() { super(NAMES,DOMAINS); }
  public String getUUID() { return Long.toString(-1806915013443955212L); }

  // Pass in data in a double[], pre-aligned to the Model's requirements.
  // Jam predictions into the preds[] array; preds[0] is reserved for the
  // main prediction (class for classifiers or value for regression),
  // and remaining columns hold a probability distribution for classifiers.
  public final double[] score0( double[] data, double[] preds ) {
    final double [] b = BETA.VALUES;
    for(int i = 0; i < 2; ++i) if(Double.isNaN(data[i])) data[i] = CAT_MODES.VALUES[i];
    for(int i = 0; i < 1; ++i) if(Double.isNaN(data[i + 2])) data[i+2] = NUM_MEANS.VALUES[i];
    double eta = 0.0;
    for(int i = 0; i < CATOFFS.length-1; ++i) if(data[i] != 0) {
      int ival = (int)data[i] - 1;
      if(ival != data[i] - 1) throw new IllegalArgumentException("categorical value out of range");
      ival += CATOFFS[i];
      if(ival < CATOFFS[i + 1])
        eta += b[ival];
    }
    for(int i = 2; i < b.length-1-1; ++i)
    eta += b[1+i]*data[i];
    eta += b[b.length-1]; // reduce intercept
    double mu = hex.genmodel.GenModel.GLM_logitInv(eta);
    preds[0] = (mu >= 0.3701702514726391) ? 1 : 0; // threshold given by ROC
    preds[1] = 1.0 - mu; // class 0
    preds[2] =       mu; // class 1
    return preds;
  }
    public static class BETA implements java.io.Serializable {
      public static final double[] VALUES = new double[5];
      static {
        BETA_0.fill(VALUES);
      }
      static final class BETA_0 implements java.io.Serializable {
        static final void fill(double[] sa) {
          sa[0] = -1.280567936795408;
          sa[1] = -2.2896567020762353;
          sa[2] = -2.4978421167555616;
          sa[3] = -0.034393168117166584;
          sa[4] = 3.5220688949789816;
        }
      }
}
// Imputed numeric values
    static class NUM_MEANS implements java.io.Serializable {
      public static final double[] VALUES = new double[1];
      static {
        NUM_MEANS_0.fill(VALUES);
      }
      static final class NUM_MEANS_0 implements java.io.Serializable {
        static final void fill(double[] sa) {
          sa[0] = 29.881134512434045;
        }
      }
}
// Imputed categorical values.
    static class CAT_MODES implements java.io.Serializable {
      public static final int[] VALUES = new int[2];
      static {
        CAT_MODES_0.fill(VALUES);
      }
      static final class CAT_MODES_0 implements java.io.Serializable {
        static final void fill(int[] sa) {
          sa[0] = 2;
          sa[1] = 1;
        }
      }
}
    // Categorical Offsets
    public static final int[] CATOFFS = {0,2,3};
}
// The class representing training column names
class NamesHolder_demo_glm implements java.io.Serializable {
  public static final String[] VALUES = new String[3];
  static {
    NamesHolder_demo_glm_0.fill(VALUES);
  }
  static final class NamesHolder_demo_glm_0 implements java.io.Serializable {
    static final void fill(String[] sa) {
      sa[0] = "pclass";
      sa[1] = "sex";
      sa[2] = "age";
    }
  }
}
// The class representing column pclass
class demo_glm_ColInfo_0 implements java.io.Serializable {
  public static final String[] VALUES = new String[3];
  static {
    demo_glm_ColInfo_0_0.fill(VALUES);
  }
  static final class demo_glm_ColInfo_0_0 implements java.io.Serializable {
    static final void fill(String[] sa) {
      sa[0] = "1st";
      sa[1] = "2nd";
      sa[2] = "3rd";
    }
  }
}
// The class representing column sex
class demo_glm_ColInfo_1 implements java.io.Serializable {
  public static final String[] VALUES = new String[2];
  static {
    demo_glm_ColInfo_1_0.fill(VALUES);
  }
  static final class demo_glm_ColInfo_1_0 implements java.io.Serializable {
    static final void fill(String[] sa) {
      sa[0] = "female";
      sa[1] = "male";
    }
  }
}
// The class representing column survived
class demo_glm_ColInfo_3 implements java.io.Serializable {
  public static final String[] VALUES = new String[2];
  static {
    demo_glm_ColInfo_3_0.fill(VALUES);
  }
  static final class demo_glm_ColInfo_3_0 implements java.io.Serializable {
    static final void fill(String[] sa) {
      sa[0] = "0";
      sa[1] = "1";
    }
  }
}

2。到目前为止我已经尝试过

在单独的 EC2 实例上安装 Jetty 后,我按照上面评论中的说明进行操作:

cd $JETTY_HOME/demo-base/webapps
mkdir model_demo
cd model_demo
curl http://XXX.XX.XX.XXX:54321/3/h2o-genmodel.jar > h2o-genmodel.jar
curl http://XXX.XX.XX.XXX:54321/3/Models.java/demo_glm > demo_glm.java
javac -cp h2o-genmodel.jar -J-Xmx2g -J-XX:MaxPermSize=128m 

我可以通过http://XXX.XX.XX.YY:8080/访问servlet,并在浏览器中或通过curl看到“欢迎来到Jetty-9”屏幕。

我的问题是,当我尝试时:

curl http://XXX.XX.XX.YY:8080/predict?pclass=1st&age=29&sex=female

或者:

curl http://XXX.XX.XX.YY:8080/model_demo/predict?pclass=1st&age=29&s‌​ex=female

我得到:

HTTP ERROR 404

Problem accessing /predict. Reason:

  Not Found 

最佳答案

您可以查看以下两个存储库,以查看部署在 jetty 中的 POJO 的工作示例:

以及部署在 jetty 的 MOJO:

对于上述具体问题,您可能需要将 web.xml 文件添加到 .war 文件中。这是 app-mojo-servlet 存储库中的 web.xml:

$ cat src/main/webapp/WEB-INF/web.xml

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
         version="2.4">
    <servlet>
        <servlet-name>Predict</servlet-name>
        <servlet-class>ai.h2o.PredictServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Predict</servlet-name>
        <url-pattern>/predict</url-pattern>
    </servlet-mapping>
</web-app>

关于amazon-ec2 - 将H2O生成的POJO部署到Jetty :/predict returns 404,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46205042/

相关文章:

java - 只需在 BDD (Hibernate) 中插入日期的 "Hour:Minutes"

amazon-web-services - Wireshark 已安装但无法在 Amazon linux 上运行

linux - aws ec2 iptables 端口 80 (http)

java - 通用 hibernate 对象的面向对象设计

spring - jetty 因扫描而启动延迟

java - FreeMarker 文件路径

java - POJO 是反面向对象(OO)的吗?

php - Amazon SES 从实例配置文件元数据服务器检索凭证时出错。 (客户端错误 : 404)

linux - 亚马逊 AWS EC2 实例未收到电子邮件

Java servlet 和数据库连接池