精华内容
下载资源
问答
  • 2017-03-23 11:43:40
    引言

     

      最近LZ带头在做一个互联网项目,互联网的东西总是那么新鲜,这也难怪大部分猿友都喜欢互联网。这个互联网项目不仅让LZ开发了一个HBase大数据应用,近期的一次需求讨论会上,又出来一个小需求,蛮有意思的。这些需求在之前枯燥的企业内部应用开发中,还是很难见到的,毕竟内部应用更多的是业务流程的体现。

      具体的需求这里不方便透露,但简单的描述一下需求,就是如何判断两个公司名是一个。这其实就是Java当中字符串的相等判断,最简单的当然是用equals来判断。但是由于实际情况是,公司名是由客户手动输出的,难免有小小的偏差,因此equals自然就不适用了。比如“博客园科技发展有限公司”和“博客园科技发展(北京)有限公司”,这两个显然应该是一个公司,但是如果用equals,自然结果会是false。

      

    方案提出

     

      会议上,LZ简单提出了一个解决方案,就是利用分词来计算两者的匹配度,如果匹配度达到一定数值,我们就认为两个字符串是相等的。不过不论算法如何高明,准确率都不可能达到100%,这点也是LZ一再给业务同事强调的,否则到时候匹配错了,他们找LZ的茬可咋办。不过好在业务同事只是希望有一个提示功能,并不做严格的判断标准,所以系统需要做的只是初步的判断,因此准确率要求并不是特别的高,只能说越高越好。

      由于这个项目是LZ以PM介入开发的,而且LZ一直都兼任SM,所以技术方案自然是LZ说了算了。没有讨论,没有异议,方案就这么在会议上定了。

     

    小研究

     

      由于LZ最近负责的事情比较多,所以上班的时候自然是没有时间研究这些东西,只能趁着周末小小研究一下。其实LZ对于分词并不是特别了解,这些东西与算法的关联度比较高,而LZ的算法基础只能说“呵呵”。不过不管怎样,作为一个项目的领头人,总得向前冲。如果到时候算法的时间、空间成本太高,或者准确率太低,等着后续寻找大神优化也不晚。

      这件事的思路比较清晰,LZ需要做的就是两件事,第一件事就是“分词”,第二件事就是“匹配”。

     

    分词

     

      分词是比较简单的一步,有很多现成的类库可以使用,只要选择一个使用就可以了。Lucene是LZ第一个想到的,毕竟LZ也算是Apache的脑残粉,因此话不多说,第一时间就下载Lucene,开始了探究之旅。

      以下是LZ在网络上找到的示例,稍微进行了一点修改。

    package com.creditease.borrow.lucene;
    
    import java.io.IOException;
    
    import org.apache.lucene.analysis.TokenStream;
    import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
    import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
    import org.apache.lucene.util.Version;
    
    public class App 
    {
        public static void main( String[] args ) throws IOException
        {
            String text = "博客园科技发展(北京)有限公司";
            SmartChineseAnalyzer smartChineseAnalyzer = new SmartChineseAnalyzer(Version.LUCENE_47);
            TokenStream tokenStream = smartChineseAnalyzer.tokenStream("field", text);
            CharTermAttribute charTermAttribute = tokenStream.getAttribute(CharTermAttribute.class);
            tokenStream.reset();
            while (tokenStream.incrementToken()) {
                System.out.print(charTermAttribute.toString() + "  ");
            }
            tokenStream.end();
            tokenStream.close();
            smartChineseAnalyzer.close();
        }
        
    }

      输出结果为以下内容。

    博  客  园  科技  发展  北京  有限公司  

      这种分词结果勉强可以接受了,最理想的应该是将“博客”放在一起,不过看来Lucene的字典里没有这个词。没关系,这对我们的计划并不影响,我们接下来开始着手匹配的事。

     

    匹配

     

      有了分词,我们要做的,就是匹配两个字符串数组,并得到一个匹配度。既然是匹配度,那么肯定就有分母和分子。我们可以挑其中一个数组的长度为分母,以另外一个数组中的元素找到匹配分词的个数作为分子。为了减少程序的复杂度,我们采用Set集合的去重特点来进行计算。就像以下程序这样。

    package com.creditease.borrow.lucene;
    
    import java.io.IOException;
    import java.util.HashSet;
    import java.util.Set;
    
    import org.apache.lucene.analysis.TokenStream;
    import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
    import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
    import org.apache.lucene.util.Version;
    
    public class App 
    {
        
        private static SmartChineseAnalyzer smartChineseAnalyzer = new SmartChineseAnalyzer(Version.LUCENE_47);
        
        public static void main( String[] args ) throws IOException
        {
            String text1 = "博客园科技发展(北京)有限公司";
            String text2 = "博客园科技发展有限公司";
            System.out.println(oneWayMatch(text1, text2));
        }
        
        public static double oneWayMatch(String text1,String text2) {
            try {
                Set<String> set = new HashSet<String>(10);
                TokenStream tokenStream = smartChineseAnalyzer.tokenStream("field", text1);
                CharTermAttribute charTermAttribute = tokenStream.getAttribute(CharTermAttribute.class);
                tokenStream.reset();
                while (tokenStream.incrementToken()) {
                    set.add(charTermAttribute.toString());
                }
                int denominator = set.size();
                tokenStream.end();
                tokenStream.close();
                tokenStream = smartChineseAnalyzer.tokenStream("field", text2);
                charTermAttribute = tokenStream.getAttribute(CharTermAttribute.class);
                tokenStream.reset();
                while (tokenStream.incrementToken()) {
                    set.add(charTermAttribute.toString());
                }
                int numerator = set.size() - denominator;
                double unmatchRate = ((double)numerator)/denominator;
                tokenStream.end();
                tokenStream.close();
                return unmatchRate;
            } catch (IOException e) {
                return 1D;
            }
            
        }
        
    }

      输出的结果为0,也就是说匹配度为100%。这显然是不对的,两个字符串很明显不是一模一样,得到匹配度为100%说明我们的算法还是有问题。

      仔细分析一下,问题就出在我们是拿text2中不匹配的分词作为分子,而text2中的分词在text1中全部都包含,因此分子最终会是0,那么不匹配度自然就是0(unmatchRate)。为了弥补这一缺陷,LZ想来想去最终还是决定采取“双向”(twoWay)的办法解决这个问题,可以看到LZ给上面那个方法取的名字为“单向”匹配(oneWay)。

      双向匹配其实就是将两者顺序颠倒,再进行一次匹配而已,因此我们的程序可以简单的更改为以下形式。

    package com.creditease.borrow.lucene;
    
    import java.io.IOException;
    import java.util.HashSet;
    import java.util.Set;
    
    import org.apache.lucene.analysis.TokenStream;
    import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
    import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
    import org.apache.lucene.util.Version;
    
    public class App 
    {
        
        private static SmartChineseAnalyzer smartChineseAnalyzer = new SmartChineseAnalyzer(Version.LUCENE_47);
        
        public static void main( String[] args ) throws IOException
        {
            String text1 = "博客园科技发展(北京)有限公司";
            String text2 = "博客园科技发展有限公司";
            System.out.println(twoWayMatch(text1, text2));
        }
        
        public static double twoWayMatch(String text1,String text2) {
            return (oneWayMatch(text1, text2) + oneWayMatch(text2, text1));
        }
        
        public static double oneWayMatch(String text1,String text2) {
            try {
                Set<String> set = new HashSet<String>(10);
                TokenStream tokenStream = smartChineseAnalyzer.tokenStream("field", text1);
                CharTermAttribute charTermAttribute = tokenStream.getAttribute(CharTermAttribute.class);
                tokenStream.reset();
                while (tokenStream.incrementToken()) {
                    set.add(charTermAttribute.toString());
                }
                int denominator = set.size();
                tokenStream.end();
                tokenStream.close();
                tokenStream = smartChineseAnalyzer.tokenStream("field", text2);
                charTermAttribute = tokenStream.getAttribute(CharTermAttribute.class);
                tokenStream.reset();
                while (tokenStream.incrementToken()) {
                    set.add(charTermAttribute.toString());
                }
                int numerator = set.size() - denominator;
                double unmatchRate = ((double)numerator)/denominator;
                tokenStream.end();
                tokenStream.close();
                return unmatchRate;
            } catch (IOException e) {
                return 1D;
            }
            
        }
        
    }

      该程序的输出结果为0.1666666666...,也就是0.17,也就是说两者的匹配度为83%。这个值显然更加接近实际的情况。可以看到,双向匹配以单向匹配为基础,将顺序颠倒的结果相加,就能得到不匹配度。

      事情原本到此就可以结束了,但是还有一个更大的难点没有处理。那就是匹配度到底设置为多少合适。这个问题到目前为止,LZ还没有更好的办法。按照上面的小例子来讲,自然是设为80%就可以。

      但是看下下面这个例子,就会发现这个数值很不正确,或者说匹配算法还是有问题。

    public static void main( String[] args ) throws IOException
        {
            String text1 = "博客园科技发展(北京)有限公司";
            String text2 = "博客园有限公司";
            System.out.println(twoWayMatch(text1, text2));
        }

      运行的结果为0.75,也就是说匹配度大约只有25%。但是很明显,上面两个公司实际上匹配度是很高的,因为最重要的三个字是匹配的。

      再仔细分析一下,问题就变成权重了。也就是说,每个词的权重应该是不一样的,这样的话,匹配的准确度可能会更高一点。我们稍微改善一下程序。(以下统一使用后面加双斜线的方式表示程序主要改变的地方)

    package com.creditease.borrow.lucene;
    
    import java.io.IOException;
    import java.util.Arrays;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    import org.apache.lucene.analysis.TokenStream;
    import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
    import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
    import org.apache.lucene.util.Version;
    
    public class App 
    {
        
        private static SmartChineseAnalyzer smartChineseAnalyzer = new SmartChineseAnalyzer(Version.LUCENE_47);
        
        private static List<String> smallWeightWords = Arrays.asList("公司","有限公司","科技","发展","股份");
        
        private static double smallWeight = 0.3D;
        
        public static void main( String[] args ) throws IOException
        {
            String text1 = "博客园科技发展(北京)有限公司";
            String text2 = "博客园有限公司";
            System.out.println(twoWayMatch(text1, text2));
        }
        
        public static double twoWayMatch(String text1,String text2) {
            return (oneWayMatch(text1, text2) + oneWayMatch(text2, text1));
        }
        
        public static double oneWayMatch(String text1,String text2) {
            try {
                Set<String> set = new HashSet<String>(10);
                TokenStream tokenStream = smartChineseAnalyzer.tokenStream("field", text1);
                CharTermAttribute charTermAttribute = tokenStream.getAttribute(CharTermAttribute.class);
                tokenStream.reset();
                while (tokenStream.incrementToken()) {
                    set.add(charTermAttribute.toString());
                }
                int denominator = set.size();
                tokenStream.end();
                tokenStream.close();
                tokenStream = smartChineseAnalyzer.tokenStream("field", text2);
                charTermAttribute = tokenStream.getAttribute(CharTermAttribute.class);
                tokenStream.reset();
                int smallWeightWordsCount = 0;//
                while (tokenStream.incrementToken()) {
                    String word = charTermAttribute.toString();//
                    int tempSize = set.size();//
                    set.add(word);//
                    if (tempSize + 1 == set.size() && smallWeightWords.contains(word)) {//
                        smallWeightWordsCount++;//
                    }//
                }
                int numerator = set.size() - denominator;
                double unmatchRate = (smallWeightWordsCount * smallWeight + numerator - ((double)smallWeightWordsCount))/denominator;//
                tokenStream.end();
                tokenStream.close();
                return unmatchRate;
            } catch (IOException e) {
                return 1D;
            }
            
        }
        
    }

      现在程序的输出结果为0.4,匹配度为60%。从结果来看,依然有点不尽人意。仔细分析一下程序,会发现,我们计算不匹配度的时候,是交叉计算的。也就是说,我们使用一个数组中不匹配的数目去除以另外一个数组的大小,这可能会造成“极端”数值。

      我们需要调整程序,让数组自己与自己计算,这样就不会出现那种情况。如下。

    package com.creditease.borrow.lucene;
    
    import java.io.IOException;
    import java.util.Arrays;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    import org.apache.lucene.analysis.TokenStream;
    import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
    import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
    import org.apache.lucene.util.Version;
    
    public class App 
    {
        
        private static SmartChineseAnalyzer smartChineseAnalyzer = new SmartChineseAnalyzer(Version.LUCENE_47);
        
        private static List<String> smallWeightWords = Arrays.asList("公司","有限公司","科技","发展","股份");
        
        private static double smallWeight = 0.3D;
        
        public static void main( String[] args ) throws IOException
        {
            String text1 = "博客园科技发展(北京)有限公司";
            String text2 = "博客园有限公司";
            System.out.println(twoWayMatch(text1, text2));
        }
        
        public static double twoWayMatch(String text1,String text2) {
            return (oneWayMatch(text1, text2) + oneWayMatch(text2, text1));
        }
        
        public static double oneWayMatch(String text1,String text2) {
            try {
                Set<String> set = new HashSet<String>(10);
                TokenStream tokenStream = smartChineseAnalyzer.tokenStream("field", text1);
                CharTermAttribute charTermAttribute = tokenStream.getAttribute(CharTermAttribute.class);
                tokenStream.reset();
                while (tokenStream.incrementToken()) {
                    set.add(charTermAttribute.toString());
                }
                int originalCount = set.size();//
                tokenStream.end();
                tokenStream.close();
                tokenStream = smartChineseAnalyzer.tokenStream("field", text2);
                charTermAttribute = tokenStream.getAttribute(CharTermAttribute.class);
                tokenStream.reset();
                int smallWeightWordsCount = 0;
                int denominator = 0;//
                while (tokenStream.incrementToken()) {
                    denominator++;//
                    String word = charTermAttribute.toString();
                    int tempSize = set.size();
                    set.add(word);
                    if (tempSize + 1 == set.size() && smallWeightWords.contains(word)) {
                        smallWeightWordsCount++;
                    }
                }
                int numerator = set.size() - originalCount;
                double unmatchRate = (smallWeightWordsCount * smallWeight + numerator - ((double)smallWeightWordsCount))/denominator;//
                tokenStream.end();
                tokenStream.close();
                return unmatchRate;
            } catch (IOException e) {
                return 1D;
            }
            
        }
        
    }

      程序的输出结果为0.2285714285714286,也就是匹配度大约为77%,这个数值还是比较科学的。这次我们主要调整了分母,将分母调整为不匹配元素自己的数组大小。

      现在我们需要做的就很简单了,就是把有可能改变的地方都在程序当中做成可配置的,比如从数据库读取。需要做成可配置项的内容有以下几个。

      1、低权重的词语,也就是smallWeightWords。

      2、低权重的数值,也就是smallWeight。

      3、匹配度的最小值,也就是说匹配度大于等于多少的时候,我们就认为是一个公司。

      具体如何做成可配置项,这里LZ就不再赘述了,真实的web项目当中有无数种办法可以达到这个目的,最常用的当然是存储到数据库。但第一项更适合放入数据库,后面两项更适合存放在配置文件当中。无论放在哪里,这些配置都要支持动态刷新,这样应用在运行的时候就可以动态调整判断规则了。

      

    小结

     

      LZ的算法不一定是最好的,或者说一定不是最好的。但是有时候慢慢解决一个问题,让答案逐渐靠近自己的判断也是一种乐趣不是吗?

    更多相关内容
  • 参考资料-PS.01.03 ×× U9 ERP项目-客户需求匹配度分析.zip
  • 客户订单与需求管理

    千次阅读 2022-02-18 17:52:49
    对企业的订单交付和卓越运营而言,做准、做好市场需求和销售预测是关键的一步,但还远远不够,企业还需要进一步考虑如何应用销售预测来指导供应链活动,以更好地满足客户需求。 我们知道,企业要想实现客户满意和...

    对企业的订单交付和卓越运营而言,做准、做好市场需求和销售预测是关键的一步,但还远远不够,企业还需要进一步考虑如何应用销售预测来指导供应链活动,以更好地满足客户需求。

    我们知道,企业要想实现客户满意和生产、供应的经济性,必须做好供应与需求之间的精确匹配。在实际执行中,客户需求与供应活动往往存在多种矛盾:

    • 时间上的矛盾。客户提交订单以后总是希望能够马上拿到自己所订购的产品(客户所期望的订单交货周期最好为“0”),而企业组织零部件的采购、产品的生产和供应往往需要一定的时间,有时短则一两天,长则数周,乃至数月。

    • 批量上的矛盾。客户的订购批量一般不大,有时的订购数量是“1”个,而企业按照单个产品来组织生产就很难有经济性可言,通常会按一定的经济批量来组织生产。

    • 位置上的矛盾。客户所处的位置往往是全国各地,乃至全球的各个角落,而企业的生产工厂和配送中心通常是集中在某几个区域。

    为了平衡上述矛盾,显然,企业的供应活动不可能等收到客户订单后才进行,而客户的供应活动包括工程设计、原材料或外协采购、零件加工、半成品生产、成品装配、成品发运、区域配送中心缓存等多种形式,供应活动开始得太早或太晚都会有问题,而哪些供应活动,在什么的时间点开始,这就牵涉到供应链活动解耦点的选择。

    1 解耦点选择

    所谓解耦点,指的是供应链中,以销售预测来驱动的供应链活动和以客户订单来驱动的供应链活动之间的临界点。换句话说,在解耦点以前,所有的供应链活动都是由销售预测来驱动的,这也是销售预测的业务价值所在,以销售预测来驱动供应链活动的触发机制又称为“推式(Push)”供应链组织;在解耦点以后,所有的供应链活动都是由客户订单来驱动的。正是因为有解耦点选择的不同,才有所谓的MTS、ATO/CTO、MTO、ETO等不同形式和内容的生产模型。
    在这里插入图片描述

    库存生产(MTS)

    如图1所示,在面向库存生产(MTS)的生产模式中,供应链解耦点在成品总装与分销发运之间。也就是说,在接到客户订单之前,工程设计、原材料或外协采购、零件加工、成品装配等供应链活动已经完成,其活动依据是企业的销售预测。在接到客户订单以后,企业才开始进行产品的分销发运等其他供应链活动。当然,在MTS的生产模式中,客户订单的交货周期通常是最短的,但如果销售预测的准确性比较低,就会发生物料呆滞和库存积压等现象。

    订单装配(ATO)

    在面向订单装配(ATO)的生产模式中,供应链解耦点在半成品加工和成品总装之间。也就是说,在接到客户订单之前,工程设计、原材料或外协采购、零件加工的供应链活动已经完成了;一旦接到客户订单,企业就开始组织成品总装等后续供应链活动。至于面向订单配置(CTO),与ATO的差异之处主要体现在客户下单时,允许客户按自己的需求或偏好选择产品的相关配置或特性,前提是产品是可配置产品。

    订单生产(MTO)

    在面向订单生产(MTO)的生产模式中,供应链解耦点在原材料或外协采购与零件加工之间。也就是说,在接到客户订单之前,工程设计、原材料或外协采购是根据销售预测来组织并已完成,而零件加工、成品装配等后续供应链活动则是在接到客户订单后才开始。在MTO生产模式中,其订单交付周期通常要比MTS模式长得多,但发生半成品、成品呆滞和库存积压的可能也基本没有。

    订单工程(ETO)

    在面向订单工程(ETO)中,基本上,绝大部分供应链活动,包括工程设计、原材料或外协采购、零件加工、成品总装,等等,都是在接到客户订单以后才开始的。在ETO模式中,企业如果做市场需求和销售预测的话,预测数据也只是用于指导产品架构和平台的开发、工厂建设和生产能力的准备、员工招聘和培训,等等,产品的定型或改型设计都是要接到客户订单以后才开始。

    在ATO/CTO、MTO等生产模式中,以销售预测来指导部分供应链活动的组织和执行,显然还需要对销售预测的数据做适当的处理或转换。以ATO模式为例,销售预测的对象通常是成品,而ATO模式中原材料和外协采购、零件加工等供应链活动的工作对象是原材料或零部件。

    另外,理论上讲,销售预测的制订在客户订单的接收之前。但是,在企业的实际运营中,具体某个产品,销售预测的制订和客户订单的接收往往是同时进行,不同之处也主要是各自的展望期不同而已,销售预测的展望期有长期、中期和短期,而客户订单的交货周期往往较短,时间上会与短期的销售预测重叠。既然销售预测和客户订单所代表的都是客户需求,当所接收的客户订单与短期销售预测在时间上出现重叠时,它们之间应该要做时间和数量上的勾兑处理,然后再传递到供应环节去指导供应的展开。至于销售预测与客户订单如何勾兑,取决于企业的业务需求和计划管理。

    如上所述,不管是将成品的销售预测转换为原材料或零部件的生产计划输入,还是销售预测与客户订单之间勾兑逻辑的定义,都需要企业设计相应的流程和机制来进行,也就是所谓的需求管理。

    2 需求管理

    对企业而言,总是要寻求需求与供应的精准匹配和动态平衡,以保证既不能丢失任何市场机会,又不要让库存太高。为此,企业不仅要做准、做好市场需求和销售预测,还要考虑如何用销售预测去指导采购、生产、分销等供应活动,且尽量保证这些活动的最优。
    以ATO生产模式为例,企业的原材料或外协采购和零部件生产等活动是通过销售预测来驱动的。为了保证供应活动的规模化、均衡化,企业肯定会以经济批量或单件流的重复式生产来组织这些供应活动,这就有要求既不能供应过度,也不能供应不足。落实到实践中,一则是如何合理使用成品的销售预测数据,二则是销售预测与客户订单之间勾兑逻辑的定义。

    在这里插入图片描述

    如图2所示,供应点的解构点,既是销售预测驱动的供应链活动与客户订单驱动的供应链活动的衔接点,又是需求信息(包括销售预测与客户订单)向上游供应环节进行传递的临界点。

    从需求信息的内容来看,销售预测和客户订单都代表市场需求,销售预测的内容涵盖更更广、时间展望期更长,但信息可能失真,实际上做不到百分百的准确;客户订单的内容更特定、时间展望期更短,但信息却基本真实。从集合的角度来看,客户订单数据理论上应该是销售预测数据的子集,但因为销售预测的部分失真,客户订单数据与销售预测数据实际上可能是存在交集的两个不同数据集。

    在这里插入图片描述

    转自 数字化演易

    展开全文
  • 匹配需求化繁为简 智能投顾专题报告 0 摘要 智能投顾能够克服部分传统投顾的痛点我国财富管理行业和投顾业务的发展起步较晚但是近年来我国居民的理财需求 和风险意识发展迅速相比传统投顾智能投顾借助科技的手段具有...
  • 该方法从三个方面对集群协同制造服务匹配策略进行了深入研究,包括服务匹配策略的设计(只考虑服务资源QoS(quality of service)属性变化的服务匹配策略、只考虑客户需求变化的服务匹配策略、综合考虑服务资源QoS...
  • 优选 优选 优选 优选 优选 行业客户信息化需求分析 主讲人苏时伟昆山分公司 课时10:3012:30 Page* 课程目标 业信息化发展史讲述 加深行业信息化的理解与认知 1 如何进行客户需求分析寻找公司合适产品进行匹配 2 成功...
  • 在CMS开发中,经常会有类似这样的需求:  提问——回答模式,经典的例子是百度提问。  提问者提出问题,由其他人回答,其他人可以是用户,也可以是服务商。  在这个模式中,如何充分利用历史数据是关键的...
  • 了解客户业务流程,规划ERP系统业务流程; 了解客户管理控制点,规划ERP系统功能匹配点; 了解客户运营现状,规划ERP系统运行; 了解客户岗位现状,规划ERP系统岗位流程.
  • 项目需求.docx

    2019-08-28 14:01:37
    客户在文本输入框中输入企业名,在下拉菜单中选择需要查询的关系,即可在同一页面中显示出以该企业为中心节点的知识图谱,客户可以点击图谱中的节点,查看该节点的详细属性。企业属性表见表1,自然人属性表见表2。...
  • 有同学问:领导总让我们挖掘用户需求,咋个挖掘法?特别是手头还没什么数据,最多只有一个用户购货记录,感觉挖不出东西。今天系统解答一下。做用户需求挖掘上,有很多很流行的无解,今天也一并澄清。...

    有同学问:领导总让我们挖掘用户需求,咋个挖掘法?特别是手头还没什么数据,最多只有一个用户购货记录,感觉挖不出东西。今天系统解答一下。做用户需求挖掘上,有很多很流行的无解,今天也一并澄清。

      1   

    用户需求挖掘的错误做法

    这个段子很多人都听过:

    一个小哥来五金店买钉子

    买钉子是因为他想挂一幅画

    挂一幅画是因为他很孤单

    他很孤单因为他很想找女朋友

    所以他真正的需求是个女朋友

    应该给他介绍个女朋友

     

    故事很好听,可是却大错特错……从业务上看,一个五金店老板,如果不想着怎么卖金属器械,而是研究牵线搭桥的话,那小店离倒闭也就不远了。从数据上看,想不想找女朋友,估计连自己七姑八姨都懒得说,又怎么会轻易告诉陌生人(况且他还是个卖钢筋的)。

    这是个普遍的错误:误以为,用户需求挖掘,非得挖到别人不知道的八卦奇闻,才算有深度,非得满足很深层的需求,才算是真需求。

     

    实际上,只有极少数行业能如此深度地了解用户,能无限度地满足用户。比如金融行业,针对极高端客户的私人服务,或许能做到这一点(分行行长亲自开车送大客户儿子上学也不是啥新鲜事)。

    但,大部分企业业务范围有限,面对的是海量用户。因此,不能脱离业务实际,做太细腻深刻的挖掘。无论是业务上还是数据上,都做不到,也没有必要做到。

     

    所以,用户需求挖掘的本质,是从有限的数据里,筛选关键区分维度,提升用户响应概率。我们要做的,不是搞清楚每个用户的每个层次的需求。而是通过区分,提高用户响应概率,识别核心用户群体。让用户对我们的业务响应率,比闭着眼睛瞎做要高。每高出来一个百分点,都是数据分析师对企业的贡献。

      2   

    用户需求挖掘的五个步骤

    ▌ 第一步:区分核心用户

    还拿五金店老板举例。在精力有限的情况下,先抓住大客户才是关键,分类是很必要的。五金店的用户分类,可能是:

     

    第一等:物业维修部、装修队、工地(B2B类客户)

    第二等:装修、改水电、维修的客户(B2C类大客户)

    第三等:偶尔买一个灯泡、插座、钉子的散客(B2C类小客户)

     

    问题在于,当一个小哥进门,五金店老板并不知道他到底是哪一类。如果置之不理,可能损失掉一个大生意。但如果每个人都上来问一大堆问题,估计会把客人吓跑。这里就开始了第一步的用户需求挖掘,挖掘的问题很简单:“您想买点什么”。

    ▌ 第二步:对业务分类

    小哥回答:“我想要买钉子”——你联想到了什么?这个回答听起来很简单,可透露了很多信息。因为,每一类业务,可能有固定的商品组合和消费特点,比如对五金店而言:

     

    ● 工程类业务:大量的钢筋、各种物料(不会零散采购)

    ● 水类改造:水管、扳手,防水胶带

    ● 电类改造:电线、开关、插座

    ● 墙体维修:水泥、刷子、油漆

    ● 物件维修:钉子、锤子、钻机

     

    这叫:业务强相关性。即使不做关联分析,这些商品也是天生捆绑出现的。并且根据业务规模大小,有固定消费量。做好事先业务分类非常重要。当我们无法采集大量用户信息的时候,可以通过仅有的一点点购货记录,利用业务相关性去推断用户需求。

    比如这里老板听到小哥需要钉子,可以很快推断:不是B类用户,和维修有关。但是老板仍不知道,小哥到底是C类大客户还是散客,还需要第二步挖掘。问题也非常简单:“您买钉子做什么”。

    ▌ 第三步:抓关键信息

    小哥回答:“我想要买钉子,在墙上钉一副画”——听到这句,你是不是马上想到要说什么了!是滴,我们可以看到,做好用户分群和业务分类以后,再做需求挖掘的时候是非常容易的。

    基于前边的分类,读者们听到钉一幅画,也能立即反映出来:这是个散客,价值不高。钉子和锤子、钻机是高度关联的,有交叉销售机会。这里借助2个简单的问题,我们已经完成了抓关键信息。

    当然,实际业务中,传统企业靠销售、导购、业务员去抓关键信息,互联网企业靠埋点、推送/反映、问卷、浏览频次等抓关键信息。

    ▌ 第四步:推送商品/活动

    现在有了假设,我们可以尝试验证,推一个商品/活动试验下。这时候五金店老板就不会花大力气去问小哥是不是想谈恋爱,而是说:“你需要钉画的话,用1寸小钉子比3寸的大钉子好看,容易钉还不显眼。”这样就能锁定小哥的需求,比那些不理不睬的老板成功几率高。

    同时,还能做个交叉推荐:“你有锤子了吗?可以买个小钻机,比锤子省事,修其他东西也能用”如果推荐成功,就能成功地把客单价从1块钱提升到200块,也是小赚一笔。

    ▌ 第五步:验证推送效果

    有推送,就有成功和失败两种可能,因此需要验证效果。需求挖掘,本质上是个概率问题。需要通过数据验证我们推送,进而验证我们选择的挖掘维度和挖掘方向是否正确。对五金店老板而言,这里有两个维度要验证:

     

    1、钉墙推荐1寸钉子(假设:基于用户需求考虑,更容易成交)

    2、钉墙的男性推荐风钻(假设:男性喜欢机械,有机会成功)

     

    这实际上已经是个小型ABtest了。如果有一个数据可记录的话,老板会看到,这两个假设可能成立,也可能失败。

    比如做了200组,发现用户根本不考虑美观,都是什么便宜买什么,那以后的策略,就是散客来了直接丢最便宜的东西给他。

    当然,也有可能发现这个策略可行,10单能交叉卖出3单钻机。那以后就按这个策略走。到这里,我们的需求挖掘结束。我们找到了一个区分方向,验证了一个可提升成交的机会点,从用户买钉子挖出了钻机的需求。这么做,可比天天琢磨小哥到底有没有女朋友,是喜欢萝莉还是喜欢御姐要靠谱的多。

     

    虽然只是一个搞笑的例子。(实际上五金店老板才没这个耐心,五金店也没有数据可以记录)。但是它很形象得展示出了挖掘用户需求的工作流程:

    1、区分用户类型

    2、区分业务类型

    3、抓关键信息

    4、推送商品/活动

    5、验证推送效果

     

    这套方法论是可以推广到各个行业的,特别是数据记录较少的情况下。注意,这里先区分用户还是先区分业务,是有行业差异的。

    一般传统企业的业务类型比较固定,倾向于先区分业务。互联网企业业务比较灵活,甚至能无中生有创造新场景,往往倾向于先区分用户,甚至有可能针对一个用户不同场景做文章。

     

    但无论怎么做,区分用户与业务都是第一步预动作,也是最重要的一步。通过分类可以清晰后续挖掘的方向,明确挖掘深度,为验证挖掘是否有用提供标准。所以这一步下边会单独拿出来讲。很多同学做用户需求挖掘毫无头绪,都是因为缺少分类。而很多同学陷于Abtest,缺少整体判断,也是因为缺少分类。

      3   

    用户/业务区分的注意事项

    一提用户分类,很多文章都扯RFM,这是非常错误的。并非所有的业务都需要高频次消费,也不是所有业务都累积高金额,甚至有可能一个业务同时存在一次消费和高频消费。如果从频次和金额的角度来看,常见的业务可以归纳如下:

                             

    传统企业的业务相对聚焦,业务分类相对容易。

    比如房子,分置业、投资。置业再分首次、二次改善,养老。二次改善又有面积改善、环境改善、配套改善、资源改善等若干。

    家装、汽车、贷款等等业务都有类似归类法(文字太多,先不展开了)每一种对应的用户需求会很聚焦。因此传统企业的用户需求挖掘,没有那么依赖“大数据”。更多是类似五金店老板,做好业务分类,在前端销售、导购、业务员做好关键信息采集。

     

    互联网公司需特别注意:一个平台有可能同时融合多种业务,这些业务看似相似,可实际对应的用户需求,相关的业务,完全不同。

    如上图红圈所示,一个订票平台,对商旅客人,可能就是高频次高金额频繁发生的事,这时候可以用RFM来进一步细分。

    但对新婚游,可能就是个很低频的需求,找的关联业务就是酒店、租车、回程以后休闲地(出趟国,十几二十天回来真的很累,需要补假)。类似地,电商平台,卖的同时有零食、手机、充值卡、电视等等,在挖需求的时候也要区分常见,而不是一锅炖了了事。

     

    用户分群的具体操作内容太多,需要单独开一篇文章写,这篇已经3000字了,怕大家读着累。写长文最怕没人看,有兴趣的同学点个在看。如果在看超过60个陈老师就排期写哈。

      4   

    推送/验证的注意事项

    做数据的同学,往往做ABtest的很多,但做得很被动。往往是业务拿着方案,数据只是机械操作。自己提假设,自己进行验证的能力差。这里关键是:提假设。很多同学对着交易数据没感觉,数据库里评论、需求、浏览数据又太少。这里举个简单的例子。比如我们看到一个购物单,我们可以大胆做假设:

     

    所以你看,不需要特别多数据,也能提假设。当然,不是所有假设都有必要投入ABtest,我们可以先从数据上作区分。

    比如从一个用户身上发现的假设点,先看:是否该用户有强烈的特征,比如我们假设他是优惠驱动,那么他参与优惠订单》n次,优惠力度》50%的活动参与率》X%,总之,他得真的表现出对优惠有特别兴趣。

    再看,是否有足够数量用户有类似特征,如果用户数量太少,那即使是个机会点,也不一定被业务所用。如果符合以上两点,可以考虑提建议,让业务做方案,上Abtest了。

      4   

    需求挖掘,做到多深合适

    看到上边,有的同学可能会问:既然有这么多方向可以挖,该从哪里挖起?答:从目前业务发展最紧迫的问题开始。业务上,需要:

     

    ● 提升转化率:挖用户首次购买的产品

    ● 提升客单价:挖用户交叉品类需求

    ● 提升交易金额:挖重度用户

    ● 提升复购率:挖二次购货需求

    ● ……

     

    有明确目标指引的情况下,更容易找到答案。当然,也有可能挖了一圈发现没啥收获,数据上找不到机会点。但至少也能反向证明:花里胡哨地砸钱营销没啥屁用,那也能指导运营做一些节省成本的工作,也是功劳一件。

     

    以上就是挖用户需求的基本思路,大家可以看到,它融合了用户分群,假设检验,ABTest等具体工作,是个综合性很高的事,同时也能看到,它不是一蹴而就的,而是需要大量基础工作打底,再结合大量的尝试才能得到结论。

    挖用户需求,不是像路边摆摊的算命师傅那样,铜钱一丢就无所不知了。去粗取精,去伪存真,反复迭代,逼近真相,这才是数据分析师的价值所在。

    原创精选:

    关于需求挖掘、用户运营的更多实用技巧,陈老师在《业务知识一站通》视频课程有详细讲解,学习课程可加入学员群,和陈老师一对一讨论问题,提升能力。

    《业务知识一站通》

    长按扫描二维码
    了解陈老师的视频课程

    还可加入学员群

    享受陈老师一对一咨询服务

    点左下角“阅读原文”听陈老师讲课噢!

    展开全文
  • 柔性测试系统是测试需求导向的客户化定制系统,其组建和运行的前提是如何根据具体的测试任务需求匹配出能够完成测试任务的最优测试资源集合。本文首先在面向信号描述测试任务需求和测试资源能力的基础上,求得测试...
  • 实施服务供应链管理,需要洞悉并满足客户需求,并向客户即时传递他们需要的服务产品知识,使客户对服务产品的利用价值最大化,提高客户的忠诚度;通过与客户的交流和互动可以加深对客户的理解,不断创造新的知识,从而...
  • 所谓语义匹配,就是在语义上衡量文本的相似度,在产业界有很多的应用需求。例如,在FAQ场景中需要计算用户输入与标问之间的相似度来寻找合适的答案。本文介绍一种经典的语义匹配技术,DSSM,主...

    所谓语义匹配,就是在语义上衡量文本的相似度,在产业界有很多的应用需求。例如,在FAQ场景中需要计算用户输入与标问之间的相似度来寻找合适的答案。本文介绍一种经典的语义匹配技术,DSSM,主要用于语料的召回和粗排。

    作者&编辑 | 小Dream哥

    1 DSSM的提出 

    较早期的语义匹配模型都是基于关键词的匹配,例如LSA等,无法匹配语义层面的信息。基于此,DSSM(Deep Structured Semantic Models)提出深度语义匹配模型,期望能够在语义层面匹配query之间的相似性。

    顾名思义,DSSM是一种用于语义相似度计算的深度网络,我们来看看它的庐山真面目到底是怎么样的。

    2  整体看结构

    我们先来整体来看一下DSSM的网络结构,以整体上对它有一个把握和感觉。如下图所示,是DSSM的网络架构图:

    论文原文:https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/cikm2013_DSSM_fullversion.pdf

    整体上来看,DSSM网络总共有6层:

    1.第一层是输入层,DSSM用的词袋模型,后面再详细介绍;

    2.第二层经过word hashing,将维度由500K降为30K;

    3.第三,四,五层是3个全连接层,通过这三个全连接层,进行语义特征的提取,并降维度降低到128维;

    4.第六层为输出层,计算Q和D之间的余弦相似度之后,输出他们之间的相似度。

    3 输入层及word hashing  

    DSSM的输入层结合了词哈希(word hashing)和语义匹配,我们在讲词向量的时候详细介绍了词袋模型,忘记的同学可以点击如下链接先了解:

    【NLP-词向量】词向量的由来及本质

    总的来说词袋模型就是把文本看成是一个装着词的袋子,记录一个文本中,有这个词几个,那个词几个。前提到过,当词典非常大时,用词袋模型会造成维度灾难。所以DSSM还引入了word hashing。

    Word hashing主要目的是为了减少维度,在英文里,采用letter-ngams来对单词进行切分,如下图所示,加入采用letter-trigams来对词进行切分,则boy这个词可以切分为(#bo,boy,oy#)三个。按这个方法,再将上述词袋里的进行转化。因为英文只有26个字母,这样可以极大的减少维度,如论文中所示将维度从500K转化为30K。

    也许反应快的同学很快就会问,英文可以这样做,但是好像中文没有办法这样处理呀?总不能按照偏旁来拆吧?当然不会按照偏旁来拆了,加入汉字部首偏旁特征的研究目前还不很成功。

    那么中文怎么处理呢?其实很简单,在单纯的DSSM模型中,中文是按照“字袋模型”来处理的,参考词袋模型,也就是将文本转化成,有几个某某字,有几个某某字。因为中文字个数是有限的,常用的字大概有15K左右,因此这种做法不会有维度过大的问题。

    4  特征提取层和相似度计算

    熟悉深度学习的朋友,应该很容易看明白DSSM的特征抽取层,其实就是3个全连接层串行的连接起来。看看数学:

    可以看出,在DSSM中采用tanh作为激活函数。

    通过计算各个Q及D的特征表征,得到了一些128维的特征向量。随后在DSSM中,通过计算Q和D之间的余弦距离来评价他们之间相似度,计算公式如下图所示:

    5  DSSM的训练

    那么DSSM训练的过程是怎么样的呢?细心的同学会发现,DSSM网络结构图中,DSSM的输入是一个Querry和一个文本集DD中包含正样本和负样本。

    其中 r 为 softmax 的平滑因子,D 为 Query 下的正样本,D 为 Query 下的整个样本空间。

    上述公式,计算一个样本空间内正样本的平滑概率,R(Q,D)为两个文本之间余弦距离。

    在训练阶段,通过极大似然估计,最小化损失函数为:

    总结

    DSSM的优点在于能够快速的计算多个query和Doc对之间的语义相似度;相对于词向量的方式,它采用有监督的方法,准确度要高很多。

    但是DSSM也有它的缺点,首先,它采用词袋模型,没有考虑词的位置关系,这对语义理解是一个大的损失;此外,采用弱监督、端到端的模型,预测结果不可控。

    基于DSSM的上述特点,它最适合应用的场景就是召回和粗排。例如在FAQ中,因为标问会非常多,将标问和用户输入一一匹配时几乎不可能的事情。通常的做法就是,首先基于ES和DSSM做一遍召回和粗排,得到一定数目的标问后再用精排模型得到答案。

    除了使用它,更关键的是albert模型的实现和理论。我们会在知识星球讨论相关的内容,感兴趣的话可以扫描下面的二维码了解。

    读者们可以留言,或者加入我们的NLP群进行讨论。感兴趣的同学可以微信搜索jen104,备注"加入有三AI NLP群"

    下期预告:暂无

    知识星球推荐

    扫描上面的二维码,就可以加入我们的星球,助你成长为一名合格的自然语言处理算法工程师。

    知识星球主要有以下内容:

    (1) 聊天机器人。包括对话系统,FAQ以及闲聊型机器人。

    (2) 知识图谱。介绍知识图谱的理论和世纪搭建。

    (3) NLP预训练模型,包括BERT,ALBERT等模型的理论及实践。

    转载文章请后台联系

    侵权必究

    往期精选

    展开全文
  • 软件工程导论—需求分析

    万次阅读 多人点赞 2020-05-05 12:09:46
    需求分析概述1.1. 软件需求的概念1.2. 需求分析的准则1.3. 需求分析的任务和步骤2. 需求获取的常用方法和步骤3. 分析建模3.1. 结构化分析模型3.1.1. 结构化分析模型概述3.1.2.实体联系图 E-R图3.1.3.数据流图 DFD...
  • 城市配送与车辆管理面临着需求与供应不相匹配需求的时效性和随机性越来越强、车辆利用率低的实际情况。针对该问题提出了在不考虑城市各路段拥堵的情况下的需求驱动下的城市配送车辆动态调度模型。该模型首先用客户...
  • 【软件工程】需求分析文档——需求规格说明书

    万次阅读 多人点赞 2021-03-18 10:13:37
    文章目录1 引言1.1 编写目的1.2 背景1.3 术语和缩略词1.4 参考资料2 任务概述2.1 项目概述2.1.1 项目来源及背景2.1.2 项目目标2.1.3 系统功能概述2.2 用户特点2.3 假定和约束3 功能需求3.1 功能划分3.1.1 系统功能...
  • 多技能需求的现场产品服务调度结合了多旅行商问题与多技能项目调度问题,需综合考虑路径优化与技能匹配。针对该问题,考虑时间窗因素,以最短旅途时间和最少客户等待时间为目标建立数学模型,基于分段染色体编码的...
  • UML大作业: 保险公司智能运营系统——软件需求规格说明
  • 作为中间服务商,售电公司为了追求利润最大化,需要将用户的需求电量与电厂的供应电量进行匹配,要求用Python实现匹配出各个月满足用户需求的最低价的电量及对应的电厂。 数据集: 用户需求电量表: [月份、用户需求...
  • 财务系统需求分析 目录 1.引言 2 1.1概述 2 1.2用户分析 3 2.功能需求 3 2.1总体功能介绍 3 2.2功能需求分析 3 2.2.2基础信息设置 4 2.2.3账务管理 4 2.2.4出纳管理 4 2.2.5电子报表 5 ...
  • 突然手机响了,一看原来是组织语音会议, 讨论客户需要系统的er图,有400多张要求晚上搞定明天发出去。由于我们没设置外键约束,因此用powerdesigner无法把表之间的关联关系展示出来。由于表数量多、时间紧急,大家...
  • 敏捷开发下的需求评审传统瀑布模型下的需求评审对传统瀑布模型现有需求评审的分析传统瀑布模型在需求阶段末期安排有关键的需求里程碑评审,其特征参见2.8节情况1。在业界实际操作中,往往出现如下情况: 1,召集...
  • UML 需求建模基础与实例

    千次阅读 2016-04-26 10:56:02
    层次:1)业务需求(问题的定义,与计算机无关) 2)用户需求(人、客户的角度分析) 3)系统需求(开发人员的角度) 失败原因: 1)不完整的需求 2)没有用户的介入 3)不实际的客户期望 4)需求与规范的变更 5)提供...
  • 针对基于实例推理的产品配置设计中客户需求匹配搜索的问题,引入了实体集、实体、属性、主属性集、相似元等概念,建立了基于实体属性的相似度计算模型;研究了产品配置过程中客户需求与产品结构单元特征之间的映射...
  • 随着软件发展到不同的阶段对自动化会有不同的测试需求,因此也产生了多种测试类型,然而万变不离其宗,一切皆可自动化
  • 针对产品族多数零部件结构相同、个别差异的特点,建立产品族零部件模型数据库,根据客户对同类产品的不同需求,利用数据匹配原理和零件模型修改再设计技术,实现对单个产品的快速、智能化、自动化设计,既节省了人力成本,...
  • 智慧赋能企业供应链,快速满足客户需求
  • 产品研发过程是不断迭代的过程,发生需求变更、设计变更的情况非常多,需要系统的管理变更。 1 产品变更管理方案 1.1 产品变更的原则 变更管理的原则是产品基准化、变更管理过程规范化,妥善保存变更所产生的相关...
  • 用户满意度和用户需求:Kano模型

    千次阅读 2021-01-10 18:06:30
    1.分哪几种需求,每种需求对用户满意度的影响情况是什么? 2.怎么判断属于哪种需求? 3.针对这几种需求,正确的策略是什么? 一,需求分类以及影响 必备属性:优化此需求,用户满意度不会提升;不提供此需求,用户...
  • 如何进行软件需求分析

    万次阅读 多人点赞 2018-09-14 09:43:52
    如何进行软件需求分析 1、需求分析的重要性 软件需求是指用户对目标软件系统在功能、行为、性能、设计约束等方面的期望。 通常,软件生存周期包括可行性分析与开发项计划、需求分析、设计(概要设计和详细设计)...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 98,253
精华内容 39,301
关键字:

匹配客户需求