matrixprofile

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 3, 2022 License: Apache-2.0 Imports: 22 Imported by: 0

Documentation

Overview

Package matrixprofile computes the matrix profile and matrix profile index of a time series

Example
sig := []float64{0, 0.99, 1, 0, 0, 0.98, 1, 0, 0, 0.96, 1, 0}

mp, err := New(sig, nil, 4)
if err != nil {
	panic(err)
}

if err = mp.Compute(nil); err != nil {
	panic(err)
}

fmt.Printf("Signal:         %.3f\n", sig)
fmt.Printf("Matrix Profile: %.3f\n", mp.MP)
fmt.Printf("Profile Index:  %5d\n", mp.Idx)
Output:

Signal:         [0.000 0.990 1.000 0.000 0.000 0.980 1.000 0.000 0.000 0.960 1.000 0.000]
Matrix Profile: [0.014 0.014 0.029 0.029 0.014 0.014 0.029 0.029 0.029]
Profile Index:  [    4     5     6     7     0     1     2     3     4]
Example (CaseStudy)
sin := siggen.Sin(1, 5, 0, 0, 100, 2)
sin2 := siggen.Sin(0.25, 10, 0, 0.75, 100, 0.25)
saw := siggen.Sawtooth(0.5, 7, 0, 0, 100, 1)
line := siggen.Line(0, 0, len(sin2)*4)
sig := siggen.Append(sin, sin2, sin, line, sin2, line, sin2, line, saw)

noise := siggen.Noise(0.1, len(sig))
sig = siggen.Add(sig, noise)

var m int
m = 32
mp, err := New(sig, nil, m)
if err != nil {
	panic(err)
}

ao := NewAnalyzeOpts()
ao.OutputFilename = "mp_sine.png"

if err = mp.Analyze(nil, ao); err != nil {
	panic(err)
}

fmt.Printf("Saved png file result to %s\n", ao.OutputFilename)
Output:

Saved png file result to mp_sine.png
Example (KDimensionalCaseStudy)
sin := siggen.Sin(1, 4, 0, 0, 100, 0.25)
saw := siggen.Sawtooth(1, 4, 0, 0, 100, 0.25)
square := siggen.Square(1, 4, 0, 0, 100, 0.25)
line := siggen.Line(0, 0, len(sin)*4)
line2 := siggen.Line(0, 0, len(sin)*3)
sig := make([][]float64, 3)
sig[0] = siggen.Append(line, line, line, saw, line2, saw, line2)
sig[1] = siggen.Append(line, sin, line2, sin, line2, sin, line2, sin, line2)
sig[2] = siggen.Append(line, square, line2, square, line2, square, line2, square, line2)

sig[0] = siggen.Add(sig[0], siggen.Noise(0.1, len(sig[0])))
sig[1] = siggen.Add(sig[1], siggen.Noise(0.1, len(sig[0])))
sig[2] = siggen.Add(sig[2], siggen.Noise(0.1, len(sig[0])))

m := 25
mp, err := NewKMP(sig, m)
if err != nil {
	panic(err)
}

if err = mp.Compute(); err != nil {
	panic(err)
}

if err = mp.Visualize("mp_kdim.png"); err != nil {
	panic(err)
}

fmt.Println("Saved png file result to mp_kdim.png")
Output:

Saved png file result to mp_kdim.png

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func MPDist

func MPDist(a, b []float64, w int, o *MPDistOpts) (float64, error)

MPDist computes the matrix profile distance measure between a and b with a subsequence window of m.

Types

type Algo

type Algo string
const (
	AlgoSTOMP Algo = "stomp"
	AlgoSTAMP Algo = "stamp"
	AlgoSTMP  Algo = "stmp"
	AlgoMPX   Algo = "mpx"
)

type AnalyzeOpts

type AnalyzeOpts struct {
	OutputFilename string // relative or absolute filepath for the visualization output
	// contains filtered or unexported fields
}

AnalyzeOpts contains all the parameters needed for basic features to discover from a matrix profile. This is currently limited to motif, discord, and segmentation discovery.

func NewAnalyzeOpts

func NewAnalyzeOpts() *AnalyzeOpts

NewAnalyzeOpts creates a default set of parameters to analyze the matrix profile.

type KMP

type KMP struct {
	T [][]float64 // a set of timeseries where the number of row represents the number of dimensions and each row is a separate time series

	W   int         // length of a subsequence
	MP  [][]float64 // matrix profile
	Idx [][]int     // matrix profile index
	// contains filtered or unexported fields
}

KMP is a struct that tracks the current k-dimensional matrix profile computation for a given slice of timeseries of length N and subsequence length of M. The profile and the profile index are stored here.

func NewKMP

func NewKMP(t [][]float64, w int) (*KMP, error)

NewKMP creates a matrix profile struct specifically to be used with the k dimensional matrix profile computation. The number of rows represents the number of dimensions, and each row holds a series of points of equal length as each other.

func (KMP) Analyze

func (k KMP) Analyze(mo *MPOpts, ao *AnalyzeOpts) error

Analyze has not been implemented yet

func (*KMP) Compute

func (k *KMP) Compute() error

Compute runs a k dimensional matrix profile calculation across all time series

func (KMP) DiscoverDiscords

func (k KMP) DiscoverDiscords(kDiscords int, exclusionZone int) ([]int, error)

DiscoverDiscords has not been implemented yet

func (KMP) DiscoverMotifs

func (k KMP) DiscoverMotifs(kMotifs int, r float64) ([]MotifGroup, error)

DiscoverMotifs has not been implemented yet

func (KMP) DiscoverSegments

func (k KMP) DiscoverSegments() (int, float64, []float64)

DiscoverSegments has not been implemented yet

func (*KMP) Load

func (k *KMP) Load(filepath, format string) error

Load will attempt to load a matrix profile from a file for iterative use

func (KMP) Save

func (k KMP) Save(filepath, format string) error

Save will save the current matrix profile struct to disk

func (KMP) Visualize

func (k KMP) Visualize(fn string) error

Visualize creates a png of the k-dimensional matrix profile.

type MPDistOpts

type MPDistOpts struct {
	AV   av.AV
	Opts *MPOpts
}

func NewMPDistOpts

func NewMPDistOpts() *MPDistOpts

type MPOpts

type MPOpts struct {
	Algorithm    Algo    `json:"algorithm"`  // choose which algorithm to compute the matrix profile
	SamplePct    float64 `json:"sample_pct"` // only applicable to algorithm STAMP
	NJobs        int     `json:"n_jobs"`
	Euclidean    bool    `json:"euclidean"`                  // defaults to using euclidean distance instead of pearson correlation for matrix profile
	RemapNegCorr bool    `json:"remap_negative_correlation"` // defaults to no remapping. This is used so that highly negatively correlated sequences will show a low distance as well.
}

MPOpts are parameters to vary the algorithm to compute the matrix profile.

func NewMPOpts

func NewMPOpts() *MPOpts

NewMPOpts returns a default MPOpts

type MatrixProfile

type MatrixProfile struct {
	A        []float64    `json:"a"`                 // query time series
	B        []float64    `json:"b"`                 // timeseries to perform full join with
	AMean    []float64    `json:"a_mean"`            // sliding mean of a with a window of m each
	AStd     []float64    `json:"a_std"`             // sliding standard deviation of a with a window of m each
	BMean    []float64    `json:"b_mean"`            // sliding mean of b with a window of m each
	BStd     []float64    `json:"b_std"`             // sliding standard deviation of b with a window of m each
	BF       []complex128 `json:"b_fft"`             // holds an existing calculation of the FFT of b timeseries
	N        int          `json:"n"`                 // length of the timeseries
	W        int          `json:"w"`                 // length of a subsequence
	SelfJoin bool         `json:"self_join"`         // indicates whether a self join is performed with an exclusion zone
	MP       []float64    `json:"mp"`                // matrix profile
	Idx      []int        `json:"pi"`                // matrix profile index
	MPB      []float64    `json:"mp_ba"`             // matrix profile for the BA join
	IdxB     []int        `json:"pi_ba"`             // matrix profile index for the BA join
	AV       av.AV        `json:"annotation_vector"` // type of annotation vector which defaults to all ones
	Opts     *MPOpts      `json:"options"`           // options used for the computation
	Motifs   []MotifGroup
	Discords []int
}

MatrixProfile is a struct that tracks the current matrix profile computation for a given timeseries of length N and subsequence length of W. The profile and the profile index are stored here.

func New

func New(a, b []float64, w int) (*MatrixProfile, error)

New creates a matrix profile struct with a given timeseries length n and subsequence length of m. The first slice, a, is used as the initial timeseries to join with the second, b. If b is nil, then the matrix profile assumes a self join on the first timeseries.

func (MatrixProfile) Analyze

func (mp MatrixProfile) Analyze(mo *MPOpts, ao *AnalyzeOpts) error

Analyze performs the matrix profile computation and discovers various features from the profile such as motifs, discords, and segmentation. The results are visualized and saved into an output file.

func (MatrixProfile) ApplyAV

func (mp MatrixProfile) ApplyAV() ([]float64, []float64, error)

ApplyAV applies an annotation vector to the current matrix profile. Annotation vector values must be between 0 and 1.

func (*MatrixProfile) Compute

func (mp *MatrixProfile) Compute(o *MPOpts) error

Compute calculate the matrixprofile given a set of input options.

func (*MatrixProfile) DiscoverDiscords

func (mp *MatrixProfile) DiscoverDiscords(k int, exclusionZone int) ([]int, error)

DiscoverDiscords finds the top k time series discords starting indexes from a computed matrix profile. Each discovery of a discord will apply an exclusion zone around the found index so that new discords can be discovered.

func (*MatrixProfile) DiscoverMotifs

func (mp *MatrixProfile) DiscoverMotifs(k int, radius float64, neighborCount, exclusionZone int) ([]MotifGroup, error)

DiscoverMotifs will iteratively go through the matrix profile to find the top k motifs with a given radius. Only applies to self joins.

Example
// generate a signal mainly composed of sine waves and switches
// frequencies, amplitude, and offset midway through

// amplitude of 1, frequency of 5Hz, sampling frequency of 100 Hz,
// time of 2 seconds
sin := siggen.Sin(1, 5, 0, 0, 100, 2)

// amplitude of 0.25, frequency of 10Hz, offset of 0.75, sampling
// frequency of 100 Hz, time of 1 second
sin2 := siggen.Sin(0.25, 10, 0, 0.75, 100, 1)
sig := siggen.Append(sin, sin2)

// create a new MatrixProfile struct using the signal and a
// subsequence length of 32. The second subsequence is set to nil
// so we perform a self join.
mp, err := New(sig, nil, 32)
if err != nil {
	panic(err)
}

// run the STMP algorithm with self join. The matrix profile
// will be stored in mp.MP and the matrix profile index will
// be stored in mp.Idx
o := NewMPOpts()
o.Algorithm = AlgoSTMP

if err = mp.Compute(o); err != nil {
	panic(err)
}

// finds the top 3 motifs in the signal. Motif groups include
// all subsequences that are within 2 times the distance of the
// original motif pair
motifs, err := mp.DiscoverMotifs(2, 2, 10, mp.W/2)
if err != nil {
	panic(err)
}

for i, mg := range motifs {
	fmt.Printf("Motif Group %d\n", i)
	fmt.Printf("  %d motifs\n", len(mg.Idx))
}
Output:

Motif Group 0
  2 motifs
Motif Group 1
  2 motifs

func (MatrixProfile) DiscoverSegments

func (mp MatrixProfile) DiscoverSegments() (int, float64, []float64)

DiscoverSegments finds the the index where there may be a potential timeseries change. Returns the index of the potential change, value of the corrected arc curve score and the histogram of all the crossings for each index in the matrix profile index. This approach is based on the UCR paper on segmentation of timeseries using matrix profiles which can be found https://www.cs.ucr.edu/%7Eeamonn/Segmentation_ICDM.pdf

Example
// generate a signal mainly composed of sine waves and switches
// frequencies, amplitude, and offset midway through

// amplitude of 1, frequency of 5Hz, sampling frequency of 100 Hz,
// time of 2 seconds
sin := siggen.Sin(1, 5, 0, 0, 100, 2)

// amplitude of 0.25, frequency of 10Hz, offset of 0.75, sampling
// frequency of 100 Hz, time of 1 second
sin2 := siggen.Sin(0.25, 10, 0, 0.75, 100, 1)
sig := siggen.Append(sin, sin2)

// noise with an amplitude of 0.1
noise := siggen.Noise(0.01, len(sig))
sig = siggen.Add(sig, noise)

// create a new MatrixProfile struct using the signal and a
// subsequence length of 32. The second subsequence is set to nil
// so we perform a self join.
mp, err := New(sig, nil, 32)
if err != nil {
	panic(err)
}

// run the STMP algorithm with self join. The matrix profile
// will be stored in mp.MP and the matrix profile index will
// be stored in mp.Idx
o := NewMPOpts()
o.Algorithm = AlgoSTMP

if err = mp.Compute(o); err != nil {
	panic(err)
}

// segment the timeseries using the number of arc crossings over
// each index in the matrix profile index
idx, cac, _ := mp.DiscoverSegments()
fmt.Printf("Signal change foud at index: %d\n", idx)
fmt.Printf("Corrected Arc Curve (CAC) value: %.3f\n", cac)
Output:

Signal change foud at index: 194
Corrected Arc Curve (CAC) value: 0.000

func (*MatrixProfile) Load

func (mp *MatrixProfile) Load(filepath, format string) error

Load will attempt to load a matrix profile from a file for iterative use

func (MatrixProfile) Save

func (mp MatrixProfile) Save(filepath, format string) error

Save will save the current matrix profile struct to disk

func (*MatrixProfile) Update

func (mp *MatrixProfile) Update(newValues []float64) error

Update updates a matrix profile and matrix profile index in place providing streaming like behavior.

func (MatrixProfile) Visualize

func (mp MatrixProfile) Visualize(fn string) error

Visualize creates a png of the matrix profile given a matrix profile.

type MotifGroup

type MotifGroup struct {
	Idx     []int
	MinDist float64
}

MotifGroup stores a list of indices representing a similar motif along with the minimum distance that this set of motif composes of.

type PMP

type PMP struct {
	A        []float64   `json:"a"`         // query time series
	B        []float64   `json:"b"`         // timeseries to perform full join with
	SelfJoin bool        `json:"self_join"` // indicates whether a self join is performed with an exclusion zone
	PMP      [][]float64 `json:"pmp"`       // pan matrix profile
	PIdx     [][]int     `json:"ppi"`       // pan matrix profile index
	PWindows []int       `json:"windows"`   // pan matrix windows used and is aligned with PMP and PIdx
	Opts     *PMPOpts    `json:"options"`   // options used for the computation
}

PMP represents the pan matrix profile

func NewPMP

func NewPMP(a, b []float64) (*PMP, error)

NewPMP creates a new Pan matrix profile

func (PMP) Analyze

func (p PMP) Analyze(co *MPOpts, ao *AnalyzeOpts) error

Analyze has not been implemented yet

func (*PMP) Compute

func (p *PMP) Compute(o *PMPOpts) error

Compute calculate the pan matrixprofile given a set of input options.

func (PMP) DiscoverDiscords

func (p PMP) DiscoverDiscords(k int, exclusionZone int) ([]int, error)

DiscoverDiscords has not been implemented yet

func (PMP) DiscoverMotifs

func (p PMP) DiscoverMotifs(k int, r float64) ([]MotifGroup, error)

DiscoverMotifs has not been implemented yet

func (PMP) DiscoverSegments

func (p PMP) DiscoverSegments() (int, float64, []float64)

DiscoverSegments has not been implemented yet

func (*PMP) Load

func (p *PMP) Load(filepath, format string) error

Load will attempt to load a matrix profile from a file for iterative use

func (PMP) Save

func (p PMP) Save(filepath, format string) error

Save will save the current matrix profile struct to disk

func (PMP) Visualize

func (p PMP) Visualize(fn string, motifs []MotifGroup, discords []int, cac []float64) error

Visualize has not been implemented yet

type PMPOpts

type PMPOpts struct {
	LowerM int     `json:"lower_m"` // used for pan matrix profile
	UpperM int     `json:"upper_m"` // used for pan matrix profile
	MPOpts *MPOpts `json:"mp_options"`
}

PMPOpts are parameters to vary the algorithm to compute the pan matrix profile.

func NewPMPOpts

func NewPMPOpts(l, u int) *PMPOpts

NewPMPOpts returns a default PMPOpts

Directories

Path Synopsis
Package av generates a set of annotation vectors that can be applied onto a matrix profile before computing other features such as motifs, discords, etc.
Package av generates a set of annotation vectors that can be applied onto a matrix profile before computing other features such as motifs, discords, etc.
Package siggen provides basic timeseries generation wrappers
Package siggen provides basic timeseries generation wrappers
Package util is a set of utility functions that are used throughout the matrixprofile package.
Package util is a set of utility functions that are used throughout the matrixprofile package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL