bayes

package module
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Mar 10, 2024 License: MIT Imports: 6 Imported by: 0

README

Go Version Go Reference

go-bayes

github.com/KEINOS/go-bayes is a Go package for Bayesian inference.

Usage

# Download the module
go get github.com/KEINOS/go-bayes
// Import the package
import "github.com/KEINOS/go-bayes"
package main

import (
	"fmt"
	"log"

	"github.com/KEINOS/go-bayes"
)

func Example() {
    // "Happy Birthday", the train data. The types of slices available for the
    // training are as follows:
    //   bool, int, int16-int64, uint, uint16-uint64, float32, float64, string.
    score := []string{
        "So", "So", "La", "So", "Do", "Si",
        "So", "So", "La", "So", "Re", "Do",
        "So", "So", "So", "Mi", "Do", "Si", "La",
        "Fa", "Fa", "Mi", "Do", "Re", "Do",
    }

    // Reset the trained model
    bayes.Reset()

    // Train
    if err := bayes.Train(score); err != nil {
        log.Fatal(err)
    }

    // Predict the next note from the introduction notes
    for _, intro := range [][]string{
        {"So", "So", "La", "So", "Do", "Si"},             // --> So
        {"So", "So", "La", "So", "Do", "Si", "So", "So"}, // --> La
        {"So", "So", "La"},                               // --> So
        {"So", "So", "So"},                               // --> Mi
    } {
        nextNoteID, err := bayes.Predict(intro)
        if err != nil {
            log.Fatal(err)
        }

        // Print the predicted next note
        nextNoteString := bayes.GetClass(nextNoteID)

        fmt.Printf("Next is: %v (Class ID: %v)\n", nextNoteString, nextNoteID)
    }

    // Output:
    // Next is: So (Class ID: 10062876669317908741)
    // Next is: La (Class ID: 17627200281938459623)
    // Next is: So (Class ID: 10062876669317908741)
    // Next is: Mi (Class ID: 6586414841969023711)
}

Examples

Contribute

unit-test golangci-lint codecov CodeQL Go Report Card

  • Any PullRequest for improvement are welcome!
  • Branch to PR: main
    • Draft PR before full implementation is recommended.
  • We will merge any PR for the better, as long as it passes the CIs and not a prank-kind commit. ;-)

License


Wishlist/Todo

  • 100% code coverage for the current implementation
  • fix all golangci-lint issues for the current implementation
  • vulnerability scanning with CodeQL
  • feat CIs with GitHub Actions
  • feat benchmarking
  • feat dumping the trained model to a file
  • testdata with big sized data
  • SQLite3 as a storage backend (implementation of NodeLogger with SQLite3)
  • more examples of use cases
  • simple command tool to train and predict

Documentation

Overview

Example
// "Happy Birthday", the train data. The types of slices available for the
// training are as follows:
//   bool, int, int16-int64, uint, uint16-uint64, float32, float64, string.
score := []string{
	"So", "So", "La", "So", "Do", "Si",
	"So", "So", "La", "So", "Re", "Do",
	"So", "So", "So", "Mi", "Do", "Si", "La",
	"Fa", "Fa", "Mi", "Do", "Re", "Do",
}

// Reset the trained model
bayes.Reset()

// Train
if err := bayes.Train(score); err != nil {
	log.Fatal(err)
}

// Predict the next note from the introduction notes
for _, intro := range [][]string{
	{"So", "So", "La", "So", "Do", "Si"},             // --> So
	{"So", "So", "La", "So", "Do", "Si", "So", "So"}, // --> La
	{"So", "So", "La"},                               // --> So
	{"So", "So", "So"},                               // --> Mi
} {
	nextNoteID, err := bayes.Predict(intro)
	if err != nil {
		log.Fatal(err)
	}

	// Print the predicted next note
	nextNoteString := bayes.GetClass(nextNoteID)

	fmt.Printf("Next is: %v (Class ID: %v)\n", nextNoteString, nextNoteID)
}
Output:

Next is: So (Class ID: 10062876669317908741)
Next is: La (Class ID: 17627200281938459623)
Next is: So (Class ID: 10062876669317908741)
Next is: Mi (Class ID: 6586414841969023711)

Index

Examples

Constants

View Source
const (
	// StorageDefault is the default storage used by the predictor. Currently, it
	// is an in-memory log (logmem package).
	StorageDefault = MemoryStorage
	// ScopeIDDefault is the default scope ID on creating an instance of the
	// predictor.
	ScopeIDDefault = uint64(0)
)

Variables

This section is empty.

Functions

func GetClass

func GetClass(classID uint64) any

GetClass returns the original value of the given class ID.

func HashTrans

func HashTrans[T any](transitions ...T) (uint64, error)

HashTrans returns a unique hash from the input transitions. Note that the hash is not cryptographically secure.

Example
// list of transition IDs. If the order or the value of the list is changed,
// the hash will be changed.
for _, transitions := range [][]uint64{
	{10, 11, 12, 13, 14, 15},
	{10, 11, 12, 13, 15, 14},
	{1, 11, 12, 13, 14, 15},
	{1},
} {
	hashed, err := bayes.HashTrans(transitions...)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Dec: %020d\n", hashed)
	fmt.Printf("Hex: %016x\n", hashed)
}
Output:

Dec: 07573192273568316974
Hex: 6919623f91c5be2e
Dec: 07941539160827123980
Hex: 6e3603ca6af4590c
Dec: 16813156106886104905
Hex: e95454663822c749
Dec: 01877176418821510543
Hex: 1a0d1201d898958f

func Predict

func Predict[T any](items []T) (classID uint64, err error)

Predict returns the next class ID inferred from the given items.

To get the original value of the class, use `GetClass()`.

func Reset

func Reset()

Reset resets the train object.

func SetStorage

func SetStorage(storage Storage)

SetStorage sets the storage used by the predictor. This won't affect the predictors created via `New()`.

Do not forget to `Reset()` the predictor after changing the storage.

func Train

func Train[T any](items []T) error

Train trains the predictor with the given items.

Once the item appears in the training set, the item is added to the class list.

Example (Bool)
defer bayes.Reset()

// "Save Our Souls" Morse code.
// In this case, the class is 2. Such as true and false.
codes := []bool{
	true, true, true, // ... ==> S
	false, false, false, // ___ ==> O
	true, true, true, // ... ==> S
}

// Train
if err := bayes.Train(codes); err != nil {
	log.Panic(err) // panic to defer Reset()
}

// Quiz
quiz := []bool{
	true, true, true,
	false, false, false,
	true, true, // --> expect next to be true
}

// Predict the next code
nextCode, err := bayes.Predict(quiz)
if err != nil {
	log.Panic(err) // panic to defer Reset()
}

// Type assertion to bool since the type of the class is bool
classPredicted, ok := bayes.GetClass(nextCode).(bool)
if !ok {
	log.Panic("Failed to convert the class to bool") // panic to defer Reset()
}

classExpected := true
if classExpected == classPredicted {
	fmt.Println("OK")
}
Output:

OK
Example (Int)
defer bayes.Reset()

const (
	Do int = iota
	Re
	Mi
	Fa
	So
	La
	Si
)

// Happy Birthday
score := []int{
	So, So, La, So, Do, Si,
	So, So, La, So, Re, Do,
	So, So, So, Mi, Do, Si, La,
	Fa, Fa, Mi, Do, Re, Do,
}

// Train
if err := bayes.Train(score); err != nil {
	log.Panic(err) // panic to defer Reset()
}

// Convert int to string that represents the note
getNote := func(noteID int) string {
	switch noteID {
	case Do:
		return "Do"
	case Re:
		return "Re"
	case Mi:
		return "Mi"
	case Fa:
		return "Fa"
	case So:
		return "So"
	case La:
		return "La"
	case Si:
		return "Si"
	}

	return "Unknown"
}

// Predict the next note
for _, notes := range [][]int{
	{So, So, La, So, Do, Si},         // --> So
	{So, So, La, So, Do, Si, So, So}, // --> La
	{So, So, La},                     // --> So
	{So, So, So},                     // --> Mi
} {
	nextNote, err := bayes.Predict(notes)
	if err != nil {
		log.Panic(err) // panic to defer Reset()
	}

	// Print the next note
	noteID, ok := bayes.GetClass(nextNote).(int)
	if !ok {
		log.Panic("Invalid class type") // panic to defer Reset()
	}

	fmt.Printf("Class: %v (ID: %v)\n", getNote(noteID), nextNote)
}
Output:

Class: So (ID: 4)
Class: La (ID: 5)
Class: So (ID: 4)
Class: Mi (ID: 2)
Example (String)
defer bayes.Reset()

// Happy Birthday
score := []string{
	"So", "So", "La", "So", "Do", "Si",
	"So", "So", "La", "So", "Re", "Do",
	"So", "So", "So", "Mi", "Do", "Si", "La",
	"Fa", "Fa", "Mi", "Do", "Re", "Do",
}

// Train
if err := bayes.Train(score); err != nil {
	log.Panic(err) // panic to defer Reset()
}

// Predict the next note
for _, notes := range [][]string{
	{"So", "So", "La", "So", "Do", "Si"},             // --> So
	{"So", "So", "La", "So", "Do", "Si", "So", "So"}, // --> La
	{"So", "So", "La"},                               // --> So
	{"So", "So", "So"},                               // --> Mi
} {
	nextNote, err := bayes.Predict(notes)
	if err != nil {
		log.Panic(err) // panic to defer Reset()
	}

	// Print the next note
	nextNoteString := bayes.GetClass(nextNote)

	fmt.Printf("Class: %v (ID: %v)\n", nextNoteString, nextNote)
}
Output:

Class: So (ID: 10062876669317908741)
Class: La (ID: 17627200281938459623)
Class: So (ID: 10062876669317908741)
Class: Mi (ID: 6586414841969023711)

Types

type NodeLogger

type NodeLogger interface {
	// ID returns the ID of the logger.
	ID() uint64
	// Predict returns the probability of the next node to be toNodeB if the incoming
	// node is fromNodeA.
	Predict(fromNodeA, toNodeB uint64) float64
	// PriorPtoB returns the prior probability of the node to be B.
	// Which is the number of accesses to the node B divided by the total number
	// of accesses of current node.
	PriorPtoB(nodeB uint64) float64
	// PriorPfromAtoB returns the prior probability of the node to be B if the
	// previous node is A.
	PriorPfromAtoB(fromA, toB uint64) float64
	// PriorPNotFromAtoB returns the prior probability of the node not to be B
	// if the previous node is A.
	PriorPNotFromAtoB(fromA, toB uint64) float64
	// Update updates the records of a node. It must be called by the next node
	// accessed.
	Update(fromA, toB uint64)
}

NodeLogger is an interface to log the node's state. Here, node is something in between the predecessor and the successor.

Each uint64 argument of the method is a node ID. Consider node IDs to be equivalent to item IDs.

func New

func New(engine Storage, scopeID uint64) (NodeLogger, error)

New returns a new NodeLogger instance.

Use this function if you want to have more control over the NodeLogger instance rather than using the convenient functions.

Example
// Scope ID is used to distinguish the stored data.
scopeID := uint64(100)

// Create a new bayes instance with in-memory storage.
trainer, err := bayes.New(bayes.MemoryStorage, scopeID)
if err != nil {
	log.Fatal(err)
}

fmt.Println(trainer.ID())
Output:

100

type Storage

type Storage int

Storage is the type of storage to log the accesses.

const (
	// UnknwonStorage represents the unknown storage.
	UnknwonStorage Storage = iota
	// MemoryStorage represents the in-memory storage.
	MemoryStorage
	// SQLite3Storage represents the SQLite3 as a storage.
	SQLite3Storage
)

func (Storage) Type

func (s Storage) Type() string

Type returns the type name of the storage.

Example
fmt.Println(bayes.MemoryStorage.Type())
fmt.Println(bayes.SQLite3Storage.Type())
fmt.Println(bayes.UnknwonStorage.Type())
Output:

in-memory
SQLite3
unknown

Directories

Path Synopsis
pkg
nodelogger/logmem
Package logmem is an implementation of bayes.NodeLogger for memory-based logging.
Package logmem is an implementation of bayes.NodeLogger for memory-based logging.
theorem
Package theorem is an Bayes' theorem implementation.
Package theorem is an Bayes' theorem implementation.

Jump to

Keyboard shortcuts

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