(* File: learn.ml AIFAD - Automated Induction of Functions over Algebraic Datatypes Author: Markus Mottl email: markus.mottl@gmail.com WWW: http://www.ocaml.info Copyright (C) 2002 Austrian Research Institute for Artificial Intelligence Copyright (C) 2003- Markus Mottl This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) (* $Id: learn_nothreads.ml,v 1.9 2006/01/17 00:23:38 mottl Exp $ *) open Utils open Algdt_types open Algdt_utils open Model_utils open Info_utils open Complexity open Model_data open C45_io open Data_io open Typing open Cmd_args (* Learn random gain models *) let learn_many dfspec dvars cfspec cvars cinit_tps model rand_model = let calc_complexity model = calc_model_complexity dfspec dvars cfspec cinit_tps model in let c = calc_complexity model in let rec loop n model c = if n <= 0 then model, c else let new_model = rand_model dvars cvars in let new_c = calc_complexity new_model in if new_c <= c then loop (n - 1) new_model new_c else loop (n - 1) model c in let new_model, new_c = loop n_rand_gain model c in Printf.eprintf "Model complexity: %f\n" new_c; flush stderr; new_model (* Learn AIFAD-data *) let learn spec = let { ispec = dispec } as dispec_info, ({ ispec = cispec } as cispec_info) = do_open_in spec (fun sp_ic -> read_spec (Lexing.from_channel sp_ic)) in let dfspec, dinit_tps = flatten_ispec dispec in let cfspec, cinit_tps = flatten_ispec cispec in let dsamples, csamples = match maybe_data_name with | Some data_name -> do_open_in data_name (fun data_ic -> let data_lexbuf = Lexing.from_channel data_ic in read_samples data_lexbuf dispec_info dfspec cispec_info cfspec) | None -> let data_lexbuf = Lexing.from_channel stdin in read_samples data_lexbuf dispec_info dfspec cispec_info cfspec in let dvars = make_vars dfspec dinit_tps dsamples in let cvars = make_vars cfspec cinit_tps csamples in let module Spec = struct let (dfspec, cfspec) as fspecs = dfspec, cfspec let find_split, find_rand_split = if indep_entropy then if shallow_entropy then let module GainSpec = struct let dfspec, cfspec = fspecs include Is_entropy end in let module Gain = Gain_impl.Make (GainSpec) in Gain.choose_gain_ratio gain_c45 with_min_gr, Gain.rand_gain_ratio with_min_gr else let module GainSpec = struct let dfspec, cfspec = fspecs include Id_entropy end in let module Gain = Gain_impl.Make (GainSpec) in Gain.choose_gain_ratio gain_c45 with_min_gr, Gain.rand_gain_ratio with_min_gr else if shallow_entropy then let module GainSpec = struct let dfspec, cfspec = fspecs include Ds_entropy end in let module Gain = Gain_impl.Make (GainSpec) in Gain.choose_gain_ratio gain_c45 with_min_gr, Gain.rand_gain_ratio with_min_gr else let module GainSpec = struct let dfspec, cfspec = fspecs include Dd2_entropy end in let module Gain = Gain_impl.Make (GainSpec) in Gain.choose_gain_ratio gain_c45 with_min_gr, Gain.rand_gain_ratio with_min_gr let most_prob_csums = if indep_most_prob then Most_prob.indep_most_prob_sums cfspec else Most_prob.dep_most_prob_sums cfspec let split_null_branches = split_null_branches let factorize_models = if factorize then Factor.factorize_models else fun _ -> Factor.FactorNone end in let module Split = Split_impl.Make (Spec) in let model = Split.derive_model dvars cvars in let module RandSpec = struct include Spec let find_split = find_rand_split end in let module SplitRand = Split_impl.Make (RandSpec) in let model = learn_many dfspec dvars cfspec cvars cinit_tps model SplitRand.derive_model in let mdat = `Model (dispec_info, cispec_info, model) in maybe_save_mdat mdat maybe_model_name; if print_hmod then print_model "" "`" dispec_info cispec_info model (* Learn C4.5-data *) let learn_c45 spec = let c45_spec = read_c45_spec spec in let dispec_info, dvars, cispec_info, cvars = match maybe_data_name with | Some data_name -> do_open_in data_name (read_c45_data c45_spec mv) | None -> read_c45_data c45_spec mv stdin in let dfspec, _ = if Array.fold_left coll_n_cnstrs 0 dispec_info.cnstr_tbl = 0 then empty_fspec, [||] else flatten_ispec dispec_info.ispec in let cfspec, cinit_tps = flatten_ispec cispec_info.ispec in let module Spec = struct let (dfspec, cfspec) as fspecs = dfspec, cfspec let find_split, find_rand_split = if shallow_entropy then let module GainSpec = struct let dfspec, cfspec = fspecs include Is_entropy end in let module Gain = Gain_impl.Make (GainSpec) in Gain.choose_gain_ratio gain_c45 with_min_gr, Gain.rand_gain_ratio with_min_gr else let module GainSpec = struct let dfspec, cfspec = fspecs include Id_entropy end in let module Gain = Gain_impl.Make (GainSpec) in Gain.choose_gain_ratio gain_c45 with_min_gr, Gain.rand_gain_ratio with_min_gr let most_prob_csums = Most_prob.indep_most_prob_sums cfspec let split_null_branches = split_null_branches let factorize_models = if factorize then Factor.factorize_models else fun _ -> Factor.FactorNone end in let module Split = Split_impl.Make (Spec) in let model = Split.derive_model dvars cvars in let module RandSpec = struct include Spec let find_split = find_rand_split end in let module SplitRand = Split_impl.Make (RandSpec) in let model = learn_many dfspec dvars cfspec cvars cinit_tps model SplitRand.derive_model in let mdat = `C45Model (c45_spec, dispec_info, cispec_info, mv, model) in maybe_save_mdat mdat maybe_model_name; if print_hmod then print_model "t__" "`V" dispec_info cispec_info model