An outlier process is an infrequent simulated mechanism that produces records, or groups of records, rare and significantly different from normal records. Simulations make these anomalies realistic by preserving sensible ordering and context: each record reflects the state created by preceding records. section 11.4
Use outlier processes to create anomalies that ordinary record-level generators may miss:
- Model many ordinary agents alongside a small number of anomalous agents. section 11.4
- Generate unusual sequences or records that are abnormal given preceding rows. section 11.4
- Use known anomalies to test collective outlier and time-series detection methods. section 11.4
Listing 11.6 Simulation representing one company for 1 year
class Purchacer:
def consider_purchase(self): #1
global inventory
global transactions
if (current_datetime.hour < 9) or \
(current_datetime.hour > 17): #2
return
if np.random.random() > 0.01: #3
product_id = np.random.choice(range(num_items_in_inventory))
if inventory[product_id] > 1000: #4
return
supplier_id = \
np.random.choice(range(num_suppliers)) #5
unit_cost = np.random.exponential() * 20.0
num_purchased = np.random.randint(10, 200)
total_cost = num_purchased * unit_cost
inventory[product_id] += num_purchased
transactions.append([
'Purchase', self.staff_id,
supplier_id, product_id,
current_datetime.strftime("%Y-%m-%d %H:%M"),
num_purchased, unit_cost, total_cost,
inventory[product_id]])
A one-year, minute-by-minute company simulation combines purchaser and sales processes, while time, inventory, and prior transactions constrain plausible records. section 11.4
class RoguePurchaser: #1
def consider_purchase(self):
if (current_datetime.hour < 9) or (current_datetime.hour > 17):
return
if (current_datetime.day == 28) and \
(current_datetime.month not in \
self.extra_purchase_months): #2
product_id = 5
supplier_id = 10
unit_cost = np.random.exponential() * 250.0
trend_factor = np.log2(current_datetime.month+1) + 1
num_purchased = int(np.random.randint(50, 60) * trend_factor)
total_cost = num_purchased * unit_cost
inventory[product_id] += num_purchased
transactions.append([
'Purchase', self.staff_id, supplier_id,
product_id,
current_datetime.strftime("%Y-%m-%d %H:%M"),
num_purchased, unit_cost, total_cost,
inventory[product_id]])
self.extra_purchase_months.append(current_datetime.month)
elif np.random.random() > 0.01:
product_id = np.random.choice(range(num_items_in_inventory))
if product_id == 0: #3
return
if inventory[product_id] > 1000:
return
supplier_id = np.random.choice(range(num_suppliers))
unit_cost = np.random.exponential() * 20.0
num_purchased = np.random.randint(10, 200) #4
total_cost = num_purchased * unit_cost
inventory[product_id] += num_purchased
transactions.append([
'Purchase', self.staff_id, supplier_id, product_id,
current_datetime.strftime("%Y-%m-%d %H:%M"),
num_purchased, unit_cost, total_cost,
inventory[product_id]])
A rogue purchaser creates scheduled, unusually costly purchases with distinctive products, suppliers, quantities, and trends. section 11.4
