Thoughtworks是一家创办于1993年的全球性软件及咨询公司,致力于用科技驱动商业变革,针对全球客户数字化业务提供专业组织转型咨询、创新软件交付、用户体验设计、产品及一体化解决方案等服务。
客户遍及全球汽车、金融保险、医疗、旅游、运输、零售、电商、能源、公共事业等领域。在澳大利亚、中国、厄瓜多尔、德国、印度、意大利等17个国家设立48个办公室,拥有超过9000名员工。
thoughtworks是一家创办于1993年的全球性软件及咨询公司,致力于用科技驱动商业变革,针对全球客户数字化业务提供专业组织转型咨询、创新软件交付、用户体验设计、产品及一体化解决方案等服务。
客户遍及全球汽车、金融保险、医疗、旅游、运输、零售、电商、能源、公共事业等领域。在澳大利亚、中国、厄瓜多尔、德国、印度、意大利等17个国家设立48个办公室,拥有超过9000名员工。
是
是的,思特沃克本质上是外包公司。虽然思特沃克的自我定位是高级外包,但其本质上就是外包公司。外包的本质就是外包,而思特沃克则是外包公司。在思特沃克的工作中,员工需要接受公司提供的培训和指导,但如果员工的能力不达标,则需要被拉入各种项目,这些项目可能涉及技术。
靠谱。
Thoughtworks是一家创办于1993年的全球性软件及咨询公司,致力于用科技驱动商业变革,针对全球客户数字化业务提供专业组织转型咨询、创新软件交付、用户体验设计、产品及一体化解决方案等服务。客户遍及全球汽车、金融保险、医疗、旅游、运输、零售、电商、能源、公共事业等领域。
在澳大利亚、中国、厄瓜多尔、德国、印度、意大利等17个国家设立48个办公室,拥有超过9000名员工。2004年进入中国,已在北京、西安、成都、上海、武汉、深圳及香港等地设立七个办公室,拥有超过2000名员工。Thoughtworks的业务模式主要通过咨询帮助改善企业的IT组织,改进软件开发方法,以软件带动企业业务发展。Thoughtworks为客户提供集创意设计、开发及交付为一体的定制服务。而且随着企业知识处理能力发展需求不断提升,知识流程外包(KPO)越来越成为被行业认可的热点模式,而Thoughtworks对于KPO的核心-战略性的关键IT系统交付同样经验丰富。
工资待遇:¥30000-50000
岗位内容:
1.研究并理解软件工程领域技术趋势,挖掘并揭示客户的痛点和诉求
2.对研发过程有深刻理解,具备一定高度抽象能力,摒弃细节探求本质
3.熟悉不同类型的研发体系,例如应用系统,移动端开发,数据型项目等
4.能够总结对应的的工程优秀实践,结合工具提供完整的解决方案,帮助客户进行设计规划和落地希望是:
1.对软件设计和架构有深刻的思考,如果有数据挖掘和分析或者统计学背景优先。
2.开放且乐于沟通和合作,强调团队协作3.良好的对内对外沟通能力以及面对客户的能力4接受一定比例的出差5英语具备读写能力。
是外包公司。
thoutworks是一家专业的软件外包公司,提供软件开发、测试、维护等服务。
他们有专业的团队和丰富的项目经验,通过与客户合作,为他们提供高质量的解决方案和定制化的软件开发服务。
作为外包公司,thoutworks与客户进行合作,帮助客户实现各种软件开发需求。
他们的专业团队可以根据客户的要求进行定制开发,同时也能提供软件测试、项目迭代和维护等服务。
thoutworks的目标是以高效、专业的方式满足客户的需求,帮助他们提高业务效率
和竞争力。
Thoughtworks是⼀家创办于1993年的全球性软件及咨询公司。追求技术卓越,致⼒于⽤科技驱动商业变⾰,为世界创造⾮凡影响。针对全球顶尖客户数字化业务提供专业组织转型咨询、创新软件交付、⽤户体验设计、产品及⼀体化解决⽅案等服务。客户遍及全球汽⻋、⾦融保险、医疗、旅游、运输、零售、电商、能源、公共事业等领域
thoughtworks是世界五百强企业。全球软件设计与定制 企业ThoughtWorks是与谷歌齐名的IT企业,目前在美国、英国、澳大利亚、加拿大、德国、印度、巴西、南非、中国等十个国家成立分公司,聘用超过2000位行业精英,员工招聘体系比谷歌更为严苛,主要服务英特尔、惠普等 企业。
先说明下,这不是广告,咱也没广告费,客观说点观察到的优势。
在thoughtworks工作,能学到技术什么的就不多说了,作为一家技术公司,技术是根本,来说说其他亮点,尤其是在大多数普通公司学不到的。
在大多数公司,员工比较难找到施展自己才才华的舞台,在thoughtworks可以。tw鼓励员工以多种形式树立个人影响力,项目内部带buddy,积累知识沉淀,团队内部做各种分享活动,对外写书,组织各种丰富的社区活动,甚至到各种大会上公开演讲,只要你有意愿,发扬自己,发光发热,公司都会给予各种支持。
大多数公司,技术人员都是螺丝钉,在thoughtworks不是。很多公司的技术团队是根据层级划分,有部门墙,在tw的各种项目里,不论你是开发,还是设计师,还是ba,都可以从一开始需求分析到产品开发上线全程参与到各种分析和讨论里去,打破层级和部门墙,在客户现场和客户团队的各种领导们一起开会、讨论需求是家常便饭。
大多数公司,人才培养十分薄弱,有的公司只希望员工产出,有的公司只有少数领导层或者混到高级别才有机会参与一些培训。在tw全年,全国各地office不知道发生过多少场培训,而且培训内容多种多样,可以说是发自肺腑的希望帮助每一个员工健康成长。除此之外,tw的一项福利是每年提供几千元的培训经费,福利大家采购书籍,学习和提升自己。业界各种大型conference也都会有人参加,并且把内容带回tw内部,转化为知识沉淀和分享。
先写到这吧,嘻嘻。
之前看了Mahout官方示例 20news 的调用实现;于是想根据示例的流程实现其他例子。网上看到了一个关于天气适不适合打羽毛球的例子。
训练数据:
Day Outlook Temperature Humidity Wind PlayTennis
D1 Sunny Hot High Weak No
D2 Sunny Hot High Strong No
D3 Overcast Hot High Weak Yes
D4 Rain Mild High Weak Yes
D5 Rain Cool Normal Weak Yes
D6 Rain Cool Normal Strong No
D7 Overcast Cool Normal Strong Yes
D8 Sunny Mild High Weak No
D9 Sunny Cool Normal Weak Yes
D10 Rain Mild Normal Weak Yes
D11 Sunny Mild Normal Strong Yes
D12 Overcast Mild High Strong Yes
D13 Overcast Hot Normal Weak Yes
D14 Rain Mild High Strong No
检测数据:
sunny,hot,high,weak
结果:
Yes=》 0.007039
No=》 0.027418
于是使用Java代码调用Mahout的工具类实现分类。
基本思想:
1. 构造分类数据。
2. 使用Mahout工具类进行训练,得到训练模型。
3。将要检测数据转换成vector数据。
4. 分类器对vector数据进行分类。
接下来贴下我的代码实现=》
1. 构造分类数据:
在hdfs主要创建一个文件夹路径 /zhoujainfeng/playtennis/input 并将分类文件夹 no 和 yes 的数据传到hdfs上面。
数据文件格式,如D1文件内容: Sunny Hot High Weak
2. 使用Mahout工具类进行训练,得到训练模型。
3。将要检测数据转换成vector数据。
4. 分类器对vector数据进行分类。
这三步,代码我就一次全贴出来;主要是两个类 PlayTennis1 和 BayesCheckData = =》
package myTesting.bayes;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.util.ToolRunner;
import org.apache.mahout.classifier.naivebayes.training.TrainNaiveBayesJob;
import org.apache.mahout.text.SequenceFilesFromDirectory;
import org.apache.mahout.vectorizer.SparseVectorsFromSequenceFiles;
public class PlayTennis1 {
private static final String WORK_DIR = "hdfs://192.168.9.72:9000/zhoujianfeng/playtennis";
/*
* 测试代码
*/
public static void main(String[] args) {
//将训练数据转换成 vector数据
makeTrainVector();
//产生训练模型
makeModel(false);
//测试检测数据
BayesCheckData.printResult();
}
public static void makeCheckVector(){
//将测试数据转换成序列化文件
try {
Configuration conf = new Configuration();
conf.addResource(new Path("/usr/local/hadoop/conf/core-site.xml"));
String input = WORK_DIR+Path.SEPARATOR+"testinput";
String output = WORK_DIR+Path.SEPARATOR+"tennis-test-seq";
Path in = new Path(input);
Path out = new Path(output);
FileSystem fs = FileSystem.get(conf);
if(fs.exists(in)){
if(fs.exists(out)){
//boolean参数是,是否递归删除的意思
fs.delete(out, true);
}
SequenceFilesFromDirectory sffd = new SequenceFilesFromDirectory();
String[] params = new String[]{"-i",input,"-o",output,"-ow"};
ToolRunner.run(sffd, params);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("文件序列化失败!");
System.exit(1);
}
//将序列化文件转换成向量文件
try {
Configuration conf = new Configuration();
conf.addResource(new Path("/usr/local/hadoop/conf/core-site.xml"));
String input = WORK_DIR+Path.SEPARATOR+"tennis-test-seq";
String output = WORK_DIR+Path.SEPARATOR+"tennis-test-vectors";
Path in = new Path(input);
Path out = new Path(output);
FileSystem fs = FileSystem.get(conf);
if(fs.exists(in)){
if(fs.exists(out)){
//boolean参数是,是否递归删除的意思
fs.delete(out, true);
}
SparseVectorsFromSequenceFiles svfsf = new SparseVectorsFromSequenceFiles();
String[] params = new String[]{"-i",input,"-o",output,"-lnorm","-nv","-wt","tfidf"};
ToolRunner.run(svfsf, params);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("序列化文件转换成向量失败!");
System.out.println(2);
}
}
public static void makeTrainVector(){
//将测试数据转换成序列化文件
try {
Configuration conf = new Configuration();
conf.addResource(new Path("/usr/local/hadoop/conf/core-site.xml"));
String input = WORK_DIR+Path.SEPARATOR+"input";
String output = WORK_DIR+Path.SEPARATOR+"tennis-seq";
Path in = new Path(input);
Path out = new Path(output);
FileSystem fs = FileSystem.get(conf);
if(fs.exists(in)){
if(fs.exists(out)){
//boolean参数是,是否递归删除的意思
fs.delete(out, true);
}
SequenceFilesFromDirectory sffd = new SequenceFilesFromDirectory();
String[] params = new String[]{"-i",input,"-o",output,"-ow"};
ToolRunner.run(sffd, params);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("文件序列化失败!");
System.exit(1);
}
//将序列化文件转换成向量文件
try {
Configuration conf = new Configuration();
conf.addResource(new Path("/usr/local/hadoop/conf/core-site.xml"));
String input = WORK_DIR+Path.SEPARATOR+"tennis-seq";
String output = WORK_DIR+Path.SEPARATOR+"tennis-vectors";
Path in = new Path(input);
Path out = new Path(output);
FileSystem fs = FileSystem.get(conf);
if(fs.exists(in)){
if(fs.exists(out)){
//boolean参数是,是否递归删除的意思
fs.delete(out, true);
}
SparseVectorsFromSequenceFiles svfsf = new SparseVectorsFromSequenceFiles();
String[] params = new String[]{"-i",input,"-o",output,"-lnorm","-nv","-wt","tfidf"};
ToolRunner.run(svfsf, params);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("序列化文件转换成向量失败!");
System.out.println(2);
}
}
public static void makeModel(boolean completelyNB){
try {
Configuration conf = new Configuration();
conf.addResource(new Path("/usr/local/hadoop/conf/core-site.xml"));
String input = WORK_DIR+Path.SEPARATOR+"tennis-vectors"+Path.SEPARATOR+"tfidf-vectors";
String model = WORK_DIR+Path.SEPARATOR+"model";
String labelindex = WORK_DIR+Path.SEPARATOR+"labelindex";
Path in = new Path(input);
Path out = new Path(model);
Path label = new Path(labelindex);
FileSystem fs = FileSystem.get(conf);
if(fs.exists(in)){
if(fs.exists(out)){
//boolean参数是,是否递归删除的意思
fs.delete(out, true);
}
if(fs.exists(label)){
//boolean参数是,是否递归删除的意思
fs.delete(label, true);
}
TrainNaiveBayesJob tnbj = new TrainNaiveBayesJob();
String[] params =null;
if(completelyNB){
params = new String[]{"-i",input,"-el","-o",model,"-li",labelindex,"-ow","-c"};
}else{
params = new String[]{"-i",input,"-el","-o",model,"-li",labelindex,"-ow"};
}
ToolRunner.run(tnbj, params);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("生成训练模型失败!");
System.exit(3);
}
}
}
package myTesting.bayes;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.PathFilter;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.mahout.classifier.naivebayes.BayesUtils;
import org.apache.mahout.classifier.naivebayes.NaiveBayesModel;
import org.apache.mahout.classifier.naivebayes.StandardNaiveBayesClassifier;
import org.apache.mahout.common.Pair;
import org.apache.mahout.common.iterator.sequencefile.PathType;
import org.apache.mahout.common.iterator.sequencefile.SequenceFileDirIterable;
import org.apache.mahout.math.RandomAccessSparseVector;
import org.apache.mahout.math.Vector;
import org.apache.mahout.math.Vector.Element;
import org.apache.mahout.vectorizer.TFIDF;
import com.google.common.collect.ConcurrentHashMultiset;
import com.google.common.collect.Multiset;
public class BayesCheckData {
private static StandardNaiveBayesClassifier classifier;
private static Map<String, Integer> dictionary;
private static Map<Integer, Long> documentFrequency;
private static Map<Integer, String> labelIndex;
public void init(Configuration conf){
try {
String modelPath = "/zhoujianfeng/playtennis/model";
String dictionaryPath = "/zhoujianfeng/playtennis/tennis-vectors/dictionary.file-0";
String documentFrequencyPath = "/zhoujianfeng/playtennis/tennis-vectors/df-count";
String labelIndexPath = "/zhoujianfeng/playtennis/labelindex";
dictionary = readDictionnary(conf, new Path(dictionaryPath));
documentFrequency = readDocumentFrequency(conf, new Path(documentFrequencyPath));
labelIndex = BayesUtils.readLabelIndex(conf, new Path(labelIndexPath));
NaiveBayesModel model = NaiveBayesModel.materialize(new Path(modelPath), conf);
classifier = new StandardNaiveBayesClassifier(model);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("检测数据构造成vectors初始化时报错。。。。");
System.exit(4);
}
}
/**
* 加载字典文件,Key: TermValue; Value:TermID
* @param conf
* @param dictionnaryDir
* @return
*/
private static Map<String, Integer> readDictionnary(Configuration conf, Path dictionnaryDir) {
Map<String, Integer> dictionnary = new HashMap<String, Integer>();
PathFilter filter = new PathFilter() {
@Override
public boolean accept(Path path) {
String name = path.getName();
return name.startsWith("dictionary.file");
}
};
for (Pair<Text, IntWritable> pair : new SequenceFileDirIterable<Text, IntWritable>(dictionnaryDir, PathType.LIST, filter, conf)) {
dictionnary.put(pair.getFirst().toString(), pair.getSecond().get());
}
return dictionnary;
}
/**
* 加载df-count目录下TermDoc频率文件,Key: TermID; Value:DocFreq
* @param conf
* @param dictionnaryDir
* @return
*/
private static Map<Integer, Long> readDocumentFrequency(Configuration conf, Path documentFrequencyDir) {
Map<Integer, Long> documentFrequency = new HashMap<Integer, Long>();
PathFilter filter = new PathFilter() {
@Override
public boolean accept(Path path) {
return path.getName().startsWith("part-r");
}
};
for (Pair<IntWritable, LongWritable> pair : new SequenceFileDirIterable<IntWritable, LongWritable>(documentFrequencyDir, PathType.LIST, filter, conf)) {
documentFrequency.put(pair.getFirst().get(), pair.getSecond().get());
}
return documentFrequency;
}
public static String getCheckResult(){
Configuration conf = new Configuration();
conf.addResource(new Path("/usr/local/hadoop/conf/core-site.xml"));
String classify = "NaN";
BayesCheckData cdv = new BayesCheckData();
cdv.init(conf);
System.out.println("init done...............");
Vector vector = new RandomAccessSparseVector(10000);
TFIDF tfidf = new TFIDF();
//sunny,hot,high,weak
Multiset<String> words = ConcurrentHashMultiset.create();
words.add("sunny",1);
words.add("hot",1);
words.add("high",1);
words.add("weak",1);
int documentCount = documentFrequency.get(-1).intValue(); // key=-1时表示总文档数
for (Multiset.Entry<String> entry : words.entrySet()) {
String word = entry.getElement();
int count = entry.getCount();
Integer wordId = dictionary.get(word); // 需要从dictionary.file-0文件(tf-vector)下得到wordID,
if (StringUtils.isEmpty(wordId.toString())){
continue;
}
if (documentFrequency.get(wordId) == null){
continue;
}
Long freq = documentFrequency.get(wordId);
double tfIdfValue = tfidf.calculate(count, freq.intValue(), 1, documentCount);
vector.setQuick(wordId, tfIdfValue);
}
// 利用贝叶斯算法开始分类,并提取得分最好的分类label
Vector resultVector = classifier.classifyFull(vector);
double bestScore = -Double.MAX_VALUE;
int bestCategoryId = -1;
for(Element element: resultVector.all()) {
int categoryId = element.index();
double score = element.get();
System.out.println("categoryId:"+categoryId+" score:"+score);
if (score > bestScore) {
bestScore = score;
bestCategoryId = categoryId;
}
}
classify = labelIndex.get(bestCategoryId)+"(categoryId="+bestCategoryId+")";
return classify;
}
public static void printResult(){
System.out.println("检测所属类别是:"+getCheckResult());
}
}