001/* 002 * Copyright (c) 2015-2020, Oracle and/or its affiliates. All rights reserved. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.tribuo.anomaly; 018 019import com.oracle.labs.mlrg.olcut.provenance.Provenance; 020import org.tribuo.ImmutableOutputInfo; 021import org.tribuo.MutableOutputInfo; 022import org.tribuo.OutputFactory; 023import org.tribuo.anomaly.Event.EventType; 024import org.tribuo.anomaly.evaluation.AnomalyEvaluation; 025import org.tribuo.anomaly.evaluation.AnomalyEvaluator; 026import org.tribuo.evaluation.Evaluator; 027import org.tribuo.provenance.OutputFactoryProvenance; 028 029import java.util.Map; 030 031/** 032 * A factory for generating events. 033 */ 034public final class AnomalyFactory implements OutputFactory<Event> { 035 private static final long serialVersionUID = 1L; 036 037 /** 038 * The unknown event. Used at inference time. 039 */ 040 public static final Event UNKNOWN_EVENT = new Event(EventType.UNKNOWN); 041 042 /** 043 * The expected event. Used for things which are not anomalous. 044 */ 045 public static final Event EXPECTED_EVENT = new Event(EventType.EXPECTED); 046 047 /** 048 * The anomalous event. It's anomalous. 049 */ 050 public static final Event ANOMALOUS_EVENT = new Event(EventType.ANOMALOUS); 051 052 private static final AnomalyEvaluator evaluator = new AnomalyEvaluator(); 053 054 @Override 055 public <V> Event generateOutput(V label) { 056 if (label.toString().equalsIgnoreCase(EventType.ANOMALOUS.toString())) { 057 return ANOMALOUS_EVENT; 058 } else { 059 return EXPECTED_EVENT; 060 } 061 } 062 063 @Override 064 public Event getUnknownOutput() { 065 return UNKNOWN_EVENT; 066 } 067 068 @Override 069 public MutableOutputInfo<Event> generateInfo() { 070 return new MutableAnomalyInfo(); 071 } 072 073 @Override 074 public ImmutableOutputInfo<Event> constructInfoForExternalModel(Map<Event,Integer> mapping) { 075 // Validate inputs are dense 076 OutputFactory.validateMapping(mapping); 077 078 Integer expectedMapping = mapping.get(EXPECTED_EVENT); 079 Integer anomalousMapping = mapping.get(ANOMALOUS_EVENT); 080 081 if (((expectedMapping != null) && (expectedMapping != EventType.EXPECTED.getID())) || 082 ((anomalousMapping != null) && anomalousMapping != EventType.ANOMALOUS.getID())){ 083 throw new IllegalArgumentException("Anomaly detection requires that anomalous events have id " + EventType.ANOMALOUS.getID() + ", and expected events have id " + EventType.EXPECTED.getID()); 084 } 085 086 MutableAnomalyInfo info = new MutableAnomalyInfo(); 087 return info.generateImmutableOutputInfo(); 088 } 089 090 @Override 091 public Evaluator<Event, AnomalyEvaluation> getEvaluator() { 092 return evaluator; 093 } 094 095 @Override 096 public OutputFactoryProvenance getProvenance() { 097 return new AnomalyFactoryProvenance(); 098 } 099 100 /** 101 * Provenance for {@link AnomalyFactory}. 102 */ 103 public final static class AnomalyFactoryProvenance implements OutputFactoryProvenance { 104 private static final long serialVersionUID = 1L; 105 106 /** 107 * Constructs an anomaly factory provenance. 108 */ 109 AnomalyFactoryProvenance() {} 110 111 /** 112 * Constructs an anomaly factory provenance from the marshalled form. 113 * @param map An empty map. 114 */ 115 public AnomalyFactoryProvenance(Map<String, Provenance> map) { } 116 117 @Override 118 public String getClassName() { 119 return AnomalyFactory.class.getName(); 120 } 121 122 @Override 123 public String toString() { 124 return generateString("OutputFactory"); 125 } 126 127 @Override 128 public boolean equals(Object other) { 129 return other instanceof AnomalyFactoryProvenance; 130 } 131 132 @Override 133 public int hashCode() { 134 return 31; 135 } 136 } 137}