Alink漫談(六) : TF-IDF算法的實現

Alink漫談(六) : TF-IDF算法的實現

目錄

  • Alink漫談(六) : TF-IDF算法的實現
    • 0x00 摘要
    • 0x01 TF-IDF
      • 1.1 原理
      • 1.2 計算方法
    • 0x02 Alink示例代碼
      • 2.1 示例代碼
      • 2.2 TF-IDF模型
      • 2.3 TF-IDF預測
    • 0x03 分詞 Segment
      • 3.1 結巴分詞
      • 3.2 分詞過程
    • 0x04 訓練
      • 4.1 計算IDF
      • 4.2 排序
        • 4.2.1 SortUtils.pSort
          • 採樣SampleSplitPoint
          • 歸併 SplitPointReducer
          • SplitData把真實數據IDF插入
          • reduceGroup計算同類型單詞數目
        • 4.2.2 localSort
      • 4.3 過濾
    • 0x05 生成模型
      • 5.1 DocCountVectorizerModelData
      • 5.2 BuildDocCountModel
    • 0x06 預測
    • 0x07 參考

0x00 摘要

Alink 是阿里巴巴基於實時計算引擎 Flink 研發的新一代機器學習算法平台,是業界首個同時支持批式算法、流式算法的機器學習平台。TF-IDF(term frequency–inverse document frequency)是一種用於信息檢索與數據挖掘的常用加權技術。本文將為大家展現Alink如何實現TF-IDF。

0x01 TF-IDF

TF-IDF(term frequency–inverse document frequency)是一種統計方法,一種用於信息檢索與數據挖掘的常用加權技術。

TF是詞頻(Term Frequency),IDF是逆文本頻率指數(Inverse Document Frequency)。

為什麼要用TF-IDF?因為計算機只能識別数字,對於一個一個的單詞,計算機是看不懂的,更別說是一句話,或是一篇文章。而TF-IDF就是用來將文本轉換成計算機看得懂的語言,或者說是機器學習或深度學習模型能夠進行學習訓練的數據集

1.1 原理

TF-IDF用以評估一個詞對於一個文件集或一個語料庫中的其中一份文件的重要程度。字詞的重要性隨着它在文件中出現的次數成正比增加,但同時會隨着它在語料庫中出現的頻率成反比下降。

TF-IDF的主要思想是:如果某個詞或短語在一篇文章中出現的頻率TF高,並且在其他文章中很少出現,則認為此詞或者短語具有很好的類別區分能力,適合用來分類。

TF-IDF實際上是:TF * IDF,TF詞頻(Term Frequency),IDF逆向文件頻率(Inverse Document Frequency)。

詞頻(term frequency,TF)指的是某一個給定的詞語在該文件中出現的頻率。這個数字是對詞數(term count)的歸一化,以防止它偏向長的文件(同一個詞語在長文件里可能會比短文件有更高的詞數,而不管該詞語重要與否)。

IDF逆向文件頻率 (inverse document frequency, IDF)反應了一個詞在所有文本(整個文檔)中出現的頻率,如果一個詞在很多的文本中出現,那麼它的IDF值應該低。而反過來如果一個詞在比較少的文本中出現,那麼它的IDF值應該高。比如一些專業的名詞如“Machine Learning”。這樣的詞IDF值應該高。一個極端的情況,如果一個詞在所有的文本中都出現,那麼它的IDF值應該為0。

如果單單以TF或者IDF來計算一個詞的重要程度都是片面的,因此TF-IDF綜合了TF和IDF兩者的優點,用以評估一字詞對於一個文件集或一個語料庫中的其中一份文件的重要程度。字詞的重要性隨着它在文件中出現的次數成正比增加,但同時會隨着它在語料庫中出現的頻率成反比下降。上述引用總結就是:一個詞語在一篇文章中出現次數越多, 同時在所有文檔中出現次數越少, 越能夠代表該文章,越能與其它文章區分開來。

1.2 計算方法

TF的計算公式如下:

\[TF_w = \frac {N_w}{N} \]

其中 N_w 是在某一文本中詞條w出現的次數,N 是該文本總詞條數。

IDF的計算公式如下:

\[IDF_w = log(\frac {Y}{Y_w + 1}) \]

其中 Y 是語料庫的文檔總數,Y_w 是包含詞條w的文檔數,分母加一是為了避免w 未出現在任何文檔中從而導致分母為0 的情況。

TF-IDF 就是將TF和IDF相乘 :

\[TF-IDF_w = TF_w * IDF_w \]

從以上計算公式便可以看出,某一特定文件內的高詞語頻率,以及該詞語在整個文件集合中的低文件頻率,可以產生出高權重的TF-IDF。因此,TF-IDF傾向於過濾掉常見的詞語,保留重要的詞語。

0x02 Alink示例代碼

2.1 示例代碼

首先我們給出示例代碼,下文是通過一些語料來訓練出一個模型,然後用這個模型來做預測:

public class DocCountVectorizerExample {

    AlgoOperator getData(boolean isBatch) {
        Row[] rows = new Row[]{
                Row.of(0, "二手舊書:醫學電磁成像"),
                Row.of(1, "二手美國文學選讀( 下冊 )李宜燮南開大學出版社 9787310003969"),
                Row.of(2, "二手正版圖解象棋入門/謝恩思主編/華齡出版社"),
                Row.of(3, "二手中國糖尿病文獻索引"),
                Row.of(4, "二手郁達夫文集( 國內版 )全十二冊館藏書")
        };

        String[] schema = new String[]{"id", "text"};

        if (isBatch) {
            return new MemSourceBatchOp(rows, schema);
        } else {
            return new MemSourceStreamOp(rows, schema);
        }
    }

    public static void main(String[] args) throws Exception {
        DocCountVectorizerExample test = new DocCountVectorizerExample();
        BatchOperator batchData = (BatchOperator) test.getData(true);

         // 分詞
        SegmentBatchOp segment = new SegmentBatchOp() 
                                                .setSelectedCol("text")
                                                .linkFrom(batchData);
        // TF-IDF訓練
        DocCountVectorizerTrainBatchOp model = new DocCountVectorizerTrainBatchOp()
                                                .setSelectedCol("text")
                                                .linkFrom(segment);
        // TF-IDF預測
        DocCountVectorizerPredictBatchOp predictBatch = new 
            																		DocCountVectorizerPredictBatchOp()
                                                .setSelectedCol("text")
                                                .linkFrom(model, segment);
        model.print();
        predictBatch.print();
    }
}

2.2 TF-IDF模型

TF-IDF模型打印出來如下:

model_id|model_info
--------|----------
0|{"minTF":"1.0","featureType":"\"WORD_COUNT\""}
1048576|{"f0":"二手","f1":0.0,"f2":0}
2097152|{"f0":"/","f1":1.0986122886681098,"f2":1}
3145728|{"f0":"出版社","f1":0.6931471805599453,"f2":2}
4194304|{"f0":")","f1":0.6931471805599453,"f2":3}
5242880|{"f0":"(","f1":0.6931471805599453,"f2":4}
6291456|{"f0":"入門","f1":1.0986122886681098,"f2":5}
......
36700160|{"f0":"美國","f1":1.0986122886681098,"f2":34}
37748736|{"f0":"謝恩","f1":1.0986122886681098,"f2":35}
38797312|{"f0":"象棋","f1":1.0986122886681098,"f2":36}

2.3 TF-IDF預測

TF-IDF預測結果如下:

id|text
--|----
0|$37$0:1.0 6:1.0 10:1.0 25:1.0 26:1.0 28:1.0
1|$37$0:1.0 1:1.0 2:1.0 4:1.0 11:1.0 15:1.0 16:1.0 19:1.0 20:1.0 32:1.0 34:1.0
2|$37$0:1.0 3:2.0 4:1.0 5:1.0 8:1.0 22:1.0 23:1.0 24:1.0 29:1.0 35:1.0 36:1.0
3|$37$0:1.0 12:1.0 27:1.0 31:1.0 33:1.0
4|$37$0:1.0 1:1.0 2:1.0 7:1.0 9:1.0 13:1.0 14:1.0 17:1.0 18:1.0 21:1.0 30:1.0

0x03 分詞 Segment

中文分詞(Chinese Word Segmentation) 指的是將一個漢字序列切分成一個一個單獨的詞。分詞就是將連續的字序列按照一定的規範重新組合成詞序列的過程。

示例代碼中,分詞部分如下:

    SegmentBatchOp segment = new SegmentBatchOp() 
                                            .setSelectedCol("text")
                                            .linkFrom(batchData);

分詞主要是如下兩個類,其作用就是把中文文檔分割成單詞。

public final class SegmentBatchOp extends MapBatchOp <SegmentBatchOp>
	implements SegmentParams <SegmentBatchOp> {

	public SegmentBatchOp(Params params) {
		super(SegmentMapper::new, params);
	}
}

public class SegmentMapper extends SISOMapper {
	private JiebaSegmenter segmentor;
}

3.1 結巴分詞

有經驗的同學看到這裏就會露出微笑:結巴分詞。

jieba分詞是國內使用人數最多的中文分詞工具https://github.com/fxsjy/jieba。jieba分詞支持四種分詞模式:

  • 精確模式,試圖將句子最精確地切開,適合文本分析;
  • 全模式,把句子中所有的可以成詞的詞語都掃描出來, 速度非常快,但是不能解決歧義;
  • 搜索引擎模式,在精確模式的基礎上,對長詞再次切分,提高召回率,適合用於搜索引擎分詞。
  • paddle模式,利用PaddlePaddle深度學習框架,訓練序列標註(雙向GRU)網絡模型實現分詞。

Alink使用了com.alibaba.alink.operator.common.nlp.jiebasegment.viterbi.FinalSeg;來 完成分詞。具體是在https://github.com/huaban/jieba-analysis的基礎上稍微做了調整。

public class JiebaSegmenter implements Serializable {
    private static FinalSeg finalSeg = FinalSeg.getInstance();
    private WordDictionary wordDict;
    ......
    private Map<Integer, List<Integer>> createDAG(String sentence) 
}

從Alink代碼中看,實現了索引分詞和查詢分詞兩種模式,應該是有分詞粒度粗細之分。

createDAG函數的作用是 :在處理句子過程中,基於前綴詞典實現高效的詞圖掃描,生成句子中漢字所有可能成詞情況所構成的有向無環圖 (DAG)。

結巴分詞對於未登錄詞,採用了基於漢字成詞能力的 HMM 模型,使用了 Viterbi 算法。

3.2 分詞過程

分詞過程主要是在SegmentMapper.mapColumn函數中完成的,當輸入是 “二手舊書:醫學電磁成像”,結巴分詞將這個句子分成了六個單詞。具體參見如下:

input = "二手舊書:醫學電磁成像"
tokens = {ArrayList@9619}  size = 6
 0 = {SegToken@9630} "[二手, 0, 2]"
 1 = {SegToken@9631} "[舊書, 2, 4]"
 2 = {SegToken@9632} "[:, 4, 5]"
 3 = {SegToken@9633} "[醫學, 5, 7]"
 4 = {SegToken@9634} "[電磁, 7, 9]"
 5 = {SegToken@9635} "[成像, 9, 11]"
 
mapColumn:44, SegmentMapper (com.alibaba.alink.operator.common.nlp)
apply:-1, 35206803 (com.alibaba.alink.common.mapper.SISOMapper$$Lambda$646)
handleMap:75, SISOColsHelper (com.alibaba.alink.common.mapper)
map:52, SISOMapper (com.alibaba.alink.common.mapper)
map:21, MapperAdapter (com.alibaba.alink.common.mapper)
map:11, MapperAdapter (com.alibaba.alink.common.mapper)
collect:79, ChainedMapDriver (org.apache.flink.runtime.operators.chaining)
collect:35, CountingCollector (org.apache.flink.runtime.operators.util.metrics)
invoke:196, DataSourceTask (org.apache.flink.runtime.operators)

0x04 訓練

訓練是在DocCountVectorizerTrainBatchOp類完成的,其通過linkFrom完成了模型的構建。其實計算TF IDF相對 簡單,複雜之處在於之後的大規模排序。

public DocCountVectorizerTrainBatchOp linkFrom(BatchOperator<?>... inputs) {
        BatchOperator<?> in = checkAndGetFirst(inputs);
  
        DataSet<DocCountVectorizerModelData> resDocCountModel = generateDocCountModel(getParams(), in);

        DataSet<Row> res = resDocCountModel.mapPartition(new MapPartitionFunction<DocCountVectorizerModelData, Row>() {
            @Override
            public void mapPartition(Iterable<DocCountVectorizerModelData> modelDataList, Collector<Row> collector) {
                new DocCountVectorizerModelDataConverter().save(modelDataList.iterator().next(), collector);
            }
        });
        this.setOutput(res, new DocCountVectorizerModelDataConverter().getModelSchema());
        return this;
}

4.1 計算IDF

計算 IDF 的工作是在generateDocCountModel完成的,具體步驟如下:

第一步 通過DocWordSplitCount和UDTF的混合使用得到了文檔中的單詞數目docWordCnt

BatchOperator<?> docWordCnt = in.udtf(
        params.get(SELECTED_COL),
        new String[] {WORD_COL_NAME, DOC_WORD_COUNT_COL_NAME},
        new DocWordSplitCount(NLPConstant.WORD_DELIMITER),
        new String[] {});

DocWordSplitCount.eval的輸入是已經分詞的句子,然後按照空格分詞,按照單詞計數。其結果是:

map = {HashMap@9816}  size = 6
 "醫學" -> {Long@9833} 1
 "電磁" -> {Long@9833} 1
 ":" -> {Long@9833} 1
 "成像" -> {Long@9833} 1
 "舊書" -> {Long@9833} 1
 "二手" -> {Long@9833} 1

第二步 得到了文檔數目docCnt

BatchOperator docCnt = in.select("COUNT(1) AS " + DOC_COUNT_COL_NAME);

這個數目會廣播出去 .withBroadcastSet(docCnt.getDataSet(), "docCnt");,後面的CalcIdf會繼續使用,進行 行數統計。

第三步 會通過CalcIdf計算出每一個單詞的DF和IDF

open時候會獲取docCnt。然後reduce會計算IDF,具體計算如下:

double idf = Math.log((1.0 + docCnt) / (1.0 + df));
collector.collect(Row.of(featureName, -wordCount, idf));

具體得到如下

df = 1.0
wordCount = 1.0
featureName = "中國"
idf = 1.0986122886681098
docCnt = 5

這裏一個重點是:返回值中,是 -wordCount,因為單詞越多權重越小,為了比較所以取負

4.2 排序

得到所有單詞的IDF之後,就得到了一個IDF字典,這時候需要對字典按照權重進行排序。排序具體分為兩步。

4.2.1 SortUtils.pSort

第一步是SortUtils.pSort,大規模并行抽樣排序。

Tuple2<DataSet<Tuple2<Integer, Row>>, DataSet<Tuple2<Integer, Long>>> partitioned = SortUtils.pSort(sortInput, 1);

這步非常複雜,Alink參考了論文,如果有興趣的兄弟可以深入了解下。

* reference: Yang, X. (2014). Chong gou da shu ju tong ji (1st ed., pp. 25-29).
* Note: This algorithm is improved on the base of the parallel sorting by regular sampling(PSRS).

pSort返回值是:

* @return f0: dataset which is indexed by partition id, f1: dataset which has partition id and count.

pSort中又分如下幾步

採樣SampleSplitPoint

SortUtils.SampleSplitPoint.mapPartition這裏完成了採樣。

DataSet <Tuple2 <Object, Integer>> splitPoints = input
   .mapPartition(new SampleSplitPoint(index))
   .reduceGroup(new SplitPointReducer());

這裏的輸入row就是上文IDF的返回數值。

用allValues記錄了本task目前處理的句子有多少個單詞。

用splitPoints做了採樣。如何選擇呢,通過genSampleIndex函數。

public static Long genSampleIndex(Long splitPointIdx, Long count, Long splitPointSize) {
   splitPointIdx++;
   splitPointSize++;

   Long div = count / splitPointSize;
   Long mod = count % splitPointSize;

   return div * splitPointIdx + ((mod > splitPointIdx) ? splitPointIdx : mod) - 1;
}

後續操作也使用同樣的genSampleIndex函數來做選擇,這樣保證在操作所有序列上可以選取同樣的採樣點。

allValues = {ArrayList@10264}  size = 8  //本task有多少單詞
 0 = {Double@10266} -2.0
 1 = {Double@10271} -1.0
 2 = {Double@10272} -1.0
 3 = {Double@10273} -1.0
 4 = {Double@10274} -1.0
 5 = {Double@10275} -1.0
 6 = {Double@10276} -1.0
 7 = {Double@10277} -1.0
 
splitPoints = {ArrayList@10265}  size = 7 //採樣了7個
 0 = {Double@10266} -2.0
 1 = {Double@10271} -1.0
 2 = {Double@10272} -1.0
 3 = {Double@10273} -1.0
 4 = {Double@10274} -1.0
 5 = {Double@10275} -1.0
 6 = {Double@10276} -1.0

最後返回採樣數據,返回時候附帶當前taskIDnew Tuple2 <Object, Integer>(obj,taskId)

這裡有一個trick點

  for (Object obj : splitPoints) {
     Tuple2 <Object, Integer> cur
        = new Tuple2 <Object, Integer>(
        obj,
        taskId); //這裏返回的是類似 (-5.0,2) :其中2就是task id,-5.0是-wordcount。
     out.collect(cur);
  }

  out.collect(new Tuple2(
     getRuntimeContext().getNumberOfParallelSubtasks(),
     -taskId - 1));//這裏返回的是一個特殊元素,類似(4,-2) :其中4是本應用中并行task數目,-2是當前-taskId - 1。這個task數目後續就會用到。

具體數據參見如下:

row = {Row@10211} "中國,-1.0,1.0986122886681098"
 fields = {Object[3]@10214} 
 
cur = {Tuple2@10286} "(-5.0,2)" // 返回採樣數據,返回時候附帶當前taskID
 f0 = {Double@10285} -5.0 // -wordcount。
 f1 = {Integer@10300} 2 // 當前taskID
歸併 SplitPointReducer

歸併所有task生成的sample。然後再次sample,把sample數據組成一個數據塊,這個數據塊選擇的原則是:每個task都盡量選擇若干sample

這裏其實是有一個轉換,就是從正常單詞的抽樣 轉換到 某一類單詞的抽樣,這某一類的意思舉例是:出現次數為一,或者出現次數為五 這種單詞

這裏all是所有採樣數據,其中一個元素內容舉例 (-5.0,2) :其中2就是task id,-5.0是-wordcount。

這裏用 Collections.sort(all, new PairComparator()); 來對所有採樣數據做排序。排序基準是首先對 -wordcount,然後對task ID。

SplitPointReducer的返回採樣數值就作為廣播變量存儲起來:.withBroadcastSet(splitPoints, "splitPoints");

這裏的trick點是:

for (Tuple2 <Object, Integer> value : values) {
   if (value.f1 < 0) { 
      instanceCount = (int) value.f0;  // 特殊數據,類似(4,-2) :其中4是本應用中task數目,這個就是後續選擇哪些taskid的基準
      continue;
   }
   all.add(new Tuple2 <>(value.f0, value.f1)); // (-5.0,2) 正常數據
}

選擇sample index splitPoints.add(allValues.get(index));也使用了同樣的genSampleIndex。

計算中具體數據如下:

for (int i = 0; i < splitPointSize; ++i) {
		int index = genSampleIndex(
					Long.valueOf(i),
					Long.valueOf(count),
					Long.valueOf(splitPointSize))
					.intValue();
		spliters.add(all.get(index));
}
for (Tuple2 <Object, Integer> spliter : spliters) {
		out.collect(spliter);
}

count = 33
all = {ArrayList@10245}  size = 33 // 所有採樣數據,
0 = {Tuple2@10256} "(-5.0,2)"// 2就是task id,-5.0是-wordcount。
1 = {Tuple2@10285} "(-2.0,0)"
......
6 = {Tuple2@10239} "(-1.0,0)"
7 = {Tuple2@10240} "(-1.0,0)"
8 = {Tuple2@10241} "(-1.0,0)"
9 = {Tuple2@10242} "(-1.0,0)"
10 = {Tuple2@10243} "(-1.0,0)"
11 = {Tuple2@10244} "(-1.0,1)"
......
16 = {Tuple2@10278} "(-1.0,1)"
......
24 = {Tuple2@10279} "(-1.0,2)"
......
32 = {Tuple2@10313} "(-1.0,3)"
  
// spliters是返回結果,這裏分別選取了all中index為8,16,24這個三個record。每個task都選擇了一個元素。
spliters = {HashSet@10246}  size = 3
 0 = {Tuple2@10249} "(-1.0,0)" // task 0 被選擇。就是說,這裏從task 0中選擇了一個count是1的元素,具體選擇哪個單詞其實不重要,就是為了選擇count是1的這種即可。
 1 = {Tuple2@10250} "(-1.0,1)" // task 1 被選擇。具體同上。
 2 = {Tuple2@10251} "(-1.0,2)" // task 2 被選擇。具體同上。
SplitData把真實數據IDF插入

use binary search to partition data into sorted subsets。前面函數給出的是詞的count,但是沒有IDF。這裏將用二分法查找 找到IDF,然後把IDF插入到partition data中。

首先要注意一點:splitData的輸入就是原始輸入input, 和splitPoints的輸入是一樣 的

DataSet <Tuple2 <Integer, Row>> splitData = input
   .mapPartition(new SplitData(index))
   .withBroadcastSet(splitPoints, "splitPoints");

open函數中會取出廣播變量 splitPoints。

splitPoints = {ArrayList@10248}  size = 3
 0 = {Tuple2@10257} "(-1.0,0)"
 1 = {Tuple2@10258} "(-1.0,1)"
 2 = {Tuple2@10259} "(-1.0,2)"

本函數的輸入舉例

row = {Row@10232} "入門,-1.0,1.0986122886681098"

會在splitPoints中二分法查找,得到splits中每一個 sample 對應的真實IDF。然後發送出去。

這裏需要特殊說明下,這個二分法查找查找的是IDF數值,比如count為1的這種單詞對應的IDF數值,可能很多單詞都是count為1,所以找到一個這樣單詞的IDF即可

splitPoints = {ArrayList@10223}  size = 3
 0 = {Tuple2@10229} "(-1.0,0)"
 1 = {Tuple2@10230} "(-1.0,1)"
 2 = {Tuple2@10231} "(-1.0,2)"
curTuple.f0 = {Double@10224} -1.0
  
int bsIndex = Collections.binarySearch(splitPoints, curTuple, new PairComparator());

		int curIndex;
		if (bsIndex >= 0) {
			curIndex = bsIndex;
		} else {
			curIndex = -bsIndex - 1;
		}

// 假設單詞是 "入門",則發送的是 "入門" 這類單詞在本partition的index,和 "入門" 的單詞本身
// 其實,從調試過程看,是否發送單詞信息本身並不重要,因為接下來的那一步操作中,並沒有用到單詞本身信息
out.collect(new Tuple2 <>(curIndex, row)); 
reduceGroup計算同類型單詞數目

這裡是計算在某一partition中,某一種類單詞的數目。比如count為1的單詞,這種單詞總共有多少個

後續會把new Tuple2 <>(id, count)作為partitionCnt廣播變量存起來。

id就是這類單詞在這partition中間的index,我們暫時稱之為partition index。count就是這類單詞在本partition的數目。

// 輸入舉例
value = {Tuple2@10312} "(0,入門,-1.0,1.0986122886681098)"
 f0 = {Integer@10313} 0
 
// 計算數目
for (Tuple2 <Integer, Row> value : values) {
		id = value.f0;
		count++;
}

out.collect(new Tuple2 <>(id, count));  
  
// 輸出舉例,假如是序號為0的這類單詞,其總體數目是12。這個序號0就是這類單詞在某一partition中的序號。就是上面的 curIndex。
id = {Integer@10313} 0
count = {Long@10338} 12

4.2.2 localSort

第二步是localSort。Sort a partitioned dataset. 最終排序並且會返回最終數值,比如 (29, “主編,-1.0,1.0986122886681098″), 29就是”主編” 這個單詞在 IDF字典中的序號。

DataSet<Tuple2<Long, Row>> ordered = localSort(partitioned.f0, partitioned.f1, 1);

open函數中會獲取partitionCnt。然後計算出某一種類單詞,其在本partition之前所有partition中,這類單詞數目。

public void open(Configuration parameters) throws Exception {
		List <Tuple2 <Integer, Long>> bc = getRuntimeContext().getBroadcastVariable("partitionCnt");
		startIdx = 0L;
		int taskId = getRuntimeContext().getIndexOfThisSubtask();
		for (Tuple2 <Integer, Long> pcnt : bc) {
			if (pcnt.f0 < taskId) {
					startIdx += pcnt.f1;
			}
		}
}

bc = {ArrayList@10303}  size = 4
 0 = {Tuple2@10309} "(0,12)"  // 就是task0裏面,這種單詞有12個
 1 = {Tuple2@10310} "(2,9)"// 就是task1裏面,這種單詞有2個
 2 = {Tuple2@10311} "(1,7)"// 就是task2裏面,這種單詞有1個
 3 = {Tuple2@10312} "(3,9)"// 就是task3裏面,這種單詞有3個
// 如果本task id是4,則其startIdx為30。就是所有partition之中,它前面index所有單詞的和。  

然後進行排序。Collections.sort(valuesList, new RowComparator(field));

valuesList = {ArrayList@10405}  size = 9
 0 = {Row@10421} ":,-1.0,1.0986122886681098"
 1 = {Row@10422} "主編,-1.0,1.0986122886681098"
 2 = {Row@10423} "國內,-1.0,1.0986122886681098"
 3 = {Row@10424} "文獻,-1.0,1.0986122886681098"
 4 = {Row@10425} "李宜燮,-1.0,1.0986122886681098"
 5 = {Row@10426} "糖尿病,-1.0,1.0986122886681098"
 6 = {Row@10427} "美國,-1.0,1.0986122886681098"
 7 = {Row@10428} "謝恩,-1.0,1.0986122886681098"
 8 = {Row@10429} "象棋,-1.0,1.0986122886681098"
  
  
// 最後返回時候,就是  (29, "主編,-1.0,1.0986122886681098"),29就是“主編”這個單詞在最終字典中的序號。
// 這個序號是startIdx + cnt,startIdx是某一種類單詞,其在本partition之前所有partition中,這類單詞數目。比如在本partition之前,這類單詞有28個,則本partition中,從29開始計數。就是最終序列號
	for (Row row : valuesList) {
		out.collect(Tuple2.of(startIdx + cnt, row));
		cnt++; // 這裏就是在某一類單詞中,單調遞增,然後賦值一個字典序列而已
	}  
cnt = 1
row = {Row@10336} "主編,-1.0,1.0986122886681098"
 fields = {Object[3]@10339} 
startIdx = 28

4.3 過濾

最後還要進行過濾,如果文字個數超出了字典大小,就拋棄多餘文字。

ordered.filter(new FilterFunction<Tuple2<Long, Row>>() {
    @Override
    public boolean filter(Tuple2<Long, Row> value) {
        return value.f0 < vocabSize;
    }
})

0x05 生成模型

具體生成模型代碼如下。

DataSet<DocCountVectorizerModelData> resDocCountModel = ordered.filter(new FilterFunction<Tuple2<Long, Row>>() {
    @Override
    public boolean filter(Tuple2<Long, Row> value) {
        return value.f0 < vocabSize;
    }
}).mapPartition(new BuildDocCountModel(params)).setParallelism(1);
return resDocCountModel;

其中關鍵類是 DocCountVectorizerModelData 和 BuildDocCountModel。

5.1 DocCountVectorizerModelData

這是向量信息。

/**
 * Save the data for DocHashIDFVectorizer.
 *
 * Save a HashMap: index(MurMurHash3 value of the word), value(Inverse document frequency of the word).
 */
public class DocCountVectorizerModelData {
    public List<String> list;
    public String featureType;
    public double minTF;
}

5.2 BuildDocCountModel

最終生成的模型信息如下,這個也就是之前樣例代碼給出的輸出。

modelData = {DocCountVectorizerModelData@10411} 
 list = {ArrayList@10409}  size = 37
  0 = "{"f0":"9787310003969","f1":1.0986122886681098,"f2":19}"
  1 = "{"f0":"下冊","f1":1.0986122886681098,"f2":20}"
  2 = "{"f0":"全","f1":1.0986122886681098,"f2":21}"
  3 = "{"f0":"華齡","f1":1.0986122886681098,"f2":22}"
  4 = "{"f0":"圖解","f1":1.0986122886681098,"f2":23}"
  5 = "{"f0":"思","f1":1.0986122886681098,"f2":24}"
  6 = "{"f0":"成像","f1":1.0986122886681098,"f2":25}"
  7 = "{"f0":"舊書","f1":1.0986122886681098,"f2":26}"
  8 = "{"f0":"索引","f1":1.0986122886681098,"f2":27}"
  9 = "{"f0":":","f1":1.0986122886681098,"f2":28}"
  10 = "{"f0":"主編","f1":1.0986122886681098,"f2":29}"
  11 = "{"f0":"國內","f1":1.0986122886681098,"f2":30}"
  12 = "{"f0":"文獻","f1":1.0986122886681098,"f2":31}"
  13 = "{"f0":"李宜燮","f1":1.0986122886681098,"f2":32}"
  14 = "{"f0":"糖尿病","f1":1.0986122886681098,"f2":33}"
  15 = "{"f0":"美國","f1":1.0986122886681098,"f2":34}"
  16 = "{"f0":"謝恩","f1":1.0986122886681098,"f2":35}"
  17 = "{"f0":"象棋","f1":1.0986122886681098,"f2":36}"
  18 = "{"f0":"二手","f1":0.0,"f2":0}"
  19 = "{"f0":")","f1":0.6931471805599453,"f2":1}"
  20 = "{"f0":"/","f1":1.0986122886681098,"f2":2}"
  21 = "{"f0":"出版社","f1":0.6931471805599453,"f2":3}"
  22 = "{"f0":"(","f1":0.6931471805599453,"f2":4}"
  23 = "{"f0":"入門","f1":1.0986122886681098,"f2":5}"
  24 = "{"f0":"醫學","f1":1.0986122886681098,"f2":6}"
  25 = "{"f0":"文集","f1":1.0986122886681098,"f2":7}"
  26 = "{"f0":"正版","f1":1.0986122886681098,"f2":8}"
  27 = "{"f0":"版","f1":1.0986122886681098,"f2":9}"
  28 = "{"f0":"電磁","f1":1.0986122886681098,"f2":10}"
  29 = "{"f0":"選讀","f1":1.0986122886681098,"f2":11}"
  30 = "{"f0":"中國","f1":1.0986122886681098,"f2":12}"
  31 = "{"f0":"書","f1":1.0986122886681098,"f2":13}"
  32 = "{"f0":"十二冊","f1":1.0986122886681098,"f2":14}"
  33 = "{"f0":"南開大學","f1":1.0986122886681098,"f2":15}"
  34 = "{"f0":"文學","f1":1.0986122886681098,"f2":16}"
  35 = "{"f0":"郁達夫","f1":1.0986122886681098,"f2":17}"
  36 = "{"f0":"館藏","f1":1.0986122886681098,"f2":18}"
 featureType = "WORD_COUNT"
 minTF = 1.0

0x06 預測

預測業務邏輯是DocCountVectorizerModelMapper

首先我們可以看到 FeatureType,這個可以用來配置輸出哪種信息。比如可以輸出以下若干種:

public enum FeatureType implements Serializable {
    /**
     * IDF type, the output value is inverse document frequency.
     */
    IDF(
        (idf, termFrequency, tokenRatio) -> idf
    ),
    /**
     * WORD_COUNT type, the output value is the word count.
     */
    WORD_COUNT(
        (idf, termFrequency, tokenRatio) -> termFrequency
    ),
    /**
     * TF_IDF type, the output value is term frequency * inverse document frequency.
     */
    TF_IDF(
        (idf, termFrequency, tokenRatio) -> idf * termFrequency * tokenRatio
    ),
    /**
     * BINARY type, the output value is 1.0.
     */
    BINARY(
        (idf, termFrequency, tokenRatio) -> 1.0
    ),
    /**
     * TF type, the output value is term frequency.
     */
    TF(
        (idf, termFrequency, tokenRatio) -> termFrequency * tokenRatio
    );
}

其次,在open函數中,會加載模型,比如:

wordIdWeight = {HashMap@10838}  size = 37
 "醫學" -> {Tuple2@10954} "(6,1.0986122886681098)"
 "選讀" -> {Tuple2@10956} "(11,1.0986122886681098)"
 "十二冊" -> {Tuple2@10958} "(14,1.0986122886681098)"
...
 "華齡" -> {Tuple2@11022} "(22,1.0986122886681098)"
 "索引" -> {Tuple2@11024} "(27,1.0986122886681098)"
featureType = {DocCountVectorizerModelMapper$FeatureType@10834} "WORD_COUNT"

最後,預測時候調用predictSparseVector函數,會針對輸入 二手 舊書 : 醫學 電磁 成像來進行匹配。生成稀疏向量SparseVector。

0|$37$0:1.0 6:1.0 10:1.0 25:1.0 26:1.0 28:1.0

以上表示那幾個單詞 分別對應0 6 10 25 26 28 這幾個字典中對應序號的單詞,其在本句對應的出現數目都是一個。

0x07 參考

Tf-Idf詳解及應用

https://github.com/fxsjy/jieba

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※回頭車貨運收費標準

※推薦評價好的iphone維修中心

※超省錢租車方案

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

※推薦台中搬家公司優質服務,可到府估價

kubernetes pod內抓包,telnet檢查網絡連接的幾種方式

背景

在日常kubernetes的運維中,經常遇到pod的網絡問題,如pod間網絡不通,或者端口不通,更複雜的,需要在容器裏面抓包分析才能定位。而kubertnets的場景,pod使用的鏡像一般都是盡量精簡,很多都是基於alpine基礎鏡像製作的,因而pod內沒有ping,telnet,nc,curl命令,更別說tcpdump這種複雜的工具了。除了在容器或者鏡像內直接安裝這些工具這種最原始的法子,我們探討下其他法子。

實現

kubectl debug插件方式

項目地址 kubect debug,https://github.com/aylei/kubectl-debug

kubectl-debug 是一個簡單的 kubectl 插件,能夠幫助你便捷地進行 Kubernetes 上的 Pod 排障診斷。背後做的事情很簡單: 在運行中的 Pod 上額外起一個新容器,並將新容器加入到目標容器的 pid, network, user 以及 ipc namespace 中,這時我們就可以在新容器中直接用 netstat, tcpdump 這些熟悉的工具來解決問題了, 而舊容器可以保持最小化,不需要預裝任何額外的排障工具。操作流程可以參見官方項目地址文檔。

一條 kubectl debug命令背後是這樣的

步驟分別是:

  1. 插件查詢 ApiServer:demo-pod 是否存在,所在節點是什麼
  2. ApiServer 返回 demo-pod 所在所在節點
  3. 插件請求在目標節點上創建 Debug Agent Pod
  4. Kubelet 創建 Debug Agent Pod
  5. 插件發現 Debug Agent 已經 Ready,發起 debug 請求(長連接)
  6. Debug Agent 收到 debug 請求,創建 Debug 容器並加入目標容器的各個 Namespace 中,創建完成后,與 Debug 容器的 tty 建立連接

接下來,客戶端就可以開始通過 5,6 這兩個連接開始 debug 操作。操作結束后,Debug Agent 清理 Debug 容器,插件清理 Debug Agent,一次 Debug 完成。

直接進入容器net ns方式

有2種進入pod 所在net ns的方式,前提都是需要登錄到pod所在宿主機,且需要找出pod對應的容器ID或者名字。

ip netns方式

  • 獲取pod對應容器的ID或者name

    pid="$(docker inspect -f '{{.State.Pid}}' <container_name | uuid>)" #替換為環境實際的容器名字或者uuid
    
  • 創建容器對應netns

    ip netns會到/var/run/netns目錄下尋找network namespace,把容器進程中netns連接到這個目錄中后,ip netns才會感知到

    $ sudo mkdir -p /var/run/netns
    
    #docker默認不會創建這個鏈接,需要手動創建,這時候執行ip netns,就應當看到鏈接過來的network namespace
    $ sudo ln -sf /proc/$pid/ns/net "/var/run/netns/<container_name|uuid>" 
    
  • 執行ip netns <<container_name|uuid > bash,進入容器ns

    ip netns exec <container_name|uuid>  bash
    
  • 執行telnet,tcpdump等命令,此時執行ip a或者ifconfig,只能看到容器本身的IP

如下圖,執行ifconfig,只看到容器本身的IP,此時執行telnet,tcpdump等於直接在容器內操作

nsenter方式

nsenter為util-linux裏面的一個工具,除了進入容器net ns,還支持其他很多操作,可以查看官方文檔。

pid="$(docker inspect -f '{{.State.Pid}}' <container_name | uuid>)"
nsenter -t $pid -n /bin/bash
tcpdump -i eth0 -nn  #此時利用宿主機的tcpdump執行抓包操作,等於在容器內抓包

總結

  1. kubectl debug方式功能更強大,缺點是需要附加鏡像,要在目標pod創建debug agent的容器,比較笨重,但是優點是能使用的工具更多,不需要ssh到pod所在節點,除了netstat,tcpdump工具,還能使用htop,iostat等其他高級工具,不僅能對網絡進行debug,還能對IO等其他場景進行診斷,適用更複雜的debug場景。
  2. 直接進入容器net ns方式相對比較輕量,復用pod所在宿主機工具,但魚和熊掌不可兼得,缺點是只能進行網絡方面的debug,且需要ssh登錄到pod所在節點操作。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※回頭車貨運收費標準

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※推薦評價好的iphone維修中心

※教你寫出一流的銷售文案?

台中搬家公司教你幾個打包小技巧,輕鬆整理裝箱!

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

16款車評選投票結果公布,小米MAX獲獎名單在此!

按照規則,5篇文章中任意1篇,評論獲得支持率最高的用戶可以獲得小米MAX一台。支持率排名2-5位的用戶,可以獲得變形金剛吸塵器1個。支持率排名6-10位的用戶,可以獲得變形金剛皮套1個。注意:每位微信用戶在本次活動僅能獲得一個獎品,以最高排名的文章為準,其餘文章的排名作廢,獎品將順延至下一位。

經過4天時間的激烈角逐,玩車、車買買、玩車TV三大號聯合舉辦的“2016我就喜歡”年度車型評選投票,終於完滿結束。

本次參与投票的年度車型共有8款SUV和8款轎車,是由我們三大號資深編輯共同探討票選的,涵蓋10-50萬今年較為熱門的車型,名單如下所示。

活動評選規則為:由三大號5篇對比文章的投票數相加,得票最高的車型,將被評選為我們的“年度最受網友喜愛的車型”。

話不多說,馬上來看看本次評選的投票結果。

從數據中可以看出,三大平台用戶對車的喜好是相近的,投票的結果都差不多,TOp3車型更是符合小編的心理預期。

年度車型評選的投票結果公布完畢,但別忘了還有件正事——“送小米MAX”活動獲獎名單公布!

為了回饋我們三大號的粉絲,小編可是下了血本購回5台小米MAX,20個變形金剛大黃蜂吸塵器,以及25個變形金剛大黃蜂皮套來送給大家。活動規則公平,在微信平台上全程公開,所以人人的機會都是平等的。

按照規則,5篇文章中任意1篇,評論獲得支持率最高的用戶可以獲得小米MAX一台;支持率排名2-5位的用戶,可以獲得變形金剛吸塵器1個;支持率排名6-10位的用戶,可以獲得變形金剛皮套1個。

注意:每位微信用戶在本次活動僅能獲得一個獎品,以最高排名的文章為準,其餘文章的排名作廢,獎品將順延至下一位。

經過4天的龍爭虎鬥,跌宕起伏的排名終於在11月22日晚24點那一刻定格,獲獎名單如下:

請獲獎用戶按以下步驟聯繫我們:

1、獲獎評論的“留言入選提示”截圖

2、投票頁面截圖

3、編輯您的姓名、電話、郵寄地址

4、將2張截圖以及您的信息,用中獎微信號發送至文章所在公眾號的聊天界面(玩車、車買買、玩車TV)

最後,我們會有專人在工作日第一時間與您取得聯繫,中獎獎品將在確認信息后,在3個工作日內陸續發出。如果在11月25日晚24:00尚未領獎的,我們將順延至下一位用戶,以此類推。

活動詳情規則請點擊

寫在最後:

我們辦這個活動的初衷,就是以有趣的形式給大家帶來相關車型的對比,車型數龐大、內容精緻,讓用戶通過3個平台不同的對比能更直觀地了解一台車。最後活動也取得了非常高的關注度,還有用戶在看完我們的建議後果斷訂了車,總之非常感謝大家能給予我們支持,我們在日後還會給大家帶來更有價值的汽車內容。

回顧8款轎車/8款SUV精彩專題報道

請點擊此處:【廣州車展專題回顧】本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

網頁設計最專業,超強功能平台可客製化

※別再煩惱如何寫文案,掌握八大原則!

小喬累得全身濕透!如何拯救路上爆胎的美女?

此時你可以將被換下的輪胎墊在車底,謹防車身壓到

作為一個備胎,你是不是整天躺在後備箱,想着有一天可以逆襲?不用怕,今天讓我們的小喬姐姐親身示範,教你如何換備胎。

第一步 放置三角牌

如果你在馬路邊需要換胎,首先要做的就是在車後放置三角牌,最安全距離是150米以外,這樣可以提示後面來車,謹防追尾事故。

第二步 擰松輪胎螺絲

如果你所用的是非全尺寸備胎,同時很不幸的前輪受損,一般情況下是先將後輪換到前輪,再把備胎裝到後輪,因為前輪是屬於驅動輪,這樣換置會更安全些。而在本視頻中由於時間關係,所以只換了前胎作為示範。

在鬆開螺絲時,我們一般會用腳踩着扳手,這樣會更省力更便捷。

第三步 用千斤頂頂起車身

使用千斤頂是要先找到車底的凹槽位,需對準后才可以進行車輛的升起,否則容易卡壞凹槽部位和車底,也可能會發生安全事故。此外,很多老司機都會習慣先用千斤頂頂起車身,再鬆開螺絲拆卸輪胎,但是其實先鬆開輪胎螺絲再用千斤頂才是最方便的方法。

第四步 卸下輪胎

姿勢要到位,深蹲,抬起輪胎往外拔。

第五步 裝上備胎 預緊螺絲

在裝備胎時,要對準螺絲孔位,然後把螺絲裝上,用手預擰緊它。此時你可以將被換下的輪胎墊在車底,謹防車身壓到本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

※回頭車貨運收費標準

15萬中日韓SUV大比拼 本田現代能比傳祺GS4更值得買嗎?

內飾內飾上傳祺GS4採用了環抱式設計,六邊形元素設計的中控台和按鍵比較新穎,搭配着鍍鉻和烤漆裝飾條,裝配工藝良好。雖然繽智為精英型車型,但是車內整體看上去並不覺得廉價,表現得中規中矩。現代ix25採用了家族式T形設計理念,整體布局合理且錯落有致。

在國內火爆的SUV市場中,狀態最火熱的非小型SUV和緊湊型SUV莫屬了,而其中的車型又實在太多太多了,小編在SUV排行榜中順着找下來,發現傳祺GS4、本田繽智、現代ix25這三款車是中日韓SUV中比較熱門的,那麼15萬左右的購車預算,他么之中哪款最適合你呢?

有人就好奇了,本田CR-V、現代途勝的銷量不是比他們好么,為什麼沒入選呢,原因是15萬左右的價格並不能買得到,所以。。。

北京現代ix25

2015款 1.6L 自動兩驅智能型GLS

廠商指導價 14.28萬

繽智

2015款 1.8L CVT兩驅精英型

廠商指導價 14.68萬

傳祺GS4

2016款 235T G-DCT豪華版

廠商指導價 14.38萬

傳祺GS4在外觀原創度上極高,顛覆了自主品牌的抄襲現象,整體造型很有個性,飽滿而結實,凌雲翼式的進氣格柵搭配犀利的前大燈,辨識度很高;繽智的設計則要時尚柔美得多,無論從哪個角度看去都給人圓潤飽滿的感覺,很耐看;而ix25的外觀則給人簡潔幹練的感覺,運用了更多的直線條設計理念,比較硬派。

內飾上傳祺GS4採用了環抱式設計,六邊形元素設計的中控台和按鍵比較新穎,搭配着鍍鉻和烤漆裝飾條,裝配工藝良好;雖然繽智為精英型車型,但是車內整體看上去並不覺得廉價,表現得中規中矩;現代ix25採用了家族式T形設計理念,整體布局合理且錯落有致。

配置上繽智和傳祺GS4均配備了电子駐車、自動駐車、多功能方向盤、倒車影像、中控彩色大屏等配置,而在無鑰匙啟動/進入系統、陡坡緩降、電動天窗等配置繽智是缺少的,唯一的亮點就是其配備了發動機啟停技術,傳祺GS4配置最為豐富,前後排頭部氣囊、胎壓監測、定速巡航、前排座椅加熱等配置。

從車身尺寸上面我們可以清楚的看出,傳祺GS4各方面都佔優勢,空間表現上更為出色,而繽智雖然定位於小型SUV,但是本田善於利用空間設計,乘坐空間表現非常好,ix25空間上則不佔優勢,只能說將將夠用吧。

傳祺GS4 1.5T渦輪增壓發動機馬力最大,但雙離合的耐用可靠性還有待考驗;本田1.8L發動機+CVT的動力組合駕駛平順性出色,燃油經濟性好;ix25的1.6L+6擋手自一體變速器動力總成技術成熟,但功率上稍微欠缺。

總結:有人就說小編了,你拿個緊湊型SUV和小型SUV比有點不公平啊,但是同一價位內,跨級別的錯位競爭必然是存在的,銷量上就證明了好多問題,這也是傳祺GS4性價比那麼高的原因所在。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

※回頭車貨運收費標準

2.0T+7速雙離合 神車哈弗H6又出新款競爭力超強?

藍標版的進氣格柵較小,看起來更加精緻,紅標版本將採用大尺寸的進氣格柵(這是紅標版的一貫造型)看起來運動感十足,非常霸氣,底部霧燈區域的造型的尺寸也會更大,可以說紅標版和藍標版的不同點主要集中在前臉部分。

如今SUV大賣熱賣,受到消費者的熱捧,但是說起國內的SUV,那就不得不提哈弗了,因為就銷量來看,哈弗是當之無愧的自主SUV大哥。

作為哈弗最成功的一個車型,H6給哈弗貢獻了太多的銷量,今年10月份H6賣了56667輛,1-10月份累計賣了429896輛,甩第二名好幾條街。

但是這個銷量是有貓膩的,細心的讀者可以留意到每次看到銷量榜的時候,無論怎麼樣仔細查找,都找不到H6 coupe這款車。其實答案是這樣的。H6 coupe和H6完全不是同一台車,是全新的一代車型,主打運動風,但是在統計銷量的時候,H6 coupe是算到H6車型裏面的。根據長城官方的透漏,H6 coupe的月銷量佔H6銷量的30%左右。

所以,你看到H6的銷量才會那麼高。同時,H6 coupe的市場容量也挺大的。目前在售的H6 coupe搭載1.5T和2.0T發動機,為藍標版車型,那麼對於喜歡拉皮換殼折騰的哈弗來說,這遠遠是不夠的。所以就像H2s推出紅標版和藍標版一樣。H6 coupe也打算這樣折騰,推出紅標版車型。

廣州車展,H6 Coupe紅標版車型已經亮相了,同時我們在國家工信部官網看到了一款哈弗全新SUV的申報信息,所以我們大膽的猜測,這個車子就是即將上市的H6 COUpE紅標版車型。

長城的用意很明確,就是造出盡可能多的車型,滿足不同的消費者對外觀的不同需求,爭取銷量最大化,H6 Coupe紅標版和在售的藍標版主要的變化體現在外觀和全新的2.0T發動機。

藍標版的進氣格柵較小,看起來更加精緻,紅標版本將採用大尺寸的進氣格柵(這是紅標版的一貫造型)看起來運動感十足,非常霸氣,底部霧燈區域的造型的尺寸也會更大,可以說紅標版和藍標版的不同點主要集中在前臉部分。

但是到了側面和尾部,差別就比較小了,畢竟還是“臉”最重要麼。不過,H6 coupe的懸浮式車頂的造型看上去倒是很時尚,賣點不少。

內飾造型和在售藍標版完全一致,看起來簡潔大方,內飾用料很實在,做工很精細,看起來很有檔次感。

其實說到這裏大家也都知道了,紅標版和藍標版的差別並不大,只是外觀有少許差別。另外新車將會搭載GW4G15B 1.5T和GW4C20 2.0T汽油發動機,匹配6速手動、7速雙離合變速箱。

紅標版車型的長寬高為4590/1845/1700mm,軸距為2720mm。同時我們根據申報的信息來看,1.5T車型的百公里綜合油耗申報值為7.4L/100km,2.0T車型的為8.5L/100km。當然實際油耗肯定不止這麼低。

總結:和H2s的紅藍標車型一樣,H6 coupe也是搞兩個外觀有差別,但是內在都一樣的車子,所以對於這種車型,你只需要考慮喜歡哪個外觀就行。不過紅標版的H6 coupe上市以後,也會面諸如博越、榮威RX5等這些強大的對手。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※回頭車貨運收費標準

台中搬家公司費用怎麼算?

廣州車展 這些“見所未見”的轎跑/SUV絕不能錯過

渾身肌肉一臉野性的“美式壯man”近一個世紀以來,雪佛蘭皮卡不斷演化——讓人們體驗到更加豐富而時尚的生活樂趣。本次索羅德Silverado、庫羅德Colorado的展示,也讓中國的消費者真正的認識以及觸碰到皮卡,其像無畏的騎士,是一種血性的代表,彷彿每時每刻都想衝出家門去越野。

雪佛蘭誕生於賽道之上,但卻回歸到群眾之中。雪佛蘭給我們的印象是一個普及化的品牌,產品覆蓋面很廣,服務於各種人群,但有很多人不知道的是,第一輛雪佛蘭汽車其實是一輛高性能的高端車型,Classic six不僅在性能上超越當時市面上的車型,搭載的發動機在技術上也是領先同行,雖然售價偏高,但是一炮打響了雪佛蘭的金字招牌,就如創始人路易·雪佛蘭的賽車手熱誠一般,在人們心中留下深深的激情勇敢、創新突破的印跡。

縱然雪佛蘭在那之後調整了方向,更加側重於製造服務廣大受眾的汽車,但這樣的DNA已深入雪佛蘭汽車的骨髓,雪佛蘭的產品一直是高品質駕駛樂趣的代表,歷經百年後,如今的雪佛蘭已經是一種生活態度的體現。在本次的廣州車展上,這個百年金領結更是給大家展示了一道“見所未見”的風景線,年輕的轎跑,硬漢的皮卡,極致的跑車,你想要的這裏都有。

從變形金剛穿越的燃爆大黃蜂

沒錯,如今展示在廣州車展舞台的就是《變形金剛》電影里鼎鼎大名的“大黃蜂”—— 全新第六代科邁羅。雖身處展台,但從前臉的進氣格柵,經典肌肉線條,LED扁平前大燈,都能讓人感受到科邁羅馭風疾馳的賽道氣息。

自誕生以來,這輛有着“非凡魅力“的大黃蜂,其轟鳴便橫掃了國際各大賽事。這也得益於創始人路易·雪佛蘭,在雪佛蘭公司成立之前,他就是一名賽車手,每天夢想的就是生產高品質的跑車,直至今天的通用汽車總裁丹·阿曼先生都是賽車的好手。很顯然,這個金領結早在誕生時,就與運動一直捆綁着。

硬派氣質秒殺同級的探界者Equinox

身為SUV陣營“主導者”——探界者Equinox,在碰撞展檯燈光之間,顯露了十足的美式力量。同時也在用一種無聲的力量詮釋着探界者的英文名Equinox所表達的含義:晝夜均分的春分與秋分時節,蓄含突破與改變現狀的力量,不受界限與束縛地探索各種可能。

另外,更值得一提的是,在小排量渦輪發動機成為主流的當下,誠然各大廠商的技術已不存在明顯的“代差”,但毋庸置疑通用的發動機一直處於一線。目前在Equinox車上配備了9AT變速箱,從机械結構上來看,沒有採用絞牙式的離合器,但體積沒有增大,平順性會有更好的保證。

渾身肌肉一臉野性的“美式壯man”

近一個世紀以來,雪佛蘭皮卡不斷演化——讓人們體驗到更加豐富而時尚的生活樂趣。本次索羅德Silverado、庫羅德Colorado的展示,也讓中國的消費者真正的認識以及觸碰到皮卡,其像無畏的騎士,是一種血性的代表,彷彿每時每刻都想衝出家門去越野。

這兩款皮卡,跟我們通常認知的皮卡可以說不是一種產物,雪佛蘭的皮卡絕對稱得上高級好開。它們的加入,也將會讓許久沒有全新車型加入的中國高端皮卡市場競爭更加激烈,很是值得期待。

索羅德Silverado

庫羅德Colorado

此次車展,雪佛蘭帶給消費者的不單是一場視覺上的盛宴,更是一個關於夢的兌現。時光荏苒,這個金領結已經走過百年,從K系列與福特T型車比肩開始,成功度過大蕭條,不斷推出新產品,甚至還一定程度上為現在汽車製造工業奠定了基礎。

雪佛蘭已橫跨140多個國家與地區,馳騁了無數世界超級賽事,征服了全球2.3億車主,同時,在品牌建設上的突破,也取得耀眼的成績——作為上海迪斯尼官方度假區的官方汽車合作品牌,獨家贊助了極具標誌性景點的“創極速光輪”,還與曼聯聯合為廣大球迷帶來眾多精彩賽事,贊助紅粉筆計劃為鄉村支教事業出一份力。

(快閃視頻)

說了這麼多,“棒球、熱狗、蘋果派,不能少了雪佛蘭”。雪佛蘭已經完成了美國夢,也終將成為與可口可樂、蘋果一樣的icon,從美國夢成就世界夢。你我的生活也可能都逃不過一輛雪佛蘭。而本次車展無論你聚焦於以上任何一款產品,它都能代表雪佛蘭。

未來雪佛蘭還將會繼續研發與進步,夢想不止,夢創未來。無論是新能源,車聯網,自動駕駛等等有關未來出行的一切,雪佛蘭都有着充足的技術儲備,期待雪佛蘭將持續以一種高品質的姿態,帶給你我更多“見所未見“的產品。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計最專業,超強功能平台可客製化

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※回頭車貨運收費標準

※推薦評價好的iphone維修中心

※教你寫出一流的銷售文案?

台中搬家公司教你幾個打包小技巧,輕鬆整理裝箱!

台中搬家公司費用怎麼算?

排量小動力猛!10.9萬起緊湊型家用車更貴了反而更值得買?

2T發動機最大馬力116匹,峰值扭矩185牛米,與之匹配的是一台模擬八個檔位的S-CVT無級變速箱,由於定位依舊是一款家用轎車,在轉向手感建立和油門響應的調校方式上還是保留了雷凌以往較為輕盈的特性,駕駛依舊平易近人。除了發動機,它貴在哪。

雷凌1.2T

自從卡羅拉推出了1.2T版本以後,作為與其同平台的雷凌也很快的裝配上了同樣的渦輪增壓發動機,由於雷凌的設計會顯得更加的運動激進化一些,這也是很多年輕人的首次購車選擇,但是在很多人眼裡,1.2T的雷凌上市以後比以往要貴了幾千塊,這車到底還值得購買嗎?

廣汽豐田雷凌1.2T

指導價格:10.98-13.38萬

外觀並無變化

廣汽豐田雷凌的新款1.2T渦輪增壓車型畢竟只是一款中期改款車型,在外觀上並沒有什麼過多的變化,僅僅是在頂配車型當中增加了一套LED光源的日間行車燈以及中網採用了鋼琴黑騎的裝飾,值得一提的是,廣汽豐田雷凌1.2T新增了一種名為琥珀棕的車身配色。

運動化的內飾是為亮點

內飾設計其實也沒多少改動,只是在原有的基礎上增添了紅色的裝飾,添置於中控台和門板上,增加了內飾視覺感官上的精緻度,並且將前排座椅改動成為帶兩側護翼的運動型座椅設計,縫線工藝所綉出來的LEVIN字樣彰顯着身份,也讓雷凌內飾看上去更加動感。

小排量渦輪增壓才是重點

我們可以注意到1.2T雷凌的尾標上標註的是D-4T的標識,意為:Dirct-injuction 4 stroke gasoline engine with Turbo.翻譯過來就是:四衝程缸內直噴渦輪增壓發動機。與市面上多數“少了排量就少了缸數”的小排量三缸渦輪增壓機不同,豐田這款1.2T發動機依然使用了直列四缸的布局,更多的缸數也意味着這款發動機在運轉過程中可以保持優良的平順性。

由於使用了豐田雙VVT-iW可變氣門正時技術、以及使用缸內直噴的噴油方式,這款發動機的升功率也會相應增高,而且這款發動機的內燃機熱力循環方式可以在奧拓循環和阿特金森循環之間切換,所以在保證了發動機工作效率的同時,也保證了燃油經濟性。

雷凌1.2T發動機最大馬力116匹,峰值扭矩185牛米,與之匹配的是一台模擬八個檔位的S-CVT無級變速箱,由於定位依舊是一款家用轎車,在轉向手感建立和油門響應的調校方式上還是保留了雷凌以往較為輕盈的特性,駕駛依舊平易近人。

除了發動機,它貴在哪?

很多人會覺得,既然換了渦輪增壓發動機肯定在技術成本上就變得更加昂貴了,但其實我們可以對比一下,作為以往雷凌的主力車型1.6L自然吸氣版本指導價格為10.78-13.08萬,而雷凌1.2T的指導價格為10.98-13.38萬,但雷凌1.2T的配置卻是對得起它的售價。

雷凌1.2T車型標配了發動機啟停系統,並且增加了車身穩定系統,牽引力控制系統,以及上坡輔助系統,這些主動安全配置的搭載在以往的1.6L車型中並沒有裝配,如此看來這兩三千的定價換來的是更多的安全配置,這波交易並不虧。

全文總結:與雙胞胎車型卡羅拉不同的是,雷凌1.2T的上市是作為全面取代1.6L自然吸氣版本的角色存在,所以從主動安全配置上看雷凌的性價比有所提高,而1.2T渦輪增壓的搭載動力表現也比原來作為主力的1.6L車型更好,所以從品控、定位以及車型本身的綜合產品力來說,雷凌仍舊是一款不錯的值得購買的合資緊湊型家用轎車。至於究竟是否值得購買,那就要看你對於日系車,對於豐田品牌的接受程度有多高了,本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※回頭車貨運收費標準

※推薦評價好的iphone維修中心

※超省錢租車方案

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

※推薦台中搬家公司優質服務,可到府估價

這台800萬的自主車 馬化騰 劉強東 雷軍人手一台

全球最快電動車發布 蔚來 Ep9動力方面搭載了4台高性能電機以及4個獨立變速箱,最終能夠輸出1,360匹馬力,0到200公里加速7。1秒,極速313公里。Ep9採用彈匣式可換電池系統,快充模式下充滿電僅需45分鐘,續航里程可達427公里。搭載的DRS可調擾流控制系統,包括三種可調模式的動態尾翼系統,和全尺寸底盤擴散器等空氣動力裝置,使得Ep9在每小時240公里的速度下能夠獲得高達24,000牛的下壓力。

思域1.0T正式發布

本次只有手動/自動各一個車型,價格分別是11.59萬和12.79萬元。相比1.5T的豪華型,前排側氣囊、前後排頭部氣簾、無鑰匙進入/啟動、電動天窗、后駐車雷達、全液晶儀錶盤、後排杯架、後排中央扶手、中控屏、前霧燈、后視鏡加熱、自動空調統統都沒有了,3缸發動機還簡配成這樣,大致意思就是說這已經是最低價了,所以 1.5T的車型該加價的加價,該等車的等車繼續等吧。

樂視 lucid motors

官方表明,從造電池到造車,Atieva算是進行了一個大的跨越,而其核心競爭力則是其獨特的電池冷卻和能量管理技術,電池的能量密度比其他競爭對手普遍高出20%,續航里程可以輕鬆超過480km,它的最大馬力可以達到1200匹,最後為了安全起見被設置在900匹。儘管如此,它的百公里加速時間也可以達到2.69秒,還沒看到實車在路上跑之前,我們就看看咯。

全球最快電動車發布 蔚來 Ep9

動力方面搭載了4台高性能電機以及4個獨立變速箱,最終能夠輸出1,360匹馬力,0到200公里加速7.1秒,極速313公里。Ep9採用彈匣式可換電池系統,快充模式下充滿電僅需45分鐘,續航里程可達427公里。

搭載的DRS可調擾流控制系統,包括三種可調模式的動態尾翼系統,和全尺寸底盤擴散器等空氣動力裝置,使得Ep9在每小時240公里的速度下能夠獲得高達24,000牛的下壓力。

紀錄片显示Ep9在10月12日德國紐博格林北環賽道進行的測試中,創造了7分05秒的最快電動汽車圈速,公司創始投資人包括雷軍,馬化騰,奶茶妹夫劉強東,整個發布會過程中透露Ep9的造價達到了120萬美元,據之前消息稱未來量產的首款車型將會是一款20萬左右的SUV車型,大家覺得怎麼樣?

新能源汽車騙補貼披露 金龍汽車罰款近8億

本月財政部向工信部抄送了《財政部行政處罰事項告知書》,確認蘇州金龍公司申報2015年度中央財政補貼資金的新能源汽車中,有1683輛車截至2015年底仍未完工,但在2015年卻提前辦理了機動車行駛證。涉及補助資金5.19億元。根據相關法規,工信部將責令蘇州金龍公司停止生產和銷售問題車型,暫停蘇州金龍公司申報新能源汽車推廣應用推薦車型資質,並將問題車型從《新能源汽車推廣應用推薦車型目錄》予以剔除,進行為期6個月整改,整改完成后,工信部將對整改情況進行驗收。

最終追回罰款達7.78億,其實不止金龍汽車,現在國內93家新能源汽車企業中有72家存在有騙補貼的行為,這一次的強力打壓會不會對以後的新能源電動車發展有所改進呢?本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※回頭車貨運收費標準

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※推薦評價好的iphone維修中心

※教你寫出一流的銷售文案?

台中搬家公司教你幾個打包小技巧,輕鬆整理裝箱!

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

人生繞不開的BMW 3系,迎來最佳出手時機

4%。在配置方面,2017款BMW 3系相比前代車型也有所提升,更突顯運動風範和豪華感。此次BMW將M套件拓展至BMW 3系長軸距車型上,推出了一款新車型,320Li M運動型。BMW 320Li M車型上的M運動套件擁有多達11項專屬裝備,絕對喚起你的運動激情。

盛名不負,挑戰最美彎道

前段時間,BMW 3系又在功名簿書寫了濃墨重彩的一筆,因為它成功挑戰了世界最美彎道——雲南宜良六十八道拐。高原氣候條件本身對車輛動力表現就是一大挑戰,連續性角度刁鑽的崎嶇山路更是讓許多車型望而生畏。

明知山有虎,寶馬的自信不是憑空而來。1975年第一台寶馬3系就定義了豪華運動轎車。41年後的今天,它毫不妥協的運動特性以及卓越的操控讓它穩坐運動車的第一把交椅,這個王位背後站着的是數以百萬計的忠實粉絲。

你也許會問,它何以為王?看看2017款3系就能略知一二。2017款3系裝載了全新B系列發動機,動力強勁輸出線性,駕馭起來十分輕鬆。前雙球節彈簧減振支柱前橋+后多連桿獨立懸架也堪稱完美的運動利器,這套懸挂系統使用運動化調教,在彎道中對於車身的支撐十分到位,側傾抑制優秀,並且雙球節彈簧減振支柱前橋能夠大幅度提升操控的精準性,這也是BMW 3系指向性幾近完美的奧秘所在。

開車和駕馭是兩個概念,BMW 3系解釋了什麼是駕馭,這就是那麼多人愛它的原因。

“心”有不同,新有不同

2017款3系搭載了曾獲“沃德十佳發動機稱號”的B系列發動機,相比之前的N系列發動機在調教方面更加完美。全新的2.0T發動機最大功率提升了5千瓦,3.0T發動機最大功率提升了14千瓦,最大扭矩提升了50牛·米,同時最大功率爆發點更低,讓3系的提速反應更敏捷,進一步增強了駕駛樂趣。B系列發動機帶來的燃油經濟性表現也更佳,2017款3系全系產品油耗平均降低了8.4%。

在配置方面,2017款BMW 3系相比前代車型也有所提升,更突顯運動風範和豪華感。此次BMW將M套件拓展至BMW 3系長軸距車型上,推出了一款新車型,320Li M運動型。BMW 320Li M車型上的M運動套件擁有多達11項專屬裝備,絕對喚起你的運動激情。同時,BMW 320Li M車型還配備了十分實用且顯檔次的HUD抬頭显示系統,可以把車速導航等信息投影到前擋風玻璃上,讀取信息時不需要低頭看儀錶,確保了更好的行車安全性。隨着BMW 320Li M車型的推出,將絕對吸引那些既看中3系駕駛樂趣又對空間有執著需求的消費者。

2017款BMW 3系在智能化的互聯駕駛方面展示了BMW的前沿技術優勢。BMW “自然語音識別系統”(NLU),是市場上首套實現真正意義上的自然語音識別功能的智能系統,NLU能夠識別本土化語言,無須手動操作就可以實現導航設定,娛樂,車輛信息查看等功能。同時,寶馬也十分大方地把應用於旗艦車型BMW 7系的新一代iDrive 人機交互界面也引入到2017款BMW 3繫上。全新界面的显示質感更豪華,顏色更細膩,子菜單內容直觀清晰。

鉅惠模式開啟 錯過等一年

2017款3系一經推出,就讓眾多3系粉絲又一次熱血澎湃起來,而突出的性價比優勢更收穫了良好的市場反饋。臨近年底,BMW 3系仍有不同幅度的優惠。其中,搭載1.5T發動機的318車型還享有購置稅減半政策,親民的價格加上BMW為客戶貼心定製的多款超值金融政策,夢想中的3系已經駛近你的生活。此時不入手3系,一旦優惠幅度縮緊以及12月31日後購置稅減半政策的終止,就等着哭暈在廁所吧。

本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

網頁設計最專業,超強功能平台可客製化

※別再煩惱如何寫文案,掌握八大原則!