java - 通过 java 运行时使用腌制的 python 类
问题描述
我使用 scikit-learn 从一些字符串构建了一个二进制 SVM 分类器:
count_vect = TfidfVectorizer(sublinear_tf=True, min_df=10, norm='l2', encoding='latin-1', ngram_range=(1, 4))
X_counts = count_vect.fit_transform(X)
tfidf_transformer = TfidfTransformer()
X_tfidf = tfidf_transformer.fit_transform(X_counts)
clf = SGDClassifier(loss='hinge', penalty='l2', tol=1e-3)
clf.fit(X_tfidf, Y)
然后我围绕经过训练的分类器创建了一个包装类并将其腌制:
class Classifier:
def __init__(self, clf, vect):
self.classifier = clf
self.vectorizer = vect
def classify(self, s):
return self.classifier.predict(self.vectorizer.transform([s]))[0]
with open('my_classifier.pkl', 'wb') as fout:
pickle.dump(Classifier(clf, count_vect), fout)
在单独的脚本中,我可以加载腌制分类器并正确使用它:
with open('my_classifier.pkl', 'rb') as fin:
clf = pickle.load(fin)
result = clf.classify(sys.argv[1])
print(result)
但是,当我尝试通过 java Runtime 执行脚本时,它显示不正确的输出。
public boolean classify(String s) throws IOException {
String cmd = "python3 pkl_classifier.py \"" + s + "\"";
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader stdIn = new BufferedReader(new InputStreamReader(p.getInputStream()));
String out = stdIn.readLine();
if (out != null) {
switch (Integer.parseInt(out)) {
case 0: return false;
case 1: return true;
default: throw new RuntimeException("Error with classifier script:" + out);
}
}
return false;
}
分类器的输出可以是 0 或 1。但是这个 java 代码总是产生一个 0。我已经从 java 打印出整个命令 ( cmd
) 并直接在终端中执行它,它产生了正确的输出。但是java Runtime产生的输出总是0。
有什么我想念的吗?
解决方案
才发现问题。
它在我通过java执行的脚本中。
假设我要分类的字符串是"lorem ipsum dolor sit amet"
. 当我形成命令在我的 java 类中将其分类为
String cmd = "python3 pkl_classifier.py \"" + s + "\"";
它看起来像
python3 pkl_classifier.py "lorem ipsum dolor sit amet"
这正是我想要执行的命令。当我打印出变量cmd
时,它看起来还不错。但是当我在 python 脚本中使用打印命令时
print(sys.argv)
它看起来像
['pkl_classifier.py', '"lorem', 'ipsum', 'dolor', 'sit', 'amet"']
因此,显然它是通过忽略引号的空格来拆分命令。
然后我改变了脚本
result = clf.classify(sys.argv[1])
至
result = clf.classify(' '.join(sys.argv[1:]))
它工作得很好!
更好的解决方案:
与其调整 python 脚本,不如使用其他将参数作为字符串数组的类exec()
方法。Process
它将在内部处理参数中的空格。
String[] cmd = { "python3", "pkl_classifier.py", s };
p = Runtime.getRuntime().exec(cmd);
推荐阅读
- flutter - dart 中的错误处理 - 评估用户输入
- android - Flutter Websocket 使用 STOMP - 消息未接收
- python - Matplotlib:在动画期间包括某些点
- pine-script - IB数据的选定时间段进行数据分析
- javascript - 从实时 videojs hls 流中获取 MediaStream
- ruby-on-rails - Apple Silicon (M1) 上 Docker 中的 Ruby on Rails
- jquery - 如何防止 jquery 函数运行?
- jquery - 根据第一个日期选择器设置第二个日期选择器的 minDate
- c# - [CascadingParameter] 与 [Parameter] 相比是否会影响性能?
- security - 如何删除服务器标头 .NET Core Blazor 应用程序